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 <danselmi@gmx.ch>
Reviewed-on: https://review.openocd.org/c/openocd/+/7825
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Daniel Anselmi 2022-12-17 13:11:30 +01:00 committed by Antonio Borneo
parent 536f2a9f2a
commit 302027094b
4 changed files with 90 additions and 0 deletions

View File

@ -231,3 +231,76 @@ int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattic
return lattice_certus_exit_programming_mode(tap); 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;
}

View File

@ -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_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_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_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 */ #endif /* OPENOCD_PLD_CERTUS_H */

View File

@ -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); return lattice_ecp2_3_connect_spi_to_jtag(pld_device_info);
else if (pld_device_info->family == LATTICE_ECP5) else if (pld_device_info->family == LATTICE_ECP5)
return lattice_ecp5_connect_spi_to_jtag(pld_device_info); 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; 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); return lattice_ecp2_3_disconnect_spi_from_jtag(pld_device_info);
else if (pld_device_info->family == LATTICE_ECP5) else if (pld_device_info->family == LATTICE_ECP5)
return lattice_ecp5_disconnect_spi_from_jtag(pld_device_info); 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; 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); return lattice_ecp2_3_get_facing_read_bits(pld_device_info, facing_read_bits);
else if (pld_device_info->family == LATTICE_ECP5) else if (pld_device_info->family == LATTICE_ECP5)
return lattice_ecp5_get_facing_read_bits(pld_device_info, facing_read_bits); 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; return ERROR_FAIL;
} }

View File

@ -12,3 +12,11 @@ transport select jtag
adapter speed 10000 adapter speed 10000
source [find fpga/lattice_certuspro.cfg] 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