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