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

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)