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 97ebab609d5d..2566ee5cbc95 100644 --- a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c +++ b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c @@ -108,9 +108,20 @@ int spi_mcux_configure(const struct device *dev, const struct spi_config *spi_cf master_config.direction = (spi_cfg->operation & SPI_TRANSFER_LSB) ? kLPSPI_LsbFirst : kLPSPI_MsbFirst; master_config.baudRate = spi_cfg->frequency; - master_config.pcsToSckDelayInNanoSec = config->pcs_sck_delay; - master_config.lastSckToPcsDelayInNanoSec = config->sck_pcs_delay; - master_config.betweenTransferDelayInNanoSec = config->transfer_delay; + + /* TODO: deprecate the DT delay props */ + master_config.pcsToSckDelayInNanoSec = config->pcs_sck_delay ? + config->pcs_sck_delay : spi_cfg->cs.pcs_to_sck_delay_ns; + master_config.lastSckToPcsDelayInNanoSec = config->sck_pcs_delay ? + config->sck_pcs_delay : spi_cfg->cs.sck_to_pcs_delay_ns; + if (config->transfer_delay > 0) { + master_config.betweenTransferDelayInNanoSec = config->transfer_delay; + } else if (spi_cfg->dfs_delay_ns > 0) { + master_config.betweenTransferDelayInNanoSec = spi_cfg->dfs_delay_ns; + } else { + master_config.betweenTransferDelayInNanoSec = (1000000000 / spi_cfg->frequency) / 2; + } + master_config.whichPcs = spi_cfg->slave + kLPSPI_Pcs0; master_config.pcsActiveHighOrLow = (spi_cfg->operation & SPI_CS_ACTIVE_HIGH) ? kLPSPI_PcsActiveHigh : kLPSPI_PcsActiveLow; 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 e02db078028f..8fc6afc066b5 100644 --- a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_priv.h +++ b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_priv.h @@ -99,12 +99,10 @@ void lpspi_wait_tx_fifo_empty(const struct device *dev); .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ .irq_config_func = spi_mcux_config_func_##n, \ - .pcs_sck_delay = UTIL_AND(DT_INST_NODE_HAS_PROP(n, pcs_sck_delay), \ - DT_INST_PROP(n, pcs_sck_delay)), \ - .sck_pcs_delay = UTIL_AND(DT_INST_NODE_HAS_PROP(n, sck_pcs_delay), \ - DT_INST_PROP(n, sck_pcs_delay)), \ - .transfer_delay = UTIL_AND(DT_INST_NODE_HAS_PROP(n, transfer_delay), \ - DT_INST_PROP(n, transfer_delay)), \ + /* TODO: deprecate the DT delay props */ \ + .pcs_sck_delay = DT_INST_PROP_OR(n, pcs_sck_delay, 0), \ + .sck_pcs_delay = DT_INST_PROP_OR(n, sck_pcs_delay, 0), \ + .transfer_delay = DT_INST_PROP_OR(n, transfer_delay, 0), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .data_pin_config = DT_INST_ENUM_IDX(n, data_pin_config), \ .output_config = DT_INST_PROP(n, tristate_output), \ diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index ba11b5e73c61..b84dc6cc4990 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -152,24 +152,49 @@ extern "C" { /** * @brief SPI Chip Select control structure * - * This can be used to control a CS line via a GPIO line, instead of - * using the controller inner CS logic. + * This describes how the SPI CS line should be controlled, including whether + * to use GPIO or native hardware CS, and timing parameters. * */ struct spi_cs_control { /** * GPIO devicetree specification of CS GPIO. - * The device pointer can be set to NULL to fully inhibit CS control if - * necessary. The GPIO flags GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be + * + * If set to NULL, hardware driver can attempt to natively control CS + * automatically if it has that capability and the correct pinmux has + * been applied. Otherwise, NULL will inhibit CS control. + * + * The GPIO flags GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be * equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct * spi_config. */ struct gpio_dt_spec gpio; + /** - * Delay in microseconds to wait before starting the - * transmission and before releasing the CS line. + * Timing configuration. + * For GPIO CS, delay is microseconds to wait before starting + * transmission and releasing CS. + * For hardware CS, pcs_to_sck_delay_ns and sck_to_pcs_delay_ns + * control assertion/deassertion timing. */ - uint32_t delay; + union { + /** + * In the case of GPIO CS, this is delay in microseconds to wait + * before starting the transmission and before releasing the CS line. + */ + uint32_t delay; + + struct { + /** @brief Delay from PCS assertion to first SCK edge in nanoseconds. + * If set to 0, hardware default will be used. + */ + uint8_t pcs_to_sck_delay_ns; + /** @brief Delay from last SCK edge to PCS deassertion in nanoseconds. + * If set to 0, hardware default will be used. + */ + uint8_t sck_to_pcs_delay_ns; + }; + }; }; /** @@ -329,8 +354,10 @@ struct spi_config { * if not used). */ struct spi_cs_control cs; -}; + /** @brief Delay between data frames in nanoseconds (0 means 50% of frequency) */ + uint16_t dfs_delay_ns; +}; /** * @brief Structure initializer for spi_config from devicetree *