drivers: spi: Add optional delays to mcux flexcomm spi driver

Adds optional device tree properties to insert delays between spi chip
select assert/deassert and the clock edges, and also between spi
frames and transfers to the mcux flexcomm spi driver. If the properties
are not set, no additional delay is inserted.

Verified expected behavior on mimxrt685_evk and check with a scope
that the pre- and post-delay could be changed from the device tree
properties.

Signed-off-by: Bryce Wilkins <bryce.wilkins@gmail.com>
This commit is contained in:
Bryce Wilkins 2021-12-02 00:13:00 -08:00 committed by Maureen Helm
commit 219bf88fe8
2 changed files with 62 additions and 0 deletions

View file

@ -15,6 +15,7 @@
#ifdef CONFIG_SPI_MCUX_FLEXCOMM_DMA
#include <drivers/dma.h>
#endif
#include <sys_clock.h>
LOG_MODULE_REGISTER(spi_mcux_flexcomm, CONFIG_SPI_LOG_LEVEL);
@ -28,6 +29,10 @@ struct spi_mcux_config {
const struct device *clock_dev;
clock_control_subsys_t clock_subsys;
void (*irq_config_func)(const struct device *dev);
uint32_t pre_delay;
uint32_t post_delay;
uint32_t frame_delay;
uint32_t transfer_delay;
};
#ifdef CONFIG_SPI_MCUX_FLEXCOMM_DMA
@ -143,6 +148,18 @@ static void spi_mcux_transfer_callback(SPI_Type *base,
spi_mcux_transfer_next_packet(data->dev);
}
static uint8_t spi_clock_cycles(uint32_t delay_ns, uint32_t sck_frequency_hz)
{
/* Convert delay_ns to an integer number of clock cycles of frequency
* sck_frequency_hz. The maximum delay is 15 clock cycles.
*/
uint8_t delay_cycles = (uint64_t)delay_ns * sck_frequency_hz / NSEC_PER_SEC;
delay_cycles = MIN(delay_cycles, 15);
return delay_cycles;
}
static int spi_mcux_configure(const struct device *dev,
const struct spi_config *spi_cfg)
{
@ -211,6 +228,17 @@ static int spi_mcux_configure(const struct device *dev,
master_config.baudRate_Bps = spi_cfg->frequency;
spi_delay_config_t *delayConfig = &master_config.delayConfig;
delayConfig->preDelay = spi_clock_cycles(config->pre_delay,
spi_cfg->frequency);
delayConfig->postDelay = spi_clock_cycles(config->post_delay,
spi_cfg->frequency);
delayConfig->frameDelay = spi_clock_cycles(config->frame_delay,
spi_cfg->frequency);
delayConfig->transferDelay = spi_clock_cycles(config->transfer_delay,
spi_cfg->frequency);
SPI_MasterInit(base, &master_config, clock_freq);
SPI_MasterTransferCreateHandle(base, &data->handle,
@ -769,6 +797,10 @@ static void spi_mcux_config_func_##id(const struct device *dev) \
.clock_subsys = \
(clock_control_subsys_t)DT_INST_CLOCKS_CELL(id, name),\
SPI_MCUX_FLEXCOMM_IRQ_HANDLER_FUNC(id) \
.pre_delay = DT_INST_PROP_OR(id, pre_delay, 0), \
.post_delay = DT_INST_PROP_OR(id, post_delay, 0), \
.frame_delay = DT_INST_PROP_OR(id, frame_delay, 0), \
.transfer_delay = DT_INST_PROP_OR(id, transfer_delay, 0), \
}; \
static struct spi_mcux_data spi_mcux_data_##id = { \
SPI_CONTEXT_INIT_LOCK(spi_mcux_data_##id, ctx), \

View file

@ -6,3 +6,33 @@ description: NXP LPC SPI controller
compatible: "nxp,lpc-spi"
include: [spi-controller.yaml, "nxp,lpc-flexcomm.yaml"]
properties:
pre-delay:
type: int
required: false
description: |
Delay in nanoseconds inserted between chip select assert to the first
clock edge. If not set, no additional delay is inserted.
post-delay:
type: int
required: false
description: |
Delay in nanoseconds inserted between the last clock edge to the chip
select deassert. If not set, no additional delay is inserted.
frame-delay:
type: int
required: false
description: |
Delay in nanoseconds inserted between data frames when chip select is
asserted and the EOF flag is set. If not set, no additional delay is
inserted.
transfer-delay:
type: int
required: false
description: |
Delay in nanoseconds inserted between transfers when chip select is
deasserted. If not set, no additional delay is inserted.