Skip to content

NXP LPSPI: Convert to native zephyr driver, remove MCUX shim #85010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions drivers/clock_control/clock_control_mcux_ccm.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control);

#ifdef CONFIG_SPI_MCUX_LPSPI
#ifdef CONFIG_SPI_NXP_LPSPI
static const clock_name_t lpspi_clocks[] = {
kCLOCK_Usb1PllPfd1Clk,
kCLOCK_Usb1PllPfd0Clk,
Expand Down Expand Up @@ -207,7 +207,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
break;
#endif

#ifdef CONFIG_SPI_MCUX_LPSPI
#ifdef CONFIG_SPI_NXP_LPSPI
case IMX_CCM_LPSPI_CLK:
{
uint32_t lpspi_mux = CLOCK_GetMux(kCLOCK_LpspiMux);
Expand Down
4 changes: 2 additions & 2 deletions drivers/clock_control/clock_control_mcux_ccm_rev2.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
break;
#endif

#ifdef CONFIG_SPI_MCUX_LPSPI
#ifdef CONFIG_SPI_NXP_LPSPI
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
case IMX_CCM_LPSPI0102_CLK:
clock_root = kCLOCK_Root_Lpspi0102 + instance;
Expand All @@ -91,7 +91,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
clock_root = kCLOCK_Root_Lpspi1 + instance;
break;
#endif /* CONFIG_SOC_SERIES_IMXRT118X */
#endif /* CONFIG_SPI_MCUX_LPSPI */
#endif /* CONFIG_SPI_NXP_LPSPI */

#ifdef CONFIG_UART_MCUX_LPUART
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
Expand Down
8 changes: 4 additions & 4 deletions drivers/spi/spi_nxp_lpspi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright 2024 NXP
# Copyright 2024-2025 NXP

zephyr_library_sources_ifdef(CONFIG_SPI_MCUX_LPSPI spi_nxp_lpspi_common.c)
zephyr_library_sources_ifdef(CONFIG_SPI_MCUX_LPSPI_NORMAL spi_nxp_lpspi.c)
zephyr_library_sources_ifdef(CONFIG_SPI_MCUX_LPSPI_DMA spi_nxp_lpspi_dma.c)
zephyr_library_sources_ifdef(CONFIG_SPI_NXP_LPSPI spi_nxp_lpspi_common.c)
zephyr_library_sources_ifdef(CONFIG_SPI_NXP_LPSPI_CPU spi_nxp_lpspi.c)
zephyr_library_sources_ifdef(CONFIG_SPI_NXP_LPSPI_DMA spi_nxp_lpspi_dma.c)
18 changes: 9 additions & 9 deletions drivers/spi/spi_nxp_lpspi/Kconfig
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2018, 2024 NXP
# Copyright 2018, 2024-2025 NXP
# SPDX-License-Identifier: Apache-2.0

config SPI_MCUX_LPSPI
config SPI_NXP_LPSPI
bool "NXP LPSPI peripheral"
default y
depends on DT_HAS_NXP_LPSPI_ENABLED
Expand All @@ -10,21 +10,21 @@ config SPI_MCUX_LPSPI
help
Enable support for NXP LPSPI.

if SPI_MCUX_LPSPI
if SPI_NXP_LPSPI

config SPI_MCUX_LPSPI_DMA
bool "MCUX LPSPI SPI DMA Support"
config SPI_NXP_LPSPI_DMA
bool "NXP LPSPI SPI DMA Driver"
select DMA
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_NXP_LPSPI),dmas)
help
Enable the SPI DMA mode for SPI instances
that enable dma channels in their device tree node.

config SPI_MCUX_LPSPI_NORMAL
bool "NXP MCUX LPSPI driver"
config SPI_NXP_LPSPI_CPU
bool "NXP LPSPI CPU based driver"
default y
depends on $(dt_compat_any_not_has_prop,$(DT_COMPAT_NXP_LPSPI),dmas) || !SPI_MCUX_LPSPI_DMA
depends on $(dt_compat_any_not_has_prop,$(DT_COMPAT_NXP_LPSPI),dmas) || !SPI_NXP_LPSPI_DMA
help
Use the traditional (non-RTIO) SPI driver for NXP LPSPI.

