jtag-mpsse

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit a7d29a11b2b18d515f0303071251338960cae5ce
parent 7b0db42e5617040a6873d7af5736bfd6c9fcd570
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun, 20 Apr 2014 23:58:36 -0700

big pile of work in progress

- added bit level shift transaction tracing (#ifdef TRACE_JTAG)
- fixed bogus bitcount for TMS moves at end of a shift
- fixed bogus bitread paths
- started sketching out AP and DP access

Diffstat:
Mjtag-mpsse.c | 54++++++++++++++++++++++++++++++++++++++++++++++++------
Mjtag.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mzynq.h | 57++++++++++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 215 insertions(+), 13 deletions(-)

diff --git a/jtag-mpsse.c b/jtag-mpsse.c @@ -219,6 +219,22 @@ static int jtag_move(JTAG *jtag, int count, unsigned bits){ if (count > 32) return -1; +#if TRACE_JTAG + { + u64 tmp = bits; + int n; + fprintf(stderr,"TDI <- "); + for (n = 0; n < count; n++) { + fprintf(stderr, "X"); + } + fprintf(stderr,"\nTMS <- "); + for (n = 0; n < count; n++) { + fprintf(stderr,"%c", (tmp & 1) ? '1' : '0'); + tmp >>= 1; + } + fprintf(stderr,"\n"); + } +#endif while (count > 0) { xfer = (count > 6) ? 6 : count; *p++ = 0x4b; @@ -251,6 +267,29 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out, if (count <= 0) return -1; +#if TRACE_JTAG + { + u64 tmp = bits; + int n; + fprintf(stderr,"TDI <- "); + for (n = 0; n < count; n++) { + fprintf(stderr,"%c", (tmp & 1) ? '1' : '0'); + tmp >>= 1; + } + for (n = 0; n < movebits; n++) + fprintf(stderr,"%c", (tmp & 1) ? '1' : '0'); + fprintf(stderr,"\nTMS <- "); + for (n = 0; n < count; n++) + fprintf(stderr,"0"); + tmp = movebits; + for (n = 0; n < movebits; n++) { + fprintf(stderr,"%c", (tmp & 1) ? '1' : '0'); + tmp >>= 1; + } + fprintf(stderr,"\n"); + } +#endif + bytes = count / 8; readbytes = bytes; iobytes = bytes; @@ -281,7 +320,7 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out, if (movebits > 6) return -1; /* TODO */ *p++ = out ? 0x6b : 0x4b; - *p++ = movebits; + *p++ = movecount - 1; *p++ = ((bits & 1) << 7) | (movebits & 0x3F); iobytes++; } @@ -294,7 +333,7 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out, return -1; if (out) { - u64 n = 0; + u64 n = 0, bit; unsigned shift = 0; if (ftdi_read(jtag, buf, iobytes, 1000)) return -1; @@ -305,12 +344,15 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out, } while (readbits > 0) { xfer = (readbits > 6) ? 6 : readbits; - n |= ((*p++ & bitxfermask[xfer]) << shift); - shift <<= xfer; + bit = ((*p++) >> (8 - xfer)) & bitxfermask[xfer]; + n |= (bit << shift); + shift += xfer; readbits -= xfer; } if (movecount) { - n |= ((*p++ & bitxfermask[movecount]) << shift); + /* we only ever care about the first bit */ + bit = ((*p++) >> (8 - movecount)) & 1; + n |= (bit << shift); } *out = n; } @@ -364,7 +406,7 @@ static int jtag_shift_ir(JTAG *jtag, int count, u64 bits, #define MOVE_ANY_TO_RESET_IDLE 8,0b01111111 #define MOVE_IDLE_TO_SHIFTDR 3,0b001 #define MOVE_IDLE_TO_SHIFTIR 4,0b0011 -#define MOVE_SHIFTxR_TO_IDLE 2,0b011 +#define MOVE_SHIFTxR_TO_IDLE 3,0b011 void jtag_close(JTAG *jtag) { diff --git a/jtag.c b/jtag.c @@ -18,10 +18,84 @@ #include "jtag.h" #include "zynq.h" +void pause(const char *msg) { + char crap[1024]; + fprintf(stderr,">>> %s <<<\n", msg); + fgets(crap, sizeof(crap), stdin); +} + +int jtag_dp_rd(JTAG *jtag, u32 addr, u32 *val) { + int retry = 30; + u64 u; + jtag_ir_wr(jtag, DAP_IR_DPACC); + jtag_dr_io(jtag, 35, XPACC_RD(addr), NULL); + while (retry-- > 0) { + jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u); + switch (XPACC_STATUS(u)) { + case XPACC_OK: + *val = u >> 3; + return 0; + case XPACC_WAIT: + fprintf(stderr,"!"); + continue; + default: + return -1; + } + } + return -1; +} + +int jtag_dp_wr(JTAG *jtag, u32 addr, u32 val) { + int retry = 30; + u64 u; + u = XPACC_WR(addr); + u |= (((u64) val) << 3); + jtag_ir_wr(jtag, DAP_IR_DPACC); + jtag_dr_io(jtag, 35, u, NULL); + while (retry-- > 0) { + jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u); + switch (XPACC_STATUS(u)) { + case XPACC_OK: + return 0; + case XPACC_WAIT: + fprintf(stderr,"!"); + continue; + default: + return -1; + } + } + return -1; +} + +/* TODO: cache state, check errors */ +int jtag_ap_rd(JTAG *jtag, u32 addr, u32 *val) { + u64 u; + jtag_dp_wr(jtag, DPACC_SELECT, DPSEL_APSEL(0) | DPSEL_APBANKSEL(addr)); + jtag_ir_wr(jtag, DAP_IR_APACC); + jtag_dr_io(jtag, 35, XPACC_RD(addr), NULL); + jtag_ir_wr(jtag, DAP_IR_DPACC); + jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u); + *val = (u >> 3); + return 0; +} + +int jtag_ap_wr(JTAG *jtag, u32 addr, u32 val) { + u64 u; + jtag_dp_wr(jtag, DPACC_SELECT, DPSEL_APSEL(0) | DPSEL_APBANKSEL(addr)); + jtag_ir_wr(jtag, DAP_IR_APACC); + u = XPACC_WR(addr); + u |= (((u64) val) << 3); + jtag_dr_io(jtag, 35, u, NULL); + jtag_ir_wr(jtag, DAP_IR_DPACC); + jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u); + return 0; +} + int main(int argc, char **argv) { JTAG *jtag; unsigned n; u64 u; + u32 x; if (!(jtag = jtag_open())) return -1; @@ -31,11 +105,50 @@ int main(int argc, char **argv) { if (jtag_select(jtag, 0x4ba00477)) return -1; - if (jtag_ir_wr(jtag, DAP_IDCODE)) + if (jtag_ir_wr(jtag, DAP_IR_IDCODE)) return -1; if (jtag_dr_io(jtag, 32, 0, &u)) return -1; - fprintf(stderr,"idcode? %08lx\n", u); + + jtag_dp_rd(jtag, DPACC_CSW, &x); + fprintf(stderr,"CSW %08x\n", x); + + jtag_dp_wr(jtag, DPACC_CSW, DPCSW_CSYSPWRUPREQ | DPCSW_CDBGPWRUPREQ); + do { + jtag_dp_rd(jtag, DPACC_CSW, &x); + fprintf(stderr,"CSW %08x\n", x); + } while ((x & (DPCSW_CSYSPWRUPACK | DPCSW_CDBGPWRUPACK)) != (DPCSW_CSYSPWRUPACK | DPCSW_CDBGPWRUPACK)); + + jtag_ap_rd(jtag, APACC_BASE, &x); + fprintf(stderr,"base %08x\n", x); + + jtag_ap_rd(jtag, APACC_IDR, &x); + fprintf(stderr,"idr %08x\n", x); + +#if STRESSTEST + for (n = 0; n < 0xFFFFFFFF; n++) { + u32 z = (n >> 16) | (n << 16); + x = 0xeeeeeeee; + jtag_ap_wr(jtag, APACC_TAR, z); + jtag_ap_rd(jtag, APACC_TAR, &x); + if (z != x) { + fprintf(stderr,"%08x != %08x\n", z, x); + } + //if ((n & 0xFFF) == 0) + fprintf(stderr,"%08x\r", z); + } + + jtag_ap_wr(jtag, APACC_TAR, 0x12345678); +#endif + + jtag_ap_rd(jtag, APACC_TAR, &x); + fprintf(stderr,"tar %08x\n", x); + +#if 0 + fprintf(stderr,"done\n"); + jtag_dp_wr(jtag, DPACC_CSW, 0); +#endif + return 0; } diff --git a/zynq.h b/zynq.h @@ -2,11 +2,58 @@ /* ARM DAP Controller (4bit IR) */ #define DAP_IR_SIZE 4 -#define DAP_ABORT 0x08 -#define DAP_DPACC 0x0A -#define DAP_APACC 0x0B -#define DAP_IDCODE 0x0E -#define DAP_BYPASS 0x0F +#define DAP_IR_ABORT 0x08 +#define DAP_IR_DPACC 0x0A +#define DAP_IR_APACC 0x0B +#define DAP_IR_IDCODE 0x0E +#define DAP_IR_BYPASS 0x0F + +#define XPACC_STATUS(n) ((n) & 0x3) +#define XPACC_WAIT 0x1 +#define XPACC_OK 0x2 +#define XPACC_RD(n) (0x1 | (((n) >> 1) & 6)) +#define XPACC_WR(n) (0x0 | (((n) >> 1) & 6)) + +#define DPACC_RESERVED 0x0 +#define DPACC_CSW 0x4 +#define DPACC_SELECT 0x8 +#define DPACC_RDBUFF 0xC + +#define DPCSW_CSYSPWRUPACK (1 << 31) +#define DPCSW_CSYSPWRUPREQ (1 << 30) +#define DPCSW_CDBGPWRUPACK (1 << 29) +#define DPCSW_CDBGPWRUPREQ (1 << 28) +#define DPCSW_CDBGRSTACK (1 << 27) +#define DPCSW_CDBGRSTREQ (1 << 26) +#define DPCSW_TRNCNT(n) (((n) & 0x3FF) << 12) +#define DPCSW_MASKLANE(n) (((n) & 0xF) << 8) // pushed verify or compare +#define DPCSW_WDATAERR (1 << 7) // reserved on jtag +#define DPCSW_READOK (1 << 6) // reserved on jtag +#define DPCSW_STICKYERR (1 << 5) +#define DPCSW_STICKYCMP (1 << 4) +#define DPCSW_TRNMODE_NORMAL (0 << 2) +#define DPCSW_TRNMODE_PUSH_VRFY (1 << 2) +#define DPCSW_TRNMODE_PUSH_CMP (2 << 2) +#define DPCSW_STICKYORUN (1 << 1) +#define DPCSW_ORUNDETECT (1 << 0) + +#define DPSEL_APSEL(n) (((n) & 0xFF) << 24) +#define DPSEL_APBANKSEL(a) ((a) & 0xF0) +#define DPSEL_CTRLSEL (1 << 0) // reserved on jtag + +/* Reading RDBUFF returns 0, has no side effects */ +/* Can be used to obtain final read result and ack values at end of seq */ + +#define APACC_CSW 0x00 +#define APACC_TAR 0x04 +#define APACC_DRW 0x0C +#define APACC_BD0 0x10 +#define APACC_BD1 0x14 +#define APACC_BD2 0x18 +#define APACC_BD3 0x1C +#define APACC_CFG 0xF4 +#define APACC_BASE 0xF8 +#define APACC_IDR 0xFC /* Xilinx TAP Controller (6bit IR) */