Skip to content

Commit f6cd662

Browse files
VCASTMbroonie
authored andcommitted
spi: stm32: add st,stm32mp25-spi compatible supporting STM32MP25 soc
Add support for the STM32MP25: - Burst should not be enabled with the new DMA used on STM32MP25. - STM32MP25 SPI8 has a limited feature set, it can only send words of 8 or 16 bits and with a maximum words number of 1024. Signed-off-by: Valentin Caron <valentin.caron@foss.st.com> Signed-off-by: Alain Volmat <alain.volmat@foss.st.com> Link: https://msgid.link/r/20231218155721.359198-4-alain.volmat@foss.st.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent f034a15 commit f6cd662

File tree

1 file changed

+120
-12
lines changed

1 file changed

+120
-12
lines changed

drivers/spi/spi-stm32.c

Lines changed: 120 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,20 @@
154154
/* STM32H7_SPI_I2SCFGR bit fields */
155155
#define STM32H7_SPI_I2SCFGR_I2SMOD BIT(0)
156156

157+
/* STM32MP25 SPI registers bit fields */
158+
#define STM32MP25_SPI_HWCFGR1 0x3F0
159+
160+
/* STM32MP25_SPI_CR2 bit fields */
161+
#define STM32MP25_SPI_TSIZE_MAX_LIMITED GENMASK(9, 0)
162+
163+
/* STM32MP25_SPI_HWCFGR1 */
164+
#define STM32MP25_SPI_HWCFGR1_FULLCFG GENMASK(27, 24)
165+
#define STM32MP25_SPI_HWCFGR1_FULLCFG_LIMITED 0x0
166+
#define STM32MP25_SPI_HWCFGR1_FULLCFG_FULL 0x1
167+
#define STM32MP25_SPI_HWCFGR1_DSCFG GENMASK(19, 16)
168+
#define STM32MP25_SPI_HWCFGR1_DSCFG_16_B 0x0
169+
#define STM32MP25_SPI_HWCFGR1_DSCFG_32_B 0x1
170+
157171
/* STM32H7 SPI Master Baud Rate min/max divisor */
158172
#define STM32H7_SPI_MBR_DIV_MIN (2 << STM32H7_SPI_CFG1_MBR_MIN)
159173
#define STM32H7_SPI_MBR_DIV_MAX (2 << STM32H7_SPI_CFG1_MBR_MAX)
@@ -207,6 +221,7 @@ struct stm32_spi_reg {
207221
* @br: baud rate register and bitfields
208222
* @rx: SPI RX data register
209223
* @tx: SPI TX data register
224+
* @fullcfg: SPI full or limited feature set register
210225
*/
211226
struct stm32_spi_regspec {
212227
const struct stm32_spi_reg en;
@@ -219,6 +234,7 @@ struct stm32_spi_regspec {
219234
const struct stm32_spi_reg br;
220235
const struct stm32_spi_reg rx;
221236
const struct stm32_spi_reg tx;
237+
const struct stm32_spi_reg fullcfg;
222238
};
223239

224240
struct stm32_spi;
@@ -250,6 +266,7 @@ struct stm32_spi;
250266
* @has_fifo: boolean to know if fifo is used for driver
251267
* @has_device_mode: is this compatible capable to switch on device mode
252268
* @flags: compatible specific SPI controller flags used at registration time
269+
* @prevent_dma_burst: boolean to indicate to prevent DMA burst
253270
*/
254271
struct stm32_spi_cfg {
255272
const struct stm32_spi_regspec *regs;
@@ -274,6 +291,7 @@ struct stm32_spi_cfg {
274291
bool has_fifo;
275292
bool has_device_mode;
276293
u16 flags;
294+
bool prevent_dma_burst;
277295
};
278296

279297
/**
@@ -287,6 +305,8 @@ struct stm32_spi_cfg {
287305
* @lock: prevent I/O concurrent access
288306
* @irq: SPI controller interrupt line
289307
* @fifo_size: size of the embedded fifo in bytes
308+
* @t_size_max: maximum number of data of one transfer
309+
* @feature_set: SPI full or limited feature set
290310
* @cur_midi: host inter-data idleness in ns
291311
* @cur_speed: speed configured in Hz
292312
* @cur_half_period: time of a half bit in us
@@ -314,6 +334,10 @@ struct stm32_spi {
314334
spinlock_t lock; /* prevent I/O concurrent access */
315335
int irq;
316336
unsigned int fifo_size;
337+
unsigned int t_size_max;
338+
unsigned int feature_set;
339+
#define STM32_SPI_FEATURE_LIMITED STM32MP25_SPI_HWCFGR1_FULLCFG_LIMITED /* 0x0 */
340+
#define STM32_SPI_FEATURE_FULL STM32MP25_SPI_HWCFGR1_FULLCFG_FULL /* 0x1 */
317341

318342
unsigned int cur_midi;
319343
unsigned int cur_speed;
@@ -371,6 +395,28 @@ static const struct stm32_spi_regspec stm32h7_spi_regspec = {
371395
.tx = { STM32H7_SPI_TXDR },
372396
};
373397

398+
static const struct stm32_spi_regspec stm32mp25_spi_regspec = {
399+
/* SPI data transfer is enabled but spi_ker_ck is idle.
400+
* CFG1 and CFG2 registers are write protected when SPE is enabled.
401+
*/
402+
.en = { STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE },
403+
404+
.dma_rx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_RXDMAEN },
405+
.dma_tx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN },
406+
407+
.cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL },
408+
.cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA },
409+
.lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST },
410+
.cs_high = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_SSIOP },
411+
.br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR,
412+
STM32H7_SPI_CFG1_MBR_SHIFT },
413+
414+
.rx = { STM32H7_SPI_RXDR },
415+
.tx = { STM32H7_SPI_TXDR },
416+
417+
.fullcfg = { STM32MP25_SPI_HWCFGR1, STM32MP25_SPI_HWCFGR1_FULLCFG },
418+
};
419+
374420
static inline void stm32_spi_set_bits(struct stm32_spi *spi,
375421
u32 offset, u32 bits)
376422
{
@@ -457,6 +503,28 @@ static int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi)
457503
return SPI_BPW_RANGE_MASK(4, max_bpw);
458504
}
459505

