spi: stm32: add support for STM32F4

Add routines, registers & bitfield definition. Also baud rate divisor
definitions for STM32F4 SPI. This version supports full-duplex,
simplex TX and half-duplex TX communication with 8 or 16-bit per word.
DMA capability is optionally supported for transfer longer than 16 bytes.
For transfer less than 16 bytes frames can be send in discontinuous mode.

Signed-off-by: Cezary Gapinski <cezary.gapinski@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Cezary Gapinski 2018-12-24 23:00:38 +01:00 committed by Mark Brown
parent 55166853b2
commit 00505edf95
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -20,6 +20,59 @@
#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_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)
#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)
/* 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)
/* 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)
/* STM32F4_SPI_I2SCFGR bit fields */
#define STM32F4_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)
/* STM32H7 SPI registers */
#define STM32H7_SPI_CR1 0x00
#define STM32H7_SPI_CR2 0x04
@ -116,6 +169,12 @@
#define SPI_1HZ_NS 1000000000
/*
* use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers
* without fifo buffers.
*/
#define SPI_DMA_MIN_BYTES 16
/**
* stm32_spi_reg - stm32 SPI register & bitfield desc
* @reg: register offset
@ -257,6 +316,21 @@ struct stm32_spi {
dma_addr_t phys_addr;
};
static const struct stm32_spi_regspec stm32f4_spi_regspec = {
.en = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE },
.dma_rx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_RXDMAEN },
.dma_tx_en = { STM32F4_SPI_CR2, STM32F4_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 },
.br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT },
.rx = { STM32F4_SPI_DR },
.tx = { STM32F4_SPI_DR },
};
static const struct stm32_spi_regspec stm32h7_spi_regspec = {
/* SPI data transfer is enabled but spi_ker_ck is idle.
* CFG1 and CFG2 registers are write protected when SPE is enabled.
@ -315,6 +389,16 @@ static int stm32h7_spi_get_fifo_size(struct stm32_spi *spi)
return count;
}
/**
* stm32f4_spi_get_bpw_mask - Return bits per word mask
* @spi: pointer to the spi controller data structure
*/
static int stm32f4_spi_get_bpw_mask(struct stm32_spi *spi)
{
dev_dbg(spi->dev, "8-bit or 16-bit data frame supported\n");
return SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
}
/**
* stm32h7_spi_get_bpw_mask - Return bits per word mask
* @spi: pointer to the spi controller data structure
@ -408,6 +492,35 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi)
return fthlv;
}
/**
* stm32f4_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 stm32f4_spi_write_tx(struct stm32_spi *spi)
{
if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) &
STM32F4_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);
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);
spi->tx_len -= sizeof(u8);
}
}
dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len);
}
/**
* stm32h7_spi_write_txfifo - Write bytes in Transmit Data Register
* @spi: pointer to the spi controller data structure
@ -443,6 +556,35 @@ static void stm32h7_spi_write_txfifo(struct stm32_spi *spi)
dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len);
}
/**
* stm32f4_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 stm32f4_spi_read_rx(struct stm32_spi *spi)
{
if ((spi->rx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) &
STM32F4_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);
spi->rx_len -= sizeof(u16);
} else {
u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs);
*rx_buf8 = readb_relaxed(spi->base + STM32F4_SPI_DR);
spi->rx_len -= sizeof(u8);
}
}
dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->rx_len);
}
/**
* stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register
* @spi: pointer to the spi controller data structure
@ -501,6 +643,54 @@ static void stm32_spi_enable(struct stm32_spi *spi)
spi->cfg->regs->en.mask);
}
/**
* stm32f4_spi_disable - Disable SPI controller
* @spi: pointer to the spi controller data structure
*/
static void stm32f4_spi_disable(struct stm32_spi *spi)
{
unsigned long flags;
u32 sr;
dev_dbg(spi->dev, "disable controller\n");
spin_lock_irqsave(&spi->lock, flags);
if (!(readl_relaxed(spi->base + STM32F4_SPI_CR1) &
STM32F4_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);
/* Wait until BSY = 0 */
if (readl_relaxed_poll_timeout_atomic(spi->base + STM32F4_SPI_SR,
sr, !(sr & STM32F4_SPI_SR_BSY),
10, 100000) < 0) {
dev_warn(spi->dev, "disabling condition timeout\n");
}
if (spi->cur_usedma && spi->dma_tx)
dmaengine_terminate_all(spi->dma_tx);
if (spi->cur_usedma && spi->dma_rx)
dmaengine_terminate_all(spi->dma_rx);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN |
STM32F4_SPI_CR2_RXDMAEN);
/* Sequence to clear OVR flag */
readl_relaxed(spi->base + STM32F4_SPI_DR);
readl_relaxed(spi->base + STM32F4_SPI_SR);
spin_unlock_irqrestore(&spi->lock, flags);
}
/**
* stm32h7_spi_disable - Disable SPI controller
* @spi: pointer to the spi controller data structure
@ -568,18 +758,128 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
/**
* stm32_spi_can_dma - Determine if the transfer is eligible for DMA use
*
* If the current transfer size is greater than fifo size, use DMA.
* If driver has fifo and the current transfer size is greater than fifo size,
* use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes.
*/
static bool stm32_spi_can_dma(struct spi_master *master,
struct spi_device *spi_dev,
struct spi_transfer *transfer)
{
unsigned int dma_size;
struct stm32_spi *spi = spi_master_get_devdata(master);
dev_dbg(spi->dev, "%s: %s\n", __func__,
(transfer->len > spi->fifo_size) ? "true" : "false");
if (spi->cfg->has_fifo)
dma_size = spi->fifo_size;
else
dma_size = SPI_DMA_MIN_BYTES;
return (transfer->len > spi->fifo_size);
dev_dbg(spi->dev, "%s: %s\n", __func__,
(transfer->len > dma_size) ? "true" : "false");
return (transfer->len > dma_size);
}
/**
* stm32f4_spi_irq_event - Interrupt handler for SPI controller events
* @irq: interrupt line
* @dev_id: SPI controller master interface
*/
static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
u32 sr, mask = 0;
unsigned long flags;
bool end = false;
spin_lock_irqsave(&spi->lock, flags);
sr = readl_relaxed(spi->base + STM32F4_SPI_SR);
/*
* BSY flag is not handled in interrupt but it is normal behavior when
* this flag is set.
*/
sr &= ~STM32F4_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;
}
if (!spi->cur_usedma && spi->cur_comm == SPI_FULL_DUPLEX) {
/* 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;
}
if (!(sr & mask)) {
dev_dbg(spi->dev, "spurious IT (sr=0x%08x)\n", sr);
spin_unlock_irqrestore(&spi->lock, flags);
return IRQ_NONE;
}
if (sr & STM32F4_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);
/*
* If overrun is detected, it means that something went wrong,
* so stop the current transfer. Transfer can wait for next
* RXNE but DR is already read and end never happens.
*/
end = true;
goto end_irq;
}
if (sr & STM32F4_SPI_SR_TXE) {
if (spi->tx_buf)
stm32f4_spi_write_tx(spi);
if (spi->tx_len == 0)
end = true;
}
if (sr & STM32F4_SPI_SR_RXNE) {
stm32f4_spi_read_rx(spi);
if (spi->rx_len == 0)
end = true;
else /* Load data for discontinuous mode */
stm32f4_spi_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);
spin_unlock_irqrestore(&spi->lock, flags);
return IRQ_WAKE_THREAD;
}
spin_unlock_irqrestore(&spi->lock, flags);
return IRQ_HANDLED;
}
/**
* stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
* @dev_id: SPI controller master interface
*/
static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
spi_finalize_current_transfer(master);
stm32f4_spi_disable(spi);
return IRQ_HANDLED;
}
/**
@ -748,6 +1048,34 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
return 0;
}
/**
* stm32f4_spi_dma_tx_cb - dma callback
*
* DMA callback is called when the transfer is complete for DMA TX channel.
*/
static void stm32f4_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->master);
stm32f4_spi_disable(spi);
}
}
/**
* stm32f4_spi_dma_rx_cb - dma callback
*
* DMA callback is called when the transfer is complete for DMA RX channel.
*/
static void stm32f4_spi_dma_rx_cb(void *data)
{
struct stm32_spi *spi = data;
spi_finalize_current_transfer(spi->master);
stm32f4_spi_disable(spi);
}
/**
* stm32h7_spi_dma_cb - dma callback
*
@ -790,11 +1118,15 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
else
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
/* Valid for DMA Half or Full Fifo threshold */
if (spi->cur_fthlv == 2)
if (spi->cfg->has_fifo) {
/* Valid for DMA Half or Full Fifo threshold */
if (spi->cur_fthlv == 2)
maxburst = 1;
else
maxburst = spi->cur_fthlv;
} else {
maxburst = 1;
else
maxburst = spi->cur_fthlv;
}
memset(dma_conf, 0, sizeof(struct dma_slave_config));
dma_conf->direction = dir;
@ -815,6 +1147,46 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
}
}
/**
* stm32f4_spi_transfer_one_irq - transfer a single spi_transfer using
* interrupts
*
* 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)
{
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;
} else if (spi->cur_comm == SPI_FULL_DUPLEX) {
/* In transmit-only mode, the OVR flag is set in the SR register
* 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;
} else {
return -EINVAL;
}
spin_lock_irqsave(&spi->lock, flags);
stm32_spi_set_bits(spi, STM32F4_SPI_CR2, cr2);
stm32_spi_enable(spi);
/* starting data transfer when buffer is loaded */
if (spi->tx_buf)
stm32f4_spi_write_tx(spi);
spin_unlock_irqrestore(&spi->lock, flags);
return 1;
}
/**
* stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using
* interrupts
@ -856,6 +1228,26 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi)
return 1;
}
/**
* stm32f4_spi_transfer_one_dma_start - Set SPI driver registers to start
* transfer using DMA
*/
static void stm32f4_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 ||
spi->cur_comm == SPI_FULL_DUPLEX) {
/*
* In transmit-only mode, the OVR flag is set in the SR register
* 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_enable(spi);
}
/**
* stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start
* transfer using DMA
@ -976,6 +1368,18 @@ dma_desc_error:
return spi->cfg->transfer_one_irq(spi);
}
/**
* stm32f4_spi_set_bpw - Configure bits per word
* @spi: pointer to the spi controller data structure
*/
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);
else
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF);
}
/**
* stm32h7_spi_set_bpw - configure bits per word
* @spi: pointer to the spi controller data structure
@ -1053,6 +1457,28 @@ static unsigned int stm32_spi_communication_type(struct spi_device *spi_dev,
return type;
}
/**
* stm32f4_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)
{
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);
} else if (comm_type == SPI_FULL_DUPLEX) {
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIMODE |
STM32F4_SPI_CR1_BIDIOE);
} else {
return -EINVAL;
}
return 0;
}
/**
* stm32h7_spi_set_mode - configure communication mode
* @spi: pointer to the spi controller data structure
@ -1267,6 +1693,36 @@ static int stm32_spi_unprepare_msg(struct spi_master *master,
return 0;
}
/**
* stm32f4_spi_config - Configure SPI controller as SPI master
*/
static int stm32f4_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);
/*
* - SS input value high
* - transmitter half duplex direction
* - Set the master mode (default Motorola mode)
* - 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);
spin_unlock_irqrestore(&spi->lock, flags);
return 0;
}
/**
* stm32h7_spi_config - Configure SPI controller as SPI master
*/
@ -1304,6 +1760,24 @@ static int stm32h7_spi_config(struct stm32_spi *spi)
return 0;
}
static const struct stm32_spi_cfg stm32f4_spi_cfg = {
.regs = &stm32f4_spi_regspec,
.get_bpw_mask = stm32f4_spi_get_bpw_mask,
.disable = stm32f4_spi_disable,
.config = stm32f4_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,
.dma_rx_cb = stm32f4_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,
.has_fifo = false,
};
static const struct stm32_spi_cfg stm32h7_spi_cfg = {
.regs = &stm32h7_spi_regspec,
.get_fifo_size = stm32h7_spi_get_fifo_size,
@ -1326,6 +1800,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 },
{},
};
MODULE_DEVICE_TABLE(of, stm32_spi_of_match);