mips32_dmaacc: add new funct ejtag_dma_dstrt_poll
[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
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 void ejtag_dma_dstrt_poll(struct mips_ejtag *ejtag_info)
57 {
58 uint32_t ejtag_ctrl;
59 do {
60 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
61 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
62 } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
63 }
64
65 static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data)
66 {
67 uint32_t v;
68 uint32_t ejtag_ctrl;
69 int retries = RETRY_ATTEMPTS;
70
71 begin_ejtag_dma_read:
72
73 /* Setup Address */
74 v = addr;
75 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
76 mips_ejtag_drscan_32(ejtag_info, &v);
77
78 /* Initiate DMA Read & set DSTRT */
79 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
80 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
81 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
82
83 /* Wait for DSTRT to Clear */
84 ejtag_dma_dstrt_poll(ejtag_info);
85
86 /* Read Data */
87 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
88 mips_ejtag_drscan_32(ejtag_info, data);
89
90 /* Clear DMA & Check DERR */
91 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
92 ejtag_ctrl = ejtag_info->ejtag_ctrl;
93 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
94 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
95 if (retries--) {
96 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
97 goto begin_ejtag_dma_read;
98 } else
99 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
100 return ERROR_JTAG_DEVICE_ERROR;
101 }
102
103 return ERROR_OK;
104 }
105
106 static int ejtag_dma_read_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint16_t *data)
107 {
108 uint32_t v;
109 uint32_t ejtag_ctrl;
110 int retries = RETRY_ATTEMPTS;
111
112 begin_ejtag_dma_read_h:
113
114 /* Setup Address */
115 v = addr;
116 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
117 mips_ejtag_drscan_32(ejtag_info, &v);
118
119 /* Initiate DMA Read & set DSTRT */
120 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
121 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD |
122 EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
123 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
124
125 /* Wait for DSTRT to Clear */
126 ejtag_dma_dstrt_poll(ejtag_info);
127
128 /* Read Data */
129 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
130 mips_ejtag_drscan_32(ejtag_info, &v);
131
132 /* Clear DMA & Check DERR */
133 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
134 ejtag_ctrl = ejtag_info->ejtag_ctrl;
135 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
136 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
137 if (retries--) {
138 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
139 goto begin_ejtag_dma_read_h;
140 } else
141 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
142 return ERROR_JTAG_DEVICE_ERROR;
143 }
144
145 /* Handle the bigendian/littleendian */
146 if (addr & 0x2)
147 *data = (v >> 16) & 0xffff;
148 else
149 *data = (v & 0x0000ffff);
150
151 return ERROR_OK;
152 }
153
154 static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data)
155 {
156 uint32_t v;
157 uint32_t ejtag_ctrl;
158 int retries = RETRY_ATTEMPTS;
159
160 begin_ejtag_dma_read_b:
161
162 /* Setup Address */
163 v = addr;
164 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
165 mips_ejtag_drscan_32(ejtag_info, &v);
166
167 /* Initiate DMA Read & set DSTRT */
168 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
169 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
170 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
171
172 /* Wait for DSTRT to Clear */
173 ejtag_dma_dstrt_poll(ejtag_info);
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 ejtag_dma_dstrt_poll(ejtag_info);
236
237 /* Clear DMA & Check DERR */
238 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
239 ejtag_ctrl = ejtag_info->ejtag_ctrl;
240 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
241 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
242 if (retries--) {
243 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
244 goto begin_ejtag_dma_write;
245 } else
246 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
247 return ERROR_JTAG_DEVICE_ERROR;
248 }
249
250 return ERROR_OK;
251 }
252
253 static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
254 {
255 uint32_t v;
256 uint32_t ejtag_ctrl;
257 int retries = RETRY_ATTEMPTS;
258
259 /* Handle the bigendian/littleendian */
260 data &= 0xffff;
261 data |= data << 16;
262
263 begin_ejtag_dma_write_h:
264
265 /* Setup Address */
266 v = addr;
267 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
268 mips_ejtag_drscan_32(ejtag_info, &v);
269
270 /* Setup Data */
271 v = data;
272 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
273 mips_ejtag_drscan_32(ejtag_info, &v);
274
275 /* Initiate DMA Write & set DSTRT */
276 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
277 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
278 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
279
280 /* Wait for DSTRT to Clear */
281 ejtag_dma_dstrt_poll(ejtag_info);
282
283 /* Clear DMA & Check DERR */
284 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
285 ejtag_ctrl = ejtag_info->ejtag_ctrl;
286 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
287 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
288 if (retries--) {
289 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
290 goto begin_ejtag_dma_write_h;
291 } else
292 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
293 return ERROR_JTAG_DEVICE_ERROR;
294 }
295
296 return ERROR_OK;
297 }
298
299 static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
300 {
301 uint32_t v;
302 uint32_t ejtag_ctrl;
303 int retries = RETRY_ATTEMPTS;
304
305 /* Handle the bigendian/littleendian */
306 data &= 0xff;
307 data |= data << 8;
308 data |= data << 16;
309
310 begin_ejtag_dma_write_b:
311
312 /* Setup Address*/
313 v = addr;
314 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
315 mips_ejtag_drscan_32(ejtag_info, &v);
316
317 /* Setup Data */
318 v = data;
319 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
320 mips_ejtag_drscan_32(ejtag_info, &v);
321
322 /* Initiate DMA Write & set DSTRT */
323 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
324 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
325 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
326
327 /* Wait for DSTRT to Clear */
328 ejtag_dma_dstrt_poll(ejtag_info);
329
330 /* Clear DMA & Check DERR */
331 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
332 ejtag_ctrl = ejtag_info->ejtag_ctrl;
333 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
334 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
335 if (retries--) {
336 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
337 goto begin_ejtag_dma_write_b;
338 } else
339 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
340 return ERROR_JTAG_DEVICE_ERROR;
341 }
342
343 return ERROR_OK;
344 }
345
346 int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
347 {
348 switch (size) {
349 case 1:
350 return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
351 case 2:
352 return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
353 case 4:
354 return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
355 }
356
357 return ERROR_OK;
358 }
359
360 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
361 {
362 int i;
363 int retval;
364
365 for (i = 0; i < count; i++) {
366 retval = ejtag_dma_read(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
367 if (retval != ERROR_OK)
368 return retval;
369 }
370
371 return ERROR_OK;
372 }
373
374 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
375 {
376 int i;
377 int retval;
378
379 for (i = 0; i < count; i++) {
380 retval = ejtag_dma_read_h(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
381 if (retval != ERROR_OK)
382 return retval;
383 }
384
385 return ERROR_OK;
386 }
387
388 static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
389 {
390 int i;
391 int retval;
392
393 for (i = 0; i < count; i++) {
394 retval = ejtag_dma_read_b(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
395 if (retval != ERROR_OK)
396 return retval;
397 }
398
399 return ERROR_OK;
400 }
401
402 int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
403 {
404 switch (size) {
405 case 1:
406 return mips32_dmaacc_write_mem8(ejtag_info, addr, count, (uint8_t *)buf);
407 case 2:
408 return mips32_dmaacc_write_mem16(ejtag_info, addr, count, (uint16_t *)buf);
409 case 4:
410 return mips32_dmaacc_write_mem32(ejtag_info, addr, count, (uint32_t *)buf);
411 }
412
413 return ERROR_OK;
414 }
415
416 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
417 {
418 int i;
419 int retval;
420
421 for (i = 0; i < count; i++) {
422 retval = ejtag_dma_write(ejtag_info, addr + i * sizeof(*buf), buf[i]);
423 if (retval != ERROR_OK)
424 return retval;
425 }
426
427 return ERROR_OK;
428 }
429
430 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
431 {
432 int i;
433 int retval;
434
435 for (i = 0; i < count; i++) {
436 retval = ejtag_dma_write_h(ejtag_info, addr + i * sizeof(*buf), buf[i]);
437 if (retval != ERROR_OK)
438 return retval;
439 }
440
441 return ERROR_OK;
442 }
443
444 static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
445 {
446 int i;
447 int retval;
448
449 for (i = 0; i < count; i++) {
450 retval = ejtag_dma_write_b(ejtag_info, addr + i * sizeof(*buf), buf[i]);
451 if (retval != ERROR_OK)
452 return retval;
453 }
454
455 return ERROR_OK;
456 }

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)