123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- #define MODULE "fpga"
- #include "common.h"
- #include "pins.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)
- 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 */
- return fpga_finish(err);
- }
|