Commit 55166853 authored by Cezary Gapinski's avatar Cezary Gapinski Committed by Mark Brown

spi: stm32: introduce compatible data cfg

Prepare support for STM32F4 spi variant by introducing compatible
configuration data.
Move STM32H7 specific stuff to compatible data structure:
 - registers & bit fields
 - routines to control driver
 - baud rate divisor definitions
 - fifo availability
 - split IRQ functions to parts to be called when the IRQ occurs
   and for threaded interrupt what helps to provide less discontinuous
   mode for drivers without FIFO.
Signed-off-by: default avatarCezary Gapinski <cezary.gapinski@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent f8bb12f2
......@@ -116,10 +116,96 @@
#define SPI_1HZ_NS 1000000000
/**
* stm32_spi_reg - stm32 SPI register & bitfield desc
* @reg: register offset
* @mask: bitfield mask
* @shift: left shift
*/
struct stm32_spi_reg {
int reg;
int mask;
int shift;
};
/**
* stm32_spi_regspec - stm32 registers definition, compatible dependent data
* en: enable register and SPI enable bit
* dma_rx_en: SPI DMA RX enable register end SPI DMA RX enable bit
* dma_tx_en: SPI DMA TX enable register end SPI DMA TX enable bit
* cpol: clock polarity register and polarity bit
* cpha: clock phase register and phase bit
* lsb_first: LSB transmitted first register and bit
* br: baud rate register and bitfields
* rx: SPI RX data register
* tx: SPI TX data register
*/
struct stm32_spi_regspec {
const struct stm32_spi_reg en;
const struct stm32_spi_reg dma_rx_en;
const struct stm32_spi_reg dma_tx_en;
const struct stm32_spi_reg cpol;
const struct stm32_spi_reg cpha;
const struct stm32_spi_reg lsb_first;
const struct stm32_spi_reg br;
const struct stm32_spi_reg rx;
const struct stm32_spi_reg tx;
};
struct stm32_spi;
/**
* stm32_spi_cfg - stm32 compatible configuration data
* @regs: registers descriptions
* @get_fifo_size: routine to get fifo size
* @get_bpw_mask: routine to get bits per word mask
* @disable: routine to disable controller
* @config: routine to configure controller as SPI Master
* @set_bpw: routine to configure registers to for bits per word
* @set_mode: routine to configure registers to desired mode
* @set_data_idleness: optional routine to configure registers to desired idle
* 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)
* @can_dma: routine to determine if the transfer is eligible for DMA use
* @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
* @dma_tx cb: routine to call after DMA TX channel operation is complete
* @transfer_one_irq: routine to configure interrupts for driver
* @irq_handler_event: Interrupt handler for SPI controller events
* @irq_handler_thread: thread of interrupt handler for SPI controller
* @baud_rate_div_min: minimum baud rate divisor
* @baud_rate_div_max: maximum baud rate divisor
* @has_fifo: boolean to know if fifo is used for driver
* @has_startbit: boolean to know if start bit is used to start transfer
*/
struct stm32_spi_cfg {
const struct stm32_spi_regspec *regs;
int (*get_fifo_size)(struct stm32_spi *spi);
int (*get_bpw_mask)(struct stm32_spi *spi);
void (*disable)(struct stm32_spi *spi);
int (*config)(struct stm32_spi *spi);
void (*set_bpw)(struct stm32_spi *spi);
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 (*transfer_one_dma_start)(struct stm32_spi *spi);
void (*dma_rx_cb)(void *data);
void (*dma_tx_cb)(void *data);
int (*transfer_one_irq)(struct stm32_spi *spi);
irqreturn_t (*irq_handler_event)(int irq, void *dev_id);
irqreturn_t (*irq_handler_thread)(int irq, void *dev_id);
unsigned int baud_rate_div_min;
unsigned int baud_rate_div_max;
bool has_fifo;
};
/**
* struct stm32_spi - private data of the SPI controller
* @dev: driver model representation of the controller
* @master: controller master interface
* @cfg: compatible configuration data
* @base: virtual memory area
* @clk: hw kernel clock feeding the SPI clock generator
* @clk_rate: rate of the hw kernel clock feeding the SPI clock generator
......@@ -145,6 +231,7 @@
struct stm32_spi {
struct device *dev;
struct spi_master *master;
const struct stm32_spi_cfg *cfg;
void __iomem *base;
struct clk *clk;
u32 clk_rate;
......@@ -170,6 +257,25 @@ struct stm32_spi {
dma_addr_t phys_addr;
};
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.
*/
.en = { STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE },
.dma_rx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_RXDMAEN },
.dma_tx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN },
.cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL },
.cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA },
.lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST },
.br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR,
STM32H7_SPI_CFG1_MBR_SHIFT },
.rx = { STM32H7_SPI_RXDR },
.tx = { STM32H7_SPI_TXDR },
};
static inline void stm32_spi_set_bits(struct stm32_spi *spi,
u32 offset, u32 bits)
{
......@@ -185,10 +291,10 @@ static inline void stm32_spi_clr_bits(struct stm32_spi *spi,
}
/**
* stm32_spi_get_fifo_size - Return fifo size
* stm32h7_spi_get_fifo_size - Return fifo size
* @spi: pointer to the spi controller data structure
*/
static int stm32_spi_get_fifo_size(struct stm32_spi *spi)
static int stm32h7_spi_get_fifo_size(struct stm32_spi *spi)
{
unsigned long flags;
u32 count = 0;
......@@ -210,10 +316,10 @@ static int stm32_spi_get_fifo_size(struct stm32_spi *spi)
}
/**
* stm32_spi_get_bpw_mask - Return bits per word mask
* stm32h7_spi_get_bpw_mask - Return bits per word mask
* @spi: pointer to the spi controller data structure
*/
static int stm32_spi_get_bpw_mask(struct stm32_spi *spi)
static int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi)
{
unsigned long flags;
u32 cfg1, max_bpw;
......@@ -276,10 +382,10 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz,
}
/**
* stm32_spi_prepare_fthlv - Determine FIFO threshold level
* stm32h7_spi_prepare_fthlv - Determine FIFO threshold level
* @spi: pointer to the spi controller data structure
*/
static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi)
static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi)
{
u32 fthlv, half_fifo;
......@@ -303,13 +409,13 @@ static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi)
}
/**
* stm32_spi_write_txfifo - Write bytes in Transmit Data Register
* stm32h7_spi_write_txfifo - Write bytes in 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 stm32_spi_write_txfifo(struct stm32_spi *spi)
static void stm32h7_spi_write_txfifo(struct stm32_spi *spi)
{
while ((spi->tx_len > 0) &&
(readl_relaxed(spi->base + STM32H7_SPI_SR) &
......@@ -338,13 +444,13 @@ static void stm32_spi_write_txfifo(struct stm32_spi *spi)
}
/**
* stm32_spi_read_rxfifo - Read bytes in Receive Data Register
* stm32h7_spi_read_rxfifo - Read bytes in 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 stm32_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
{
u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR);
u32 rxplvl = (sr & STM32H7_SPI_SR_RXPLVL) >>
......@@ -386,26 +492,28 @@ static void stm32_spi_read_rxfifo(struct stm32_spi *spi, bool flush)
/**
* stm32_spi_enable - Enable SPI controller
* @spi: pointer to the spi controller data structure
*
* SPI data transfer is enabled but spi_ker_ck is idle.
* SPI_CFG1 and SPI_CFG2 are now write protected.
*/
static void stm32_spi_enable(struct stm32_spi *spi)
{
dev_dbg(spi->dev, "enable controller\n");
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE);
stm32_spi_set_bits(spi, spi->cfg->regs->en.reg,
spi->cfg->regs->en.mask);
}
/**
* stm32_spi_disable - Disable SPI controller
* stm32h7_spi_disable - Disable SPI controller
* @spi: pointer to the spi controller data structure
*
* RX-Fifo is flushed when SPI controller is disabled. To prevent any data
* loss, use stm32_spi_read_rxfifo(flush) to read the remaining bytes in
* loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in
* RX-Fifo.
* Normally, if TSIZE has been configured, we should relax the hardware at the
* reception of the EOT interrupt. But in case of error, EOT will not be
* raised. So the subsystem unprepare_message call allows us to properly
* complete the transfer from an hardware point of view.
*/
static void stm32_spi_disable(struct stm32_spi *spi)
static void stm32h7_spi_disable(struct stm32_spi *spi)
{
unsigned long flags;
u32 cr1, sr;
......@@ -438,7 +546,7 @@ static void stm32_spi_disable(struct stm32_spi *spi)
}
if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0))
stm32_spi_read_rxfifo(spi, true);
stm32h7_spi_read_rxfifo(spi, true);
if (spi->cur_usedma && spi->dma_tx)
dmaengine_terminate_all(spi->dma_tx);
......@@ -475,11 +583,11 @@ static bool stm32_spi_can_dma(struct spi_master *master,
}
/**
* stm32_spi_irq_thread - Thread of interrupt handler for SPI controller
* stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
* @dev_id: SPI controller master interface
*/
static irqreturn_t stm32_spi_irq_thread(int irq, void *dev_id)
static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
......@@ -513,7 +621,7 @@ static irqreturn_t stm32_spi_irq_thread(int irq, void *dev_id)
if (sr & STM32H7_SPI_SR_SUSP) {
dev_warn(spi->dev, "Communication suspended\n");
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
stm32_spi_read_rxfifo(spi, false);
stm32h7_spi_read_rxfifo(spi, false);
/*
* If communication is suspended while using DMA, it means
* that something went wrong, so stop the current transfer
......@@ -530,7 +638,7 @@ static irqreturn_t stm32_spi_irq_thread(int irq, void *dev_id)
if (sr & STM32H7_SPI_SR_OVR) {
dev_warn(spi->dev, "Overrun: received value discarded\n");
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
stm32_spi_read_rxfifo(spi, false);
stm32h7_spi_read_rxfifo(spi, false);
/*
* If overrun is detected while using DMA, it means that
* something went wrong, so stop the current transfer
......@@ -541,17 +649,17 @@ static irqreturn_t stm32_spi_irq_thread(int irq, void *dev_id)
if (sr & STM32H7_SPI_SR_EOT) {
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
stm32_spi_read_rxfifo(spi, true);
stm32h7_spi_read_rxfifo(spi, true);
end = true;
}
if (sr & STM32H7_SPI_SR_TXP)
if (!spi->cur_usedma && (spi->tx_buf && (spi->tx_len > 0)))
stm32_spi_write_txfifo(spi);
stm32h7_spi_write_txfifo(spi);
if (sr & STM32H7_SPI_SR_RXP)
if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
stm32_spi_read_rxfifo(spi, false);
stm32h7_spi_read_rxfifo(spi, false);
writel_relaxed(mask, spi->base + STM32H7_SPI_IFCR);
......@@ -559,7 +667,7 @@ static irqreturn_t stm32_spi_irq_thread(int irq, void *dev_id)
if (end) {
spi_finalize_current_transfer(master);
stm32_spi_disable(spi);
stm32h7_spi_disable(spi);
}
return IRQ_HANDLED;
......@@ -598,7 +706,7 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
struct spi_device *spi_dev = msg->spi;
struct device_node *np = spi_dev->dev.of_node;
unsigned long flags;
u32 cfg2_clrb = 0, cfg2_setb = 0;
u32 clrb = 0, setb = 0;
/* SPI slave device may need time between data frames */
spi->cur_midi = 0;
......@@ -606,19 +714,19 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
dev_dbg(spi->dev, "%dns inter-data idleness\n", spi->cur_midi);
if (spi_dev->mode & SPI_CPOL)
cfg2_setb |= STM32H7_SPI_CFG2_CPOL;
setb |= spi->cfg->regs->cpol.mask;
else
cfg2_clrb |= STM32H7_SPI_CFG2_CPOL;
clrb |= spi->cfg->regs->cpol.mask;
if (spi_dev->mode & SPI_CPHA)
cfg2_setb |= STM32H7_SPI_CFG2_CPHA;
setb |= spi->cfg->regs->cpha.mask;
else
cfg2_clrb |= STM32H7_SPI_CFG2_CPHA;
clrb |= spi->cfg->regs->cpha.mask;
if (spi_dev->mode & SPI_LSB_FIRST)
cfg2_setb |= STM32H7_SPI_CFG2_LSBFRST;
setb |= spi->cfg->regs->lsb_first.mask;
else
cfg2_clrb |= STM32H7_SPI_CFG2_LSBFRST;
clrb |= spi->cfg->regs->lsb_first.mask;
dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n",
spi_dev->mode & SPI_CPOL,
......@@ -628,11 +736,12 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
spin_lock_irqsave(&spi->lock, flags);
if (cfg2_clrb || cfg2_setb)
/* CPOL, CPHA and LSB FIRST bits have common register */
if (clrb || setb)
writel_relaxed(
(readl_relaxed(spi->base + STM32H7_SPI_CFG2) &
~cfg2_clrb) | cfg2_setb,
spi->base + STM32H7_SPI_CFG2);
(readl_relaxed(spi->base + spi->cfg->regs->cpol.reg) &
~clrb) | setb,
spi->base + spi->cfg->regs->cpol.reg);
spin_unlock_irqrestore(&spi->lock, flags);
......@@ -640,12 +749,12 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
}
/**
* stm32_spi_dma_cb - dma callback
* stm32h7_spi_dma_cb - dma callback
*
* DMA callback is called when the transfer is complete or when an error
* occurs. If the transfer is complete, EOT flag is raised.
*/
static void stm32_spi_dma_cb(void *data)
static void stm32h7_spi_dma_cb(void *data)
{
struct stm32_spi *spi = data;
unsigned long flags;
......@@ -690,14 +799,14 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
memset(dma_conf, 0, sizeof(struct dma_slave_config));
dma_conf->direction = dir;
if (dma_conf->direction == DMA_DEV_TO_MEM) { /* RX */
dma_conf->src_addr = spi->phys_addr + STM32H7_SPI_RXDR;
dma_conf->src_addr = spi->phys_addr + spi->cfg->regs->rx.reg;
dma_conf->src_addr_width = buswidth;
dma_conf->src_maxburst = maxburst;
dev_dbg(spi->dev, "Rx DMA config buswidth=%d, maxburst=%d\n",
buswidth, maxburst);
} else if (dma_conf->direction == DMA_MEM_TO_DEV) { /* TX */
dma_conf->dst_addr = spi->phys_addr + STM32H7_SPI_TXDR;
dma_conf->dst_addr = spi->phys_addr + spi->cfg->regs->tx.reg;
dma_conf->dst_addr_width = buswidth;
dma_conf->dst_maxburst = maxburst;
......@@ -707,13 +816,13 @@ static void stm32_spi_dma_config(struct stm32_spi *spi,
}
/**
* stm32_spi_transfer_one_irq - transfer a single spi_transfer using
* stm32h7_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 stm32_spi_transfer_one_irq(struct stm32_spi *spi)
static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi)
{
unsigned long flags;
u32 ier = 0;
......@@ -736,7 +845,7 @@ static int stm32_spi_transfer_one_irq(struct stm32_spi *spi)
/* Be sure to have data in fifo before starting data transfer */
if (spi->tx_buf)
stm32_spi_write_txfifo(spi);
stm32h7_spi_write_txfifo(spi);
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
......@@ -748,10 +857,10 @@ static int stm32_spi_transfer_one_irq(struct stm32_spi *spi)
}
/**
* stm32_spi_transfer_one_dma_start - Set SPI driver registers to start transfer
* using DMA
* stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start
* transfer using DMA
*/
static void stm32_spi_transfer_one_dma_start(struct stm32_spi *spi)
static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi)
{
/* Enable the interrupts relative to the end of transfer */
stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE |
......@@ -785,8 +894,8 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
dmaengine_slave_config(spi->dma_rx, &rx_dma_conf);
/* Enable Rx DMA request */
stm32_spi_set_bits(spi, STM32H7_SPI_CFG1,
STM32H7_SPI_CFG1_RXDMAEN);
stm32_spi_set_bits(spi, spi->cfg->regs->dma_rx_en.reg,
spi->cfg->regs->dma_rx_en.mask);
rx_dma_desc = dmaengine_prep_slave_sg(
spi->dma_rx, xfer->rx_sg.sgl,
......@@ -815,7 +924,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
goto dma_desc_error;
if (rx_dma_desc) {
rx_dma_desc->callback = stm32_spi_dma_cb;
rx_dma_desc->callback = spi->cfg->dma_rx_cb;
rx_dma_desc->callback_param = spi;
if (dma_submit_error(dmaengine_submit(rx_dma_desc))) {
......@@ -829,7 +938,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
if (tx_dma_desc) {
if (spi->cur_comm == SPI_SIMPLEX_TX ||
spi->cur_comm == SPI_3WIRE_TX) {
tx_dma_desc->callback = stm32_spi_dma_cb;
tx_dma_desc->callback = spi->cfg->dma_tx_cb;
tx_dma_desc->callback_param = spi;
}
......@@ -841,11 +950,11 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
dma_async_issue_pending(spi->dma_tx);
/* Enable Tx DMA request */
stm32_spi_set_bits(spi, STM32H7_SPI_CFG1,
STM32H7_SPI_CFG1_TXDMAEN);
stm32_spi_set_bits(spi, spi->cfg->regs->dma_tx_en.reg,
spi->cfg->regs->dma_tx_en.mask);
}
stm32_spi_transfer_one_dma_start(spi);
spi->cfg->transfer_one_dma_start(spi);
spin_unlock_irqrestore(&spi->lock, flags);
......@@ -856,21 +965,22 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
dmaengine_terminate_all(spi->dma_rx);
dma_desc_error:
stm32_spi_clr_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_RXDMAEN);
stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg,
spi->cfg->regs->dma_rx_en.mask);
spin_unlock_irqrestore(&spi->lock, flags);
dev_info(spi->dev, "DMA issue: fall back to irq transfer\n");
spi->cur_usedma = false;
return stm32_spi_transfer_one_irq(spi);
return spi->cfg->transfer_one_irq(spi);
}
/**
* stm32_spi_set_bpw - configure bits per word
* stm32h7_spi_set_bpw - configure bits per word
* @spi: pointer to the spi controller data structure
*/
static void stm32_spi_set_bpw(struct stm32_spi *spi)
static void stm32h7_spi_set_bpw(struct stm32_spi *spi)
{
u32 bpw, fthlv;
u32 cfg1_clrb = 0, cfg1_setb = 0;
......@@ -881,7 +991,7 @@ static void stm32_spi_set_bpw(struct stm32_spi *spi)
cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) &
STM32H7_SPI_CFG1_DSIZE;
spi->cur_fthlv = stm32_spi_prepare_fthlv(spi);
spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi);
fthlv = spi->cur_fthlv - 1;
cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV;
......@@ -901,15 +1011,15 @@ static void stm32_spi_set_bpw(struct stm32_spi *spi)
*/
static void stm32_spi_set_mbr(struct stm32_spi *spi, u32 mbrdiv)
{
u32 cfg1_clrb = 0, cfg1_setb = 0;
u32 clrb = 0, setb = 0;
cfg1_clrb |= STM32H7_SPI_CFG1_MBR;
cfg1_setb |= ((u32)mbrdiv << STM32H7_SPI_CFG1_MBR_SHIFT) &
STM32H7_SPI_CFG1_MBR;
clrb |= spi->cfg->regs->br.mask;
setb |= ((u32)mbrdiv << spi->cfg->regs->br.shift) &
spi->cfg->regs->br.mask;
writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CFG1) &
~cfg1_clrb) | cfg1_setb,
spi->base + STM32H7_SPI_CFG1);
writel_relaxed((readl_relaxed(spi->base + spi->cfg->regs->br.reg) &
~clrb) | setb,
spi->base + spi->cfg->regs->br.reg);
}
/**
......@@ -944,11 +1054,11 @@ static unsigned int stm32_spi_communication_type(struct spi_device *spi_dev,
}
/**
* stm32_spi_set_mode - configure communication mode
* stm32h7_spi_set_mode - configure communication mode
* @spi: pointer to the spi controller data structure
* @comm_type: type of communication to configure
*/
static int stm32_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
static int stm32h7_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
{
u32 mode;
u32 cfg2_clrb = 0, cfg2_setb = 0;
......@@ -980,12 +1090,12 @@ static int stm32_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
}
/**
* stm32_spi_data_idleness - configure minimum time delay inserted between two
* stm32h7_spi_data_idleness - configure minimum time delay inserted between two
* consecutive data frames in master mode
* @spi: pointer to the spi controller data structure
* @len: transfer len
*/
static void stm32_spi_data_idleness(struct stm32_spi *spi, u32 len)
static void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len)
{
u32 cfg2_clrb = 0, cfg2_setb = 0;
......@@ -1008,11 +1118,11 @@ static void stm32_spi_data_idleness(struct stm32_spi *spi, u32 len)
}
/**
* stm32_spi_number_of_data - configure number of data at current transfer
* stm32h7_spi_number_of_data - configure number of data at current transfer
* @spi: pointer to the spi controller data structure
* @len: transfer length
*/
static int stm32_spi_number_of_data(struct stm32_spi *spi, u32 nb_words)
static int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words)
{
u32 cr2_clrb = 0, cr2_setb = 0;
......@@ -1047,7 +1157,7 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
if (spi->cur_bpw != transfer->bits_per_word) {
spi->cur_bpw = transfer->bits_per_word;
stm32_spi_set_bpw(spi);
spi->cfg->set_bpw(spi);
}
if (spi->cur_speed != transfer->speed_hz) {
......@@ -1055,8 +1165,8 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
/* Update spi->cur_speed with real clock speed */
mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
STM32H7_SPI_MBR_DIV_MIN,
STM32H7_SPI_MBR_DIV_MAX);
spi->cfg->baud_rate_div_min,
spi->cfg->baud_rate_div_max);
if (mbr < 0) {
ret = mbr;
goto out;
......@@ -1068,7 +1178,7 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
comm_type = stm32_spi_communication_type(spi_dev, transfer);
if (spi->cur_comm != comm_type) {
stm32_spi_set_mode(spi, comm_type);
ret = spi->cfg->set_mode(spi, comm_type);
if (ret < 0)
goto out;
......@@ -1076,7 +1186,8 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
spi->cur_comm = comm_type;
}
stm32_spi_data_idleness(spi, transfer->len);
if (spi->cfg->set_data_idleness)
spi->cfg->set_data_idleness(spi, transfer->len);
if (spi->cur_bpw <= 8)
nb_words = transfer->len;
......@@ -1085,9 +1196,11 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
else
nb_words = DIV_ROUND_UP(transfer->len * 8, 32);
ret = stm32_spi_number_of_data(spi, nb_words);
if (spi->cfg->set_number_of_data) {
ret = spi->cfg->set_number_of_data(spi, nb_words);
if (ret < 0)
goto out;
}
spi->cur_xferlen = transfer->len;
......@@ -1138,31 +1251,26 @@ static int stm32_spi_transfer_one(struct spi_master *master,
if (spi->cur_usedma)
return stm32_spi_transfer_one_dma(spi, transfer);
else
return stm32_spi_transfer_one_irq(spi);
return spi->cfg->transfer_one_irq(spi);
}
/**
* stm32_spi_unprepare_msg - relax the hardware
*
* Normally, if TSIZE has been configured, we should relax the hardware at the
* reception of the EOT interrupt. But in case of error, EOT will not be
* raised. So the subsystem unprepare_message call allows us to properly
* complete the transfer from an hardware point of view.
*/
static int stm32_spi_unprepare_msg(struct spi_master *master,
struct spi_message *msg)
{
struct stm32_spi *spi = spi_master_get_devdata(master);
stm32_spi_disable(spi);
spi->cfg->disable(spi);
return 0;
}
/**
* stm32_spi_config - Configure SPI controller as SPI master
* stm32h7_spi_config - Configure SPI controller as SPI master
*/
static int stm32_spi_config(struct stm32_spi *spi)
static int stm32h7_spi_config(struct stm32_spi *spi)
{
unsigned long flags;
......@@ -1196,8 +1304,28 @@ static int stm32_spi_config(struct stm32_spi *spi)
return 0;
}
static const struct stm32_spi_cfg stm32h7_spi_cfg = {
.regs = &stm32h7_spi_regspec,
.get_fifo_size = stm32h7_spi_get_fifo_size,
.get_bpw_mask = stm32h7_spi_get_bpw_mask,
.disable = stm32h7_spi_disable,
.config = stm32h7_spi_config,
.set_bpw = stm32h7_spi_set_bpw,
.set_mode = stm32h7_spi_set_mode,
.set_data_idleness = stm32h7_spi_data_idleness,
.set_number_of_data = stm32h7_spi_number_of_data,
.transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start,
.dma_rx_cb = stm32h7_spi_dma_cb,
.dma_tx_cb = stm32h7_spi_dma_cb,
.transfer_one_irq = stm32h7_spi_transfer_one_irq,
.irq_handler_thread = stm32h7_spi_irq_thread,
.baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN,
.baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX,
.has_fifo = true,
};
static const struct of_device_id stm32_spi_of_match[] = {
{ .compatible = "st,stm32h7-spi", },
{ .compatible = "st,stm32h7-spi", .data = (void *)&stm32h7_spi_cfg },
{},
};
MODULE_DEVICE_TABLE(of, stm32_spi_of_match);
......@@ -1221,12 +1349,17 @@ static int stm32_spi_probe(struct platform_device *pdev)
spi->master = master;
spin_lock_init(&spi->lock);
spi->cfg = (const struct stm32_spi_cfg *)
of_match_device(pdev->dev.driver->of_match_table,
&pdev->dev)->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spi->base)) {
ret = PTR_ERR(spi->base);
goto err_master_put;
}
spi->phys_addr = (dma_addr_t)res->start;
spi->irq = platform_get_irq(pdev, 0);
......@@ -1235,9 +1368,10 @@ static int stm32_spi_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err_master_put;
}
ret = devm_request_threaded_irq(&pdev->dev, spi->irq, NULL,
stm32_spi_irq_thread, IRQF_ONESHOT,
pdev->name, master);
ret = devm_request_threaded_irq(&pdev->dev, spi->irq,
spi->cfg->irq_handler_event,
spi->cfg->irq_handler_thread,
IRQF_ONESHOT, pdev->name, master);
if (ret) {
dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq,
ret);
......@@ -1270,9 +1404,10 @@ static int stm32_spi_probe(struct platform_device *pdev)
reset_control_deassert(spi->rst);
}
spi->fifo_size = stm32_spi_get_fifo_size(spi);
if (spi->cfg->has_fifo)
spi->fifo_size = spi->cfg->get_fifo_size(spi);
ret = stm32_spi_config(spi);
ret = spi->cfg->config(spi);
if (ret) {
dev_err(&pdev->dev, "controller configuration failed: %d\n",
ret);
......@@ -1284,9 +1419,9 @@ static int stm32_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
SPI_3WIRE;
master->bits_per_word_mask = stm32_spi_get_bpw_mask(spi);
master->max_speed_hz = spi->clk_rate / STM32H7_SPI_MBR_DIV_MIN;
master->min_speed_hz = spi->clk_rate / STM32H7_SPI_MBR_DIV_MAX;
master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;
master->setup = stm32_spi_setup;
master->prepare_message = stm32_spi_prepare_msg;
master->transfer_one = stm32_spi_transfer_one;
......@@ -1364,7 +1499,7 @@ static int stm32_spi_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct stm32_spi *spi = spi_master_get_devdata(master);
stm32_spi_disable(spi);
spi->cfg->disable(spi);
if (master->dma_tx)
dma_release_channel(master->dma_tx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment