Skip to content

Commit be0af18

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. Also reorder the spi_stm32_config structure to have better packing. Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
1 parent 54f58db commit be0af18

File tree

2 files changed

+63
-59
lines changed

2 files changed

+63
-59
lines changed

‎drivers/spi/spi_stm32.c‎

Lines changed: 55 additions & 53 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)
@@ -527,8 +516,9 @@ static void spi_stm32_read_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
527516
} while (nb_fifo < data->fifo_threshold && data->rx_len);
528517
}
529518

530-
static void spi_stm32_shift_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
519+
static int spi_stm32_shift_fifo(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
531520
{
521+
SPI_TypeDef *spi = cfg->spi;
532522
uint32_t transfer_dir = LL_SPI_GetTransferDirection(spi);
533523

534524
if (transfer_dir == LL_SPI_FULL_DUPLEX && LL_SPI_IsActiveFlag_DXP(spi) &&
@@ -574,6 +564,10 @@ static void spi_stm32_shift_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
574564
LL_SPI_ClearFlag_TXTF(spi);
575565
LL_SPI_ClearFlag_EOT(spi);
576566
ll_func_disable_spi(spi);
567+
if (data->tx_len > cfg->fifo_max_transfer_size) {
568+
LOG_ERR("Buffer size exceeds maximal supported value");
569+
return -EINVAL;
570+
}
577571
LL_SPI_SetTransferSize(spi, data->tx_len);
578572
LL_SPI_Enable(spi);
579573
LL_SPI_StartMasterTransfer(spi);
@@ -585,15 +579,16 @@ static void spi_stm32_shift_fifo(SPI_TypeDef *spi, struct spi_stm32_data *data)
585579
spi_stm32_send_fifo(spi, data);
586580
}
587581
}
582+
return 0;
588583
}
589584
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
590585

