diff --git a/drivers/spi/spi_nxp_lpspi/Kconfig b/drivers/spi/spi_nxp_lpspi/Kconfig index aabb4d51ce7..1d9ce8a770a 100644 --- a/drivers/spi/spi_nxp_lpspi/Kconfig +++ b/drivers/spi/spi_nxp_lpspi/Kconfig @@ -36,4 +36,17 @@ config SPI_MCUX_LPSPI_CPU This has lower latency than DMA-based driver but over the longer transfers will likely have less bandwidth and use more CPU time. +config SPI_NXP_LPSPI_TXFIFO_WAIT_CYCLES + int "Number of CPU cycles to wait on TX fifo empty" + default 0 if DEBUG + default 10000 + help + This option most likely does not need changed. + The drivers tend to need to wait on confirming the transmit command + is consumed by the hardware by checking of the TX fifo is emptied. + This option gives a maximum number of CPU cycles to wait on that check. + The special value of 0 means infinite, which can be useful for debugging + for if there is some programming error that causes TX fifo not to empty. + The default of 10000 is arbitrary. + endif # SPI_MCUX_LPSPI diff --git a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi.c b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi.c index bedf112f9c6..8f37d90164d 100644 --- a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi.c +++ b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi.c @@ -337,7 +337,10 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg base->TCR |= LPSPI_TCR_CONT_MASK; } /* tcr is written to tx fifo */ - lpspi_wait_tx_fifo_empty(dev); + ret = lpspi_wait_tx_fifo_empty(dev); + if (ret) { + return ret; + } /* start the transfer sequence which are handled by irqs */ lpspi_next_tx_fill(dev); diff --git a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c index 078a619d2f9..53df267c4ed 100644 --- a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c +++ b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c @@ -60,12 +60,24 @@ static inline clock_ip_name_t lpspi_get_clock(LPSPI_Type *const base) } #endif -void lpspi_wait_tx_fifo_empty(const struct device *dev) +int lpspi_wait_tx_fifo_empty(const struct device *dev) { LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); + int arbitrary_cycle_limit = CONFIG_SPI_NXP_LPSPI_TXFIFO_WAIT_CYCLES; + bool limit_wait = arbitrary_cycle_limit > 0; - while (LPSPI_GetTxFifoCount(base) != 0) { + while (FIELD_GET(LPSPI_FSR_TXCOUNT_MASK, base->FSR) != 0) { + if (!limit_wait) { + continue; + } + + if (arbitrary_cycle_limit-- < 0) { + LOG_WRN("Failed waiting for TX fifo empty"); + return -EIO; + } } + + return 0; } int spi_lpspi_release(const struct device *dev, const struct spi_config *spi_cfg) @@ -185,7 +197,7 @@ int spi_mcux_configure(const struct device *dev, const struct spi_config *spi_cf base->CR |= LPSPI_CR_DBGEN_MASK; } - return 0; + return lpspi_wait_tx_fifo_empty(dev); } static void lpspi_module_system_init(LPSPI_Type *base) diff --git a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_priv.h b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_priv.h index ec985367a02..58e72f105e3 100644 --- a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_priv.h +++ b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_priv.h @@ -68,7 +68,7 @@ int spi_nxp_init_common(const struct device *dev); /* common api function for now */ int spi_lpspi_release(const struct device *dev, const struct spi_config *spi_cfg); -void lpspi_wait_tx_fifo_empty(const struct device *dev); +int lpspi_wait_tx_fifo_empty(const struct device *dev); #define SPI_LPSPI_IRQ_FUNC_LP_FLEXCOMM(n) \ nxp_lp_flexcomm_setirqhandler(DEVICE_DT_GET(DT_INST_PARENT(n)), DEVICE_DT_INST_GET(n), \