506+
/**
507+
* stm32mp25_spi_get_bpw_mask - Return bits per word mask
508+
* @spi: pointer to the spi controller data structure
509+
*/
510+
static int stm32mp25_spi_get_bpw_mask(struct stm32_spi *spi)
511+
{
512+
u32 dscfg, max_bpw;
513+
514+
if (spi->feature_set == STM32_SPI_FEATURE_LIMITED) {
515+
dev_dbg(spi->dev, "8-bit or 16-bit data frame supported\n");
516+
return SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
517+
}
518+
519+
dscfg = FIELD_GET(STM32MP25_SPI_HWCFGR1_DSCFG,
520+
readl_relaxed(spi->base + STM32MP25_SPI_HWCFGR1));
521+
max_bpw = 16;
522+
if (dscfg == STM32MP25_SPI_HWCFGR1_DSCFG_32_B)
523+
max_bpw = 32;
524+
dev_dbg(spi->dev, "%d-bit maximum data frame\n", max_bpw);
525+
return SPI_BPW_RANGE_MASK(4, max_bpw);
526+
}
527+
460528
/**
461529
* stm32_spi_prepare_mbr - Determine baud rate divisor value
462530
* @spi: pointer to the spi controller data structure
@@ -1103,7 +1171,7 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl,
11031171
int ret;
11041172

11051173
ret = spi_split_transfers_maxwords(ctrl, msg,
1106-
STM32H7_SPI_TSIZE_MAX,
1174+
spi->t_size_max,
11071175
GFP_KERNEL | GFP_DMA);
11081176
if (ret)
11091177
return ret;
@@ -1168,7 +1236,7 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
11681236
{
11691237
enum dma_slave_buswidth buswidth;
11701238
struct dma_slave_caps caps;
1171-
u32 maxburst;
1239+
u32 maxburst = 1;
11721240
int ret;
11731241

11741242
if (spi->cur_bpw <= 8)
@@ -1178,15 +1246,9 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
11781246
else
11791247
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
11801248

1181-
if (spi->cfg->has_fifo) {
1182-
/* Valid for DMA Half or Full Fifo threshold */
1183-
if (spi->cur_fthlv == 2)
1184-
maxburst = 1;
1185-
else
1186-
maxburst = spi->cur_fthlv;
1187-
} else {
1188-
maxburst = 1;
1189-
}
1249+
/* Valid for DMA Half or Full Fifo threshold */
1250+
if (!spi->cfg->prevent_dma_burst && spi->cfg->has_fifo && spi->cur_fthlv != 2)
1251+
maxburst = spi->cur_fthlv;
11901252

