Skip to content

Commit a4fd230

Browse files
committed
drivers: spi: stm32: use the new fifo related property
Use the new SPI FIFO related property to retrieve FIFO size (instead of guessing it from the supported data width), and to check that the TSIZE register is not written with a value that exceeds the maximal supported transfer size. Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
1 parent bbf215e commit a4fd230

File tree

2 files changed

+57
-50
lines changed

2 files changed

+57
-50
lines changed

‎drivers/spi/spi_stm32.c‎

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,6 @@ static const uint32_t table_datawidth[] = {
115115
static const uint32_t table_fifo_threshold[] = {
116116
LISTIFY(8, STM32_SPI_FIFO_THRESHOLD, (,))
117117
};
118-
119-
static uint8_t spi_stm32_get_fifo_size(const struct device *dev)
120-
{
121-
const struct spi_stm32_config *cfg = dev->config;
122-
123-
if(cfg->datawidth == STM32_SPI_DATA_WIDTH_FULL_4_TO_32_BIT) {
124-
return 16U;
125-
} else {
126-
return 8U;
127-
}
128-
}
129118
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
130119

131120
static bool spi_stm32_is_data_width_supported(const struct device *dev, uint32_t width)
@@ -519,8 +508,9 @@ static void spi_stm32_read_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
519508
} while (nb_fifo < data->fifo_threshold && data->rx_len);
520509
}
521510

522-
static void spi_stm32_shift_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
511+
static int spi_stm32_shift_fifo(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
523512
{
513+
SPI_TypeDef *spi = cfg->spi;
524514
uint32_t transfer_dir = LL_SPI_GetTransferDirection(spi);
525515

526516
if (transfer_dir == LL_SPI_FULL_DUPLEX && LL_SPI_IsActiveFlag_DXP(spi) &&
@@ -566,7 +556,12 @@ static void spi_stm32_shift_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
566556
LL_SPI_ClearFlag_TXTF(spi);
567557
LL_SPI_ClearFlag_EOT(spi);
568558
ll_func_disable_spi(spi);
569-
LL_SPI_SetTransferSize(spi, data->tx_len);
559+
if (data->tx_len <= cfg->max_transfer_size) {
560+
LL_SPI_SetTransferSize(spi, data->tx_len);
561+
} else {
562+
LOG_ERR("Buffer size exceeds maximal supported value");
563+
return -EINVAL;
564+
}
570565
LL_SPI_Enable(spi);
571566
LL_SPI_StartMasterTransfer(spi);
572567
#ifdef CONFIG_SPI_STM32_INTERRUPT
@@ -577,15 +572,16 @@ static void spi_stm32_shift_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
577572
spi_stm32_send_fifo(spi, data);
578573
}
579574
}
575+
return 0;
580576
}
581577
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
582578

