1 /***************************************************************************
\r
2 * Copyright (C) 2008 by John McCarthy *
\r
5 * Copyright (C) 2008 by Spencer Oliver *
\r
6 * spen@spen-soft.co.uk *
\r
8 * Copyright (C) 2008 by David T.L. Wong *
\r
10 * This program is free software; you can redistribute it and/or modify *
\r
11 * it under the terms of the GNU General Public License as published by *
\r
12 * the Free Software Foundation; either version 2 of the License, or *
\r
13 * (at your option) any later version. *
\r
15 * This program is distributed in the hope that it will be useful, *
\r
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
\r
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
\r
18 * GNU General Public License for more details. *
\r
20 * You should have received a copy of the GNU General Public License *
\r
21 * along with this program; if not, write to the *
\r
22 * Free Software Foundation, Inc., *
\r
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
\r
24 ***************************************************************************/
\r
25 #ifdef HAVE_CONFIG_H
\r
32 #include "mips32_dmaacc.h"
\r
35 * The following logic shamelessly cloned from HairyDairyMaid's wrt54g_debrick
\r
36 * to support the Broadcom BCM5352 SoC in the Linksys WRT54GL wireless router
\r
37 * (and any others that support EJTAG DMA transfers).
\r
38 * Note: This only supports memory read/write. Since the BCM5352 doesn't
\r
39 * appear to support PRACC accesses, all debug functions except halt
\r
40 * do not work. Still, this does allow erasing/writing flash as well as
\r
41 * displaying/modifying memory and memory mapped registers.
\r
44 static int ejtag_dma_read(mips_ejtag_t *ejtag_info, u32 addr, u32 *data)
\r
48 int retries = RETRY_ATTEMPTS;
\r
50 begin_ejtag_dma_read:
\r
54 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
\r
55 mips_ejtag_drscan_32(ejtag_info, &v);
\r
57 // Initiate DMA Read & set DSTRT
\r
58 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
59 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
60 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
62 // Wait for DSTRT to Clear
\r
64 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
65 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
66 } while(ctrl_reg & EJTAG_CTRL_DSTRT);
\r
69 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
\r
70 mips_ejtag_drscan_32(ejtag_info, data);
\r
72 // Clear DMA & Check DERR
\r
73 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
74 ctrl_reg = EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
75 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
76 if (ctrl_reg & EJTAG_CTRL_DERR)
\r
79 printf("DMA Read Addr = %08x Data = ERROR ON READ (retrying)\n", addr);
\r
80 goto begin_ejtag_dma_read;
\r
81 } else printf("DMA Read Addr = %08x Data = ERROR ON READ\n", addr);
\r
82 return ERROR_JTAG_DEVICE_ERROR;
\r
88 static int ejtag_dma_read_h(mips_ejtag_t *ejtag_info, u32 addr, u16 *data)
\r
92 int retries = RETRY_ATTEMPTS;
\r
94 begin_ejtag_dma_read_h:
\r
98 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
\r
99 mips_ejtag_drscan_32(ejtag_info, &v);
\r
101 // Initiate DMA Read & set DSTRT
\r
102 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
103 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
104 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
106 // Wait for DSTRT to Clear
\r
108 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
109 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
110 } while(ctrl_reg & EJTAG_CTRL_DSTRT);
\r
113 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
\r
114 mips_ejtag_drscan_32(ejtag_info, &v);
\r
116 // Clear DMA & Check DERR
\r
117 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
118 ctrl_reg = EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
119 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
120 if (ctrl_reg & EJTAG_CTRL_DERR)
\r
123 printf("DMA Read Addr = %08x Data = ERROR ON READ (retrying)\n", addr);
\r
124 goto begin_ejtag_dma_read_h;
\r
125 } else printf("DMA Read Addr = %08x Data = ERROR ON READ\n", addr);
\r
126 return ERROR_JTAG_DEVICE_ERROR;
\r
129 // Handle the bigendian/littleendian
\r
130 if ( addr & 0x2 ) *data = (v>>16)&0xffff ;
\r
131 else *data = (v&0x0000ffff) ;
\r
136 static int ejtag_dma_read_b(mips_ejtag_t *ejtag_info, u32 addr, u8 *data)
\r
140 int retries = RETRY_ATTEMPTS;
\r
142 begin_ejtag_dma_read_b:
\r
146 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
\r
147 mips_ejtag_drscan_32(ejtag_info, &v);
\r
149 // Initiate DMA Read & set DSTRT
\r
150 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
151 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
152 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
154 // Wait for DSTRT to Clear
\r
156 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
157 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
158 } while(ctrl_reg & EJTAG_CTRL_DSTRT);
\r
161 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
\r
162 mips_ejtag_drscan_32(ejtag_info, &v);
\r
164 // Clear DMA & Check DERR
\r
165 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
166 ctrl_reg = EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
167 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
168 if (ctrl_reg & EJTAG_CTRL_DERR)
\r
171 printf("DMA Read Addr = %08x Data = ERROR ON READ (retrying)\n", addr);
\r
172 goto begin_ejtag_dma_read_b;
\r
173 } else printf("DMA Read Addr = %08x Data = ERROR ON READ\n", addr);
\r
174 return ERROR_JTAG_DEVICE_ERROR;
\r
177 // Handle the bigendian/littleendian
\r
178 switch(addr & 0x3) {
\r
179 case 0: *data = v & 0xff; break;
\r
180 case 1: *data = (v>>8) & 0xff; break;
\r
181 case 2: *data = (v>>16) & 0xff; break;
\r
182 case 3: *data = (v>>24) & 0xff; break;
\r
188 static int ejtag_dma_write(mips_ejtag_t *ejtag_info, u32 addr, u32 data)
\r
192 int retries = RETRY_ATTEMPTS;
\r
194 begin_ejtag_dma_write:
\r
198 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
\r
199 mips_ejtag_drscan_32(ejtag_info, &v);
\r
203 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
\r
204 mips_ejtag_drscan_32(ejtag_info, &v);
\r
206 // Initiate DMA Write & set DSTRT
\r
207 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
208 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
209 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
211 // Wait for DSTRT to Clear
\r
213 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
214 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
215 } while(ctrl_reg & EJTAG_CTRL_DSTRT);
\r
217 // Clear DMA & Check DERR
\r
218 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
219 ctrl_reg = EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
220 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
221 if (ctrl_reg & EJTAG_CTRL_DERR)
\r
224 printf("DMA Write Addr = %08x Data = ERROR ON WRITE (retrying)\n", addr);
\r
225 goto begin_ejtag_dma_write;
\r
226 } else printf("DMA Write Addr = %08x Data = ERROR ON WRITE\n", addr);
\r
227 return ERROR_JTAG_DEVICE_ERROR;
\r
233 static int ejtag_dma_write_h(mips_ejtag_t *ejtag_info, u32 addr, u32 data)
\r
237 int retries = RETRY_ATTEMPTS;
\r
240 // Handle the bigendian/littleendian
\r
244 begin_ejtag_dma_write_h:
\r
248 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
\r
249 mips_ejtag_drscan_32(ejtag_info, &v);
\r
253 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
\r
254 mips_ejtag_drscan_32(ejtag_info, &v);
\r
256 // Initiate DMA Write & set DSTRT
\r
257 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
258 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
259 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
261 // Wait for DSTRT to Clear
\r
263 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
264 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
265 } while(ctrl_reg & EJTAG_CTRL_DSTRT);
\r
267 // Clear DMA & Check DERR
\r
268 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
269 ctrl_reg = EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
270 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
271 if (ctrl_reg & EJTAG_CTRL_DERR)
\r
274 printf("DMA Write Addr = %08x Data = ERROR ON WRITE (retrying)\n", addr);
\r
275 goto begin_ejtag_dma_write_h;
\r
276 } else printf("DMA Write Addr = %08x Data = ERROR ON WRITE\n", addr);
\r
277 return ERROR_JTAG_DEVICE_ERROR;
\r
283 static int ejtag_dma_write_b(mips_ejtag_t *ejtag_info, u32 addr, u32 data)
\r
287 int retries = RETRY_ATTEMPTS;
\r
290 // Handle the bigendian/littleendian
\r
295 begin_ejtag_dma_write_b:
\r
299 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
\r
300 mips_ejtag_drscan_32(ejtag_info, &v);
\r
304 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
\r
305 mips_ejtag_drscan_32(ejtag_info, &v);
\r
307 // Initiate DMA Write & set DSTRT
\r
308 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
309 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
310 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
312 // Wait for DSTRT to Clear
\r
314 ctrl_reg = EJTAG_CTRL_DMAACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
315 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
316 } while(ctrl_reg & EJTAG_CTRL_DSTRT);
\r
318 // Clear DMA & Check DERR
\r
319 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
\r
320 ctrl_reg = EJTAG_CTRL_PROBEN | EJTAG_CTRL_PRACC;
\r
321 mips_ejtag_drscan_32(ejtag_info, &ctrl_reg);
\r
322 if (ctrl_reg & EJTAG_CTRL_DERR)
\r
325 printf("DMA Write Addr = %08x Data = ERROR ON WRITE (retrying)\n", addr);
\r
326 goto begin_ejtag_dma_write_b;
\r
327 } else printf("DMA Write Addr = %08x Data = ERROR ON WRITE\n", addr);
\r
328 return ERROR_JTAG_DEVICE_ERROR;
\r
335 int mips32_dmaacc_read_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
\r
340 return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (u8*)buf);
\r
342 return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (u16*)buf);
\r
344 return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (u32*)buf);
\r
350 int mips32_dmaacc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
\r
355 for(i=0; i<count; i++) {
\r
356 if((retval=ejtag_dma_read(ejtag_info, addr+i*sizeof(*buf), &buf[i])) != ERROR_OK)
\r
363 int mips32_dmaacc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
\r
368 for(i=0; i<count; i++) {
\r
369 if((retval=ejtag_dma_read_h(ejtag_info, addr+i*sizeof(*buf), &buf[i])) != ERROR_OK)
\r
376 int mips32_dmaacc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
\r
381 for(i=0; i<count; i++) {
\r
382 if((retval=ejtag_dma_read_b(ejtag_info, addr+i*sizeof(*buf), &buf[i])) != ERROR_OK)
\r
389 int mips32_dmaacc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
\r
394 return mips32_dmaacc_write_mem8(ejtag_info, addr, count, (u8*)buf);
\r
396 return mips32_dmaacc_write_mem16(ejtag_info, addr, count,(u16*)buf);
\r
398 return mips32_dmaacc_write_mem32(ejtag_info, addr, count, (u32*)buf);
\r
404 int mips32_dmaacc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
\r
409 for(i=0; i<count; i++) {
\r
410 if((retval=ejtag_dma_write(ejtag_info, addr+i*sizeof(*buf), buf[i])) != ERROR_OK)
\r
417 int mips32_dmaacc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
\r
422 for(i=0; i<count; i++) {
\r
423 if((retval=ejtag_dma_write_h(ejtag_info, addr+i*sizeof(*buf), buf[i])) != ERROR_OK)
\r
430 int mips32_dmaacc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
\r
435 for(i=0; i<count; i++) {
\r
436 if((retval=ejtag_dma_write_b(ejtag_info, addr+i*sizeof(*buf), buf[i])) != ERROR_OK)
\r