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