X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=firmware%2Fapps%2Fjtag%2Fjtagxscale.c;h=bbf9b9b20cf6fa53ecb20b9fee1b5d04c8ed485c;hp=ffe169cea642999419b7e3be3fde15c194fab408;hb=5fb0341d348e101b30794945a6c91546e25e8e7b;hpb=b6ef3f8c96ad4f9a457e1a7e61a39ea452fbbd66 diff --git a/firmware/apps/jtag/jtagxscale.c b/firmware/apps/jtag/jtagxscale.c index ffe169c..bbf9b9b 100644 --- a/firmware/apps/jtag/jtagxscale.c +++ b/firmware/apps/jtag/jtagxscale.c @@ -1,24 +1,219 @@ -/*! \file jtagxscale.c +/*! + \file jtagxscale.c \author Dave Huseby - \brief Intel XScale JTAG (32-bit) + \brief Intel XScale JTAG */ #include "platform.h" #include "command.h" #include "jtag.h" +#include "jtagxscale.h" -//! Handles XScale JTAG commands. Forwards others to JTAG. -void xscalehandle(unsigned char app, - unsigned char verb, - unsigned long len) +#define JTAGXSCALE_APP + +/* Handles XScale JTAG commands. Forwards others to JTAG. */ +void jtag_xscale_handle_fn( uint8_t const app, + uint8_t const verb, + uint32_t const len); + +// define the jtag xscale app's app_t +app_t const jtagxscale_app = { + + /* app number */ + JTAGXSCALE, + + /* handle fn */ + jtag_xscale_handle_fn, + + /* name */ + "JTAG XScale", + + /* desc */ + "\tThe JTAG Xscale app extends the JTAG app adding support\n" + "\tfor JTAG'ing Intel XScale devices.\n" +}; + + +/* From the Intel XScale Core Developer's Manual: + * + * The Intel XScale® core provides test features compatible with IEEE Standard + * Test Access Port and Boundary Scan Architecture (IEEE Std. 1149.1). These + * features include a TAP controller, a 5 or 7 bit instruction register, and + * test data registers to support software debug. The size of the instruction + * register depends on which variant of the Intel XScale® core is being used. + * This can be found out by examining the CoreGen field of Coprocessor 15, ID + * Register (bits 15:13). (See Table 7-4, "ID Register" on page 7-81 for more + * details.) A CoreGen value of 0x1 means the JTAG instruction register size + * is 5 bits and a CoreGen value of 0x2 means the JTAG instruction register + * size is 7 bits. + * + */ + +/* NOTE: I heavily cribbed from the ARM7TDMI jtag implementation. Credit where + * credit is due. */ + +/* this handles shifting arbitrary length bit strings into the instruction + * register and clocking out bits while leaving the JTAG state machine in a + * known state. it also handle bit swapping. */ +unsigned long jtag_xscale_shift_n(unsigned long word, + unsigned char nbits, + unsigned char flags) +{ + unsigned int bit; + unsigned long high = 1; + unsigned long mask; + + for (bit = (nbits - 1) / 8; bit > 0; bit--) + high <<= 8; + + high <<= ((nbits - 1) % 8); + + mask = high - 1; + + if (flags & LSB) + { + /* clock the bits into the IR from LSB to MSB order */ + for (bit = nbits; bit > 0; bit--) + { + /* write MOSI on trailing edge of previous clock */ + if (word & 1) + { + SETMOSI; + } + else + { + CLRMOSI; + } + word >>= 1; + + if (bit == 1 && !(flags & NOEND)) + SETTMS; /* TMS high on last bit to exit. */ + + /* tick tock the clock line */ + XTT; + + /* read MISO on trailing edge */ + if (READMISO) + { + word += (high); + } + } + } + else + { + /* clock the bits into the IR from MSB to LSB order */ + for (bit = nbits; bit > 0; bit--) + { + /* write MOSI on trailing edge of previous clock */ + if (word & high) + { + SETMOSI; + } + else + { + CLRMOSI; + } + word = (word & mask) << 1; + + if (bit == 1 && !(flags & NOEND)) + SETTMS;//TMS high on last bit to exit. + + /* tick tock the clock line */ + XTT; + + /* read MISO on trailing edge */ + word |= (READMISO); + } + } + + SETMOSI; + + if (!(flags & NOEND)) + { + /* exit state */ + XTT; + + /* update state */ + if (!(flags & NORETIDLE)) + { + CLRTMS; + XTT; + } + } + + return word; +} + + +/* this handles shifting in the IDCODE instruction and shifting the result + * out the TDO and return it. */ +unsigned long jtag_xscale_idcode() +{ + /* NOTE: this assumes that we're in the run-test-idle state */ + + /* get into the shift-ir state */ + SHIFT_IR; + + /* shift the ID code instruction into the IR and return to run-test-idle */ + jtag_xscale_shift_n(XSCALE_IR_IDCODE, 5, LSB); + + /* get into the shift-dr state */ + SHIFT_DR; + + /* now clock out the 32 bit ID code and return back to run-test-idle */ + return jtag_xscale_shift_n(0, 32, LSB); +} + +/* Handles XScale JTAG commands. Forwards others to JTAG. */ +void jtag_xscale_handle_fn( uint8_t const app, + uint8_t const verb, + uint32_t const len) { switch(verb) { + /* + * Standard Commands + */ + case SETUP: + + /* set up the pin I/O for JTAG */ + jtagsetup(); + + /* reset to run-test-idle state */ + RUN_TEST_IDLE; + + /* send back OK */ + txdata(app, OK, 0); + + break; + case START: case STOP: case PEEK: case POKE: + case READ: + case WRITE: default: - jtaghandle(app,verb,len); + + /* send back OK */ + txdata(app, OK, 0); + + break; + + /* + * XScale Commands + */ + case XSCALE_GET_CHIP_ID: + + /* reset to run-test-idle state */ + RUN_TEST_IDLE; + + /* put the ID code in the data buffer */ + cmddatalong[0] = jtag_xscale_idcode(); + + /* send it back to the client */ + txdata(app,verb,4); + + break; } }