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