jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / mips32_dmaacc.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2008 by John McCarthy *
5 * jgmcc@magma.ca *
6 * *
7 * Copyright (C) 2008 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
9 * *
10 * Copyright (C) 2008 by David T.L. Wong *
11 ***************************************************************************/
12
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
17 #include "mips32_dmaacc.h"
18 #include <helper/time_support.h>
19
20 static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info,
21 uint32_t addr, int count, uint8_t *buf);
22 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info,
23 uint32_t addr, int count, uint16_t *buf);
24 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info,
25 uint32_t addr, int count, uint32_t *buf);
26
27 static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info,
28 uint32_t addr, int count, const uint8_t *buf);
29 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info,
30 uint32_t addr, int count, const uint16_t *buf);
31 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info,
32 uint32_t addr, int count, const uint32_t *buf);
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_dstrt_poll(struct mips_ejtag *ejtag_info)
45 {
46 uint32_t ejtag_ctrl;
47 int64_t start = timeval_ms();
48
49 do {
50 if (timeval_ms() - start > 1000) {
51 LOG_ERROR("DMA time out");
52 return -ETIMEDOUT;
53 }
54 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
55 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
56 } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
57 return 0;
58 }
59
60 static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data)
61 {
62 uint32_t v;
63 uint32_t ejtag_ctrl;
64 int retries = RETRY_ATTEMPTS;
65
66 begin_ejtag_dma_read:
67
68 /* Setup Address */
69 v = addr;
70 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
71 mips_ejtag_drscan_32(ejtag_info, &v);
72
73 /* Initiate DMA Read & set DSTRT */
74 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
75 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
76 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
77
78 /* Wait for DSTRT to Clear */
79 ejtag_dma_dstrt_poll(ejtag_info);
80
81 /* Read Data */
82 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
83 mips_ejtag_drscan_32(ejtag_info, data);
84
85 /* Clear DMA & Check DERR */
86 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
87 ejtag_ctrl = ejtag_info->ejtag_ctrl;
88 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
89 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
90 if (retries--) {
91 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
92 goto begin_ejtag_dma_read;
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 |
117 EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
118 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
119
120 /* Wait for DSTRT to Clear */
121 ejtag_dma_dstrt_poll(ejtag_info);
122
123 /* Read Data */
124 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
125 mips_ejtag_drscan_32(ejtag_info, &v);
126
127 /* Clear DMA & Check DERR */
128 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
129 ejtag_ctrl = ejtag_info->ejtag_ctrl;
130 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
131 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
132 if (retries--) {
133 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
134 goto begin_ejtag_dma_read_h;
135 } else
136 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
137 return ERROR_JTAG_DEVICE_ERROR;
138 }
139
140 /* Handle the bigendian/littleendian */
141 if (addr & 0x2)
142 *data = (v >> 16) & 0xffff;
143 else
144 *data = (v & 0x0000ffff);
145
146 return ERROR_OK;
147 }
148
149 static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data)
150 {
151 uint32_t v;
152 uint32_t ejtag_ctrl;
153 int retries = RETRY_ATTEMPTS;
154
155 begin_ejtag_dma_read_b:
156
157 /* Setup Address */
158 v = addr;
159 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
160 mips_ejtag_drscan_32(ejtag_info, &v);
161
162 /* Initiate DMA Read & set DSTRT */
163 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
164 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
165 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
166
167 /* Wait for DSTRT to Clear */
168 ejtag_dma_dstrt_poll(ejtag_info);
169
170 /* Read Data */
171 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
172 mips_ejtag_drscan_32(ejtag_info, &v);
173
174 /* Clear DMA & Check DERR */
175 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
176 ejtag_ctrl = ejtag_info->ejtag_ctrl;
177 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
178 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
179 if (retries--) {
180 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
181 goto begin_ejtag_dma_read_b;
182 } else
183 LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
184 return ERROR_JTAG_DEVICE_ERROR;
185 }
186
187 /* Handle the bigendian/littleendian */
188 switch (addr & 0x3) {
189 case 0:
190 *data = v & 0xff;
191 break;
192 case 1:
193 *data = (v >> 8) & 0xff;
194 break;
195 case 2:
196 *data = (v >> 16) & 0xff;
197 break;
198 case 3:
199 *data = (v >> 24) & 0xff;
200 break;
201 }
202
203 return ERROR_OK;
204 }
205
206 static int ejtag_dma_write(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
207 {
208 uint32_t v;
209 uint32_t ejtag_ctrl;
210 int retries = RETRY_ATTEMPTS;
211
212 begin_ejtag_dma_write:
213
214 /* Setup Address */
215 v = addr;
216 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
217 mips_ejtag_drscan_32(ejtag_info, &v);
218
219 /* Setup Data */
220 v = data;
221 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
222 mips_ejtag_drscan_32(ejtag_info, &v);
223
224 /* Initiate DMA Write & set DSTRT */
225 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
226 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
227 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
228
229 /* Wait for DSTRT to Clear */
230 ejtag_dma_dstrt_poll(ejtag_info);
231
232 /* Clear DMA & Check DERR */
233 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
234 ejtag_ctrl = ejtag_info->ejtag_ctrl;
235 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
236 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
237 if (retries--) {
238 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
239 goto begin_ejtag_dma_write;
240 } else
241 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
242 return ERROR_JTAG_DEVICE_ERROR;
243 }
244
245 return ERROR_OK;
246 }
247
248 static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
249 {
250 uint32_t v;
251 uint32_t ejtag_ctrl;
252 int retries = RETRY_ATTEMPTS;
253
254 /* Handle the bigendian/littleendian */
255 data &= 0xffff;
256 data |= data << 16;
257
258 begin_ejtag_dma_write_h:
259
260 /* Setup Address */
261 v = addr;
262 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
263 mips_ejtag_drscan_32(ejtag_info, &v);
264
265 /* Setup Data */
266 v = data;
267 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
268 mips_ejtag_drscan_32(ejtag_info, &v);
269
270 /* Initiate DMA Write & set DSTRT */
271 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
272 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
273 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
274
275 /* Wait for DSTRT to Clear */
276 ejtag_dma_dstrt_poll(ejtag_info);
277
278 /* Clear DMA & Check DERR */
279 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
280 ejtag_ctrl = ejtag_info->ejtag_ctrl;
281 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
282 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
283 if (retries--) {
284 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
285 goto begin_ejtag_dma_write_h;
286 } else
287 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
288 return ERROR_JTAG_DEVICE_ERROR;
289 }
290
291 return ERROR_OK;
292 }
293
294 static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
295 {
296 uint32_t v;
297 uint32_t ejtag_ctrl;
298 int retries = RETRY_ATTEMPTS;
299
300 /* Handle the bigendian/littleendian */
301 data &= 0xff;
302 data |= data << 8;
303 data |= data << 16;
304
305 begin_ejtag_dma_write_b:
306
307 /* Setup Address*/
308 v = addr;
309 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
310 mips_ejtag_drscan_32(ejtag_info, &v);
311
312 /* Setup Data */
313 v = data;
314 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
315 mips_ejtag_drscan_32(ejtag_info, &v);
316
317 /* Initiate DMA Write & set DSTRT */
318 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
319 ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
320 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
321
322 /* Wait for DSTRT to Clear */
323 ejtag_dma_dstrt_poll(ejtag_info);
324
325 /* Clear DMA & Check DERR */
326 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
327 ejtag_ctrl = ejtag_info->ejtag_ctrl;
328 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
329 if (ejtag_ctrl & EJTAG_CTRL_DERR) {
330 if (retries--) {
331 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
332 goto begin_ejtag_dma_write_b;
333 } else
334 LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
335 return ERROR_JTAG_DEVICE_ERROR;
336 }
337
338 return ERROR_OK;
339 }
340
341 int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
342 {
343 switch (size) {
344 case 1:
345 return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
346 case 2:
347 return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
348 case 4:
349 return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
350 }
351
352 return ERROR_OK;
353 }
354
355 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
356 {
357 int i;
358 int retval;
359
360 for (i = 0; i < count; i++) {
361 retval = ejtag_dma_read(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
362 if (retval != ERROR_OK)
363 return retval;
364 }
365
366 return ERROR_OK;
367 }
368
369 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
370 {
371 int i;
372 int retval;
373
374 for (i = 0; i < count; i++) {
375 retval = ejtag_dma_read_h(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_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
384 {
385 int i;
386 int retval;
387
388 for (i = 0; i < count; i++) {
389 retval = ejtag_dma_read_b(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 int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf)
398 {
399 switch (size) {
400 case 1:
401 return mips32_dmaacc_write_mem8(ejtag_info, addr, count, buf);
402 case 2:
403 return mips32_dmaacc_write_mem16(ejtag_info, addr, count, buf);
404 case 4:
405 return mips32_dmaacc_write_mem32(ejtag_info, addr, count, buf);
406 }
407
408 return ERROR_OK;
409 }
410
411 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint32_t *buf)
412 {
413 int i;
414 int retval;
415
416 for (i = 0; i < count; i++) {
417 retval = ejtag_dma_write(ejtag_info, addr + i * sizeof(*buf), buf[i]);
418 if (retval != ERROR_OK)
419 return retval;
420 }
421
422 return ERROR_OK;
423 }
424
425 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint16_t *buf)
426 {
427 int i;
428 int retval;
429
430 for (i = 0; i < count; i++) {
431 retval = ejtag_dma_write_h(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_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint8_t *buf)
440 {
441 int i;
442 int retval;
443
444 for (i = 0; i < count; i++) {
445 retval = ejtag_dma_write_b(ejtag_info, addr + i * sizeof(*buf), buf[i]);
446 if (retval != ERROR_OK)
447 return retval;
448 }
449
450 return ERROR_OK;
451 }

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)