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

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)