Skip to content

Commit be0f915

Browse files
committed
drivers: spi: spi_max32: Fix word size support
Driver was not handling SPI word sizes other than 8 bits. Apply DFS shift wherever necessary to support non 8-bit transfers. For word sizes that are not supported, return -ENOTSUP as error so that tests do not fail. DMA mode cannot support word sizes that are less than 8 bits so return -ENOTSUP if word size less than 8-bits is required. Signed-off-by: Tahsin Mutlugun <Tahsin.Mutlugun@analog.com>
1 parent f4a0beb commit be0f915

File tree

1 file changed

+66
-42
lines changed

1 file changed

+66
-42
lines changed

drivers/spi/spi_max32.c

Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
103103

104104
ret = Wrap_MXC_SPI_Init(regs, master_mode, quad_mode, num_slaves, ss_polarity, spi_speed);
105105
if (ret) {
106-
return ret;
106+
return -EINVAL;
107107
}
108108

109109
int cpol = (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) ? 1 : 0;
@@ -119,12 +119,12 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
119119
ret = MXC_SPI_SetMode(regs, SPI_MODE_0);
120120
}
121121
if (ret) {
122-
return ret;
122+
return -EINVAL;
123123
}
124124

125125
ret = MXC_SPI_SetDataSize(regs, SPI_WORD_SIZE_GET(config->operation));
126126
if (ret) {
127-
return ret;
127+
return -ENOTSUP;
128128
}
129129

130130
#if defined(CONFIG_SPI_EXTENDED_MODES)
@@ -145,7 +145,7 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
145145
}
146146

147147
if (ret) {
148-
return ret;
148+
return -EINVAL;
149149
}
150150
#endif
151151

@@ -163,18 +163,21 @@ static inline int spi_max32_get_dfs_shift(const struct spi_context *ctx)
163163
return 1;
164164
}
165165

166-
static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req)
166+
static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req, uint8_t dfs_shift)
167167
{
168168
req->rxCnt = 0;
169169
req->txCnt = 0;
170170

171+
spi->ctrl0 &= ~ADI_MAX32_SPI_CTRL_EN;
172+
171173
if (spi->ctrl0 & ADI_MAX32_SPI_CTRL_MASTER_MODE) {
172174
MXC_SPI_SetSlave(spi, req->ssIdx);
173175
}
174176

177+
/* SPI_CTRL1 holds the number of words so apply dfs_shift first */
175178
if (req->rxData && req->rxLen) {
176179
MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_RX_NUM_CHAR,
177-
req->rxLen << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS);
180+
(req->rxLen >> dfs_shift) << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS);
178181
spi->dma |= MXC_F_SPI_DMA_RX_FIFO_EN;
179182
} else {
180183
spi->ctrl1 &= ~MXC_F_SPI_CTRL1_RX_NUM_CHAR;
@@ -183,7 +186,7 @@ static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req)
183186

