]> git.sur5r.net Git - openocd/blob - src/target/cortex_swjdp.c
From Michael Bruck
[openocd] / src / target / cortex_swjdp.c
1 /***************************************************************************\r
2  *   Copyright (C) 2006 by Magnus Lundin                                   *\r
3  *   lundin@mlu.mine.nu                                                    *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 /***************************************************************************\r
21  *                                                                         *\r
22  * CoreSight (Light?) SerialWireJtagDebugPort                              *\r
23  *                                                                         *\r
24  * CoreSightâ„¢ DAP-Lite TRM, ARM DDI 0316A                                  *\r
25  * Cortex-M3â„¢ TRM, ARM DDI 0337C                                            *\r
26  *                                                                         *\r
27 ***************************************************************************/\r
28 #ifdef HAVE_CONFIG_H\r
29 #include "config.h"\r
30 #endif\r
31 \r
32 #include "replacements.h"\r
33 \r
34 #include "cortex_m3.h"\r
35 #include "cortex_swjdp.h"\r
36 #include "jtag.h"\r
37 #include "log.h"\r
38 #include <stdlib.h>\r
39 \r
40 /*\r
41 \r
42 Transaction Mode:\r
43 swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
44 Uses Overrun checking mode and does not do actual JTAG send/receive or transaction \r
45 result checking until swjdp_end_transaction()\r
46 This must be done before using or deallocating any return variables.\r
47 \r
48 swjdp->trans_mode == TRANS_MODE_ATOMIC\r
49 All reads and writes to the AHB bus are checked for valid completion, and return values\r
50 are immediatley available.\r
51 \r
52 */\r
53 \r
54 /***************************************************************************\r
55  *                                                                         *\r
56  * DPACC and APACC scanchain access through JTAG-DR                        *\r
57  *                                                                         *\r
58 ***************************************************************************/\r
59 \r
60 /* Scan out and in from target ordered u8 buffers */\r
61 int swjdp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)\r
62 {\r
63         scan_field_t fields[2];\r
64         u8 out_addr_buf;\r
65         \r
66         jtag_add_end_state(TAP_RTI);\r
67         arm_jtag_set_instr(jtag_info, instr, NULL);\r
68 \r
69         fields[0].device = jtag_info->chain_pos;\r
70         fields[0].num_bits = 3;\r
71         buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));\r
72         fields[0].out_value = &out_addr_buf;\r
73         fields[0].out_mask = NULL;\r
74         fields[0].in_value = ack;\r
75         fields[0].in_check_value = NULL;\r
76         fields[0].in_check_mask = NULL;\r
77         fields[0].in_handler = NULL;\r
78         fields[0].in_handler_priv = NULL;\r
79 \r
80         fields[1].device = jtag_info->chain_pos;\r
81         fields[1].num_bits = 32;\r
82         fields[1].out_value = outvalue;\r
83         fields[1].out_mask = NULL;\r
84         fields[1].in_value = invalue;\r
85         fields[1].in_handler = NULL;\r
86         fields[1].in_handler_priv = NULL;\r
87         fields[1].in_check_value = NULL;\r
88         fields[1].in_check_mask = NULL;\r
89 \r
90         jtag_add_dr_scan(2, fields, -1);\r
91 \r
92         return ERROR_OK;\r
93 }\r
94 \r
95 /* Scan out and in from host ordered u32 variables */\r
96 int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)\r
97 {\r
98         scan_field_t fields[2];\r
99         u8 out_value_buf[4];\r
100         u8 out_addr_buf;\r
101         \r
102         jtag_add_end_state(TAP_RTI);\r
103         arm_jtag_set_instr(jtag_info, instr, NULL);\r
104 \r
105         fields[0].device = jtag_info->chain_pos;\r
106         fields[0].num_bits = 3;\r
107         buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));\r
108         fields[0].out_value = &out_addr_buf;\r
109         fields[0].out_mask = NULL;\r
110         fields[0].in_value = ack;\r
111         fields[0].in_check_value = NULL;\r
112         fields[0].in_check_mask = NULL;\r
113         fields[0].in_handler = NULL;\r
114         fields[0].in_handler_priv = NULL;\r
115 \r
116         fields[1].device = jtag_info->chain_pos;\r
117         fields[1].num_bits = 32;\r
118         buf_set_u32(out_value_buf, 0, 32, outvalue);\r
119         fields[1].out_value = out_value_buf;\r
120         fields[1].out_mask = NULL;\r
121         fields[1].in_value = NULL;\r
122         if (invalue)\r
123         {\r
124                 fields[1].in_handler = arm_jtag_buf_to_u32;\r
125                 fields[1].in_handler_priv = invalue;\r
126         }\r
127         else\r
128         {\r
129                 fields[1].in_handler = NULL;\r
130                 fields[1].in_handler_priv = NULL;\r
131         }\r
132         fields[1].in_check_value = NULL;\r
133         fields[1].in_check_mask = NULL;\r
134 \r
135         jtag_add_dr_scan(2, fields, -1);\r
136 \r
137         return ERROR_OK;\r
138 }\r
139 \r
140 /* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ \r
141 int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)\r
142 {\r
143         swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);\r
144         if ((RnW == DPAP_READ) && (invalue != NULL))\r
145         {\r
146                 swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);\r
147         }\r
148         \r
149         /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */\r
150         if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))\r
151         {\r
152                 return swjdp_transaction_endcheck(swjdp);\r
153         }\r
154 \r
155         return ERROR_OK;\r
156 }\r
157 \r
158 int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)\r
159 {\r
160 \r
161         swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);\r
162         if ((RnW==DPAP_READ) && (invalue != NULL))\r
163         {\r
164                 swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);\r
165         }\r
166         \r
167         /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */\r
168         if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))\r
169         {\r
170                 return swjdp_transaction_endcheck(swjdp);\r
171         }\r
172 \r
173         return ERROR_OK;\r
174 }\r
175 \r
176 int swjdp_transaction_endcheck(swjdp_common_t *swjdp)\r
177 {\r
178         int waitcount = 0;\r
179         u32 ctrlstat;\r
180 \r
181         scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
182         scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
183         jtag_execute_queue();\r
184         \r
185         swjdp->ack = swjdp->ack & 0x7;\r
186         \r
187         while (swjdp->ack != 2)\r
188         {\r
189                 if (swjdp->ack == 1)\r
190                 {\r
191                         waitcount++;\r
192                         if (waitcount > 100)\r
193                         {\r
194                                 WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");\r
195 \r
196                                 return ERROR_JTAG_DEVICE_ERROR;\r
197                         }\r
198                 }\r
199                 else\r
200                 {\r
201                         WARNING("Invalid ACK in SWJDP transaction");\r
202                         return ERROR_JTAG_DEVICE_ERROR;\r
203                 }\r
204 \r
205                 scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
206                 jtag_execute_queue();\r
207                 swjdp->ack = swjdp->ack & 0x7;\r
208         }\r
209 \r
210         /* Check for STICKYERR and STICKYORUN */\r
211         if (ctrlstat & (SSTICKYORUN | SSTICKYERR))\r
212         {\r
213                 DEBUG("swjdp: CTRL/STAT error 0x%x", ctrlstat);\r
214                 /* Check power to debug regions */\r
215                 if ((ctrlstat & 0xf0000000) != 0xf0000000)\r
216                 {\r
217                          ahbap_debugport_init(swjdp);\r
218                 }\r
219                 else\r
220                 {\r
221                         u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr;\r
222                         \r
223                         if (ctrlstat & SSTICKYORUN)\r
224                                 ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed");\r
225                         \r
226                         if (ctrlstat & SSTICKYERR)\r
227                                 ERROR("SWJ-DP STICKY ERROR");\r
228                         \r
229                         /* Clear Sticky Error Bits */\r
230                         scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);\r
231                         scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
232                         jtag_execute_queue();\r
233 \r
234                         DEBUG("swjdp: status 0x%x", ctrlstat);\r
235                         \r
236                         /* Can we find out the reason for the error ?? */                       \r
237                         ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);\r
238                         ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr);\r
239                         ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr);\r
240                         ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar);\r
241                         ERROR("dcb_dhcsr 0x%x, nvic_shcsr 0x%x, nvic_cfsr 0x%x, nvic_bfar 0x%x", dcb_dhcsr, nvic_shcsr, nvic_cfsr, nvic_bfar);\r
242                 }\r
243                 jtag_execute_queue();\r
244                 return ERROR_JTAG_DEVICE_ERROR;\r
245         }\r
246 \r
247         return ERROR_OK;\r
248 }\r
249 \r
250 /***************************************************************************\r
251  *                                                                         *\r
252  * DP and AHB-AP  register access  through APACC and DPACC                 *\r
253  *                                                                         *\r
254 ***************************************************************************/\r
255 \r
256 int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)\r
257 {\r
258         u8 out_value_buf[4];\r
259         \r
260         buf_set_u32(out_value_buf, 0, 32, value);\r
261         return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);\r
262 }\r
263 \r
264 int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)\r
265 {\r
266         scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);\r
267 \r
268     return ERROR_OK;\r
269 }\r
270 \r
271 int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)\r
272 {\r
273         u32 select;\r
274         select = (reg_addr & 0xFF0000F0);\r
275 \r
276         if (select != swjdp->dp_select_value)\r
277         {\r
278                 swjdp_write_dpacc(swjdp, select, DP_SELECT);\r
279                 swjdp->dp_select_value = select;\r
280         }\r
281 \r
282         return ERROR_OK;\r
283 }\r
284 \r
285 int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)\r
286 {\r
287         swjdp_bankselect_apacc(swjdp, reg_addr);\r
288         scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);\r
289 \r
290         return ERROR_OK;\r
291 }\r
292 \r
293 int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)\r
294 {\r
295         swjdp_bankselect_apacc(swjdp, reg_addr);\r
296         scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);\r
297 \r
298         return ERROR_OK;\r
299 }\r
300 int ahbap_write_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 value)\r
301 {\r
302         u8 out_value_buf[4];\r
303         \r
304         buf_set_u32(out_value_buf, 0, 32, value);\r
305         swjdp_bankselect_apacc(swjdp, reg_addr);\r
306         scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);\r
307 \r
308         return ERROR_OK;\r
309 }\r
310 \r
311 int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)\r
312 {\r
313         swjdp_bankselect_apacc(swjdp, reg_addr);\r
314         scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);\r
315 \r
316         return ERROR_OK;\r
317 }\r
318 \r
319 /***************************************************************************\r
320  *                                                                         *\r
321  * AHB-AP access to memory and system registers on AHB bus                 *\r
322  *                                                                         *\r
323 ***************************************************************************/\r
324 \r
325 int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)\r
326 {\r
327         csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;\r
328         if (csw != swjdp->ap_csw_value)\r
329         {\r
330                 //DEBUG("swjdp : Set CSW %x",csw);\r
331                 ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); \r
332                 swjdp->ap_csw_value = csw;\r
333         }\r
334         if (tar != swjdp->ap_tar_value)\r
335         {\r
336                 //DEBUG("swjdp : Set TAR %x",tar);\r
337                 ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar );\r
338                 swjdp->ap_tar_value = tar;\r
339         }\r
340         if (csw & CSW_ADDRINC_MASK)\r
341         {       \r
342                 /* Do not cache TAR value when autoincrementing */      \r
343                 swjdp->ap_tar_value = -1;\r
344         }\r
345         return ERROR_OK;\r
346 }\r
347 \r
348 /*****************************************************************************\r
349 *                                                                            *\r
350 * ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)      *\r
351 *                                                                            *\r
352 * Read a u32 value from memory or system register                            *\r
353 * Functionally equivalent to target_read_u32(target, address, u32 *value),   *\r
354 * but with less overhead                                                     *\r
355 *****************************************************************************/\r
356 int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)\r
357 {\r
358         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
359 \r
360         ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);\r
361         ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );\r
362         \r
363         return ERROR_OK;\r
364 }\r
365 \r
366 int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value)\r
367 {\r
368         ahbap_read_system_u32(swjdp, address, value);\r
369         \r
370         return swjdp_transaction_endcheck(swjdp);\r
371 }\r
372 \r
373 /*****************************************************************************\r
374 *                                                                            *\r
375 * ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)      *\r
376 *                                                                            *\r
377 * Write a u32 value to memory or system register                             *\r
378 *                                                                            *\r
379 *****************************************************************************/\r
380 int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)\r
381 {\r
382         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
383 \r
384         ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);\r
385         ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );\r
386 \r
387         return ERROR_OK;\r
388 }\r
389 \r
390 int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)\r
391 {\r
392         ahbap_write_system_u32(swjdp, address, value);\r
393         \r
394         return swjdp_transaction_endcheck(swjdp);\r
395 }\r
396 \r
397 /*****************************************************************************\r
398 *                                                                            *\r
399 * ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) *\r
400 *                                                                            *\r
401 * Write a buffer in target order (little endian)                             *\r
402 *                                                                            *\r
403 *****************************************************************************/\r
404 int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
405 {\r
406         u32 outvalue;\r
407         int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;\r
408 \r
409         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
410 \r
411         while ((address & 0x3) && (count > 0))\r
412         {\r
413                 ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
414                 outvalue = (*buffer++) << 8 * (address & 0x3);\r
415                 ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );\r
416                 swjdp_transaction_endcheck(swjdp);\r
417                 count--;\r
418                 address++;\r
419         }\r
420         wcount = count >> 2;\r
421         count = count - 4 * wcount;\r
422         while (wcount > 0)\r
423         {\r
424                 /* Adjust to write blocks within 4K aligned boundaries */\r
425                 blocksize = (0x1000 - (0xFFF & address)) >> 2;\r
426                 if (wcount < blocksize)\r
427                         blocksize = wcount;\r
428                 ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);\r
429                 for (writecount=0; writecount<blocksize; writecount++)\r
430                 {\r
431                         ahbap_write_reg(swjdp, AHBAP_DRW, buffer + 4 * writecount );\r
432                 }\r
433                 if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)\r
434                 {\r
435                         wcount = wcount - blocksize;\r
436                         address = address + 4 * blocksize;\r
437                         buffer = buffer + 4 * blocksize;\r
438                 }\r
439                 else\r
440                 {\r
441                         errorcount++;\r
442                 }\r
443                 if (errorcount > 1)\r
444                 {\r
445                         WARNING("Block write error address 0x%x, wcount 0x%x", address, wcount);\r
446                         return ERROR_JTAG_DEVICE_ERROR;\r
447                 }\r
448         }\r
449         \r
450         while (count > 0)\r
451         {\r
452                 ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
453                 outvalue = (*buffer++) << 8 * (address & 0x3);\r
454                 ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );\r
455                 retval = swjdp_transaction_endcheck(swjdp);\r
456                 count--;\r
457                 address++;\r
458         }\r
459 \r
460         return retval;\r
461 }\r
462 \r
463 int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
464 {\r
465         u32 outvalue;\r
466         int retval = ERROR_OK;\r
467         \r
468         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
469         \r
470         while (count > 0)\r
471         {\r
472                 ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);\r
473                 outvalue = *((u16*)buffer) << 8 * (address & 0x3);\r
474                 ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );\r
475                 retval = swjdp_transaction_endcheck(swjdp);\r
476                 count -= 2;\r
477                 address += 2;\r
478                 buffer += 2;\r
479         }\r
480 \r
481         return retval;\r
482 }\r
483 \r
484 /*****************************************************************************\r
485 *                                                                            *\r
486 * ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *\r
487 *                                                                            *\r
488 * Read block fast in target order (little endian) into a buffer       *\r
489 *                                                                            *\r
490 *****************************************************************************/\r
491 int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
492 {\r
493         u32 invalue;\r
494         int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;\r
495 \r
496         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
497 \r
498         while ((address & 0x3) && (count > 0))\r
499         {\r
500                 ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
501                 ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue);\r
502                 swjdp_transaction_endcheck(swjdp);\r
503                 *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;\r
504                 count--;\r
505                 address++;\r
506         }\r
507         wcount = count >> 2;\r
508         count = count - 4 * wcount;\r
509         while (wcount > 0)\r
510         {\r
511                 /* Adjust to read within 4K block boundaries */\r
512                 blocksize = (0x1000 - (0xFFF & address)) >> 2;\r
513                 if (wcount < blocksize)\r
514                         blocksize = wcount;\r
515                 ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);\r
516                 /* Scan out first read */\r
517                 swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);\r
518                 for (readcount = 0; readcount < blocksize - 1; readcount++)\r
519                 {\r
520                         /* Scan out read instruction and scan in previous value */\r
521                         swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);\r
522                 }\r
523                 /* Scan in last value */\r
524                 swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);\r
525                 if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)\r
526                 {\r
527                         wcount = wcount - blocksize;\r
528                         address += 4 * blocksize;\r
529                         buffer += 4 * blocksize; \r
530                 }\r
531                 else\r
532                 {\r
533                         errorcount++;\r
534                 }\r
535                 if (errorcount > 1)\r
536                 {\r
537                         WARNING("Block read error address 0x%x, count 0x%x", address, count);\r
538                         return ERROR_JTAG_DEVICE_ERROR;\r
539                 }\r
540         }\r
541 \r
542         while (count > 0)\r
543         {\r
544                 ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
545                 ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );\r
546                 retval = swjdp_transaction_endcheck(swjdp);\r
547                 *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;\r
548                 count--;\r
549                 address++;\r
550         }\r
551 \r
552         return retval;\r
553 }\r
554 \r
555 int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
556 {\r
557         u32 invalue;\r
558         int retval = ERROR_OK;\r
559         \r
560         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
561         \r
562         while (count > 0)\r
563         {\r
564                 ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);\r
565                 ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );\r
566                 retval = swjdp_transaction_endcheck(swjdp);\r
567                 *((u16*)buffer) = (invalue >> 8 * (address & 0x3));\r
568                 count -= 2;\r
569                 address += 2;\r
570                 buffer += 2;\r
571         }\r
572 \r
573         return retval;\r
574 }\r
575 \r
576 int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)\r
577 {\r
578         int readcount, errorcount = 0;\r
579         u32 blocksize;\r
580         \r
581         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
582         \r
583         while (count > 0)\r
584         {\r
585                 /* Adjust to read within 4K block boundaries */\r
586                 blocksize = (0x1000 - (0xFFF & address)) >> 2;\r
587                 if (count < blocksize)\r
588                         blocksize = count;\r
589                 ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);\r
590                 for (readcount = 0; readcount < blocksize; readcount++)\r
591                 {\r
592                         ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer + readcount );\r
593                 }\r
594                 if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)\r
595                 {\r
596                         count = count - blocksize;\r
597                         address = address + 4 * blocksize;\r
598                         buffer = buffer + blocksize;\r
599                 }\r
600                 else\r
601                 {\r
602                         errorcount++;\r
603                 }\r
604                 if (errorcount > 1)\r
605                 {\r
606                         WARNING("Block read error address 0x%x, count 0x%x", address, count);\r
607                         return ERROR_JTAG_DEVICE_ERROR;\r
608                 }\r
609         }\r
610 \r
611         return ERROR_OK;\r
612 }\r
613 \r
614 int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)\r
615 {\r
616         int retval;\r
617         u32 dcrdr;\r
618         \r
619         ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);\r
620         \r
621         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
622 \r
623         /* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */\r
624         ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);\r
625         ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum );\r
626 \r
627         /* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */\r
628         ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);\r
629         ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );\r
630         \r
631         retval = swjdp_transaction_endcheck(swjdp);\r
632         ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);\r
633         return retval;\r
634 }\r
635 \r
636 int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)\r
637 {\r
638         int retval;\r
639         u32 dcrdr;\r
640         \r
641         ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);\r
642         \r
643         swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
644         \r
645         /* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */\r
646         ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);\r
647         ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );\r
648 \r
649         /* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR       ); */\r
650         ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);\r
651         ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR );\r
652         \r
653         retval = swjdp_transaction_endcheck(swjdp);\r
654         ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);\r
655         return retval;\r
656 }\r
657 \r
658 int ahbap_debugport_init(swjdp_common_t *swjdp)\r
659 {\r
660         u32 idreg, romaddr, dummy;\r
661         u32 ctrlstat;\r
662         int cnt = 0;\r
663         \r
664         DEBUG(" ");\r
665         \r
666         swjdp->ap_csw_value = -1;\r
667         swjdp->ap_tar_value = -1;\r
668         swjdp->trans_mode = TRANS_MODE_ATOMIC;\r
669         swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
670         swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT);\r
671         swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
672         \r
673         swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;\r
674 \r
675         swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);\r
676         swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);\r
677         jtag_execute_queue();\r
678 \r
679         /* Check that we have debug power domains activated */\r
680         while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))\r
681         {\r
682                 DEBUG("swjdp: wait CDBGPWRUPACK");\r
683                 swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);\r
684                 jtag_execute_queue();\r
685                 usleep(10000);\r
686         }\r
687 \r
688         while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))\r
689         {\r
690                 DEBUG("swjdp: wait CSYSPWRUPACK");\r
691                 swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);\r
692                 jtag_execute_queue();\r
693                 usleep(10000);\r
694         }\r
695 \r
696         swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
697         /* With debug power on we can activate OVERRUN checking */\r
698         swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;\r
699         swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);\r
700         swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
701         \r
702         ahbap_read_reg_u32(swjdp, 0xFC, &idreg);\r
703         ahbap_read_reg_u32(swjdp, 0xF8, &romaddr);\r
704         \r
705         DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);       \r
706         \r
707         return ERROR_OK;\r
708 }\r