Skip to content

Commit a6d603b

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 c8ede24 commit a6d603b

File tree

2 files changed

+61
-55
lines changed

2 files changed

+61
-55
lines changed

‎drivers/spi/spi_stm32.c‎

Lines changed: 53 additions & 49 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

@@ -1170,11 +1178,10 @@ static int spi_stm32_configure(const struct device *dev,
11701178

11711179
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
11721180
if (cfg->fifo_enabled) {
1173-
uint8_t fifo_size = spi_stm32_get_fifo_size(dev);
11741181
/* Do not use bits2bytes here, we want to get 3 for 24-bit operation */
11751182
uint8_t dfs = DIV_ROUND_UP(SPI_WORD_SIZE_GET(config->operation), 8U);
11761183
/* FIFO threshold should not exceed half the FIFO size */
1177-
data->fifo_threshold = fifo_size / (dfs * 2U);
1184+
data->fifo_threshold = cfg->fifo_size / (dfs * 2U);
11781185
} else {
11791186
data->fifo_threshold = 1;
11801187
}
@@ -1210,8 +1217,6 @@ static int spi_stm32_release(const struct device *dev, const struct spi_config *
12101217
return 0;
12111218
}
12121219

1213-
#ifndef CONFIG_SPI_RTIO
1214-
12151220
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
12161221
static int32_t spi_stm32_count_bufset_frames(const struct spi_config *config,
12171222
const struct spi_buf_set *bufs)
@@ -1241,36 +1246,19 @@ static int32_t spi_stm32_count_bufset_frames(const struct spi_config *config,
12411246
return frames;
12421247
}
12431248

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

12721260
if (transfer_dir == LL_SPI_FULL_DUPLEX) {
1273-
frames = spi_stm32_count_total_frames(config, tx_bufs, rx_bufs);
1261+
frames = spi_context_max_continuous_chunk(&data->ctx);
12741262
} else if (transfer_dir == LL_SPI_HALF_DUPLEX_TX) {
12751263
frames = spi_stm32_count_bufset_frames(config, tx_bufs);
12761264
} else {
@@ -1281,12 +1269,19 @@ static int32_t spi_stm32_set_transfer_size(SPI_TypeDef *spi,
12811269
return frames;
12821270
}
12831271

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

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

1284+
#ifndef CONFIG_SPI_RTIO
12901285
static int spi_stm32_half_duplex_switch_to_receive(const struct spi_stm32_config *cfg,
12911286
struct spi_stm32_data *data)
12921287
{
@@ -1405,8 +1400,10 @@ static int transceive(const struct device *dev,
14051400

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

14121409
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */
@@ -1552,7 +1549,7 @@ static int transceive_dma(const struct device *dev,
15521549

15531550
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
15541551
if (transfer_dir == LL_SPI_HALF_DUPLEX_RX) {
1555-
ret = spi_stm32_set_transfer_size(spi, config, tx_bufs, rx_bufs);
1552+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
15561553

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

16951695
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi)
1696-
ret = spi_stm32_set_transfer_size(spi, config, tx_bufs, rx_bufs);
1696+
ret = spi_stm32_set_transfer_size(dev, config, tx_bufs, rx_bufs);
16971697

16981698
if (ret < 0) {
16991699
break;
@@ -1998,6 +1998,10 @@ static int spi_stm32_init(const struct device *dev)
19981998
(.midi_clocks = DT_INST_PROP(id, midi_clock),)) \
19991999
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
20002000
(.mssi_clocks = DT_INST_PROP(id, mssi_clock),)) \
2001+
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
2002+
(.fifo_size = DT_INST_PROP(id, fifo_size),)) \
2003+
IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi), \
2004+
(.fifo_max_transfer_size = DT_INST_PROP(id, fifo_max_transfer_size),))\
20012005
}; \
20022006
\
20032007
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;
44+
#endif
4345
};
4446

4547
#ifdef CONFIG_SPI_STM32_DMA

0 commit comments

Comments
 (0)