endif # SPI_MCUX_LPSPI
endif # SPI_NXP_LPSPI
108 changes: 46 additions & 62 deletions drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#define DT_DRV_COMPAT nxp_lpspi

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(spi_mcux_lpspi, CONFIG_SPI_LOG_LEVEL);
LOG_MODULE_REGISTER(spi_nxp_lpspi, CONFIG_SPI_LOG_LEVEL);

#include "spi_nxp_lpspi_priv.h"

Expand All @@ -18,24 +18,16 @@ struct lpspi_driver_data {
uint8_t word_size_bytes;
};

static inline void lpspi_wait_tx_fifo_empty(const struct device *dev)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);

while (LPSPI_GetTxFifoCount(base) != 0) {
}
}

/* Reads a word from the RX fifo and handles writing it into the RX spi buf */
static inline void lpspi_rx_word_write_bytes(const struct device *dev, size_t offset)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;
uint8_t num_bytes = MIN(lpspi_data->word_size_bytes, ctx->rx_len);
uint8_t *buf = ctx->rx_buf + offset;
uint32_t word = LPSPI_ReadData(base);
uint32_t word = base->RDR;

if (!spi_context_rx_buf_on(ctx) && spi_context_rx_on(ctx)) {
/* receive no actual data if rx buf is NULL */
Expand All @@ -50,7 +42,7 @@ static inline void lpspi_rx_word_write_bytes(const struct device *dev, size_t of
/* Reads a maximum number of words from RX fifo and writes them to the remainder of the RX buf */
static inline size_t lpspi_rx_buf_write_words(const struct device *dev, uint8_t max_read)
{
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;
size_t buf_len = ctx->rx_len / lpspi_data->word_size_bytes;
Expand All @@ -68,21 +60,21 @@ static inline size_t lpspi_rx_buf_write_words(const struct device *dev, uint8_t

static inline uint8_t rx_fifo_cur_len(LPSPI_Type *base)
{
return (base->FSR & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT;
return FIELD_GET(LPSPI_FSR_RXCOUNT_MASK, base->FSR);
}

static inline void lpspi_handle_rx_irq(const struct device *dev)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;
uint8_t total_words_written = 0;
uint8_t total_words_read = 0;
uint8_t words_read;
uint8_t rx_fsr;

LPSPI_ClearStatusFlags(base, kLPSPI_RxDataReadyFlag);
base->SR = LPSPI_SR_RDF_MASK;

LOG_DBG("RX FIFO: %d, RX BUF: %p", rx_fsr, ctx->rx_buf);

Expand All @@ -96,14 +88,14 @@ static inline void lpspi_handle_rx_irq(const struct device *dev)
LOG_DBG("RX done %d words to spi buf", total_words_written);

if (!spi_context_rx_on(ctx)) {
LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
LPSPI_FlushFifo(base, false, true);
base->IER &= ~LPSPI_IER_RDIE_MASK;
base->CR |= LPSPI_CR_RRF_MASK; /* flush rx fifo */
}
}

static inline uint32_t lpspi_next_tx_word(const struct device *dev, int offset)
{
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;
const uint8_t *byte = ctx->tx_buf + offset;
Expand All @@ -120,13 +112,13 @@ static inline uint32_t lpspi_next_tx_word(const struct device *dev, int offset)
static inline void lpspi_fill_tx_fifo(const struct device *dev)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
size_t bytes_in_xfer = lpspi_data->fill_len * lpspi_data->word_size_bytes;
size_t offset;

for (offset = 0; offset < bytes_in_xfer; offset += lpspi_data->word_size_bytes) {
LPSPI_WriteData(base, lpspi_next_tx_word(dev, offset));
base->TDR = lpspi_next_tx_word(dev, offset);
}

LOG_DBG("Filled TX FIFO to %d words (%d bytes)", lpspi_data->fill_len, offset);
Expand All @@ -135,20 +127,20 @@ static inline void lpspi_fill_tx_fifo(const struct device *dev)
static inline void lpspi_fill_tx_fifo_nop(const struct device *dev)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;

for (int i = 0; i < lpspi_data->fill_len; i++) {
LPSPI_WriteData(base, 0);
base->TDR = 0;
}

LOG_DBG("Filled TX fifo with %d NOPs", lpspi_data->fill_len);
}

static void lpspi_next_tx_fill(const struct device *dev)
{
const struct spi_mcux_config *config = dev->config;
struct spi_mcux_data *data = dev->data;
const struct spi_nxp_config *config = dev->config;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;
size_t max_chunk;
Expand All @@ -168,13 +160,13 @@ static void lpspi_next_tx_fill(const struct device *dev)
static inline void lpspi_handle_tx_irq(const struct device *dev)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;

spi_context_update_tx(ctx, lpspi_data->word_size_bytes, lpspi_data->fill_len);

LPSPI_ClearStatusFlags(base, kLPSPI_TxDataRequestFlag);
base->SR = LPSPI_SR_TDF_MASK;

/* Having no buffer length left indicates transfer is done, if there
* was RX to do left, the TX buf would be null but
Expand All @@ -185,7 +177,7 @@ static inline void lpspi_handle_tx_irq(const struct device *dev)
base->TCR = 0;
lpspi_wait_tx_fifo_empty(dev);
spi_context_cs_control(ctx, false);
LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable);
base->IER &= ~LPSPI_IER_TDIE_MASK;
return;
}

Expand All @@ -194,7 +186,7 @@ static inline void lpspi_handle_tx_irq(const struct device *dev)

static inline bool lpspi_is_rx_done(const struct device *dev)
{
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
struct spi_context *ctx = &data->ctx;
size_t tx_total = lpspi_data->tx_total_len;
Expand Down Expand Up @@ -222,16 +214,16 @@ static inline void lpspi_clear_remaining_rx(struct spi_context *ctx)
static void lpspi_isr(const struct device *dev)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
const struct spi_mcux_config *config = dev->config;
uint32_t status_flags = LPSPI_GetStatusFlags(base);
struct spi_mcux_data *data = dev->data;
const struct spi_nxp_config *config = dev->config;
uint32_t status_flags = base->SR;
struct spi_nxp_data *data = dev->data;
struct spi_context *ctx = &data->ctx;

if (status_flags & kLPSPI_RxDataReadyFlag) {
if (status_flags & LPSPI_SR_RDF_MASK) {
lpspi_handle_rx_irq(dev);
}

if (status_flags & kLPSPI_TxDataRequestFlag) {
if (status_flags & LPSPI_SR_TDF_MASK) {
lpspi_handle_tx_irq(dev);
}

Expand All @@ -247,7 +239,7 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
bool asynchronous, spi_callback_t cb, void *userdata)
{
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
int ret;

Expand All @@ -265,21 +257,14 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
lpspi_data->tx_total_len = spi_context_total_tx_len(&data->ctx);
lpspi_data->rx_total_len = spi_context_total_rx_len(&data->ctx);

ret = spi_mcux_configure(dev, spi_cfg);
ret = spi_nxp_configure(dev, spi_cfg);
if (ret) {
goto out;
}

LPSPI_FlushFifo(base, true, true);
LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);

LOG_DBG("Starting LPSPI transfer");
spi_context_cs_control(&data->ctx, true);

LPSPI_SetFifoWatermarks(base, 0, 0);
LPSPI_Enable(base, true);

/* keep the chip select asserted until the end of the zephyr xfer */
base->TCR |= LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK;
/* tcr is written to tx fifo */
Expand All @@ -288,8 +273,7 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
/* start the transfer sequence which are handled by irqs */
lpspi_next_tx_fill(dev);

LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable |
(uint32_t)kLPSPI_RxInterruptEnable);
base->IER |= LPSPI_IER_TDIE_MASK | LPSPI_IER_RDIE_MASK;

ret = spi_context_wait_for_completion(&data->ctx);
out:
Expand All @@ -298,15 +282,15 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
return ret;
}

static int spi_mcux_transceive_sync(const struct device *dev, const struct spi_config *spi_cfg,
static int spi_nxp_transceive_sync(const struct device *dev, const struct spi_config *spi_cfg,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL);
}

#ifdef CONFIG_SPI_ASYNC
static int spi_mcux_transceive_async(const struct device *dev, const struct spi_config *spi_cfg,
static int spi_nxp_transceive_async(const struct device *dev, const struct spi_config *spi_cfg,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs, spi_callback_t cb,
void *userdata)
Expand All @@ -315,20 +299,20 @@ static int spi_mcux_transceive_async(const struct device *dev, const struct spi_
}
#endif /* CONFIG_SPI_ASYNC */

static DEVICE_API(spi, spi_mcux_driver_api) = {
.transceive = spi_mcux_transceive_sync,
static DEVICE_API(spi, spi_nxp_driver_api) = {
.transceive = spi_nxp_transceive_sync,
#ifdef CONFIG_SPI_ASYNC
.transceive_async = spi_mcux_transceive_async,
.transceive_async = spi_nxp_transceive_async,
#endif
#ifdef CONFIG_SPI_RTIO
.iodev_submit = spi_rtio_iodev_default_submit,
#endif
.release = spi_mcux_release,
.release = spi_nxp_release,
};

static int spi_mcux_init(const struct device *dev)
static int spi_nxp_init(const struct device *dev)
{
struct spi_mcux_data *data = dev->data;
struct spi_nxp_data *data = dev->data;
int err = 0;

err = spi_nxp_init_common(dev);
Expand All @@ -343,23 +327,23 @@ static int spi_mcux_init(const struct device *dev)

#define LPSPI_INIT(n) \
SPI_NXP_LPSPI_COMMON_INIT(n) \
SPI_MCUX_LPSPI_CONFIG_INIT(n) \
SPI_NXP_LPSPI_CONFIG_INIT(n) \
\
static struct lpspi_driver_data lpspi_##n##_driver_data; \
\
static struct spi_mcux_data spi_mcux_data_##n = { \
static struct spi_nxp_data spi_nxp_data_##n = { \
SPI_NXP_LPSPI_COMMON_DATA_INIT(n) \
.driver_data = &lpspi_##n##_driver_data, \
}; \
\
SPI_DEVICE_DT_INST_DEFINE(n, spi_mcux_init, NULL, &spi_mcux_data_##n, \
&spi_mcux_config_##n, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \
&spi_mcux_driver_api);
SPI_DEVICE_DT_INST_DEFINE(n, spi_nxp_init, NULL, &spi_nxp_data_##n, \
&spi_nxp_config_##n, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \
&spi_nxp_driver_api);

#define SPI_MCUX_LPSPI_INIT_IF_DMA(n) IF_DISABLED(SPI_NXP_LPSPI_HAS_DMAS(n), (LPSPI_INIT(n)))
#define SPI_NXP_LPSPI_INIT_IF_DMA(n) IF_DISABLED(SPI_NXP_LPSPI_HAS_DMAS(n), (LPSPI_INIT(n)))

#define SPI_MCUX_LPSPI_INIT(n) \
COND_CODE_1(CONFIG_SPI_MCUX_LPSPI_DMA, \
(SPI_MCUX_LPSPI_INIT_IF_DMA(n)), (LPSPI_INIT(n)))
#define SPI_NXP_LPSPI_INIT(n) \
COND_CODE_1(CONFIG_SPI_NXP_LPSPI_DMA, \
(SPI_NXP_LPSPI_INIT_IF_DMA(n)), (LPSPI_INIT(n)))

DT_INST_FOREACH_STATUS_OKAY(SPI_MCUX_LPSPI_INIT)
DT_INST_FOREACH_STATUS_OKAY(SPI_NXP_LPSPI_INIT)
Loading
Loading