Skip to content

Commit 6896593

Browse files
committed
spi_nxp_lpspi: Basic peripheral mode support
Add basic support for basic peripheral mode operation. Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
1 parent b790019 commit 6896593

File tree

2 files changed

+95
-33
lines changed

2 files changed

+95
-33
lines changed

drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi.c

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ LOG_MODULE_REGISTER(spi_mcux_lpspi, CONFIG_SPI_LOG_LEVEL);
1414
struct lpspi_driver_data {
1515
size_t fill_len;
1616
uint8_t word_size_bytes;
17+
uint8_t lpspi_op_mode;
1718
};
1819

1920
static inline uint8_t rx_fifo_cur_len(LPSPI_Type *base)
@@ -222,6 +223,25 @@ static inline void lpspi_handle_tx_irq(const struct device *dev)
222223
lpspi_next_tx_fill(data->dev);
223224
}
224225

226+
static inline void lpspi_handle_err051588(LPSPI_Type *base, uint32_t status_flags, uint8_t op_mode)
227+
{
228+
if (op_mode != SPI_OP_MODE_SLAVE) {
229+
/* this errata is only for slave mode */
230+
return;
231+
}
232+
233+
if (!(status_flags & LPSPI_SR_TEF_MASK)) {
234+
/* the errata happens when transmit error (underrun) occurs */
235+
return;
236+
}
237+
238+
/* clear the w1c error flag as usual */
239+
base->SR = LPSPI_SR_TEF_MASK;
240+
241+
/* workaround is to reset the transmit fifo before writing any new data */
242+
base->CR |= LPSPI_CR_RTF_MASK;
243+
}
244+
225245
static void lpspi_isr(const struct device *dev)
226246
{
227247
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
@@ -230,20 +250,22 @@ static void lpspi_isr(const struct device *dev)
230250
struct spi_mcux_data *data = dev->data;
231251
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
232252
struct spi_context *ctx = &data->ctx;
253+
uint8_t op_mode = lpspi_data->lpspi_op_mode;
233254

234255
if (status_flags & kLPSPI_RxDataReadyFlag) {
235256
lpspi_handle_rx_irq(dev);
236257
}
237258

238259
if (status_flags & kLPSPI_TxDataRequestFlag) {
260+
lpspi_handle_err051588(base, status_flags, op_mode);
239261
lpspi_handle_tx_irq(dev);
240262
}
241263

242264
if (spi_context_tx_on(ctx)) {
243265
return;
244266
}
245267

246-
if (spi_context_rx_len_left(ctx) == 1) {
268+
if (op_mode == SPI_OP_MODE_MASTER && spi_context_rx_len_left(ctx) == 1) {
247269
base->TCR &= ~LPSPI_TCR_CONT_MASK;
248270
} else if (spi_context_rx_on(ctx)) {
249271
size_t rx_fifo_len = rx_fifo_cur_len(base);
@@ -269,9 +291,11 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
269291
bool asynchronous, spi_callback_t cb, void *userdata)
270292
{
271293
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
294+
const struct spi_mcux_config *config = dev->config;
272295
struct spi_mcux_data *data = dev->data;
273296
struct lpspi_driver_data *lpspi_data = (struct lpspi_driver_data *)data->driver_data;
274297
struct spi_context *ctx = &data->ctx;
298+
uint8_t op_mode = SPI_OP_MODE_GET(spi_cfg->operation);
275299
int ret = 0;
276300

277301
spi_context_lock(&data->ctx, asynchronous, cb, userdata, spi_cfg);
@@ -284,26 +308,34 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
284308
}
285309

286310
spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, lpspi_data->word_size_bytes);
311+
lpspi_data->lpspi_op_mode = op_mode;
287312

288313
ret = spi_mcux_configure(dev, spi_cfg);
289314
if (ret) {
290315
goto error;
291316
}
292317

293-
LPSPI_FlushFifo(base, true, true);
318+
LPSPI_FlushFifo(base, false, true);
294319
LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
295320
LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
296321

297322
LOG_DBG("Starting LPSPI transfer");
298323
spi_context_cs_control(ctx, true);
299324

300-
LPSPI_SetFifoWatermarks(base, 0, 0);
325+
if (op_mode == SPI_OP_MODE_MASTER) {
326+
LPSPI_SetFifoWatermarks(base, 0, 0);
327+
} else {
328+
LPSPI_SetFifoWatermarks(base, config->tx_fifo_size - 2, 0);
329+
}
330+
301331
LPSPI_Enable(base, true);
302332

303-
/* keep the chip select asserted until the end of the zephyr xfer */
304-
base->TCR |= LPSPI_TCR_CONT_MASK;
305-
/* tcr is written to tx fifo */
306-
lpspi_wait_tx_fifo_empty(dev);
333+
if (op_mode == SPI_OP_MODE_MASTER) {
334+
/* keep the chip select active until the end of the zephyr xfer */
335+
base->TCR |= LPSPI_TCR_CONT_MASK;
336+
/* tcr is written to tx fifo */
337+
lpspi_wait_tx_fifo_empty(dev);
338+
}
307339

308340
/* start the transfer sequence which are handled by irqs */
309341
lpspi_next_tx_fill(dev);
@@ -312,7 +344,6 @@ static int transceive(const struct device *dev, const struct spi_config *spi_cfg
312344
(uint32_t)kLPSPI_RxInterruptEnable);
313345

314346
return spi_context_wait_for_completion(ctx);
315-
316347
error:
317348
spi_context_release(ctx, ret);
318349
return ret;

drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_common.c

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,65 @@ int spi_mcux_release(const struct device *dev, const struct spi_config *spi_cfg)
6565
return 0;
6666
}
6767