591586
/* Shift a SPI frame as master. */
592-
static void spi_stm32_shift_m(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
587+
static int spi_stm32_shift_m(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
593588
{
594589
if (cfg->fifo_enabled) {
595590
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
596-
spi_stm32_shift_fifo(cfg->spi, data);
591+
return spi_stm32_shift_fifo(cfg, data);
597592
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
598593
} else {
599594
uint32_t transfer_dir = LL_SPI_GetTransferDirection(cfg->spi);
@@ -614,6 +609,7 @@ static void spi_stm32_shift_m(const struct spi_stm32_config *cfg, struct spi_stm
614609
spi_stm32_read_next_frame(cfg->spi, data);
615610
}
616611
}
612+
return 0;
617613
}
618614

619615
/* Shift a SPI frame as slave. */
@@ -637,9 +633,13 @@ static void spi_stm32_shift_s(SPI_TypeDef *spi, struct spi_stm32_data *data)
637633
static int spi_stm32_shift_frames(const struct spi_stm32_config *cfg, struct spi_stm32_data *data)
638634
{
639635
spi_operation_t operation = data->ctx.config->operation;
636+
int ret;
640637

641638
if (SPI_OP_MODE_GET(operation) == SPI_OP_MODE_MASTER) {
642-
spi_stm32_shift_m(cfg, data);
639+
ret = spi_stm32_shift_m(cfg, data);
640+
if (ret != 0) {
641+
return ret;
642+
}
643643
} else {
644644
spi_stm32_shift_s(cfg->spi, data);
645645
}
@@ -732,6 +732,12 @@ static void spi_stm32_iodev_complete(const struct device *dev, int status);
732732
static int spi_stm32_configure(const struct device *dev,
733733
const struct spi_config *config,
734734
bool write);
735+
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
736+
static int32_t spi_stm32_set_transfer_size(const struct device *dev,
737+
const struct spi_config *config,
738+
const struct spi_buf_set *tx_bufs,
739+
const struct spi_buf_set *rx_bufs);
740+
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
735741

736742
static void spi_stm32_iodev_msg_start(const struct device *dev, struct spi_config *config,
737743
const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t buf_len)
@@ -767,8 +773,10 @@ static void spi_stm32_iodev_msg_start(const struct device *dev, struct spi_confi
767773
/* SPI needs to be disabled to set the transfer size */
768774
ll_func_disable_spi(spi);
769775
}
770-
data->tx_len = data->rx_len = size;
771-
LL_SPI_SetTransferSize(spi, size);
776+
777+
if (spi_stm32_set_transfer_size(dev, NULL, NULL, NULL) != 0) {
778+
spi_stm32_iodev_complete(dev, -EINVAL);
779+
}
772780
}
773781
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
774782

@@ -1172,10 +1180,9 @@ static int spi_stm32_configure(const struct device *dev,
11721180
if (cfg->fifo_enabled) {
11731181
/* Do not use bits2bytes here, we want to get 3 for 24-bit operation */
11741182
uint8_t dfs = DIV_ROUND_UP(SPI_WORD_SIZE_GET(config->operation), 8U);
1175-
uint8_t fifo_size = spi_stm32_get_fifo_size(dev);
11761183

11771184
/* FIFO threshold should not exceed half the FIFO size */
1178-
data->fifo_threshold = fifo_size / (dfs * 2U);
1185+
data->fifo_threshold = cfg->fifo_size / (dfs * 2U);
11791186
} else {
11801187
data->fifo_threshold = 1;
11811188
}
@@ -1211,8 +1218,6 @@ static int spi_stm32_release(const struct device *dev, const struct spi_config *
12111218
return 0;
12121219
}
12131220

1214-
#ifndef CONFIG_SPI_RTIO
1215-
12161221
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
12171222
static int32_t spi_stm32_count_bufset_frames(const struct spi_config *config,
12181223
const struct spi_buf_set *bufs)
@@ -1242,36 +1247,19 @@ static int32_t spi_stm32_count_bufset_frames(const struct spi_config *config,
12421247
return frames;
12431248
}
12441249

1245-
static int32_t spi_stm32_count_total_frames(const struct spi_config *config,
1246-
const struct spi_buf_set *tx_bufs,
1247-
const struct spi_buf_set *rx_bufs)
1248-
{
1249-
int tx_frames = spi_stm32_count_bufset_frames(config, tx_bufs);
1250-
1251-
if (tx_frames < 0) {
1252-
return tx_frames;
1253-
}
1254-
1255-
int rx_frames = spi_stm32_count_bufset_frames(config, rx_bufs);
1256-
1257-
if (rx_frames < 0) {
1258-
return rx_frames;
1259-
}
1260-
1261-
return MAX(rx_frames, tx_frames);
1262-
}
1263-
1264-
__maybe_unused
1265-
static int32_t spi_stm32_set_transfer_size(SPI_TypeDef *spi,
1250+
static int32_t spi_stm32_set_transfer_size(const struct device *dev,
12661251
const struct spi_config *config,
12671252
const struct spi_buf_set *tx_bufs,
12681253
const struct spi_buf_set *rx_bufs)
12691254
{
1255+
struct spi_stm32_data *data = dev->data;
1256+
const struct spi_stm32_config *cfg = dev->config;
1257+
SPI_TypeDef *spi = cfg->spi;
12701258
uint32_t transfer_dir = LL_SPI_GetTransferDirection(spi);
12711259
int32_t frames;
12721260

12731261
if (transfer_dir == LL_SPI_FULL_DUPLEX) {
1274-
frames = spi_stm32_count_total_frames(config, tx_bufs, rx_bufs);
1262+
frames = spi_context_max_continuous_chunk(&data->ctx);
12751263
} else if (transfer_dir == LL_SPI_HALF_DUPLEX_TX) {
12761264
frames = spi_stm32_count_bufset_frames(config, tx_bufs);
12771265
} else {
@@ -1282,12 +1270,19 @@ static int32_t spi_stm32_set_transfer_size(SPI_TypeDef *spi,
12821270
return frames;
12831271
}
12841272

1285-
LL_SPI_SetTransferSize(spi, (uint32_t)frames);
1273+
if (frames <= cfg->fifo_max_transfer_size) {
1274+
data->tx_len = data->rx_len = frames;
1275+
LL_SPI_SetTransferSize(spi, (uint32_t)frames);
1276+
} else {
1277+
LOG_ERR("Buffer size exceeds maximal supported value");
1278+
return -EINVAL;
1279+
}
12861280

12871281
return 0;
12881282
}
12891283
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
12901284

1285+
#ifndef CONFIG_SPI_RTIO
12911286
static int spi_stm32_half_duplex_switch_to_receive(const struct spi_stm32_config *cfg,
12921287
struct spi_stm32_data *data)
12931288
{
@@ -1406,8 +1401,10 @@ static int transceive(const struct device *dev,
14061401

14071402
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
14081403
if (cfg->fifo_enabled && SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_MASTER) {
1409-
data->tx_len = data->rx_len = spi_context_max_continuous_chunk(&data->ctx);
1410-
LL_SPI_SetTransferSize(spi, data->tx_len);
1404+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
1405+
if (ret != 0) {
1406+
goto end;
1407+
}
14111408
}
14121409

14131410
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
@@ -1553,7 +1550,7 @@ static int transceive_dma(const struct device *dev,
15531550

15541551
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
15551552
if (transfer_dir == LL_SPI_HALF_DUPLEX_RX) {
1556-
ret = spi_stm32_set_transfer_size(spi, config, tx_bufs, rx_bufs);
1553+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
15571554

15581555
if (ret < 0) {
15591556
goto end;
@@ -1613,7 +1610,10 @@ static int transceive_dma(const struct device *dev,
16131610
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
16141611
if (cfg->fifo_enabled && transfer_dir == LL_SPI_FULL_DUPLEX &&
16151612
SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_MASTER) {
1616-
LL_SPI_SetTransferSize(spi, dma_len);
1613+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
1614+
if (ret != 0) {
1615+
break;
1616+
}
16171617
LL_SPI_Enable(spi);
16181618
LL_SPI_StartMasterTransfer(spi);
16191619
}
@@ -1694,7 +1694,7 @@ static int transceive_dma(const struct device *dev,
16941694
transfer_dir = LL_SPI_HALF_DUPLEX_RX;
16951695

16961696
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
1697-
ret = spi_stm32_set_transfer_size(spi, config, tx_bufs, rx_bufs);
1697+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
16981698

16991699
if (ret < 0) {
17001700
break;
@@ -1995,10 +1995,12 @@ static int spi_stm32_init(const struct device *dev)
19951995
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz), \
19961996
(.use_subghzspi_nss = \
19971997
DT_INST_PROP_OR(id, use_subghzspi_nss, false),))\
1998-
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
1999-
(.midi_clocks = DT_INST_PROP(id, midi_clock),)) \
2000-
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
2001-
(.mssi_clocks = DT_INST_PROP(id, mssi_clock),)) \
1998+
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), ( \
1999+
.midi_clocks = DT_INST_PROP(id, midi_clock), \
2000+
.mssi_clocks = DT_INST_PROP(id, mssi_clock), \
2001+
.fifo_size = DT_INST_PROP(id, fifo_size), \
2002+
.fifo_max_transfer_size = DT_INST_PROP(id, fifo_max_transfer_size), \
2003+
)) \
20022004
}; \
20032005
\
20042006
IF_ENABLED(CONFIG_SPI_RTIO, \

‎drivers/spi/spi_stm32.h‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,26 @@ typedef void (*irq_config_func_t)(const struct device *port);
2222
struct spi_stm32_config {
2323
SPI_TypeDef *spi;
2424
const struct pinctrl_dev_config *pcfg;
25+
const struct stm32_pclken *pclken;
26+
size_t pclk_len;
27+
int datawidth;
2528
#ifdef CONFIG_SPI_STM32_INTERRUPT
2629
irq_config_func_t irq_config;
2730
#ifdef CONFIG_SOC_SERIES_STM32H7X
2831
uint32_t irq_line;
2932
#endif /* CONFIG_SOC_SERIES_STM32H7X */
3033
#endif
31-
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz)
32-
bool use_subghzspi_nss;
33-
#endif
3434
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
3535
int midi_clocks;
3636
int mssi_clocks;
37+
uint32_t fifo_max_transfer_size;
38+
uint8_t fifo_size;
3739
#endif
38-
size_t pclk_len;
39-
const struct stm32_pclken *pclken;
40-
int datawidth;
4140
bool fifo_enabled: 1;
4241
bool ioswp: 1;
42+
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz)
43+
bool use_subghzspi_nss: 1;
44+
#endif
4345
};
4446

4547
#ifdef CONFIG_SPI_STM32_DMA

0 commit comments

Comments
 (0)