Skip to content

Commit b0a1ddd

Browse files
benediktibknashif
authored andcommitted
drivers: fpga: fix waveform for iCE40 configuration in SPI mode
The datasheet of the iCE40 specifies that there should be a leading and trailing clocks phase during its configuration with SPI. Due to the limitations of the SPI interface, and probably also due to a lock of support for such a feature for instance in the STM32 SPI peripheral, this is achieved with additional SPI transfers before and after the actual image. Unfortunately, this by default also affects the slave select GPIO, which has to stay high during these phases. This fixes this behaviour via not passing the slave select GPIO to the SPI driver and manipulating this GPIO manually. Signed-off-by: Benedikt Schmidt <[email protected]>
1 parent 21d0a3b commit b0a1ddd

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

drivers/fpga/fpga_ice40.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,15 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
317317
struct fpga_ice40_data *data = dev->data;
318318
uint8_t clock_buf[(UINT8_MAX + 1) / BITS_PER_BYTE];
319319
const struct fpga_ice40_config *config = dev->config;
320+
struct spi_dt_spec bus;
321+
322+
memcpy(&bus, &config->bus, sizeof(bus));
323+
/*
324+
* Disable the automatism for chip select within the SPI driver,
325+
* as the configuration sequence requires this signal to be inactive
326+
* during the leading and trailing clock phase.
327+
*/
328+
bus.config.cs.gpio.port = NULL;
320329

321330
/* crc check */
322331
crc = crc32_ieee((uint8_t *)image_ptr, img_size);
@@ -381,7 +390,7 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
381390
LOG_DBG("Send %u clocks", config->leading_clocks);
382391
tx_buf.buf = clock_buf;
383392
tx_buf.len = DIV_ROUND_UP(config->leading_clocks, BITS_PER_BYTE);
384-
ret = spi_write_dt(&config->bus, &tx_bufs);
393+
ret = spi_write_dt(&bus, &tx_bufs);
385394
if (ret < 0) {
386395
LOG_ERR("Failed to send leading %u clocks: %d", config->leading_clocks, ret);
387396
goto unlock;
@@ -397,7 +406,7 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
397406
LOG_DBG("Send bin file");
398407
tx_buf.buf = image_ptr;
399408
tx_buf.len = img_size;
400-
ret = spi_write_dt(&config->bus, &tx_bufs);
409+
ret = spi_write_dt(&bus, &tx_bufs);
401410
if (ret < 0) {
402411
LOG_ERR("Failed to send bin file: %d", ret);
403412
goto unlock;
@@ -413,7 +422,7 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
413422
LOG_DBG("Send %u clocks", config->trailing_clocks);
414423
tx_buf.buf = clock_buf;
415424
tx_buf.len = DIV_ROUND_UP(config->trailing_clocks, BITS_PER_BYTE);
416-
ret = spi_write_dt(&config->bus, &tx_bufs);
425+
ret = spi_write_dt(&bus, &tx_bufs);
417426
if (ret < 0) {
418427
LOG_ERR("Failed to send trailing %u clocks: %d", config->trailing_clocks, ret);
419428
goto unlock;
@@ -596,7 +605,10 @@ static int fpga_ice40_init(const struct device *dev)
596605
static struct fpga_ice40_data fpga_ice40_data_##inst; \
597606
\
598607
static const struct fpga_ice40_config fpga_ice40_config_##inst = { \
599-
.bus = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0), \
608+
.bus = SPI_DT_SPEC_INST_GET(inst, \
609+
SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | \
610+
SPI_WORD_SET(8) | SPI_TRANSFER_MSB, \
611+
0), \
600612
.creset = GPIO_DT_SPEC_INST_GET(inst, creset_gpios), \
601613
.cdone = GPIO_DT_SPEC_INST_GET(inst, cdone_gpios), \
602614
.clk = GPIO_DT_SPEC_INST_GET_OR(inst, clk_gpios, {0}), \

0 commit comments

Comments
 (0)