]> git.sur5r.net Git - openocd/blob - src/target/mips32_dmaacc.c
cleanup trailing whitespaces
[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 "mips32_dmaacc.h"
30
31 static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info,
32                 uint32_t addr, int count, uint8_t *buf);
33 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info,
34                 uint32_t addr, int count, uint16_t *buf);
35 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info,
36                 uint32_t addr, int count, uint32_t *buf);
37
38 static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info,
39                 uint32_t addr, int count, uint8_t *buf);
40 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info,
41                 uint32_t addr, int count, uint16_t *buf);
42 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info,
43                 uint32_t addr, int count, uint32_t *buf);
44
45 /*
46  * The following logic shamelessly cloned from HairyDairyMaid's wrt54g_debrick
47  * to support the Broadcom BCM5352 SoC in the Linksys WRT54GL wireless router
48  * (and any others that support EJTAG DMA transfers).
49  * Note: This only supports memory read/write. Since the BCM5352 doesn't
50  * appear to support PRACC accesses, all debug functions except halt
51  * do not work.  Still, this does allow erasing/writing flash as well as
52  * displaying/modifying memory and memory mapped registers.
53  */
54
55 static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data)
56 {
57         uint32_t v;
58         uint32_t ejtag_ctrl;
59         int retries = RETRY_ATTEMPTS;
60
61 begin_ejtag_dma_read:
62
63         /* Setup Address */
64         v = addr;
65         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
66         mips_ejtag_drscan_32(ejtag_info, &v);
67
68         /* Initiate DMA Read & set DSTRT */
69         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
70         ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
71         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
72
73         /* Wait for DSTRT to Clear */
74         do {
75                 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
76                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
77         } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
78
79         /* Read Data */
80         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
81         mips_ejtag_drscan_32(ejtag_info, data);
82
83         /* Clear DMA & Check DERR */
84         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
85         ejtag_ctrl = ejtag_info->ejtag_ctrl;
86         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
87         if (ejtag_ctrl  & EJTAG_CTRL_DERR)
88         {
89                 if (retries--) {
90                         LOG_ERROR("DMA Read Addr = %08" PRIx32 "  Data = ERROR ON READ (retrying)", addr);
91                         goto begin_ejtag_dma_read;
92                 }
93                 else
94                         LOG_ERROR("DMA Read Addr = %08" PRIx32 "  Data = ERROR ON READ", addr);
95                 return ERROR_JTAG_DEVICE_ERROR;
96         }
97
98         return ERROR_OK;
99 }
100
101 static int ejtag_dma_read_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint16_t *data)
102 {
103         uint32_t v;
104         uint32_t ejtag_ctrl;
105         int retries = RETRY_ATTEMPTS;
106
107 begin_ejtag_dma_read_h:
108
109         /* Setup Address */
110         v = addr;
111         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
112         mips_ejtag_drscan_32(ejtag_info, &v);
113
114         /* Initiate DMA Read & set DSTRT */
115         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
116         ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD | 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         {
135                 if (retries--) {
136                         LOG_ERROR("DMA Read Addr = %08" PRIx32 "  Data = ERROR ON READ (retrying)", addr);
137                         goto begin_ejtag_dma_read_h;
138                 }
139                 else
140                         LOG_ERROR("DMA Read Addr = %08" PRIx32 "  Data = ERROR ON READ", addr);
141                 return ERROR_JTAG_DEVICE_ERROR;
142         }
143
144         /* Handle the bigendian/littleendian */
145         if (addr & 0x2)
146                 *data = (v >> 16) & 0xffff;
147         else
148                 *data = (v & 0x0000ffff);
149
150         return ERROR_OK;
151 }
152
153 static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data)
154 {
155         uint32_t v;
156         uint32_t ejtag_ctrl;
157         int retries = RETRY_ATTEMPTS;
158
159 begin_ejtag_dma_read_b:
160
161         /* Setup Address */
162         v = addr;
163         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
164         mips_ejtag_drscan_32(ejtag_info, &v);
165
166         /* Initiate DMA Read & set DSTRT */
167         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
168         ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
169         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
170
171         /* Wait for DSTRT to Clear */
172         do {
173                 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
174                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
175         } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
176
177         /* Read Data */
178         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
179         mips_ejtag_drscan_32(ejtag_info, &v);
180
181         /* Clear DMA & Check DERR */
182         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
183         ejtag_ctrl = ejtag_info->ejtag_ctrl;
184         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
185         if (ejtag_ctrl  & EJTAG_CTRL_DERR)
186         {
187                 if (retries--) {
188                         LOG_ERROR("DMA Read Addr = %08" PRIx32 "  Data = ERROR ON READ (retrying)", addr);
189                         goto begin_ejtag_dma_read_b;
190                 }
191                 else
192                         LOG_ERROR("DMA Read Addr = %08" PRIx32 "  Data = ERROR ON READ", addr);
193                 return ERROR_JTAG_DEVICE_ERROR;
194         }
195
196         /* Handle the bigendian/littleendian */
197         switch (addr & 0x3) {
198                 case 0:
199                         *data = v & 0xff;
200                         break;
201                 case 1:
202                         *data = (v >> 8) & 0xff;
203                         break;
204                 case 2:
205                         *data = (v >> 16) & 0xff;
206                         break;
207                 case 3:
208                         *data = (v >> 24) & 0xff;
209                         break;
210         }
211
212         return ERROR_OK;
213 }
214
215 static int ejtag_dma_write(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
216 {
217         uint32_t v;
218         uint32_t ejtag_ctrl;
219         int retries = RETRY_ATTEMPTS;
220
221 begin_ejtag_dma_write:
222
223         /* Setup Address */
224         v = addr;
225         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
226         mips_ejtag_drscan_32(ejtag_info, &v);
227
228         /* Setup Data */
229         v = data;
230         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
231         mips_ejtag_drscan_32(ejtag_info, &v);
232
233         /* Initiate DMA Write & set DSTRT */
234         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
235         ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
236         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
237
238         /* Wait for DSTRT to Clear */
239         do {
240                 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
241                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
242         } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
243
244         /* Clear DMA & Check DERR */
245         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
246         ejtag_ctrl = ejtag_info->ejtag_ctrl;
247         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
248         if (ejtag_ctrl  & EJTAG_CTRL_DERR)
249         {
250                 if (retries--) {
251                         LOG_ERROR("DMA Write Addr = %08" PRIx32 "  Data = ERROR ON WRITE (retrying)", addr);
252                         goto begin_ejtag_dma_write;
253                 }
254                 else
255                         LOG_ERROR("DMA Write Addr = %08" PRIx32 "  Data = ERROR ON WRITE", addr);
256                 return ERROR_JTAG_DEVICE_ERROR;
257         }
258
259         return ERROR_OK;
260 }
261
262 static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
263 {
264         uint32_t v;
265         uint32_t ejtag_ctrl;
266         int retries = RETRY_ATTEMPTS;
267
268         /* Handle the bigendian/littleendian */
269         data &= 0xffff;
270         data |= data << 16;
271
272 begin_ejtag_dma_write_h:
273
274         /* Setup Address */
275         v = addr;
276         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
277         mips_ejtag_drscan_32(ejtag_info, &v);
278
279         /* Setup Data */
280         v = data;
281         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
282         mips_ejtag_drscan_32(ejtag_info, &v);
283
284         /* Initiate DMA Write & set DSTRT */
285         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
286         ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
287         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
288
289         /* Wait for DSTRT to Clear */
290         do {
291                 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
292                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
293         } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
294
295         /* Clear DMA & Check DERR */
296         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
297         ejtag_ctrl = ejtag_info->ejtag_ctrl;
298         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
299         if (ejtag_ctrl  & EJTAG_CTRL_DERR)
300         {
301                 if (retries--) {
302                         LOG_ERROR("DMA Write Addr = %08" PRIx32 "  Data = ERROR ON WRITE (retrying)", addr);
303                         goto begin_ejtag_dma_write_h;
304                 }
305                 else
306                         LOG_ERROR("DMA Write Addr = %08" PRIx32 "  Data = ERROR ON WRITE", addr);
307                 return ERROR_JTAG_DEVICE_ERROR;
308         }
309
310         return ERROR_OK;
311 }
312
313 static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
314 {
315         uint32_t v;
316         uint32_t ejtag_ctrl;
317         int retries = RETRY_ATTEMPTS;
318
319         /* Handle the bigendian/littleendian */
320         data &= 0xff;
321         data |= data << 8;
322         data |= data << 16;
323
324 begin_ejtag_dma_write_b:
325
326         /*  Setup Address*/
327         v = addr;
328         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
329         mips_ejtag_drscan_32(ejtag_info, &v);
330
331         /* Setup Data */
332         v = data;
333         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
334         mips_ejtag_drscan_32(ejtag_info, &v);
335
336         /* Initiate DMA Write & set DSTRT */
337         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
338         ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
339         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
340
341         /* Wait for DSTRT to Clear */
342         do {
343                 ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
344                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
345         } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
346
347         /* Clear DMA & Check DERR */
348         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
349         ejtag_ctrl = ejtag_info->ejtag_ctrl;
350         mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
351         if (ejtag_ctrl & EJTAG_CTRL_DERR)
352         {
353                 if (retries--) {
354                         LOG_ERROR("DMA Write Addr = %08" PRIx32 "  Data = ERROR ON WRITE (retrying)", addr);
355                         goto begin_ejtag_dma_write_b;
356                 }
357                 else
358                         LOG_ERROR("DMA Write Addr = %08" PRIx32 "  Data = ERROR ON WRITE", addr);
359                 return ERROR_JTAG_DEVICE_ERROR;
360         }
361
362         return ERROR_OK;
363 }
364
365 int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
366 {
367         switch (size)
368         {
369                 case 1:
370                         return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
371                 case 2:
372                         return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
373                 case 4:
374                         return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
375         }
376
377         return ERROR_OK;
378 }
379
380 static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
381 {
382         int i;
383         int     retval;
384
385         for (i = 0; i < count; i++) {
386                 if ((retval = ejtag_dma_read(ejtag_info, addr + i*sizeof(*buf), &buf[i])) != ERROR_OK)
387                         return retval;
388         }
389
390         return ERROR_OK;
391 }
392
393 static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
394 {
395         int i;
396         int retval;
397
398         for (i = 0; i < count; i++) {
399                 if ((retval = ejtag_dma_read_h(ejtag_info, addr + i*sizeof(*buf), &buf[i])) != ERROR_OK)
400                         return retval;
401         }
402
403         return ERROR_OK;
404 }
405
406 static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
407 {
408         int i;
409         int retval;
410
411         for (i = 0; i < count; i++) {
412                 if ((retval = ejtag_dma_read_b(ejtag_info, addr + i*sizeof(*buf), &buf[i])) != ERROR_OK)
413                         return retval;
414         }
415
416         return ERROR_OK;
417 }
418
419 int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
420 {
421         switch (size)
422         {
423                 case 1:
424                         return mips32_dmaacc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
425                 case 2:
426                         return mips32_dmaacc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
427                 case 4:
428                         return mips32_dmaacc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
429         }
430
431         return ERROR_OK;
432 }
433
434 static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
435 {
436         int i;
437         int retval;
438
439         for (i = 0; i < count; i++) {
440                 if ((retval = ejtag_dma_write(ejtag_info, addr + i*sizeof(*buf), buf[i])) != ERROR_OK)
441                         return retval;
442         }
443
444         return ERROR_OK;
445 }
446
447 static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
448 {
449         int i;
450         int retval;
451
452         for (i = 0; i < count; i++) {
453                 if ((retval = ejtag_dma_write_h(ejtag_info, addr + i*sizeof(*buf), buf[i])) != ERROR_OK)
454                         return retval;
455         }
456
457         return ERROR_OK;
458 }
459
460 static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
461 {
462         int i;
463         int retval;
464
465         for (i = 0; i < count; i++) {
466                 if ((retval = ejtag_dma_write_b(ejtag_info, addr + i*sizeof(*buf), buf[i])) != ERROR_OK)
467                         return retval;
468         }
469
470         return ERROR_OK;
471 }