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