68+
static inline void lpspi_master_config(const struct device *dev,
69+
const struct spi_config *spi_cfg,
70+
uint32_t clock_freq)
71+
{
72+
const struct spi_mcux_config *config = dev->config;
73+
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
74+
lpspi_master_config_t master_config;
75+
76+
LPSPI_MasterGetDefaultConfig(&master_config);
77+
78+
master_config.bitsPerFrame = SPI_WORD_SIZE_GET(spi_cfg->operation);
79+
master_config.cpol = (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL)
80+
? kLPSPI_ClockPolarityActiveLow
81+
: kLPSPI_ClockPolarityActiveHigh;
82+
master_config.cpha = (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA)
83+
? kLPSPI_ClockPhaseSecondEdge
84+
: kLPSPI_ClockPhaseFirstEdge;
85+
master_config.direction =
86+
(spi_cfg->operation & SPI_TRANSFER_LSB) ? kLPSPI_LsbFirst : kLPSPI_MsbFirst;
87+
master_config.baudRate = spi_cfg->frequency;
88+
master_config.pcsToSckDelayInNanoSec = config->pcs_sck_delay;
89+
master_config.lastSckToPcsDelayInNanoSec = config->sck_pcs_delay;
90+
master_config.betweenTransferDelayInNanoSec = config->transfer_delay;
91+
master_config.whichPcs = spi_cfg->slave + kLPSPI_Pcs0;
92+
master_config.pcsActiveHighOrLow = (spi_cfg->operation & SPI_CS_ACTIVE_HIGH)
93+
? kLPSPI_PcsActiveHigh : kLPSPI_PcsActiveLow;
94+
master_config.pinCfg = config->data_pin_config;
95+
master_config.dataOutConfig = config->output_config ? kLpspiDataOutTristate :
96+
kLpspiDataOutRetained;
97+
98+
LPSPI_MasterInit(base, &master_config, clock_freq);
99+
}
100+
101+
static inline void lpspi_slave_config(const struct device *dev,
102+
const struct spi_config *spi_cfg)
103+
{
104+
const struct spi_mcux_config *config = dev->config;
105+
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
106+
107+
base->CFGR1 = LPSPI_CFGR1_OUTCFG(config->output_config ? 1 : 0) |
108+
LPSPI_CFGR1_PINCFG(config->data_pin_config ? 1 : 0) |
109+
LPSPI_CFGR1_PCSPOL((spi_cfg->operation & SPI_CS_ACTIVE_HIGH) ? 1 : 0);
110+
111+
base->TCR = LPSPI_TCR_CPOL((SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) ? 1 : 0) |
112+
LPSPI_TCR_CPHA((SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA) ? 1 : 0) |
113+
LPSPI_TCR_LSBF((spi_cfg->operation & SPI_TRANSFER_LSB) ? 1 : 0) |
114+
LPSPI_TCR_FRAMESZ(SPI_WORD_SIZE_GET(spi_cfg->operation) - 1) |
115+
LPSPI_TCR_PCS(spi_cfg->slave);
116+
}
117+
68118
int spi_mcux_configure(const struct device *dev, const struct spi_config *spi_cfg)
69119
{
70120
const struct spi_mcux_config *config = dev->config;
71121
struct spi_mcux_data *data = dev->data;
72122
struct spi_context *ctx = &data->ctx;
73123
LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
74124
uint32_t word_size = SPI_WORD_SIZE_GET(spi_cfg->operation);
125+
uint8_t op_mode = SPI_OP_MODE_GET(spi_cfg->operation);
75126
bool configured = ctx->config != NULL;
76-
lpspi_master_config_t master_config;
77127
uint32_t clock_freq;
78128
int ret;
79129

@@ -135,30 +185,11 @@ int spi_mcux_configure(const struct device *dev, const struct spi_config *spi_cf
135185

136186
data->ctx.config = spi_cfg;
137187

138-
LPSPI_MasterGetDefaultConfig(&master_config);
139-
140-
master_config.bitsPerFrame = word_size;
141-
master_config.cpol = (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL)
142-
? kLPSPI_ClockPolarityActiveLow
143-
: kLPSPI_ClockPolarityActiveHigh;
144-
master_config.cpha = (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA)
145-
? kLPSPI_ClockPhaseSecondEdge
146-
: kLPSPI_ClockPhaseFirstEdge;
147-
master_config.direction =
148-
(spi_cfg->operation & SPI_TRANSFER_LSB) ? kLPSPI_LsbFirst : kLPSPI_MsbFirst;
149-
master_config.baudRate = spi_cfg->frequency;
150-
master_config.pcsToSckDelayInNanoSec = config->pcs_sck_delay;
151-
master_config.lastSckToPcsDelayInNanoSec = config->sck_pcs_delay;
152-
master_config.betweenTransferDelayInNanoSec = config->transfer_delay;
153-
master_config.whichPcs = spi_cfg->slave + kLPSPI_Pcs0;
154-
master_config.pcsActiveHighOrLow = (spi_cfg->operation & SPI_CS_ACTIVE_HIGH)
155-
? kLPSPI_PcsActiveHigh : kLPSPI_PcsActiveLow;
156-
master_config.pinCfg = config->data_pin_config;
157-
master_config.dataOutConfig = config->output_config ? kLpspiDataOutTristate :
158-
kLpspiDataOutRetained;
159-
160-
LPSPI_MasterInit(base, &master_config, clock_freq);
161-
LPSPI_SetDummyData(base, 0);
188+
if (op_mode == SPI_OP_MODE_MASTER) {
189+
lpspi_master_config(dev, spi_cfg, clock_freq);
190+
} else {
191+
lpspi_slave_config(dev, spi_cfg);
192+
}
162193

163194
if (IS_ENABLED(CONFIG_DEBUG)) {
164195
base->CR |= LPSPI_CR_DBGEN_MASK;

0 commit comments

Comments
 (0)