eb6cd8ce112791a7d4f68dfbf020713464ec8da6
[openocd.git] / src / target / mips32_dmaacc.c
1 /***************************************************************************
2 * Copyright (C) 2008 by John McCarthy *
3 * jgmcc@magma.ca *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2008 by David T.L. Wong *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
24 ***************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "mips32_dmaacc.h"
31 #include <helper/time_support.h>
32
33 static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info,
34 uint32_t addr, int count, uint8_t *buf);
35 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info,
36 uint32_t addr, int count, uint16_t *buf);
37 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info,
38 uint32_t addr, int count, uint32_t *buf);
39
40 static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info,
41 uint32_t addr, int count, uint8_t *buf);
42 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info,
43 uint32_t addr, int count, uint16_t *buf);
44 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info,
45 uint32_t addr, int count, uint32_t *buf);
46
47 /*
48 * The following logic shamelessly cloned from HairyDairyMaid's wrt54g_debrick
49 * to support the Broadcom BCM5352 SoC in the Linksys WRT54GL wireless router
50 * (and any others that support EJTAG DMA transfers).
51 * Note: This only supports memory read/write. Since the BCM5352 doesn't
52 * appear to support PRACC accesses, all debug functions except halt
53 * do not work. Still, this does allow erasing/writing flash as well as
54 * displaying/modifying memory and memory mapped registers.
55 */
56
57 static int ejtag_dma_dstrt_poll(struct mips_ejtag *ejtag_info)
58 {
59 uint32_t ejtag_ctrl;
60 int64_t start = timeval_ms();
61
62 do {
63 if (timeval_ms() - start > 1000) {
64 LOG_ERROR("DMA time out");
65 return -ETIMEDOUT;
66 }
67 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
68 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
69 } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
70 return 0;
71 }
72
73 static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data)
74 {
75 uint32_t v;
76 uint32_t ejtag_ctrl;
77 int retries = RETRY_ATTEMPTS;
78
79 begin_ejtag_dma_read:
80
81 /* Setup Address */
82 v = addr;
83 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
84 mips_ejtag_drscan_32(ejtag_info, &v);
85
86 /* Initiate DMA Read & set DSTRT */
87 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
88 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
89 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
90
91 /* Wait for DSTRT to Clear */
92 ejtag_dma_dstrt_poll(ejtag_info);
93
94 /* Read Data */
95 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
96 mips_ejtag_drscan_32(ejtag_info, data);
97
98 /* Clear DMA & Check DERR */
99 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
100 ejtag_ctrl = ejtag_info->ejtag_ctrl;
101 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
102 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
103 if (retries--) {
104 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
105 goto begin_ejtag_dma_read;
106 } else
107 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
108 return ERROR_JTAG_DEVICE_ERROR;
109 }
110
111 return ERROR_OK;
112 }
113
114 static int ejtag_dma_read_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint16_t *data)
115 {
116 uint32_t v;
117 uint32_t ejtag_ctrl;
118 int retries = RETRY_ATTEMPTS;
119
120 begin_ejtag_dma_read_h:
121
122 /* Setup Address */
123 v = addr;
124 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
125 mips_ejtag_drscan_32(ejtag_info, &v);
126
127 /* Initiate DMA Read & set DSTRT */
128 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
129 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD |
130 EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
131 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
132
133 /* Wait for DSTRT to Clear */
134 ejtag_dma_dstrt_poll(ejtag_info);
135
136 /* Read Data */
137 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
138 mips_ejtag_drscan_32(ejtag_info, &v);
139
140 /* Clear DMA & Check DERR */
141 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
142 ejtag_ctrl = ejtag_info->ejtag_ctrl;
143 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
144 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
145 if (retries--) {
146 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
147 goto begin_ejtag_dma_read_h;
148 } else
149 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
150 return ERROR_JTAG_DEVICE_ERROR;
151 }
152
153 /* Handle the bigendian/littleendian */
154 if (addr & 0x2)
155 *data = (v >> 16) & 0xffff;
156 else
157 *data = (v & 0x0000ffff);
158
159 return ERROR_OK;
160 }
161
162 static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data)
163 {
164 uint32_t v;
165 uint32_t ejtag_ctrl;
166 int retries = RETRY_ATTEMPTS;
167
168 begin_ejtag_dma_read_b:
169
170 /* Setup Address */
171 v = addr;
172 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
173 mips_ejtag_drscan_32(ejtag_info, &v);
174
175 /* Initiate DMA Read & set DSTRT */
176 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
177 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
178 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
179
180 /* Wait for DSTRT to Clear */
181 ejtag_dma_dstrt_poll(ejtag_info);
182
183 /* Read Data */
184 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
185 mips_ejtag_drscan_32(ejtag_info, &v);
186
187 /* Clear DMA & Check DERR */
188 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
189 ejtag_ctrl = ejtag_info->ejtag_ctrl;
190 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
191 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
192 if (retries--) {
193 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
194 goto begin_ejtag_dma_read_b;
195 } else
196 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
197 return ERROR_JTAG_DEVICE_ERROR;
198 }
199
200 /* Handle the bigendian/littleendian */
201 switch (addr & 0x3) {
202 case 0:
203 *data = v & 0xff;
204 break;
205 case 1:
206 *data = (v >> 8) & 0xff;
207 break;
208 case 2:
209 *data = (v >> 16) & 0xff;
210 break;
211 case 3:
212 *data = (v >> 24) & 0xff;
213 break;
214 }
215
216 return ERROR_OK;
217 }
218
219 static int ejtag_dma_write(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
220 {
221 uint32_t v;
222 uint32_t ejtag_ctrl;
223 int retries = RETRY_ATTEMPTS;
224
225 begin_ejtag_dma_write:
226
227 /* Setup Address */
228 v = addr;
229 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
230 mips_ejtag_drscan_32(ejtag_info, &v);
231
232 /* Setup Data */
233 v = data;
234 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
235 mips_ejtag_drscan_32(ejtag_info, &v);
236
237 /* Initiate DMA Write & set DSTRT */
238 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
239 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
240 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
241
242 /* Wait for DSTRT to Clear */
243 ejtag_dma_dstrt_poll(ejtag_info);
244
245 /* Clear DMA & Check DERR */
246 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
247 ejtag_ctrl = ejtag_info->ejtag_ctrl;
248 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
249 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
250 if (retries--) {
251 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
252 goto begin_ejtag_dma_write;
253 } else
254 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
255 return ERROR_JTAG_DEVICE_ERROR;
256 }
257
258 return ERROR_OK;
259 }
260
261 static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
262 {
263 uint32_t v;
264 uint32_t ejtag_ctrl;
265 int retries = RETRY_ATTEMPTS;
266
267 /* Handle the bigendian/littleendian */
268 data &= 0xffff;
269 data |= data << 16;
270
271 begin_ejtag_dma_write_h:
272
273 /* Setup Address */
274 v = addr;
275 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
276 mips_ejtag_drscan_32(ejtag_info, &v);
277
278 /* Setup Data */
279 v = data;
280 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
281 mips_ejtag_drscan_32(ejtag_info, &v);
282
283 /* Initiate DMA Write & set DSTRT */
284 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
285 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
286 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
287
288 /* Wait for DSTRT to Clear */
289 ejtag_dma_dstrt_poll(ejtag_info);
290
291 /* Clear DMA & Check DERR */
292 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
293 ejtag_ctrl = ejtag_info->ejtag_ctrl;
294 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
295 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
296 if (retries--) {
297 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
298 goto begin_ejtag_dma_write_h;
299 } else
300 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
301 return ERROR_JTAG_DEVICE_ERROR;
302 }
303
304 return ERROR_OK;
305 }
306
307 static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
308 {
309 uint32_t v;
310 uint32_t ejtag_ctrl;
311 int retries = RETRY_ATTEMPTS;
312
313 /* Handle the bigendian/littleendian */
314 data &= 0xff;
315 data |= data << 8;
316 data |= data << 16;
317
318 begin_ejtag_dma_write_b:
319
320 /* Setup Address*/
321 v = addr;
322 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
323 mips_ejtag_drscan_32(ejtag_info, &v);
324
325 /* Setup Data */
326 v = data;
327 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
328 mips_ejtag_drscan_32(ejtag_info, &v);
329
330 /* Initiate DMA Write & set DSTRT */
331 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
332 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
333 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
334
335 /* Wait for DSTRT to Clear */
336 ejtag_dma_dstrt_poll(ejtag_info);
337
338 /* Clear DMA & Check DERR */
339 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
340 ejtag_ctrl = ejtag_info->ejtag_ctrl;
341 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
342 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
343 if (retries--) {
344 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
345 goto begin_ejtag_dma_write_b;
346 } else
347 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
348 return ERROR_JTAG_DEVICE_ERROR;
349 }
350
351 return ERROR_OK;
352 }
353
354 int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
355 {
356 switch (size) {
357 case 1:
358 return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
359 case 2:
360 return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
361 case 4:
362 return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
363 }
364
365 return ERROR_OK;
366 }
367
368 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
369 {
370 int i;
371 int retval;
372
373 for (i = 0; i < count; i++) {
374 retval = ejtag_dma_read(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
375 if (retval != ERROR_OK)
376 return retval;
377 }
378
379 return ERROR_OK;
380 }
381
382 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
383 {
384 int i;
385 int retval;
386
387 for (i = 0; i < count; i++) {
388 retval = ejtag_dma_read_h(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
389 if (retval != ERROR_OK)
390 return retval;
391 }
392
393 return ERROR_OK;
394 }
395
396 static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
397 {
398 int i;
399 int retval;
400
401 for (i = 0; i < count; i++) {
402 retval = ejtag_dma_read_b(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
403 if (retval != ERROR_OK)
404 return retval;
405 }
406
407 return ERROR_OK;
408 }
409
410 int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
411 {
412 switch (size) {
413 case 1:
414 return mips32_dmaacc_write_mem8(ejtag_info, addr, count, (uint8_t *)buf);
415 case 2:
416 return mips32_dmaacc_write_mem16(ejtag_info, addr, count, (uint16_t *)buf);
417 case 4:
418 return mips32_dmaacc_write_mem32(ejtag_info, addr, count, (uint32_t *)buf);
419 }
420
421 return ERROR_OK;
422 }
423
424 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
425 {
426 int i;
427 int retval;
428
429 for (i = 0; i < count; i++) {
430 retval = ejtag_dma_write(ejtag_info, addr + i * sizeof(*buf), buf[i]);
431 if (retval != ERROR_OK)
432 return retval;
433 }
434
435 return ERROR_OK;
436 }
437
438 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
439 {
440 int i;
441 int retval;
442
443 for (i = 0; i < count; i++) {
444 retval = ejtag_dma_write_h(ejtag_info, addr + i * sizeof(*buf), buf[i]);
445 if (retval != ERROR_OK)
446 return retval;
447 }
448
449 return ERROR_OK;
450 }
451
452 static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
453 {
454 int i;
455 int retval;
456
457 for (i = 0; i < count; i++) {
458 retval = ejtag_dma_write_b(ejtag_info, addr + i * sizeof(*buf), buf[i]);
459 if (retval != ERROR_OK)
460 return retval;
461 }
462
463 return ERROR_OK;
464 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)