dap.c (9437B)
1 // Copyright 2014 Brian Swetland <swetland@frotz.net> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "dap.h" 20 #include "dap-registers.h" 21 22 #define CSW_ERRORS (DPCSW_STICKYERR | DPCSW_STICKYCMP | DPCSW_STICKYORUN) 23 #define CSW_ENABLES (DPCSW_CSYSPWRUPREQ | DPCSW_CDBGPWRUPREQ | DPCSW_ORUNDETECT) 24 25 #include <time.h> 26 static u64 NOW(void) { 27 struct timespec ts; 28 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) return 0; 29 return (((u64) ts.tv_sec) * ((u64)1000000000)) + ((u64) ts.tv_nsec); 30 } 31 32 struct DAP { 33 JTAG *jtag; 34 u32 device_id; 35 u32 cached_ir; 36 }; 37 38 static void q_dap_ir_wr(DAP *dap, u32 ir) { 39 if (dap->cached_ir != ir) { 40 dap->cached_ir = ir; 41 jtag_ir_wr(dap->jtag, 4, &ir); 42 } 43 } 44 45 // force ir write even if redundant 46 // used for a timing hack 47 static void _q_dap_ir_wr(DAP *dap, u32 ir) { 48 dap->cached_ir = ir; 49 jtag_ir_wr(dap->jtag, 4, &ir); 50 } 51 52 static void q_dap_dr_io(DAP *dap, u32 bitcount, u64 wdata, u64 *rdata) { 53 if (rdata) { 54 *rdata = 0; 55 jtag_dr_io(dap->jtag, bitcount, &wdata, rdata); 56 } else { 57 jtag_dr_wr(dap->jtag, bitcount, &wdata); 58 } 59 } 60 61 static void q_dap_abort(DAP *dap) { 62 u32 x; 63 u64 u; 64 x = DAP_IR_ABORT; 65 u = 8; 66 jtag_ir_wr(dap->jtag, 4, &x); 67 jtag_dr_wr(dap->jtag, 35, &u); 68 dap->cached_ir = 0xFFFFFFFF; 69 } 70 71 // queue a DPCSW status query, commit jtag txn 72 static int dap_commit(DAP *dap) { 73 u64 a, b; 74 q_dap_ir_wr(dap, DAP_IR_DPACC); 75 q_dap_dr_io(dap, 35, XPACC_RD(DPACC_CSW), &a); 76 q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &b); 77 dap->cached_ir = 0xFFFFFFFF; 78 if (jtag_commit(dap->jtag)) { 79 return -1; 80 } 81 if (XPACC_STATUS(a) != XPACC_OK) { 82 fprintf(stderr, "dap: invalid txn status\n"); 83 return -1; 84 } 85 if (XPACC_STATUS(b) != XPACC_OK) { 86 fprintf(stderr, "dap: cannot read status\n"); 87 return -1; 88 } 89 b >>= 3; 90 if (b & DPCSW_STICKYORUN) { 91 fprintf(stderr, "dap: overrun\n"); 92 return -1; 93 } 94 if (b & DPCSW_STICKYERR) { 95 fprintf(stderr, "dap: error\n"); 96 return -1; 97 } 98 return 0; 99 } 100 101 int dap_dp_rd(DAP *dap, u32 addr, u32 *val) { 102 u64 u; 103 q_dap_ir_wr(dap, DAP_IR_DPACC); 104 q_dap_dr_io(dap, 35, XPACC_RD(addr), NULL); 105 q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u); 106 if (jtag_commit(dap->jtag)) { 107 return -1; 108 } 109 if (XPACC_STATUS(u) != XPACC_OK) { 110 return -1; 111 } 112 *val = u >> 3; 113 return 0; 114 } 115 116 static void q_dap_dp_wr(DAP *dap, u32 addr, u32 val) { 117 q_dap_ir_wr(dap, DAP_IR_DPACC); 118 q_dap_dr_io(dap, 35, XPACC_WR(addr, val), NULL); 119 //q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &s->u); 120 } 121 122 int dap_dp_wr(DAP *dap, u32 addr, u32 val) { 123 q_dap_dp_wr(dap, addr, val); 124 return jtag_commit(dap->jtag); 125 } 126 127 int dap_ap_rd(DAP *dap, u32 apnum, u32 addr, u32 *val) { 128 u64 u; 129 q_dap_ir_wr(dap, DAP_IR_DPACC); 130 q_dap_dp_wr(dap, DPACC_SELECT, DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr)); 131 q_dap_ir_wr(dap, DAP_IR_APACC); 132 q_dap_dr_io(dap, 35, XPACC_RD(addr), NULL); 133 q_dap_ir_wr(dap, DAP_IR_DPACC); 134 q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u); 135 // TODO: redundant ir wr 136 if (dap_commit(dap)) { 137 return -1; 138 } 139 *val = (u >> 3); 140 return 0; 141 } 142 143 void q_dap_ap_wr(DAP *dap, u32 apnum, u32 addr, u32 val) { 144 q_dap_ir_wr(dap, DAP_IR_DPACC); 145 q_dap_dp_wr(dap, DPACC_SELECT, DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr)); 146 q_dap_ir_wr(dap, DAP_IR_APACC); 147 q_dap_dr_io(dap, 35, XPACC_WR(addr, val), NULL); 148 } 149 150 int dap_mem_wr32(DAP *dap, u32 n, u32 addr, u32 val) { 151 if (addr & 3) 152 return -1; 153 q_dap_ap_wr(dap, n, APACC_CSW, 154 APCSW_DBGSWEN | APCSW_INCR_NONE | APCSW_SIZE32); 155 q_dap_ap_wr(dap, n, APACC_TAR, addr); 156 q_dap_ap_wr(dap, n, APACC_DRW, val); 157 return dap_commit(dap); 158 } 159 160 int dap_mem_rd32(DAP *dap, u32 n, u32 addr, u32 *val) { 161 if (addr & 3) 162 return -1; 163 q_dap_ap_wr(dap, n, APACC_TAR, addr); 164 if (dap_ap_rd(dap, n, APACC_DRW, val)) 165 return -1; 166 return 0; 167 } 168 169 int dap_mem_read(DAP *dap, u32 apnum, u32 addr, void *data, u32 len) { 170 u64 scratch[1024]; 171 u32 *x = data; 172 u32 n; 173 174 if ((addr & 3) || (((u64) data) & 3)) { 175 // base and length must be aligned 176 return -1; 177 } 178 179 while (len > 0) { 180 // max transfer is 1K 181 // transfer may not cross 1K boundary 182 u32 xfer = 1024 - (addr & 0x3FF); 183 if (xfer > len) { 184 xfer = len; 185 } 186 q_dap_ap_wr(dap, apnum, APACC_CSW, 187 APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32); 188 q_dap_dr_io(dap, 35, XPACC_WR(APACC_TAR, addr), NULL); 189 // read txn will be returned on the next txn 190 q_dap_dr_io(dap, 35, XPACC_RD(APACC_DRW), NULL); 191 _q_dap_ir_wr(dap, DAP_IR_APACC); // HACK, timing 192 for (n = 0; n < (xfer-4); n += 4) { 193 q_dap_dr_io(dap, 35, XPACC_RD(APACC_DRW), &scratch[n/4]); 194 _q_dap_ir_wr(dap, DAP_IR_APACC); // HACK, timing 195 } 196 // dummy read of TAR to pick up last read value 197 q_dap_dr_io(dap, 35, XPACC_RD(APACC_TAR), &scratch[n/4]); 198 if (dap_commit(dap)) { 199 return -1; 200 } 201 for (n = 0; n < xfer; n += 4) { 202 switch(XPACC_STATUS(scratch[n/4])) { 203 case XPACC_WAIT: fprintf(stderr,"w"); break; 204 case XPACC_OK: fprintf(stderr,"o"); break; 205 default: fprintf(stderr,"?"); break; 206 } 207 *x++ = scratch[n/4] >> 3; 208 } 209 fprintf(stderr,"\n"); 210 len -= xfer; 211 addr += xfer; 212 } 213 return 0; 214 } 215 216 int dap_mem_write(DAP *dap, u32 apnum, u32 addr, void *data, u32 len) { 217 u32 *x = data; 218 u32 n; 219 220 if ((addr & 3) || (((u64) data) & 3)) { 221 // base and length must be aligned 222 return -1; 223 } 224 225 while (len > 0) { 226 // max transfer is 1K 227 // transfer may not cross 1K boundary 228 u32 xfer = 1024 - (addr & 0x3FF); 229 if (xfer > len) { 230 xfer = len; 231 } 232 q_dap_ap_wr(dap, apnum, APACC_CSW, APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32); 233 q_dap_dr_io(dap, 35, XPACC_WR(APACC_TAR, addr), NULL); 234 for (n = 0; n < xfer; n += 4) { 235 _q_dap_ir_wr(dap, DAP_IR_APACC); // HACK, timing 236 q_dap_dr_io(dap, 35, XPACC_WR(APACC_DRW, *x++), NULL); 237 } 238 if (dap_commit(dap)) { 239 return -1; 240 } 241 len -= xfer; 242 addr += xfer; 243 } 244 return 0; 245 } 246 247 DAP *dap_init(JTAG *jtag, u32 id) { 248 DAP *dap = malloc(sizeof(DAP)); 249 memset(dap, 0, sizeof(DAP)); 250 dap->jtag = jtag; 251 dap->cached_ir = 0xFFFFFFFF; 252 dap->device_id = id; 253 return dap; 254 } 255 256 int dap_attach(DAP *dap) { 257 unsigned n; 258 u32 x; 259 260 if (jtag_enumerate(dap->jtag) < 0) { 261 fprintf(stderr, "dap: jtag enumeration failed\n"); 262 return -1; 263 } 264 if (jtag_select_device(dap->jtag, dap->device_id)) { 265 fprintf(stderr, "dap: cannot find device on chain\n"); 266 return -1; 267 } 268 269 // make sure we abort any ongoing transactions first 270 q_dap_abort(dap); 271 272 // attempt to power up and clear errors 273 for (n = 0; n < 10; n++) { 274 if (dap_dp_wr(dap, DPACC_CSW, CSW_ERRORS | CSW_ENABLES)) 275 continue; 276 if (dap_dp_rd(dap, DPACC_CSW, &x)) 277 continue; 278 if (x & CSW_ERRORS) 279 continue; 280 if (!(x & DPCSW_CSYSPWRUPACK)) 281 continue; 282 if (!(x & DPCSW_CDBGPWRUPACK)) 283 continue; 284 return 0; 285 } 286 fprintf(stderr,"dap: attach failed\n"); 287 return -1; 288 } 289 290 static int read4xid(DAP *dap, u32 n, u32 addr, u32 *val) { 291 u32 a,b,c,d; 292 if (dap_mem_rd32(dap, n, addr + 0x00, &a)) return -1; 293 if (dap_mem_rd32(dap, n, addr + 0x04, &b)) return -1; 294 if (dap_mem_rd32(dap, n, addr + 0x08, &c)) return -1; 295 if (dap_mem_rd32(dap, n, addr + 0x0C, &d)) return -1; 296 *val = (a & 0xFF) | ((b & 0xFF) << 8) | ((c & 0xFF) << 16) | ((d & 0xFF) << 24); 297 return 0; 298 } 299 300 static int readinfo(DAP *dap, u32 n, u32 base, u32 *cid, u32 *pid0, u32 *pid1) { 301 if (read4xid(dap, n, base + 0xFF0, cid)) return -1; 302 if (read4xid(dap, n, base + 0xFE0, pid0)) return -1; 303 if (read4xid(dap, n, base + 0xFD0, pid1)) return -1; 304 return 0; 305 } 306 307 static void dumptable(DAP *dap, u32 n, u32 base) { 308 u32 cid, pid0, pid1, memtype; 309 u32 x, addr; 310 int i; 311 312 printf("TABLE @%08x ", base); 313 if (readinfo(dap, n, base, &cid, &pid0, &pid1)) { 314 printf("<error reading cid & pid>\n"); 315 return; 316 } 317 if (dap_mem_rd32(dap, n, base + 0xFCC, &memtype)) { 318 printf("<error reading memtype>\n"); 319 return; 320 } 321 printf("CID %08x PID %08x %08x %dKB%s\n", cid, pid1, pid0, 322 4 * (1 + ((pid1 & 0xF0) >> 4)), 323 (memtype & 1) ? " SYSMEM": ""); 324 for (i = 0; i < 128; i++) { 325 if (dap_mem_rd32(dap, n, base + i * 4, &x)) break; 326 if (x == 0) break; 327 if ((x & 3) != 3) continue; 328 addr = base + (x & 0xFFFFF000); 329 if (readinfo(dap, n, addr, &cid, &pid0, &pid1)) { 330 printf(" <error reading cid & pid>\n"); 331 continue; 332 } 333 printf(" %02d: @%08x CID %08x PID %08x %08x %dKB\n", 334 i, addr, cid, pid1, pid0, 335 4 * (1 + ((pid1 & 0xF0) >> 4))); 336 if (((cid >> 12) & 0xF) == 1) { 337 dumptable(dap, n, addr); 338 } 339 } 340 } 341 342 int dap_probe(DAP *dap) { 343 unsigned n; 344 u32 x, y; 345 346 for (n = 0; n < 256; n++) { 347 if (dap_ap_rd(dap, n, APACC_IDR, &x)) 348 break; 349 if (x == 0) 350 break; 351 y = 0; 352 dap_ap_rd(dap, n, APACC_BASE, &y); 353 printf("AP%d ID=%08x BASE=%08x\n", n, x, y); 354 if (y && (y != 0xFFFFFFFF)) { 355 dumptable(dap, n, y); 356 } 357 if (dap_ap_rd(dap, n, APACC_CSW, &x) == 0) 358 printf("AP%d CSW=%08x\n", n, x); 359 } 360 return 0; 361 } 362 363 int dap_reset(DAP *dap) { 364 u32 x; 365 if (dap_dp_wr(dap, DPACC_CSW, CSW_ENABLES | DPCSW_CDBGRSTREQ)) { 366 return -1; 367 } 368 if (dap_dp_rd(dap, DPACC_CSW, &x)) { 369 return -1; 370 } 371 printf("%08x\n", x); 372 return 0; 373 }