11911253
/* Get the DMA channel caps, and adjust maxburst if possible */
11921254
ret = dma_get_slave_caps(dma_chan, &caps);
@@ -1671,7 +1733,7 @@ static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len)
16711733
*/
16721734
static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words)
16731735
{
1674-
if (nb_words <= STM32H7_SPI_TSIZE_MAX) {
1736+
if (nb_words <= spi->t_size_max) {
16751737
writel_relaxed(FIELD_PREP(STM32H7_SPI_CR2_TSIZE, nb_words),
16761738
spi->base + STM32H7_SPI_CR2);
16771739
} else {
@@ -1954,7 +2016,37 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = {
19542016
.has_device_mode = true,
19552017
};
19562018

2019+
/*
2020+
* STM32MP2 is compatible with the STM32H7 except:
2021+
* - enforce the DMA maxburst value to 1
2022+
* - spi8 have limited feature set (TSIZE_MAX = 1024, BPW of 8 OR 16)
2023+
*/
2024+
static const struct stm32_spi_cfg stm32mp25_spi_cfg = {
2025+
.regs = &stm32mp25_spi_regspec,
2026+
.get_fifo_size = stm32h7_spi_get_fifo_size,
2027+
.get_bpw_mask = stm32mp25_spi_get_bpw_mask,
2028+
.disable = stm32h7_spi_disable,
2029+
.config = stm32h7_spi_config,
2030+
.set_bpw = stm32h7_spi_set_bpw,
2031+
.set_mode = stm32h7_spi_set_mode,
2032+
.set_data_idleness = stm32h7_spi_data_idleness,
2033+
.set_number_of_data = stm32h7_spi_number_of_data,
2034+
.transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start,
2035+
.dma_rx_cb = stm32_spi_dma_rx_cb,
2036+
/*
2037+
* dma_tx_cb is not necessary since in case of TX, dma is followed by
2038+
* SPI access hence handling is performed within the SPI interrupt
2039+
*/
2040+
.transfer_one_irq = stm32h7_spi_transfer_one_irq,
2041+
.irq_handler_thread = stm32h7_spi_irq_thread,
2042+
.baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN,
2043+
.baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX,
2044+
.has_fifo = true,
2045+
.prevent_dma_burst = true,
2046+
};
2047+
19572048
static const struct of_device_id stm32_spi_of_match[] = {
2049+
{ .compatible = "st,stm32mp25-spi", .data = (void *)&stm32mp25_spi_cfg },
19582050
{ .compatible = "st,stm32h7-spi", .data = (void *)&stm32h7_spi_cfg },
19592051
{ .compatible = "st,stm32f4-spi", .data = (void *)&stm32f4_spi_cfg },
19602052
{ .compatible = "st,stm32f7-spi", .data = (void *)&stm32f7_spi_cfg },
@@ -2058,6 +2150,22 @@ static int stm32_spi_probe(struct platform_device *pdev)
20582150
if (spi->cfg->has_fifo)
20592151
spi->fifo_size = spi->cfg->get_fifo_size(spi);
20602152

2153+
spi->feature_set = STM32_SPI_FEATURE_FULL;
2154+
if (spi->cfg->regs->fullcfg.reg) {
2155+
spi->feature_set =
2156+
FIELD_GET(STM32MP25_SPI_HWCFGR1_FULLCFG,
2157+
readl_relaxed(spi->base + spi->cfg->regs->fullcfg.reg));
2158+
2159+
dev_dbg(spi->dev, "%s feature set\n",
2160+
spi->feature_set == STM32_SPI_FEATURE_FULL ? "full" : "limited");
2161+
}
2162+
2163+
/* Only for STM32H7 and after */
2164+
spi->t_size_max = spi->feature_set == STM32_SPI_FEATURE_FULL ?
2165+
STM32H7_SPI_TSIZE_MAX :
2166+
STM32MP25_SPI_TSIZE_MAX_LIMITED;
2167+
dev_dbg(spi->dev, "one message max size %d\n", spi->t_size_max);
2168+
20612169
ret = spi->cfg->config(spi);
20622170
if (ret) {
20632171
dev_err(&pdev->dev, "controller configuration failed: %d\n",

0 commit comments

Comments
 (0)