583579
/* Shift a SPI frame as master. */
584-
static void spi_stm32_shift_m(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
580+
static int spi_stm32_shift_m(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
585581
{
586582
if (cfg->fifo_enabled) {
587583
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
588-
spi_stm32_shift_fifo(cfg->spi, data);
584+
return spi_stm32_shift_fifo(cfg, data);
589585
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
590586
} else {
591587
uint32_t transfer_dir = LL_SPI_GetTransferDirection(cfg->spi);
@@ -606,6 +602,7 @@ static void spi_stm32_shift_m(const struct spi_stm32_config *cfg, struct spi_stm
606602
spi_stm32_read_next_frame(cfg->spi, data);
607603
}
608604
}
605+
return 0;
609606
}
610607

611608
/* Shift a SPI frame as slave. */
@@ -629,9 +626,13 @@ static void spi_stm32_shift_s(SPI_TypeDef *spi, struct spi_stm32_data *data)
629626
static int spi_stm32_shift_frames(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
630627
{
631628
spi_operation_t operation = data->ctx.config->operation;
629+
int ret;
632630

633631
if (SPI_OP_MODE_GET(operation) == SPI_OP_MODE_MASTER) {
634-
spi_stm32_shift_m(cfg, data);
632+
ret = spi_stm32_shift_m(cfg, data);
633+
if (ret != 0) {
634+
return ret;
635+
}
635636
} else {
636637
spi_stm32_shift_s(cfg->spi, data);
637638
}
@@ -724,6 +725,12 @@ static void spi_stm32_iodev_complete(const struct device *dev, int status);
724725
static int spi_stm32_configure(const struct device *dev,
725726
const struct spi_config *config,
726727
bool write);
728+
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
729+
static int32_t spi_stm32_set_transfer_size(const struct device *dev,
730+
const struct spi_config *config,
731+
const struct spi_buf_set *tx_bufs,
732+
const struct spi_buf_set *rx_bufs);
733+
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
727734

728735
static void spi_stm32_iodev_msg_start(const struct device *dev, struct spi_config *config,
729736
const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t buf_len)
@@ -759,8 +766,10 @@ static void spi_stm32_iodev_msg_start(const struct device *dev, struct spi_confi
759766
/* SPI needs to be disabled to set the transfer size */
760767
ll_func_disable_spi(spi);
761768
}
762-
data->tx_len = data->rx_len = size;
763-
LL_SPI_SetTransferSize(spi, size);
769+
770+
if (spi_stm32_set_transfer_size(dev, NULL, NULL, NULL) != 0) {
771+
spi_stm32_iodev_complete(dev, -EINVAL);
772+
}
764773
}
765774
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
766775

@@ -1162,11 +1171,10 @@ static int spi_stm32_configure(const struct device *dev,
11621171

11631172
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
11641173
if (cfg->fifo_enabled) {
1165-
uint8_t fifo_size = spi_stm32_get_fifo_size(dev);
11661174
/* Do not use bits2bytes here, we want to get 3 for 24-bit operation */
11671175
uint8_t dfs = (SPI_WORD_SIZE_GET(config->operation) + 7U) / 8U;
11681176
/* FIFO threshold should not exceed half the FIFO size */
1169-
data->fifo_threshold = fifo_size / (dfs * 2U);
1177+
data->fifo_threshold = cfg->fifo_size / (dfs * 2U);
11701178
} else {
11711179
data->fifo_threshold = 1;
11721180
}
@@ -1202,8 +1210,6 @@ static int spi_stm32_release(const struct device *dev, const struct spi_config *
12021210
return 0;
12031211
}
12041212

1205-
#ifndef CONFIG_SPI_RTIO
1206-
12071213
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
12081214
static int32_t spi_stm32_count_bufset_frames(const struct spi_config *config,
12091215
const struct spi_buf_set *bufs)
@@ -1233,36 +1239,19 @@ static int32_t spi_stm32_count_bufset_frames(const struct spi_config *config,
12331239
return frames;
12341240
}
12351241

1236-
static int32_t spi_stm32_count_total_frames(const struct spi_config *config,
1237-
const struct spi_buf_set *tx_bufs,
1238-
const struct spi_buf_set *rx_bufs)
1239-
{
1240-
int tx_frames = spi_stm32_count_bufset_frames(config, tx_bufs);
1241-
1242-
if (tx_frames < 0) {
1243-
return tx_frames;
1244-
}
1245-
1246-
int rx_frames = spi_stm32_count_bufset_frames(config, rx_bufs);
1247-
1248-
if (rx_frames < 0) {
1249-
return rx_frames;
1250-
}
1251-
1252-
return MAX(rx_frames, tx_frames);
1253-
}
1254-
1255-
__maybe_unused
1256-
static int32_t spi_stm32_set_transfer_size(SPI_TypeDef *spi,
1242+
static int32_t spi_stm32_set_transfer_size(const struct device *dev,
12571243
const struct spi_config *config,
12581244
const struct spi_buf_set *tx_bufs,
12591245
const struct spi_buf_set *rx_bufs)
12601246
{
1247+
struct spi_stm32_data *data = dev->data;
1248+
const struct spi_stm32_config *cfg = dev->config;
1249+
SPI_TypeDef *spi = cfg->spi;
12611250
uint32_t transfer_dir = LL_SPI_GetTransferDirection(spi);
12621251
int32_t frames;
12631252

12641253
if (transfer_dir == LL_SPI_FULL_DUPLEX) {
1265-
frames = spi_stm32_count_total_frames(config, tx_bufs, rx_bufs);
1254+
frames = spi_context_max_continuous_chunk(&data->ctx);
12661255
} else if (transfer_dir == LL_SPI_HALF_DUPLEX_TX) {
12671256
frames = spi_stm32_count_bufset_frames(config, tx_bufs);
12681257
} else {
@@ -1273,12 +1262,19 @@ static int32_t spi_stm32_set_transfer_size(SPI_TypeDef *spi,
12731262
return frames;
12741263
}
12751264

1276-
LL_SPI_SetTransferSize(spi, (uint32_t)frames);
1265+
if (frames <= cfg->max_transfer_size) {
1266+
data->tx_len = data->rx_len = frames;
1267+
LL_SPI_SetTransferSize(spi, (uint32_t)frames);
1268+
} else {
1269+
LOG_ERR("Buffer size exceeds maximal supported value");
1270+
return -EINVAL;
1271+
}
12771272

12781273
return 0;
12791274
}
12801275
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
12811276

1277+
#ifndef CONFIG_SPI_RTIO
12821278
static int spi_stm32_half_duplex_switch_to_receive(const struct spi_stm32_config *cfg,
12831279
struct spi_stm32_data *data)
12841280
{
@@ -1397,8 +1393,10 @@ static int transceive(const struct device *dev,
13971393

13981394
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
13991395
if (cfg->fifo_enabled && SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_MASTER) {
1400-
data->tx_len = data->rx_len = spi_context_max_continuous_chunk(&data->ctx);
1401-
LL_SPI_SetTransferSize(spi, data->tx_len);
1396+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
1397+
if (ret != 0) {
1398+
goto end;
1399+
}
14021400
}
14031401

14041402
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
@@ -1544,7 +1542,7 @@ static int transceive_dma(const struct device *dev,
15441542

15451543
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
15461544
if (transfer_dir == LL_SPI_HALF_DUPLEX_RX) {
1547-
ret = spi_stm32_set_transfer_size(spi, config, tx_bufs, rx_bufs);
1545+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
15481546

15491547
if (ret < 0) {
15501548
goto end;
@@ -1604,7 +1602,10 @@ static int transceive_dma(const struct device *dev,
16041602
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
16051603
if (cfg->fifo_enabled && transfer_dir == LL_SPI_FULL_DUPLEX &&
16061604
SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_MASTER) {
1607-
LL_SPI_SetTransferSize(spi, dma_len);
1605+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
1606+
if (ret != 0) {
1607+
goto end;
1608+
}
16081609
LL_SPI_Enable(spi);
16091610
LL_SPI_StartMasterTransfer(spi);
16101611
}
@@ -1685,7 +1686,7 @@ static int transceive_dma(const struct device *dev,
16851686
transfer_dir = LL_SPI_HALF_DUPLEX_RX;
16861687

16871688
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
1688-
ret = spi_stm32_set_transfer_size(spi, config, tx_bufs, rx_bufs);
1689+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
16891690

16901691
if (ret < 0) {
16911692
break;
@@ -1990,6 +1991,10 @@ static int spi_stm32_init(const struct device *dev)
19901991
(.midi_clocks = DT_INST_PROP(id, midi_clock),)) \
19911992
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
19921993
(.mssi_clocks = DT_INST_PROP(id, mssi_clock),)) \
1994+
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
1995+
(.fifo_size = DT_INST_PROP(id, fifo_size),)) \
1996+
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
1997+
(.max_transfer_size = DT_INST_PROP(id, max_transfer_size),)) \
19931998
}; \
19941999
\
19952000
IF_ENABLED(CONFIG_SPI_RTIO, \

‎drivers/spi/spi_stm32.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ struct spi_stm32_config {
3434
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
3535
int midi_clocks;
3636
int mssi_clocks;
37+
uint8_t fifo_size;
38+
uint32_t max_transfer_size;
3739
#endif
3840
size_t pclk_len;
3941
const struct stm32_pclken *pclken;

0 commit comments

Comments
 (0)