Add STM32F7 SPI support

Merge series from Ben Wolsieffer <ben.wolsieffer@hefring.com>:

This series adds support for SPI on STM32F7 processors. The STM32F7 SPI
peripheral is nearly identical to the STM32F4, with the only significant
differences being that it supports a wider range of word sizes, and the
addition of 32-bit transmit and receive FIFOs.

v2:
  - Add missing commit body

Ben Wolsieffer (5):
  spi: stm32: rename stm32f4_* to stm32fx_*
  spi: stm32: use callbacks for read_rx and write_tx
  dt-bindings: spi: add stm32f7-spi compatible
  spi: stm32: add STM32F7 support
  ARM: dts: stm32: add SPI support on STM32F746

 .../devicetree/bindings/spi/st,stm32-spi.yaml |   1 +
 arch/arm/boot/dts/st/stm32f746.dtsi           |  60 +++
 drivers/spi/spi-stm32.c                       | 455 ++++++++++++------
 3 files changed, 367 insertions(+), 149 deletions(-)

--
2.42.0
This commit is contained in:
Mark Brown 2023-11-13 18:15:20 +00:00
commit 6f9da18171
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 303 additions and 145 deletions

View File

@ -23,6 +23,7 @@ properties:
compatible:
enum:
- st,stm32f4-spi
- st,stm32f7-spi
- st,stm32h7-spi
reg:

View File

