drivers: spi: Add optional delays to mcux dspi and lpspi drivers

Adds optional device tree properties to set delays between spi chip
select assert/deassert and clock edges in the mcux dspi and lpspi
drivers. If these properties are not set, then the minimum supported
delays are used.

Verified that tests/drivers/spi/spi_loopback/ still passes on
mimxrt1050_evk (lpspi driver) and frdm_k64f (dspi driver).

Measured with a scope that the pcs-sck-delay and sck-pcs-delay times on
the first spi transaction in the test are reduced from 7.82 us to 20 ns
on mimxrt1050_evk.

Signed-off-by: Maureen Helm <maureen.helm@nxp.com>
This commit is contained in:
Maureen Helm 2020-06-27 10:22:03 -05:00 committed by Anas Nashif
commit 10c1ded452
4 changed files with 81 additions and 5 deletions

View file

@ -23,6 +23,9 @@ struct spi_mcux_config {
char *clock_name;
clock_control_subsys_t clock_subsys;
void (*irq_config_func)(struct device *dev);
uint32_t pcs_sck_delay;
uint32_t sck_pcs_delay;
uint32_t transfer_delay;
};
struct spi_mcux_data {
@ -133,6 +136,8 @@ static int spi_mcux_configure(struct device *dev,
uint32_t clock_freq;
uint32_t word_size;
dspi_master_ctar_config_t *ctar_config = &master_config.ctarConfig;
if (spi_context_configured(&data->ctx, spi_cfg)) {
/* This configuration is already in use */
return 0;
@ -153,24 +158,28 @@ static int spi_mcux_configure(struct device *dev,
return -EINVAL;
}
master_config.ctarConfig.bitsPerFrame = word_size;
ctar_config->bitsPerFrame = word_size;
master_config.ctarConfig.cpol =
ctar_config->cpol =
(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL)
? kDSPI_ClockPolarityActiveLow
: kDSPI_ClockPolarityActiveHigh;
master_config.ctarConfig.cpha =
ctar_config->cpha =
(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA)
? kDSPI_ClockPhaseSecondEdge
: kDSPI_ClockPhaseFirstEdge;
master_config.ctarConfig.direction =
ctar_config->direction =
(spi_cfg->operation & SPI_TRANSFER_LSB)
? kDSPI_LsbFirst
: kDSPI_MsbFirst;
master_config.ctarConfig.baudRate = spi_cfg->frequency;
ctar_config->baudRate = spi_cfg->frequency;
ctar_config->pcsToSckDelayInNanoSec = config->pcs_sck_delay;
ctar_config->lastSckToPcsDelayInNanoSec = config->sck_pcs_delay;
ctar_config->betweenTransferDelayInNanoSec = config->transfer_delay;
clock_dev = device_get_binding(config->clock_name);
if (clock_dev == NULL) {
@ -285,6 +294,15 @@ static const struct spi_driver_api spi_mcux_driver_api = {
.clock_subsys = \
(clock_control_subsys_t)DT_INST_CLOCKS_CELL(id, name), \
.irq_config_func = spi_mcux_config_func_##id, \
.pcs_sck_delay = UTIL_AND( \
DT_INST_NODE_HAS_PROP(id, pcs_sck_delay), \
DT_INST_PROP(id, pcs_sck_delay)), \
.sck_pcs_delay = UTIL_AND( \
DT_INST_NODE_HAS_PROP(id, sck_pcs_delay), \
DT_INST_PROP(id, sck_pcs_delay)), \
.transfer_delay = UTIL_AND( \
DT_INST_NODE_HAS_PROP(id, transfer_delay), \
DT_INST_PROP(id, transfer_delay)), \
}; \
static struct spi_mcux_data spi_mcux_data_##id = { \
SPI_CONTEXT_INIT_LOCK(spi_mcux_data_##id, ctx), \

View file

@ -25,6 +25,9 @@ struct spi_mcux_config {
char *clock_name;
clock_control_subsys_t clock_subsys;
void (*irq_config_func)(struct device *dev);
uint32_t pcs_sck_delay;
uint32_t sck_pcs_delay;
uint32_t transfer_delay;
};
struct spi_mcux_data {
@ -173,6 +176,10 @@ static int spi_mcux_configure(struct device *dev,
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;
clock_dev = device_get_binding(config->clock_name);
if (clock_dev == NULL) {
return -EINVAL;
@ -284,6 +291,15 @@ static const struct spi_driver_api spi_mcux_driver_api = {
.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)), \
}; \
\
static struct spi_mcux_data spi_mcux_data_##n = { \

View file

@ -16,3 +16,24 @@ properties:
clocks:
required: true
pcs-sck-delay:
type: int
required: false
description: |
Delay in nanoseconds from the chip select assert to the first clock
edge. If not set, the minimum supported delay is used.
sck-pcs-delay:
type: int
required: false
description: |
Delay in nanoseconds from the last clock edge to the chip select
deassert. If not set, the minimum supported delay is used.
transfer-delay:
type: int
required: false
description: |
Delay in nanoseconds from the chip select deassert to the next chip
select assert. If not set, the minimum supported delay is used.

View file

@ -16,3 +16,24 @@ properties:
clocks:
required: true
pcs-sck-delay:
type: int
required: false
description: |
Delay in nanoseconds from the chip select assert to the first clock
edge. If not set, the minimum supported delay is used.
sck-pcs-delay:
type: int
required: false
description: |
Delay in nanoseconds from the last clock edge to the chip select
deassert. If not set, the minimum supported delay is used.
transfer-delay:
type: int
required: false
description: |
Delay in nanoseconds from the chip select deassert to the next chip
select assert. If not set, the minimum supported delay is used.