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

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)