@ -22,58 +22,65 @@
#define DRIVER_NAME "spi_stm32"
/* STM32F4 SPI registers */
#define STM32F4_SPI_CR1 0x00
#define STM32F4_SPI_CR2 0x04
#define STM32F4_SPI_SR 0x08
#define STM32F4_SPI_DR 0x0C
#define STM32F4_SPI_I2SCFGR 0x1C
/* STM32F4/7 SPI registers */
#define STM32FX_SPI_CR1 0x00
#define STM32FX_SPI_CR2 0x04
#define STM32FX_SPI_SR 0x08
#define STM32FX_SPI_DR 0x0C
#define STM32FX_SPI_I2SCFGR 0x1C
/* STM32F4_SPI_CR1 bit fields */
#define STM32F4_SPI_CR1_CPHA BIT(0)
#define STM32F4_SPI_CR1_CPOL BIT(1)
#define STM32F4_SPI_CR1_MSTR BIT(2)
#define STM32F4_SPI_CR1_BR_SHIFT 3
#define STM32F4_SPI_CR1_BR GENMASK(5, 3)
#define STM32F4_SPI_CR1_SPE BIT(6)
#define STM32F4_SPI_CR1_LSBFRST BIT(7)
#define STM32F4_SPI_CR1_SSI BIT(8)
#define STM32F4_SPI_CR1_SSM BIT(9)
#define STM32F4_SPI_CR1_RXONLY BIT(10)
/* STM32FX_SPI_CR1 bit fields */
#define STM32FX_SPI_CR1_CPHA BIT(0)
#define STM32FX_SPI_CR1_CPOL BIT(1)
#define STM32FX_SPI_CR1_MSTR BIT(2)
#define STM32FX_SPI_CR1_BR_SHIFT 3
#define STM32FX_SPI_CR1_BR GENMASK(5, 3)
#define STM32FX_SPI_CR1_SPE BIT(6)
#define STM32FX_SPI_CR1_LSBFRST BIT(7)
#define STM32FX_SPI_CR1_SSI BIT(8)
#define STM32FX_SPI_CR1_SSM BIT(9)
#define STM32FX_SPI_CR1_RXONLY BIT(10)
#define STM32F4_SPI_CR1_DFF BIT(11)
#define STM32F4_SPI_CR1_CRCNEXT BIT(12)
#define STM32F4_SPI_CR1_CRCEN BIT(13)
#define STM32F4_SPI_CR1_BIDIOE BIT(14)
#define STM32F4_SPI_CR1_BIDIMODE BIT(15)
#define STM32F4_SPI_CR1_BR_MIN 0
#define STM32F4_SPI_CR1_BR_MAX (GENMASK(5, 3) >> 3)
#define STM32F7_SPI_CR1_CRCL BIT(11)
#define STM32FX_SPI_CR1_CRCNEXT BIT(12)
#define STM32FX_SPI_CR1_CRCEN BIT(13)
#define STM32FX_SPI_CR1_BIDIOE BIT(14)
#define STM32FX_SPI_CR1_BIDIMODE BIT(15)
#define STM32FX_SPI_CR1_BR_MIN 0
#define STM32FX_SPI_CR1_BR_MAX (GENMASK(5, 3) >> 3)
/* STM32F4_SPI_CR2 bit fields */
#define STM32F4_SPI_CR2_RXDMAEN BIT(0)
#define STM32F4_SPI_CR2_TXDMAEN BIT(1)
#define STM32F4_SPI_CR2_SSOE BIT(2)
#define STM32F4_SPI_CR2_FRF BIT(4)
#define STM32F4_SPI_CR2_ERRIE BIT(5)
#define STM32F4_SPI_CR2_RXNEIE BIT(6)
#define STM32F4_SPI_CR2_TXEIE BIT(7)
/* STM32FX_SPI_CR2 bit fields */
#define STM32FX_SPI_CR2_RXDMAEN BIT(0)
#define STM32FX_SPI_CR2_TXDMAEN BIT(1)
#define STM32FX_SPI_CR2_SSOE BIT(2)
#define STM32FX_SPI_CR2_FRF BIT(4)
#define STM32FX_SPI_CR2_ERRIE BIT(5)
#define STM32FX_SPI_CR2_RXNEIE BIT(6)
#define STM32FX_SPI_CR2_TXEIE BIT(7)
#define STM32F7_SPI_CR2_DS GENMASK(11, 8)
#define STM32F7_SPI_CR2_FRXTH BIT(12)
#define STM32F7_SPI_CR2_LDMA_RX BIT(13)
#define STM32F7_SPI_CR2_LDMA_TX BIT(14)
/* STM32F4_SPI_SR bit fields */
#define STM32F4_SPI_SR_RXNE BIT(0)
#define STM32F4_SPI_SR_TXE BIT(1)
#define STM32F4_SPI_SR_CHSIDE BIT(2)
#define STM32F4_SPI_SR_UDR BIT(3)
#define STM32F4_SPI_SR_CRCERR BIT(4)
#define STM32F4_SPI_SR_MODF BIT(5)
#define STM32F4_SPI_SR_OVR BIT(6)
#define STM32F4_SPI_SR_BSY BIT(7)
#define STM32F4_SPI_SR_FRE BIT(8)
/* STM32FX_SPI_SR bit fields */
#define STM32FX_SPI_SR_RXNE BIT(0)
#define STM32FX_SPI_SR_TXE BIT(1)
#define STM32FX_SPI_SR_CHSIDE BIT(2)
#define STM32FX_SPI_SR_UDR BIT(3)
#define STM32FX_SPI_SR_CRCERR BIT(4)
#define STM32FX_SPI_SR_MODF BIT(5)
#define STM32FX_SPI_SR_OVR BIT(6)
#define STM32FX_SPI_SR_BSY BIT(7)
#define STM32FX_SPI_SR_FRE BIT(8)
#define STM32F7_SPI_SR_FRLVL GENMASK(10, 9)
#define STM32F7_SPI_SR_FTLVL GENMASK(12, 11)
/* STM32F4_SPI_I2SCFGR bit fields */
#define STM32F4_SPI_I2SCFGR_I2SMOD BIT(11)
/* STM32FX_SPI_I2SCFGR bit fields */
#define STM32FX_SPI_I2SCFGR_I2SMOD BIT(11)
/* STM32F4 SPI Baud Rate min/max divisor */
#define STM32F4_SPI_BR_DIV_MIN (2 << STM32F4_SPI_CR1_BR_MIN)
#define STM32F4_SPI_BR_DIV_MAX (2 << STM32F4_SPI_CR1_BR_MAX)
#define STM32FX_SPI_BR_DIV_MIN (2 << STM32FX_SPI_CR1_BR_MIN)
#define STM32FX_SPI_BR_DIV_MAX (2 << STM32FX_SPI_CR1_BR_MAX)
/* STM32H7 SPI registers */
#define STM32H7_SPI_CR1 0x00
@ -229,6 +236,8 @@ struct stm32_spi;
* time between frames (if driver has this functionality)
* @set_number_of_data: optional routine to configure registers to desired
* number of data (if driver has this functionality)
* @write_tx: routine to write to transmit register/FIFO
* @read_rx: routine to read from receive register/FIFO
* @transfer_one_dma_start: routine to start transfer a single spi_transfer
* using DMA
* @dma_rx_cb: routine to call after DMA RX channel operation is complete
@ -252,6 +261,8 @@ struct stm32_spi_cfg {
int (*set_mode)(struct stm32_spi *spi, unsigned int comm_type);
void (*set_data_idleness)(struct stm32_spi *spi, u32 length);
int (*set_number_of_data)(struct stm32_spi *spi, u32 length);
void (*write_tx)(struct stm32_spi *spi);
void (*read_rx)(struct stm32_spi *spi);
void (*transfer_one_dma_start)(struct stm32_spi *spi);
void (*dma_rx_cb)(void *data);
void (*dma_tx_cb)(void *data);
@ -324,20 +335,20 @@ struct stm32_spi {
bool device_mode;
};
static const struct stm32_spi_regspec stm32f4_spi_regspec = {
.en = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE },
static const struct stm32_spi_regspec stm32fx_spi_regspec = {
.en = { STM32FX_SPI_CR1, STM32FX_SPI_CR1_SPE },
.dma_rx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_RXDMAEN },
.dma_tx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN },
.dma_rx_en = { STM32FX_SPI_CR2, STM32FX_SPI_CR2_RXDMAEN },
.dma_tx_en = { STM32FX_SPI_CR2, STM32FX_SPI_CR2_TXDMAEN },
.cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL },
.cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA },
.lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST },
.cpol = { STM32FX_SPI_CR1, STM32FX_SPI_CR1_CPOL },
.cpha = { STM32FX_SPI_CR1, STM32FX_SPI_CR1_CPHA },
.lsb_first = { STM32FX_SPI_CR1, STM32FX_SPI_CR1_LSBFRST },
.cs_high = {},
.br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT },
.br = { STM32FX_SPI_CR1, STM32FX_SPI_CR1_BR, STM32FX_SPI_CR1_BR_SHIFT },
.rx = { STM32F4_SPI_DR },
.tx = { STM32F4_SPI_DR },
.rx = { STM32FX_SPI_DR },
.tx = { STM32FX_SPI_DR },
};
static const struct stm32_spi_regspec stm32h7_spi_regspec = {
@ -409,6 +420,16 @@ static int stm32f4_spi_get_bpw_mask(struct stm32_spi *spi)
return SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
}
/**
* stm32f7_spi_get_bpw_mask - Return bits per word mask
* @spi: pointer to the spi controller data structure
*/
static int stm32f7_spi_get_bpw_mask(struct stm32_spi *spi)
{
dev_dbg(spi->dev, "16-bit maximum data frame\n");
return SPI_BPW_RANGE_MASK(4, 16);
}
/**
* stm32h7_spi_get_bpw_mask - Return bits per word mask
* @spi: pointer to the spi controller data structure
@ -502,19 +523,48 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len)
*/
static void stm32f4_spi_write_tx(struct stm32_spi *spi)
{
if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) &
STM32F4_SPI_SR_TXE)) {
if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32FX_SPI_SR) &
STM32FX_SPI_SR_TXE)) {
u32 offs = spi->cur_xferlen - spi->tx_len;
if (spi->cur_bpw == 16) {
const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs);
writew_relaxed(*tx_buf16, spi->base + STM32F4_SPI_DR);
writew_relaxed(*tx_buf16, spi->base + STM32FX_SPI_DR);
spi->tx_len -= sizeof(u16);
} else {
const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs);
writeb_relaxed(*tx_buf8, spi->base + STM32F4_SPI_DR);
writeb_relaxed(*tx_buf8, spi->base + STM32FX_SPI_DR);
spi->tx_len -= sizeof(u8);
}
}
dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len);
}
/**
* stm32f7_spi_write_tx - Write bytes to Transmit Data Register
* @spi: pointer to the spi controller data structure
*
* Read from tx_buf depends on remaining bytes to avoid to read beyond
* tx_buf end.
*/
static void stm32f7_spi_write_tx(struct stm32_spi *spi)
{
if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32FX_SPI_SR) &
STM32FX_SPI_SR_TXE)) {
u32 offs = spi->cur_xferlen - spi->tx_len;
if (spi->tx_len >= sizeof(u16)) {
const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs);
writew_relaxed(*tx_buf16, spi->base + STM32FX_SPI_DR);
spi->tx_len -= sizeof(u16);
} else {
const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs);
writeb_relaxed(*tx_buf8, spi->base + STM32FX_SPI_DR);
spi->tx_len -= sizeof(u8);
}
}
@ -566,19 +616,19 @@ static void stm32h7_spi_write_txfifo(struct stm32_spi *spi)
*/
static void stm32f4_spi_read_rx(struct stm32_spi *spi)
{
if ((spi->rx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) &
STM32F4_SPI_SR_RXNE)) {
if ((spi->rx_len > 0) && (readl_relaxed(spi->base + STM32FX_SPI_SR) &
STM32FX_SPI_SR_RXNE)) {
u32 offs = spi->cur_xferlen - spi->rx_len;
if (spi->cur_bpw == 16) {
u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs);
*rx_buf16 = readw_relaxed(spi->base + STM32F4_SPI_DR);
*rx_buf16 = readw_relaxed(spi->base + STM32FX_SPI_DR);
spi->rx_len -= sizeof(u16);
} else {
u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs);
*rx_buf8 = readb_relaxed(spi->base + STM32F4_SPI_DR);
*rx_buf8 = readb_relaxed(spi->base + STM32FX_SPI_DR);
spi->rx_len -= sizeof(u8);
}
}
@ -586,6 +636,46 @@ static void stm32f4_spi_read_rx(struct stm32_spi *spi)
dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->rx_len);
}
/**
* stm32f7_spi_read_rx - Read bytes from Receive Data Register
* @spi: pointer to the spi controller data structure
*
* Write in rx_buf depends on remaining bytes to avoid to write beyond
* rx_buf end.
*/
static void stm32f7_spi_read_rx(struct stm32_spi *spi)
{
u32 sr = readl_relaxed(spi->base + STM32FX_SPI_SR);
u32 frlvl = FIELD_GET(STM32F7_SPI_SR_FRLVL, sr);
while ((spi->rx_len > 0) && (frlvl > 0)) {
u32 offs = spi->cur_xferlen - spi->rx_len;
if ((spi->rx_len >= sizeof(u16)) && (frlvl >= 2)) {
u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs);
*rx_buf16 = readw_relaxed(spi->base + STM32FX_SPI_DR);
spi->rx_len -= sizeof(u16);
} else {
u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs);
*rx_buf8 = readb_relaxed(spi->base + STM32FX_SPI_DR);
spi->rx_len -= sizeof(u8);
}
sr = readl_relaxed(spi->base + STM32FX_SPI_SR);
frlvl = FIELD_GET(STM32F7_SPI_SR_FRLVL, sr);
}
if (spi->rx_len >= sizeof(u16))
stm32_spi_clr_bits(spi, STM32FX_SPI_CR2, STM32F7_SPI_CR2_FRXTH);
else
stm32_spi_set_bits(spi, STM32FX_SPI_CR2, STM32F7_SPI_CR2_FRXTH);
dev_dbg(spi->dev, "%s: %d bytes left (sr=%08x)\n",
__func__, spi->rx_len, sr);
}
/**
* stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register
* @spi: pointer to the spi controller data structure
@ -645,10 +735,10 @@ static void stm32_spi_enable(struct stm32_spi *spi)
}
/**
* stm32f4_spi_disable - Disable SPI controller
* stm32fx_spi_disable - Disable SPI controller
* @spi: pointer to the spi controller data structure
*/
static void stm32f4_spi_disable(struct stm32_spi *spi)
static void stm32fx_spi_disable(struct stm32_spi *spi)
{
unsigned long flags;
u32 sr;
@ -657,20 +747,20 @@ static void stm32f4_spi_disable(struct stm32_spi *spi)
spin_lock_irqsave(&spi->lock, flags);
if (!(readl_relaxed(spi->base + STM32F4_SPI_CR1) &
STM32F4_SPI_CR1_SPE)) {
if (!(readl_relaxed(spi->base + STM32FX_SPI_CR1) &
STM32FX_SPI_CR1_SPE)) {
spin_unlock_irqrestore(&spi->lock, flags);
return;
}
/* Disable interrupts */
stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXEIE |
STM32F4_SPI_CR2_RXNEIE |
STM32F4_SPI_CR2_ERRIE);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR2, STM32FX_SPI_CR2_TXEIE |
STM32FX_SPI_CR2_RXNEIE |
STM32FX_SPI_CR2_ERRIE);
/* Wait until BSY = 0 */
if (readl_relaxed_poll_timeout_atomic(spi->base + STM32F4_SPI_SR,
sr, !(sr & STM32F4_SPI_SR_BSY),
if (readl_relaxed_poll_timeout_atomic(spi->base + STM32FX_SPI_SR,
sr, !(sr & STM32FX_SPI_SR_BSY),
10, 100000) < 0) {
dev_warn(spi->dev, "disabling condition timeout\n");
}
@ -680,14 +770,14 @@ static void stm32f4_spi_disable(struct stm32_spi *spi)
if (spi->cur_usedma && spi->dma_rx)
dmaengine_terminate_async(spi->dma_rx);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR1, STM32FX_SPI_CR1_SPE);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN |
STM32F4_SPI_CR2_RXDMAEN);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR2, STM32FX_SPI_CR2_TXDMAEN |
STM32FX_SPI_CR2_RXDMAEN);
/* Sequence to clear OVR flag */
readl_relaxed(spi->base + STM32F4_SPI_DR);
readl_relaxed(spi->base + STM32F4_SPI_SR);
readl_relaxed(spi->base + STM32FX_SPI_DR);
readl_relaxed(spi->base + STM32FX_SPI_SR);
spin_unlock_irqrestore(&spi->lock, flags);
}
@ -763,11 +853,11 @@ static bool stm32_spi_can_dma(struct spi_controller *ctrl,
}
/**
* stm32f4_spi_irq_event - Interrupt handler for SPI controller events
* stm32fx_spi_irq_event - Interrupt handler for SPI controller events
* @irq: interrupt line
* @dev_id: SPI controller ctrl interface
*/
static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
static irqreturn_t stm32fx_spi_irq_event(int irq, void *dev_id)
{
struct spi_controller *ctrl = dev_id;
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
@ -776,26 +866,26 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
spin_lock(&spi->lock);
sr = readl_relaxed(spi->base + STM32F4_SPI_SR);
sr = readl_relaxed(spi->base + STM32FX_SPI_SR);
/*
* BSY flag is not handled in interrupt but it is normal behavior when
* this flag is set.
*/
sr &= ~STM32F4_SPI_SR_BSY;
sr &= ~STM32FX_SPI_SR_BSY;
if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX ||
spi->cur_comm == SPI_3WIRE_TX)) {
/* OVR flag shouldn't be handled for TX only mode */
sr &= ~(STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE);
mask |= STM32F4_SPI_SR_TXE;
sr &= ~(STM32FX_SPI_SR_OVR | STM32FX_SPI_SR_RXNE);
mask |= STM32FX_SPI_SR_TXE;
}
if (!spi->cur_usedma && (spi->cur_comm == SPI_FULL_DUPLEX ||
spi->cur_comm == SPI_SIMPLEX_RX ||
spi->cur_comm == SPI_3WIRE_RX)) {
/* TXE flag is set and is handled when RXNE flag occurs */
sr &= ~STM32F4_SPI_SR_TXE;
mask |= STM32F4_SPI_SR_RXNE | STM32F4_SPI_SR_OVR;
sr &= ~STM32FX_SPI_SR_TXE;
mask |= STM32FX_SPI_SR_RXNE | STM32FX_SPI_SR_OVR;
}
if (!(sr & mask)) {
@ -804,12 +894,12 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
return IRQ_NONE;
}
if (sr & STM32F4_SPI_SR_OVR) {
if (sr & STM32FX_SPI_SR_OVR) {
dev_warn(spi->dev, "Overrun: received value discarded\n");
/* Sequence to clear OVR flag */
readl_relaxed(spi->base + STM32F4_SPI_DR);
readl_relaxed(spi->base + STM32F4_SPI_SR);
readl_relaxed(spi->base + STM32FX_SPI_DR);
readl_relaxed(spi->base + STM32FX_SPI_SR);
/*
* If overrun is detected, it means that something went wrong,
@ -820,28 +910,28 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
goto end_irq;
}
if (sr & STM32F4_SPI_SR_TXE) {
if (sr & STM32FX_SPI_SR_TXE) {
if (spi->tx_buf)
stm32f4_spi_write_tx(spi);
spi->cfg->write_tx(spi);
if (spi->tx_len == 0)
end = true;
}
if (sr & STM32F4_SPI_SR_RXNE) {
stm32f4_spi_read_rx(spi);
if (sr & STM32FX_SPI_SR_RXNE) {
spi->cfg->read_rx(spi);
if (spi->rx_len == 0)
end = true;
else if (spi->tx_buf)/* Load data for discontinuous mode */
stm32f4_spi_write_tx(spi);
spi->cfg->write_tx(spi);
}
end_irq:
if (end) {
/* Immediately disable interrupts to do not generate new one */
stm32_spi_clr_bits(spi, STM32F4_SPI_CR2,
STM32F4_SPI_CR2_TXEIE |
STM32F4_SPI_CR2_RXNEIE |
STM32F4_SPI_CR2_ERRIE);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR2,
STM32FX_SPI_CR2_TXEIE |
STM32FX_SPI_CR2_RXNEIE |
STM32FX_SPI_CR2_ERRIE);
spin_unlock(&spi->lock);
return IRQ_WAKE_THREAD;
}
@ -851,17 +941,17 @@ end_irq:
}
/**
* stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller
* stm32fx_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
* @dev_id: SPI controller interface
*/
static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
static irqreturn_t stm32fx_spi_irq_thread(int irq, void *dev_id)
{
struct spi_controller *ctrl = dev_id;
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
spi_finalize_current_transfer(ctrl);
stm32f4_spi_disable(spi);
stm32fx_spi_disable(spi);
return IRQ_HANDLED;
}
@ -1034,18 +1124,18 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl,
}
/**
* stm32f4_spi_dma_tx_cb - dma callback
* stm32fx_spi_dma_tx_cb - dma callback
* @data: pointer to the spi controller data structure
*
* DMA callback is called when the transfer is complete for DMA TX channel.
*/
static void stm32f4_spi_dma_tx_cb(void *data)
static void stm32fx_spi_dma_tx_cb(void *data)
{
struct stm32_spi *spi = data;
if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
spi_finalize_current_transfer(spi->ctrl);
stm32f4_spi_disable(spi);
stm32fx_spi_disable(spi);
}
}
@ -1114,21 +1204,21 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
}
/**
* stm32f4_spi_transfer_one_irq - transfer a single spi_transfer using
* stm32fx_spi_transfer_one_irq - transfer a single spi_transfer using
* interrupts
* @spi: pointer to the spi controller data structure
*
* It must returns 0 if the transfer is finished or 1 if the transfer is still
* in progress.
*/
static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi)
static int stm32fx_spi_transfer_one_irq(struct stm32_spi *spi)
{
unsigned long flags;
u32 cr2 = 0;
/* Enable the interrupts relative to the current communication mode */
if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
cr2 |= STM32F4_SPI_CR2_TXEIE;
cr2 |= STM32FX_SPI_CR2_TXEIE;
} else if (spi->cur_comm == SPI_FULL_DUPLEX ||
spi->cur_comm == SPI_SIMPLEX_RX ||
spi->cur_comm == SPI_3WIRE_RX) {
@ -1136,20 +1226,20 @@ static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi)
* since the received data are never read. Therefore set OVR
* interrupt only when rx buffer is available.
*/
cr2 |= STM32F4_SPI_CR2_RXNEIE | STM32F4_SPI_CR2_ERRIE;
cr2 |= STM32FX_SPI_CR2_RXNEIE | STM32FX_SPI_CR2_ERRIE;
} else {
return -EINVAL;
}
spin_lock_irqsave(&spi->lock, flags);
stm32_spi_set_bits(spi, STM32F4_SPI_CR2, cr2);
stm32_spi_set_bits(spi, STM32FX_SPI_CR2, cr2);
stm32_spi_enable(spi);
/* starting data transfer when buffer is loaded */
if (spi->tx_buf)
stm32f4_spi_write_tx(spi);
spi->cfg->write_tx(spi);
spin_unlock_irqrestore(&spi->lock, flags);
@ -1200,11 +1290,11 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi)
}
/**
* stm32f4_spi_transfer_one_dma_start - Set SPI driver registers to start
* stm32fx_spi_transfer_one_dma_start - Set SPI driver registers to start
* transfer using DMA
* @spi: pointer to the spi controller data structure
*/
static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi)
static void stm32fx_spi_transfer_one_dma_start(struct stm32_spi *spi)
{
/* In DMA mode end of transfer is handled by DMA TX or RX callback. */
if (spi->cur_comm == SPI_SIMPLEX_RX || spi->cur_comm == SPI_3WIRE_RX ||
@ -1214,12 +1304,28 @@ static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi)
* since the received data are never read. Therefore set OVR
* interrupt only when rx buffer is available.
*/
stm32_spi_set_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_ERRIE);
stm32_spi_set_bits(spi, STM32FX_SPI_CR2, STM32FX_SPI_CR2_ERRIE);
}
stm32_spi_enable(spi);
}
/**
* stm32f7_spi_transfer_one_dma_start - Set SPI driver registers to start
* transfer using DMA
* @spi: pointer to the spi controller data structure
*/
static void stm32f7_spi_transfer_one_dma_start(struct stm32_spi *spi)
{
/* Configure DMA request trigger threshold according to DMA width */
if (spi->cur_bpw <= 8)
stm32_spi_set_bits(spi, STM32FX_SPI_CR2, STM32F7_SPI_CR2_FRXTH);
else
stm32_spi_clr_bits(spi, STM32FX_SPI_CR2, STM32F7_SPI_CR2_FRXTH);
stm32fx_spi_transfer_one_dma_start(spi);
}
/**
* stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start
* transfer using DMA
@ -1353,9 +1459,34 @@ dma_desc_error:
static void stm32f4_spi_set_bpw(struct stm32_spi *spi)
{
if (spi->cur_bpw == 16)
stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF);
stm32_spi_set_bits(spi, STM32FX_SPI_CR1, STM32F4_SPI_CR1_DFF);
else
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR1, STM32F4_SPI_CR1_DFF);
}
/**
* stm32f7_spi_set_bpw - Configure bits per word
* @spi: pointer to the spi controller data structure
*/
static void stm32f7_spi_set_bpw(struct stm32_spi *spi)
{
u32 bpw;
u32 cr2_clrb = 0, cr2_setb = 0;
bpw = spi->cur_bpw - 1;
cr2_clrb |= STM32F7_SPI_CR2_DS;
cr2_setb |= FIELD_PREP(STM32F7_SPI_CR2_DS, bpw);
if (spi->rx_len >= sizeof(u16))
cr2_clrb |= STM32F7_SPI_CR2_FRXTH;
else
cr2_setb |= STM32F7_SPI_CR2_FRXTH;
writel_relaxed(
(readl_relaxed(spi->base + STM32FX_SPI_CR2) &
~cr2_clrb) | cr2_setb,
spi->base + STM32FX_SPI_CR2);
}
/**
@ -1433,26 +1564,26 @@ static unsigned int stm32_spi_communication_type(struct spi_device *spi_dev,
}
/**
* stm32f4_spi_set_mode - configure communication mode
* stm32fx_spi_set_mode - configure communication mode
* @spi: pointer to the spi controller data structure
* @comm_type: type of communication to configure
*/
static int stm32f4_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
static int stm32fx_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
{
if (comm_type == SPI_3WIRE_TX || comm_type == SPI_SIMPLEX_TX) {
stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIMODE |
STM32F4_SPI_CR1_BIDIOE);
stm32_spi_set_bits(spi, STM32FX_SPI_CR1,
STM32FX_SPI_CR1_BIDIMODE |
STM32FX_SPI_CR1_BIDIOE);
} else if (comm_type == SPI_FULL_DUPLEX ||
comm_type == SPI_SIMPLEX_RX) {
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIMODE |
STM32F4_SPI_CR1_BIDIOE);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR1,
STM32FX_SPI_CR1_BIDIMODE |
STM32FX_SPI_CR1_BIDIOE);
} else if (comm_type == SPI_3WIRE_RX) {
stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIMODE);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIOE);
stm32_spi_set_bits(spi, STM32FX_SPI_CR1,
STM32FX_SPI_CR1_BIDIMODE);
stm32_spi_clr_bits(spi, STM32FX_SPI_CR1,
STM32FX_SPI_CR1_BIDIOE);
} else {
return -EINVAL;
}
@ -1672,18 +1803,18 @@ static int stm32_spi_unprepare_msg(struct spi_controller *ctrl,
}
/**
* stm32f4_spi_config - Configure SPI controller as SPI master
* stm32fx_spi_config - Configure SPI controller as SPI master
* @spi: pointer to the spi controller data structure
*/
static int stm32f4_spi_config(struct stm32_spi *spi)
static int stm32fx_spi_config(struct stm32_spi *spi)
{
unsigned long flags;
spin_lock_irqsave(&spi->lock, flags);
/* Ensure I2SMOD bit is kept cleared */
stm32_spi_clr_bits(spi, STM32F4_SPI_I2SCFGR,
STM32F4_SPI_I2SCFGR_I2SMOD);
stm32_spi_clr_bits(spi, STM32FX_SPI_I2SCFGR,
STM32FX_SPI_I2SCFGR_I2SMOD);
/*
* - SS input value high
@ -1692,10 +1823,10 @@ static int stm32f4_spi_config(struct stm32_spi *spi)
* - Consider 1 master/n slaves configuration and
* SS input value is determined by the SSI bit
*/
stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SSI |
STM32F4_SPI_CR1_BIDIOE |
STM32F4_SPI_CR1_MSTR |
STM32F4_SPI_CR1_SSM);
stm32_spi_set_bits(spi, STM32FX_SPI_CR1, STM32FX_SPI_CR1_SSI |
STM32FX_SPI_CR1_BIDIOE |
STM32FX_SPI_CR1_MSTR |
STM32FX_SPI_CR1_SSM);
spin_unlock_irqrestore(&spi->lock, flags);
@ -1746,25 +1877,48 @@ static int stm32h7_spi_config(struct stm32_spi *spi)
}
static const struct stm32_spi_cfg stm32f4_spi_cfg = {
.regs = &stm32f4_spi_regspec,
.regs = &stm32fx_spi_regspec,
.get_bpw_mask = stm32f4_spi_get_bpw_mask,
.disable = stm32f4_spi_disable,
.config = stm32f4_spi_config,
.disable = stm32fx_spi_disable,
.config = stm32fx_spi_config,
.set_bpw = stm32f4_spi_set_bpw,
.set_mode = stm32f4_spi_set_mode,
.transfer_one_dma_start = stm32f4_spi_transfer_one_dma_start,
.dma_tx_cb = stm32f4_spi_dma_tx_cb,
.set_mode = stm32fx_spi_set_mode,
.write_tx = stm32f4_spi_write_tx,
.read_rx = stm32f4_spi_read_rx,
.transfer_one_dma_start = stm32fx_spi_transfer_one_dma_start,
.dma_tx_cb = stm32fx_spi_dma_tx_cb,
.dma_rx_cb = stm32_spi_dma_rx_cb,
.transfer_one_irq = stm32f4_spi_transfer_one_irq,
.irq_handler_event = stm32f4_spi_irq_event,
.irq_handler_thread = stm32f4_spi_irq_thread,
.baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN,
.baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX,
.transfer_one_irq = stm32fx_spi_transfer_one_irq,
.irq_handler_event = stm32fx_spi_irq_event,
.irq_handler_thread = stm32fx_spi_irq_thread,
.baud_rate_div_min = STM32FX_SPI_BR_DIV_MIN,
.baud_rate_div_max = STM32FX_SPI_BR_DIV_MAX,
.has_fifo = false,
.has_device_mode = false,
.flags = SPI_CONTROLLER_MUST_TX,
};
static const struct stm32_spi_cfg stm32f7_spi_cfg = {
.regs = &stm32fx_spi_regspec,
.get_bpw_mask = stm32f7_spi_get_bpw_mask,
.disable = stm32fx_spi_disable,
.config = stm32fx_spi_config,
.set_bpw = stm32f7_spi_set_bpw,
.set_mode = stm32fx_spi_set_mode,
.write_tx = stm32f7_spi_write_tx,
.read_rx = stm32f7_spi_read_rx,
.transfer_one_dma_start = stm32f7_spi_transfer_one_dma_start,
.dma_tx_cb = stm32fx_spi_dma_tx_cb,
.dma_rx_cb = stm32_spi_dma_rx_cb,
.transfer_one_irq = stm32fx_spi_transfer_one_irq,
.irq_handler_event = stm32fx_spi_irq_event,
.irq_handler_thread = stm32fx_spi_irq_thread,
.baud_rate_div_min = STM32FX_SPI_BR_DIV_MIN,
.baud_rate_div_max = STM32FX_SPI_BR_DIV_MAX,
.has_fifo = false,
.flags = SPI_CONTROLLER_MUST_TX,
};
static const struct stm32_spi_cfg stm32h7_spi_cfg = {
.regs = &stm32h7_spi_regspec,
.get_fifo_size = stm32h7_spi_get_fifo_size,
@ -1775,6 +1929,8 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = {
.set_mode = stm32h7_spi_set_mode,
.set_data_idleness = stm32h7_spi_data_idleness,
.set_number_of_data = stm32h7_spi_number_of_data,
.write_tx = stm32h7_spi_write_txfifo,
.read_rx = stm32h7_spi_read_rxfifo,
.transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start,
.dma_rx_cb = stm32_spi_dma_rx_cb,
/*
@ -1792,6 +1948,7 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = {
static const struct of_device_id stm32_spi_of_match[] = {
{ .compatible = "st,stm32h7-spi", .data = (void *)&stm32h7_spi_cfg },
{ .compatible = "st,stm32f4-spi", .data = (void *)&stm32f4_spi_cfg },
{ .compatible = "st,stm32f7-spi", .data = (void *)&stm32f7_spi_cfg },
{},
};
MODULE_DEVICE_TABLE(of, stm32_spi_of_match);