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

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)