OpenOCD
mips32_dmaacc.c
Go to the documentation of this file.
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;
71  mips_ejtag_drscan_32(ejtag_info, &v);
72 
73  /* Initiate DMA Read & set DSTRT */
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 */
83  mips_ejtag_drscan_32(ejtag_info, data);
84 
85  /* Clear DMA & Check DERR */
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);
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;
112  mips_ejtag_drscan_32(ejtag_info, &v);
113 
114  /* Initiate DMA Read & set DSTRT */
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 */
125  mips_ejtag_drscan_32(ejtag_info, &v);
126 
127  /* Clear DMA & Check DERR */
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);
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;
160  mips_ejtag_drscan_32(ejtag_info, &v);
161 
162  /* Initiate DMA Read & set DSTRT */
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 */
172  mips_ejtag_drscan_32(ejtag_info, &v);
173 
174  /* Clear DMA & Check DERR */
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);
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;
217  mips_ejtag_drscan_32(ejtag_info, &v);
218 
219  /* Setup Data */
220  v = data;
222  mips_ejtag_drscan_32(ejtag_info, &v);
223 
224  /* Initiate DMA Write & set DSTRT */
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 */
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);
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;
263  mips_ejtag_drscan_32(ejtag_info, &v);
264 
265  /* Setup Data */
266  v = data;
268  mips_ejtag_drscan_32(ejtag_info, &v);
269 
270  /* Initiate DMA Write & set DSTRT */
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 */
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);
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;
310  mips_ejtag_drscan_32(ejtag_info, &v);
311 
312  /* Setup Data */
313  v = data;
315  mips_ejtag_drscan_32(ejtag_info, &v);
316 
317  /* Initiate DMA Write & set DSTRT */
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 */
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);
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 }
#define ERROR_JTAG_DEVICE_ERROR
Definition: jtag.h:555
static int64_t start
Definition: log.c:41
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define ERROR_OK
Definition: log.h:155
int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint8_t *buf)
static int ejtag_dma_dstrt_poll(struct mips_ejtag *ejtag_info)
Definition: mips32_dmaacc.c:44
static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint16_t *buf)
static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data)
static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
static int ejtag_dma_write(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf)
static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data)
Definition: mips32_dmaacc.c:60
static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
static int ejtag_dma_read_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint16_t *data)
static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint32_t *buf)
static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
#define EJTAG_CTRL_DMA_WORD
Definition: mips32_dmaacc.h:20
#define EJTAG_CTRL_DMA_HALFWORD
Definition: mips32_dmaacc.h:19
#define EJTAG_CTRL_DMA_BYTE
Definition: mips32_dmaacc.h:18
#define RETRY_ATTEMPTS
Definition: mips32_dmaacc.h:23
void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr)
Definition: mips_ejtag.c:22
int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
Definition: mips_ejtag.c:130
#define EJTAG_CTRL_DRWN
Definition: mips_ejtag.h:51
#define EJTAG_CTRL_DMAACC
Definition: mips_ejtag.h:59
#define EJTAG_INST_CONTROL
Definition: mips_ejtag.h:20
#define EJTAG_INST_DATA
Definition: mips_ejtag.h:19
#define EJTAG_CTRL_DERR
Definition: mips_ejtag.h:52
#define EJTAG_CTRL_DSTRT
Definition: mips_ejtag.h:53
#define EJTAG_INST_ADDRESS
Definition: mips_ejtag.h:18
uint32_t addr
Definition: nuttx.c:65
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
uint32_t ejtag_ctrl
Definition: mips_ejtag.h:192
int64_t timeval_ms(void)
uint8_t count[4]
Definition: vdebug.c:22