From 302027094bfa9f331f5de2d25ecea01bac68a58a Mon Sep 17 00:00:00 2001 From: Daniel Anselmi Date: Sat, 17 Dec 2022 13:11:30 +0100 Subject: [PATCH] jtagspi/pld: add support from lattice certus driver Provide jtagspi with specific procedures to be able to use jtagspi for programming spi-flash devices on lattice certus and certus po devices. Change-Id: I6a8ec16be78f86073a4ef5302f6241185b08e1c6 Signed-off-by: Daniel Anselmi Reviewed-on: https://review.openocd.org/c/openocd/+/7825 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/pld/certus.c | 73 ++++++++++++++++++++++++++++++ src/pld/certus.h | 3 ++ src/pld/lattice.c | 6 +++ tcl/board/certuspro_evaluation.cfg | 8 ++++ 4 files changed, 90 insertions(+) diff --git a/src/pld/certus.c b/src/pld/certus.c index 1309c1b27d..8bfdff4952 100644 --- a/src/pld/certus.c +++ b/src/pld/certus.c @@ -231,3 +231,76 @@ int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattic return lattice_certus_exit_programming_mode(tap); } + +int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == PROGRAM_SPI) + return ERROR_OK; + + // erase configuration + int retval = lattice_preload(pld_device_info); + if (retval != ERROR_OK) + return retval; + + retval = lattice_certus_enable_programming(tap); + if (retval != ERROR_OK) + return retval; + + retval = lattice_certus_erase_device(pld_device_info); + if (retval != ERROR_OK) { + LOG_ERROR("erasing device failed"); + return retval; + } + + retval = lattice_certus_exit_programming_mode(tap); + if (retval != ERROR_OK) + return retval; + + // connect jtag to spi pins + retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + struct scan_field field; + uint8_t buffer[2] = {0xfe, 0x68}; + field.num_bits = 16; + field.out_value = buffer; + field.in_value = NULL; + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); + + return jtag_execute_queue(); +} + +int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info) +{ + if (!pld_device_info) + return ERROR_FAIL; + + struct jtag_tap *tap = pld_device_info->tap; + if (!tap) + return ERROR_FAIL; + + /* Connecting it again takes way too long to do it multiple times for writing + a bitstream (ca. 0.4s each access). + We just leave it connected since SCS will not be active when not in shift_dr state. + So there is no need to change instruction, just make sure we are not in shift dr state. */ + jtag_add_runtest(2, TAP_IDLE); + return jtag_execute_queue(); +} + +int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits) +{ + if (!pld_device_info) + return ERROR_FAIL; + + *facing_read_bits = 0; + + return ERROR_OK; +} diff --git a/src/pld/certus.h b/src/pld/certus.h index 51defc5ca2..d21ad61d20 100644 --- a/src/pld/certus.h +++ b/src/pld/certus.h @@ -14,5 +14,8 @@ int lattice_certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out); int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode); int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file); +int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info); +int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info); +int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits); #endif /* OPENOCD_PLD_CERTUS_H */ diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 14dbf2ae71..4858603a86 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -357,6 +357,8 @@ static int lattice_connect_spi_to_jtag(struct pld_device *pld_device) return lattice_ecp2_3_connect_spi_to_jtag(pld_device_info); else if (pld_device_info->family == LATTICE_ECP5) return lattice_ecp5_connect_spi_to_jtag(pld_device_info); + else if (pld_device_info->family == LATTICE_CERTUS) + return lattice_certus_connect_spi_to_jtag(pld_device_info); return ERROR_FAIL; } @@ -376,6 +378,8 @@ static int lattice_disconnect_spi_from_jtag(struct pld_device *pld_device) return lattice_ecp2_3_disconnect_spi_from_jtag(pld_device_info); else if (pld_device_info->family == LATTICE_ECP5) return lattice_ecp5_disconnect_spi_from_jtag(pld_device_info); + else if (pld_device_info->family == LATTICE_CERTUS) + return lattice_certus_disconnect_spi_from_jtag(pld_device_info); return ERROR_FAIL; } @@ -396,6 +400,8 @@ static int lattice_get_stuff_bits(struct pld_device *pld_device, unsigned int *f return lattice_ecp2_3_get_facing_read_bits(pld_device_info, facing_read_bits); else if (pld_device_info->family == LATTICE_ECP5) return lattice_ecp5_get_facing_read_bits(pld_device_info, facing_read_bits); + else if (pld_device_info->family == LATTICE_CERTUS) + return lattice_certus_get_facing_read_bits(pld_device_info, facing_read_bits); return ERROR_FAIL; } diff --git a/tcl/board/certuspro_evaluation.cfg b/tcl/board/certuspro_evaluation.cfg index 5ff2a1e329..ba2f17c221 100644 --- a/tcl/board/certuspro_evaluation.cfg +++ b/tcl/board/certuspro_evaluation.cfg @@ -12,3 +12,11 @@ transport select jtag adapter speed 10000 source [find fpga/lattice_certuspro.cfg] + +#openocd -f board/certuspro_evaluation.cfg -c "init" -c "pld load certuspro.pld shared_folder/certuspro_blinker_impl_1.bit" + +set JTAGSPI_CHAIN_ID certuspro.pld +source [find cpld/jtagspi.cfg] + +#jtagspi_init certuspro.pld "" -1 +#jtagspi_program shared_folder/certuspro_blinker_impl1.bit 0 -- 2.30.2