Skip to content

Commit 197f817

Browse files
committed
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 6843240 commit 197f817

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
@@ -327,6 +327,15 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
327327
struct fpga_ice40_data *data = dev->data;
328328
uint8_t clock_buf[(UINT8_MAX + 1) / BITS_PER_BYTE];
329329
const struct fpga_ice40_config *config = dev->config;
330+
struct spi_dt_spec bus;
331+
332+
memcpy(&bus, &config->bus, sizeof(bus));
333+
/*
334+
* Disable the automatism for chip select within the SPI driver,
335+
* as the configuration sequence requires this signal to be inactive
336+
* during the leading and trailing clock phase.
337+
*/
338+
bus.config.cs.gpio.port = NULL;
330339

331340
/* crc check */
332341
crc = crc32_ieee((uint8_t *)image_ptr, img_size);
@@ -391,7 +400,7 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
391400
LOG_DBG("Send %u clocks", config->leading_clocks);
392401
tx_buf.buf = clock_buf;
393402
tx_buf.len = DIV_ROUND_UP(config->leading_clocks, BITS_PER_BYTE);
394-
ret = spi_write_dt(&config->bus, &tx_bufs);
403+
ret = spi_write_dt(&bus, &tx_bufs);
395404
if (ret < 0) {
396405
LOG_ERR("Failed to send leading %u clocks: %d", config->leading_clocks, ret);
397406
goto unlock;
@@ -407,7 +416,7 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
407416
LOG_DBG("Send bin file");
408417
tx_buf.buf = image_ptr;
409418
tx_buf.len = img_size;
410-
ret = spi_write_dt(&config->bus, &tx_bufs);
419+
ret = spi_write_dt(&bus, &tx_bufs);
411420
if (ret < 0) {
412421
LOG_ERR("Failed to send bin file: %d", ret);
413422
goto unlock;
@@ -423,7 +432,7 @@ static int fpga_ice40_load_spi(const struct device *dev, uint32_t *image_ptr, ui
423432
LOG_DBG("Send %u clocks", config->trailing_clocks);
424433
tx_buf.buf = clock_buf;
425434
tx_buf.len = DIV_ROUND_UP(config->trailing_clocks, BITS_PER_BYTE);
426-
ret = spi_write_dt(&config->bus, &tx_bufs);
435+
ret = spi_write_dt(&bus, &tx_bufs);
427436
if (ret < 0) {
428437
LOG_ERR("Failed to send trailing %u clocks: %d", config->trailing_clocks, ret);
429438
goto unlock;
@@ -594,7 +603,10 @@ static int fpga_ice40_init(const struct device *dev)
594603
static struct fpga_ice40_data fpga_ice40_data_##inst; \
595604
\
596605
static const struct fpga_ice40_config fpga_ice40_config_##inst = { \
597-
.bus = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0), \
606+
.bus = SPI_DT_SPEC_INST_GET(inst, \
607+
SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | \
608+
SPI_WORD_SET(8) | SPI_TRANSFER_MSB, \
609+
0), \
598610
.creset = GPIO_DT_SPEC_INST_GET(inst, creset_gpios), \
599611
.cdone = GPIO_DT_SPEC_INST_GET(inst, cdone_gpios), \
600612
.clk = GPIO_DT_SPEC_INST_GET_OR(inst, clk_gpios, {0}), \

0 commit comments

Comments
 (0)