184187
if (req->txLen) {
185188
MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_TX_NUM_CHAR,
186-
req->txLen << MXC_F_SPI_CTRL1_TX_NUM_CHAR_POS);
189+
(req->txLen >> dfs_shift) << MXC_F_SPI_CTRL1_TX_NUM_CHAR_POS);
187190
spi->dma |= MXC_F_SPI_DMA_TX_FIFO_EN;
188191
} else {
189192
spi->ctrl1 &= ~MXC_F_SPI_CTRL1_TX_NUM_CHAR;
@@ -206,8 +209,8 @@ static int spi_max32_transceive_sync(mxc_spi_regs_t *spi, struct max32_spi_data
206209
MXC_SPI_ClearTXFIFO(spi);
207210
MXC_SPI_ClearRXFIFO(spi);
208211

209-
tx_len = req->txLen << dfs_shift;
210-
rx_len = req->rxLen << dfs_shift;
212+
tx_len = req->txLen;
213+
rx_len = req->rxLen;
211214
do {
212215
remain = tx_len - req->txCnt;
213216
if (remain > 0) {
@@ -251,8 +254,6 @@ static int spi_max32_transceive(const struct device *dev)
251254
uint32_t len;
252255
uint8_t dfs_shift;
253256

254-
MXC_SPI_ClearTXFIFO(cfg->regs);
255-
256257
dfs_shift = spi_max32_get_dfs_shift(ctx);
257258

258259
len = spi_context_max_continuous_chunk(ctx);
@@ -291,36 +292,46 @@ static int spi_max32_transceive(const struct device *dev)
291292
break;
292293
}
293294
#else
294-
data->req.txLen = len >> dfs_shift;
295+
data->req.txLen = len;
295296
data->req.txData = (uint8_t *)ctx->tx_buf;
296-
data->req.rxLen = len >> dfs_shift;
297+
data->req.rxLen = len;
297298
data->req.rxData = ctx->rx_buf;
298299

299-
data->req.rxData = ctx->rx_buf;
300-
301-
data->req.rxLen = len >> dfs_shift;
302300
if (!data->req.rxData) {
303301
/* Pass a dummy buffer to HAL if receive buffer is NULL, otherwise
304302
* corrupt data is read during subsequent transactions.
305303
*/
306304
data->req.rxData = data->dummy;
307305
data->req.rxLen = 0;
306+
307+
if (!data->req.txData && !data->req.txLen) {
308+
/* Both RX and TX are NULL, nothing to do */
309+
spi_context_update_tx(&data->ctx, dfs_shift ? 2 : 1, len);
310+
spi_context_update_rx(&data->ctx, dfs_shift ? 2 : 1, len);
311+
if (!spi_context_tx_on(ctx) && !spi_context_rx_on(ctx)) {
312+
spi_context_complete(ctx, dev, 0);
313+
}
314+
315+
return 0;
316+
}
308317
}
309318
#endif
310319
data->req.spi = cfg->regs;
311320
data->req.ssIdx = ctx->config->slave;
312321
data->req.ssDeassert = 0;
313322
data->req.txCnt = 0;
314323
data->req.rxCnt = 0;
315-
spi_max32_setup(cfg->regs, &data->req);
324+
spi_max32_setup(cfg->regs, &data->req, dfs_shift);
316325
#ifdef CONFIG_SPI_MAX32_INTERRUPT
317-
MXC_SPI_SetTXThreshold(cfg->regs, 1);
326+
MXC_SPI_SetTXThreshold(cfg->regs, 1 << dfs_shift);
318327
if (data->req.rxLen) {
319-
MXC_SPI_SetRXThreshold(cfg->regs, 2);
328+
MXC_SPI_SetRXThreshold(cfg->regs, 2 << dfs_shift);
320329
MXC_SPI_EnableInt(cfg->regs, ADI_MAX32_SPI_INT_EN_RX_THD);
321330
}
322331
MXC_SPI_EnableInt(cfg->regs, ADI_MAX32_SPI_INT_EN_TX_THD | ADI_MAX32_SPI_INT_EN_MST_DONE);
323332

333+
MXC_SPI_ClearTXFIFO(cfg->regs);
334+
MXC_SPI_ClearRXFIFO(cfg->regs);
324335
if (!data->req.txData) {
325336
data->req.txCnt =
326337
MXC_SPI_WriteTXFIFO(cfg->regs, data->dummy, MIN(len, sizeof(data->dummy)));
@@ -334,8 +345,8 @@ static int spi_max32_transceive(const struct device *dev)
334345
if (ret) {
335346
ret = -EIO;
336347
} else {
337-
spi_context_update_tx(ctx, 1, len);
338-
spi_context_update_rx(ctx, 1, len);
348+
spi_context_update_tx(ctx, dfs_shift ? 2 : 1, len);
349+
spi_context_update_rx(ctx, dfs_shift ? 2 : 1, len);
339350
}
340351
#endif
341352

@@ -366,7 +377,7 @@ static int transceive(const struct device *dev, const struct spi_config *config,
366377
ret = spi_configure(dev, config);
367378
if (ret != 0) {
368379
spi_context_release(ctx, ret);
369-
return -EIO;
380+
return ret;
370381
}
371382

372383
spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1);
@@ -434,9 +445,10 @@ static void spi_max32_dma_callback(const struct device *dev, void *arg, uint32_t
434445
const struct device *spi_dev = data->dev;
435446
const struct max32_spi_config *config = spi_dev->config;
436447
uint32_t len;
448+
uint8_t dfs = spi_max32_get_dfs_shift(&data->ctx) ? 2 : 1;
437449

438450
if (status < 0) {
439-
LOG_ERR("DMA callback error with channel %d.", channel);
451+
LOG_ERR("DMA callback error for channel %u: %d", channel, status);
440452
} else {
441453
/* identify the origin of this callback */
442454
if (channel == config->tx_dma.channel) {
@@ -447,14 +459,14 @@ static void spi_max32_dma_callback(const struct device *dev, void *arg, uint32_t
447459
}
448460
if ((data->dma_stat & SPI_MAX32_DMA_DONE_FLAG) == SPI_MAX32_DMA_DONE_FLAG) {
449461
len = spi_context_max_continuous_chunk(&data->ctx);
450-
spi_context_update_tx(&data->ctx, 1, len);
451-
spi_context_update_rx(&data->ctx, 1, len);
462+
spi_context_update_tx(&data->ctx, dfs, len);
463+
spi_context_update_rx(&data->ctx, dfs, len);
452464
spi_context_complete(&data->ctx, spi_dev, status == 0 ? 0 : -EIO);
453465
}
454466
}
455467

456468
static int spi_max32_tx_dma_load(const struct device *dev, const uint8_t *buf, uint32_t len,
457-
uint8_t word_shift)
469+
uint8_t dfs_shift)
458470
{
459471
int ret;
460472
const struct max32_spi_config *config = dev->config;
@@ -467,9 +479,9 @@ static int spi_max32_tx_dma_load(const struct device *dev, const uint8_t *buf, u
467479
dma_cfg.user_data = (void *)data;
468480
dma_cfg.dma_slot = config->tx_dma.slot;
469481
dma_cfg.block_count = 1;
470-
dma_cfg.source_data_size = 1U << word_shift;
471-
dma_cfg.source_burst_length = 1U;
472-
dma_cfg.dest_data_size = 1U << word_shift;
482+
dma_cfg.source_data_size = 1U << dfs_shift;
483+
dma_cfg.source_burst_length = 1U << dfs_shift;
484+
dma_cfg.dest_data_size = 1U << dfs_shift;
473485
dma_cfg.head_block = &dma_blk;
474486
dma_blk.block_size = len;
475487
if (buf) {
@@ -489,7 +501,7 @@ static int spi_max32_tx_dma_load(const struct device *dev, const uint8_t *buf, u
489501
}
490502

491503
static int spi_max32_rx_dma_load(const struct device *dev, const uint8_t *buf, uint32_t len,
492-
uint8_t word_shift)
504+
uint8_t dfs_shift)
493505
{
494506
int ret;
495507
const struct max32_spi_config *config = dev->config;
@@ -502,9 +514,9 @@ static int spi_max32_rx_dma_load(const struct device *dev, const uint8_t *buf, u
502514
dma_cfg.user_data = (void *)data;
503515
dma_cfg.dma_slot = config->rx_dma.slot;
504516
dma_cfg.block_count = 1;
505-
dma_cfg.source_data_size = 1U << word_shift;
506-
dma_cfg.source_burst_length = 1U;
507-
dma_cfg.dest_data_size = 1U << word_shift;
517+
dma_cfg.source_data_size = 1U << dfs_shift;
518+
dma_cfg.source_burst_length = 1U << dfs_shift;
519+
dma_cfg.dest_data_size = 1U << dfs_shift;
508520
dma_cfg.head_block = &dma_blk;
509521
dma_blk.block_size = len;
510522
if (buf) {
@@ -540,6 +552,7 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
540552
spi_context_lock(ctx, async, cb, userdata, config);
541553

542554
MXC_SPI_ClearTXFIFO(spi);
555+
MXC_SPI_ClearRXFIFO(spi);
543556

544557
ret = dma_get_status(cfg->tx_dma.dev, cfg->tx_dma.channel, &status);
545558
if (ret < 0 || status.busy) {
@@ -553,9 +566,14 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
553566
goto unlock;
554567
}
555568

569+
/* Word sizes less than 8-bits are not supported in DMA mode */
570+
if (SPI_WORD_SIZE_GET(config->operation) < 8) {
571+
ret = -ENOTSUP;
572+
goto unlock;
573+
}
574+
556575
ret = spi_configure(dev, config);
557576
if (ret != 0) {
558-
ret = -EIO;
559577
goto unlock;
560578
}
561579

@@ -581,12 +599,17 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
581599
dfs_shift = spi_max32_get_dfs_shift(ctx);
582600
word_count = len >> dfs_shift;
583601

602+
if (word_count == 0) {
603+
/* Nothing to do, continue */
604+
continue;
605+
}
606+
584607
MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_RX_NUM_CHAR,
585608
word_count << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS);
586609
spi->dma |= ADI_MAX32_SPI_DMA_RX_FIFO_CLEAR;
587610
spi->dma |= MXC_F_SPI_DMA_RX_FIFO_EN;
588611
spi->dma |= ADI_MAX32_SPI_DMA_RX_DMA_EN;
589-
MXC_SPI_SetRXThreshold(spi, 0);
612+
MXC_SPI_SetRXThreshold(spi, dfs_shift ? 1 : 0);
590613

591614
ret = spi_max32_rx_dma_load(dev, ctx->rx_buf, len, dfs_shift);
592615
if (ret < 0) {
@@ -598,7 +621,7 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
598621
spi->dma |= ADI_MAX32_SPI_DMA_TX_FIFO_CLEAR;
599622
spi->dma |= MXC_F_SPI_DMA_TX_FIFO_EN;
600623
spi->dma |= ADI_MAX32_SPI_DMA_TX_DMA_EN;
601-
MXC_SPI_SetTXThreshold(spi, 1);
624+
MXC_SPI_SetTXThreshold(spi, 2);
602625

603626
ret = spi_max32_tx_dma_load(dev, ctx->tx_buf, len, dfs_shift);
604627
if (ret < 0) {
@@ -754,6 +777,7 @@ static void spi_max32_callback(mxc_spi_req_t *req, int error)
754777
struct spi_context *ctx = &data->ctx;
755778
const struct device *dev = data->dev;
756779
uint32_t len;
780+
uint8_t dfs;
757781

758782
#ifdef CONFIG_SPI_RTIO
759783
struct spi_rtio *rtio_ctx = data->rtio_ctx;
@@ -762,9 +786,10 @@ static void spi_max32_callback(mxc_spi_req_t *req, int error)
762786
spi_max32_iodev_complete(data->dev, 0);
763787
}
764788
#endif
789+
dfs = spi_max32_get_dfs_shift(ctx) ? 2 : 1;
765790
len = spi_context_max_continuous_chunk(ctx);
766-
spi_context_update_tx(ctx, 1, len);
767-
spi_context_update_rx(ctx, 1, len);
791+
spi_context_update_tx(ctx, dfs, len);
792+
spi_context_update_rx(ctx, dfs, len);
768793
#ifdef CONFIG_SPI_ASYNC
769794
if (ctx->asynchronous && ((spi_context_tx_on(ctx) || spi_context_rx_on(ctx)))) {
770795
k_work_submit(&data->async_work);
@@ -804,12 +829,11 @@ static void spi_max32_isr(const struct device *dev)
804829
mxc_spi_req_t *req = &data->req;
805830
mxc_spi_regs_t *spi = cfg->regs;
806831
uint32_t flags, remain;
807-
uint8_t dfs_shift = spi_max32_get_dfs_shift(&data->ctx);
808832

809833
flags = MXC_SPI_GetFlags(spi);
810834
MXC_SPI_ClearFlags(spi);
811835

812-
remain = (req->txLen << dfs_shift) - req->txCnt;
836+
remain = req->txLen - req->txCnt;
813837
if (flags & ADI_MAX32_SPI_INT_FL_TX_THD) {
814838
if (remain) {
815839
if (!data->req.txData) {
@@ -824,10 +848,10 @@ static void spi_max32_isr(const struct device *dev)
824848
}
825849
}
826850

827-
remain = (req->rxLen << dfs_shift) - req->rxCnt;
851+
remain = req->rxLen - req->rxCnt;
828852
if (remain) {
829853
req->rxCnt += MXC_SPI_ReadRXFIFO(spi, &req->rxData[req->rxCnt], remain);
830-
remain = (req->rxLen << dfs_shift) - req->rxCnt;
854+
remain = req->rxLen - req->rxCnt;
831855
if (remain >= MXC_SPI_FIFO_DEPTH) {
832856
MXC_SPI_SetRXThreshold(spi, 2);
833857
} else {

0 commit comments

Comments
 (0)