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