#define MODULE "fpga" #include "common.h" #include "jtag.h" #include "fpga.h" #include "spz.h" /* * See: * https://github.com/RichardPlunkett/jrunner-beaglebone/blob/master/jb_jtag.c * and the Cyclone III (!) handbook, volume 1, table 9-20, page 9-63 */ enum JTAG_IR { JI_EXTEST = 0x000, JI_PULSE_NCONFIG = 0x001, JI_PROGRAM = 0x002, JI_STARTUP = 0x003, JI_CHECK_STATUS = 0x004, JI_SAMPLE = 0x005, JI_IDCODE = 0x006, JI_USERCODE = 0x007, JI_CONFIG_IO = 0x00d, JI_CLAMP = 0x00a, JI_HIGHZ = 0x00b, JI_EXTEST2 = 0x00f, /* Stratix II, Cyclone II */ JI_KEY_CLR_VREG = 0x029, JI_KEY_PROG_VOL = 0x1ad, JI_EN_ACTIVE_CLK = 0x1ee, JI_FACTORY = 0x281, JI_ACTIVE_ENGAGE = 0x2b0, JI_ACTIVE_DISENGAGE = 0x2d0, JI_DIS_ACTIVE_CLK = 0x2ee, JI_BYPASS = 0x3ff }; #define FPGA_IR_LEN 10 /* Copied from the SVF file */ #define JTAG_FPGA_LEADIN_BITS (22*8) /* * The check status chain seems to match the I/O chain, with in order * {output, control, input}; the chain represents the pads in * *reverse* order with bits [2:0] corresponding to pad 363 (D3) and * [1079:1077] to pad 0; pads 33-36 are the JTAG pins and are not * included in the chain. */ #define JTAG_FPGA_CHECK_STATUS_BITS 1080 #define PAD_TO_BIT(p,b) (((359 - ((p) - 4*((p) > 36)))*3)+(b)) #define JTAG_FPGA_CONF_DONE_BIT PAD_TO_BIT(227, 1) #define JTAG_FPGA_HZ 6000000 #define JTAG_FPGA_MS ((JTAG_FPGA_HZ+999)/1000) #define JTAG_FPGA_US ((JTAG_FPGA_HZ+999999)/1000000) #define PIN_FPGA_TDI 16 #define PIN_FPGA_TDO 17 #define PIN_FPGA_TMS 14 #define PIN_FPGA_TCK 18 #define PIN_FPGA_nCE 26 static const struct jtag_config jtag_config_fpga = { .hz = JTAG_FPGA_HZ, .pin_tdi = PIN_FPGA_TDI, .pin_tdo = PIN_FPGA_TDO, .pin_tms = PIN_FPGA_TMS, .pin_tck = PIN_FPGA_TCK, .be = false }; static bool test_bit(const uint32_t *buf, unsigned int bit) { return (buf[bit >> 5] >> (bit & 31)) & 1; } static int fpga_finish(int err) { tap_goto_state(TAP_RUN_TEST_IDLE); /* Park IR at bypass, wait 1 ms */ tap_set_ir(JI_BYPASS, FPGA_IR_LEN); tap_run_test_idle(JTAG_FPGA_MS); /* Reset?! */ jtag_disable(NULL); return err; } static uint32_t tap_get_idcode(void) { uint32_t idcode; tap_set_ir(JI_IDCODE, FPGA_IR_LEN); tap_goto_state(TAP_SHIFT_DR); jtag_io(32, JIO_TMS, NULL, &idcode); tap_goto_state(TAP_RUN_TEST_IDLE); return idcode; } /* * See the Cyclone IV handbook, volume 1, table 8-17, page 8-59 * for the programming flow. */ int fpga_program_spz(spz_stream *spz) { int err = 0; uint32_t idcode; uint32_t check_status_buf[(JTAG_FPGA_CHECK_STATUS_BITS+31) >> 5]; /* Configure JTAG to access the FPGA */ jtag_enable(&jtag_config_fpga); int idcode_loops = 4; while (idcode_loops--) { idcode = tap_get_idcode(); if (idcode == spz->header.addr) break; MSG("invalid IDCODE %08X expected %08X, %s\n", idcode, spz->header.addr, idcode_loops ? "attempting reset..." : "giving up"); if (!idcode_loops) { MSG("check for JTAG cable connected, or power cycle board\n"); err = FWUPDATE_ERR_FPGA_MISMATCH; goto fail; } tap_reset(); jtag_delay(1000); tap_goto_state(TAP_SHIFT_DR); jtag_io(32, JIO_TMS, NULL, &idcode); MSG("IDCODE after reset %08X\n", idcode); } MSG("IDCODE %08X is valid\n", idcode); /* Disengage programming hardware if active */ tap_set_ir(JI_ACTIVE_DISENGAGE, FPGA_IR_LEN); tap_run_test_idle(16); tap_set_ir(JI_PROGRAM, FPGA_IR_LEN); tap_run_test_idle(16); jtag_delay(100); tap_run_test_idle(8192); /* Leadin: shift in a number of 1s */ tap_goto_state(TAP_SHIFT_DR); jtag_io(JTAG_FPGA_LEADIN_BITS, JIO_TDI, NULL, NULL); /* The actual data */ err = jtag_shift_spz(spz, 0); /* 32 bits of 0 terminates the transaction */ jtag_io(32, JIO_TMS, NULL, NULL); tap_goto_state(TAP_RUN_TEST_IDLE); /* Check status */ int check_status_loops = 10; while (1) { tap_set_ir(JI_CHECK_STATUS, FPGA_IR_LEN); tap_run_test_idle(5*JTAG_FPGA_US); tap_goto_state(TAP_SHIFT_DR); jtag_io(JTAG_FPGA_CHECK_STATUS_BITS, JIO_TMS, NULL, check_status_buf); tap_goto_state(TAP_RUN_TEST_IDLE); if (!test_bit(check_status_buf, JTAG_FPGA_CONF_DONE_BIT)) { check_status_loops--; MSG("not ready to start... %s\n", check_status_loops ? "waiting" : "giving up"); if (!check_status_loops) { err = FWUPDATE_ERR_FPGA_FAILED; goto fail; } jtag_delay(10000); /* 10 ms */ } else { MSG("ready to start\n"); break; } } /* Go to user mode */ tap_set_ir(JI_STARTUP, FPGA_IR_LEN); tap_run_test_idle((4096*JTAG_FPGA_MS)/1000+512); /* Common finish */ fail: return fpga_finish(err); } // // Board 2.1 has IO26 connected to nCE on the FPGA; this pin has // a pulldown but can be raised high by external JTAG. We don't // want the external pulldown to fight an internal pullup, but // also don't want the pin to float on the 1.0 and 2.0 board revisions // where it is NC. // // XXX: Actually try to detect board revision 2.1... // // YYY: IO26 is CS# för PSRAM! This is invalid usage... probably will need // a rework on the 2.1 board! // void fpga_enable_nce(void) { #if 0 pinMode(PIN_FPGA_nCE, INPUT_PULLDOWN); delayMicroseconds(100); /* Just in case */ #endif } int fpga_reset(void) { int err = 0; printf("[FPGA] Resetting FPGA via JTAG\n"); fpga_enable_nce(); jtag_enable(&jtag_config_fpga); tap_run_test_idle(JTAG_FPGA_MS); /* Make sure to enable loader (not supposed to be needed...) */ tap_set_ir(JI_ACTIVE_ENGAGE, FPGA_IR_LEN); tap_run_test_idle(16); /* Pulse nCONFIG via JTAG */ tap_set_ir(JI_PULSE_NCONFIG, FPGA_IR_LEN); tap_run_test_idle(JTAG_FPGA_MS); /* Common finish */ fail: return fpga_finish(err); }