Skip to content

Commit

Permalink
Merge tag 'spi-fix-v5.14-rc2' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/broonie/spi

Pull spi fixes from Mark Brown:
 "A collection of driver specific fixes, there was a bit of a kerfuffle
  with some last minute review on hte spi-cadence-quadspi division by
  zero change but otherwise nothing terribly remarkable here - important
  fixes if you have the hardware but nothing with too wide an impact"

* tag 'spi-fix-v5.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: spi-bcm2835: Fix deadlock
  spi: cadence: Correct initialisation of runtime PM again
  spi: cadence-quadspi: Disable Auto-HW polling
  spi: spi-cadence-quadspi: Fix division by zero warning
  spi: spi-cadence-quadspi: Revert "Fix division by zero warning"
  spi: spi-cadence-quadspi: Fix division by zero warning
  spi: mediatek: move devm_spi_register_master position
  spi: mediatek: fix fifo rx mode
  spi: atmel: Fix CS and initialization bug
  spi: stm32: fixes pm_runtime calls in probe/remove
  spi: imx: mx51-ecspi: Reinstate low-speed CONFIGREG delay
  spi: stm32h7: fix full duplex irq handler handling
  • Loading branch information
Linus Torvalds committed Jul 21, 2021
2 parents 7c3d49b + c45c1e8 commit 7b6ae47
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 65 deletions.
9 changes: 2 additions & 7 deletions drivers/spi/spi-atmel.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,6 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
}

mr = spi_readl(as, MR);
if (spi->cs_gpiod)
gpiod_set_value(spi->cs_gpiod, 1);
} else {
u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
int i;
Expand All @@ -369,8 +367,6 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)

mr = spi_readl(as, MR);
mr = SPI_BFINS(PCS, ~(1 << chip_select), mr);
if (spi->cs_gpiod)
gpiod_set_value(spi->cs_gpiod, 1);
spi_writel(as, MR, mr);
}

Expand Down Expand Up @@ -400,8 +396,6 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)

if (!spi->cs_gpiod)
spi_writel(as, CR, SPI_BIT(LASTXFER));
else
gpiod_set_value(spi->cs_gpiod, 0);
}

static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
Expand Down Expand Up @@ -1483,7 +1477,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->num_chipselect = 4;
master->setup = atmel_spi_setup;
master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX);
master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX |
SPI_MASTER_GPIO_SS);
master->transfer_one = atmel_spi_one_transfer;
master->set_cs = atmel_spi_set_cs;
master->cleanup = atmel_spi_cleanup;
Expand Down
12 changes: 7 additions & 5 deletions drivers/spi/spi-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ MODULE_PARM_DESC(polling_limit_us,
* struct bcm2835_spi - BCM2835 SPI controller
* @regs: base address of register map
* @clk: core clock, divided to calculate serial clock
* @clk_hz: core clock cached speed
* @irq: interrupt, signals TX FIFO empty or RX FIFO ¾ full
* @tfr: SPI transfer currently processed
* @ctlr: SPI controller reverse lookup
Expand Down Expand Up @@ -116,6 +117,7 @@ MODULE_PARM_DESC(polling_limit_us,
struct bcm2835_spi {
void __iomem *regs;
struct clk *clk;
unsigned long clk_hz;
int irq;
struct spi_transfer *tfr;
struct spi_controller *ctlr;
Expand Down Expand Up @@ -1045,27 +1047,26 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
{
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
struct bcm2835_spidev *slv = spi_get_ctldata(spi);
unsigned long spi_hz, clk_hz, cdiv;
unsigned long spi_hz, cdiv;
unsigned long hz_per_byte, byte_limit;
u32 cs = slv->prepare_cs;

/* set clock */
spi_hz = tfr->speed_hz;
clk_hz = clk_get_rate(bs->clk);

if (spi_hz >= clk_hz / 2) {
if (spi_hz >= bs->clk_hz / 2) {
cdiv = 2; /* clk_hz/2 is the fastest we can go */
} else if (spi_hz) {
/* CDIV must be a multiple of two */
cdiv = DIV_ROUND_UP(clk_hz, spi_hz);
cdiv = DIV_ROUND_UP(bs->clk_hz, spi_hz);
cdiv += (cdiv % 2);

if (cdiv >= 65536)
cdiv = 0; /* 0 is the slowest we can go */
} else {
cdiv = 0; /* 0 is the slowest we can go */
}
tfr->effective_speed_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
tfr->effective_speed_hz = cdiv ? (bs->clk_hz / cdiv) : (bs->clk_hz / 65536);
bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);

/* handle all the 3-wire mode */
Expand Down Expand Up @@ -1354,6 +1355,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
return bs->irq ? bs->irq : -ENODEV;

clk_prepare_enable(bs->clk);
bs->clk_hz = clk_get_rate(bs->clk);

err = bcm2835_dma_init(ctlr, &pdev->dev, bs);
if (err)
Expand Down
30 changes: 17 additions & 13 deletions drivers/spi/spi-cadence-quadspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ static unsigned int cqspi_calc_dummy(const struct spi_mem_op *op, bool dtr)
{
unsigned int dummy_clk;

if (!op->dummy.nbytes)
return 0;

dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth);
if (dtr)
dummy_clk /= 2;
Expand Down Expand Up @@ -797,19 +800,20 @@ static int cqspi_write_setup(struct cqspi_flash_pdata *f_pdata,
reg = cqspi_calc_rdreg(f_pdata);
writel(reg, reg_base + CQSPI_REG_RD_INSTR);

if (f_pdata->dtr) {
/*
* Some flashes like the cypress Semper flash expect a 4-byte
* dummy address with the Read SR command in DTR mode, but this
* controller does not support sending address with the Read SR
* command. So, disable write completion polling on the
* controller's side. spi-nor will take care of polling the
* status register.
*/
reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
}
/*
* SPI NAND flashes require the address of the status register to be
* passed in the Read SR command. Also, some SPI NOR flashes like the
* cypress Semper flash expect a 4-byte dummy address in the Read SR
* command in DTR mode.
*
* But this controller does not support address phase in the Read SR
* command when doing auto-HW polling. So, disable write completion
* polling on the controller's side. spinand and spi-nor will take
* care of polling the status register.
*/
reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);

reg = readl(reg_base + CQSPI_REG_SIZE);
reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
Expand Down
14 changes: 9 additions & 5 deletions drivers/spi/spi-cadence.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,12 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_apb;
}

pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);

ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0)
master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
Expand All @@ -531,11 +537,6 @@ static int cdns_spi_probe(struct platform_device *pdev)
/* SPI controller initializations */
cdns_spi_init_hw(xspi);

pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);

irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
ret = -ENXIO;
Expand Down Expand Up @@ -566,6 +567,9 @@ static int cdns_spi_probe(struct platform_device *pdev)

master->bits_per_word_mask = SPI_BPW_MASK(8);

pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);

ret = spi_register_master(master);
if (ret) {
dev_err(&pdev->dev, "spi_register_master failed\n");
Expand Down
38 changes: 19 additions & 19 deletions drivers/spi/spi-imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
{
struct spi_device *spi = msg->spi;
u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
u32 testreg;
u32 testreg, delay;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);

/* set Master or Slave mode */
Expand Down Expand Up @@ -567,14 +567,31 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,

writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

/*
* Wait until the changes in the configuration register CONFIGREG
* propagate into the hardware. It takes exactly one tick of the
* SCLK clock, but we will wait two SCLK clock just to be sure. The
* effect of the delay it takes for the hardware to apply changes
* is noticable if the SCLK clock run very slow. In such a case, if
* the polarity of SCLK should be inverted, the GPIO ChipSelect might
* be asserted before the SCLK polarity changes, which would disrupt
* the SPI communication as the device on the other end would consider
* the change of SCLK polarity as a clock tick already.
*/
delay = (2 * 1000000) / spi_imx->spi_bus_clk;
if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
udelay(delay);
else /* SCLK is _very_ slow */
usleep_range(delay, delay + 10);

return 0;
}

static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
struct spi_device *spi)
{
u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
u32 clk, delay;
u32 clk;

/* Clear BL field and set the right value */
ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
Expand All @@ -596,23 +613,6 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,

writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);

/*
* Wait until the changes in the configuration register CONFIGREG
* propagate into the hardware. It takes exactly one tick of the
* SCLK clock, but we will wait two SCLK clock just to be sure. The
* effect of the delay it takes for the hardware to apply changes
* is noticable if the SCLK clock run very slow. In such a case, if
* the polarity of SCLK should be inverted, the GPIO ChipSelect might
* be asserted before the SCLK polarity changes, which would disrupt
* the SPI communication as the device on the other end would consider
* the change of SCLK polarity as a clock tick already.
*/
delay = (2 * 1000000) / clk;
if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
udelay(delay);
else /* SCLK is _very_ slow */
usleep_range(delay, delay + 10);

return 0;
}

Expand Down
28 changes: 19 additions & 9 deletions drivers/spi/spi-mt65xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,23 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
mtk_spi_setup_packet(master);

cnt = xfer->len / 4;
iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt);
if (xfer->tx_buf)
iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt);

if (xfer->rx_buf)
ioread32_rep(mdata->base + SPI_RX_DATA_REG, xfer->rx_buf, cnt);

remainder = xfer->len % 4;
if (remainder > 0) {
reg_val = 0;
memcpy(&reg_val, xfer->tx_buf + (cnt * 4), remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
if (xfer->tx_buf) {
memcpy(&reg_val, xfer->tx_buf + (cnt * 4), remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
if (xfer->rx_buf) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
memcpy(xfer->rx_buf + (cnt * 4), &reg_val, remainder);
}
}

mtk_spi_enable_transfer(master);
Expand Down Expand Up @@ -793,12 +803,6 @@ static int mtk_spi_probe(struct platform_device *pdev)

pm_runtime_enable(&pdev->dev);

ret = devm_spi_register_master(&pdev->dev, master);
if (ret) {
dev_err(&pdev->dev, "failed to register master (%d)\n", ret);
goto err_disable_runtime_pm;
}

if (mdata->dev_comp->need_pad_sel) {
if (mdata->pad_num != master->num_chipselect) {
dev_err(&pdev->dev,
Expand Down Expand Up @@ -838,6 +842,12 @@ static int mtk_spi_probe(struct platform_device *pdev)
dev_notice(&pdev->dev, "SPI dma_set_mask(%d) failed, ret:%d\n",
addr_bits, ret);

ret = devm_spi_register_master(&pdev->dev, master);
if (ret) {
dev_err(&pdev->dev, "failed to register master (%d)\n", ret);
goto err_disable_runtime_pm;
}

return 0;

err_disable_runtime_pm:
Expand Down
24 changes: 17 additions & 7 deletions drivers/spi/spi-stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,15 +884,18 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
ier = readl_relaxed(spi->base + STM32H7_SPI_IER);

mask = ier;
/* EOTIE is triggered on EOT, SUSP and TXC events. */
/*
* EOTIE enables irq from EOT, SUSP and TXC events. We need to set
* SUSP to acknowledge it later. TXC is automatically cleared
*/

mask |= STM32H7_SPI_SR_SUSP;
/*
* When TXTF is set, DXPIE and TXPIE are cleared. So in case of
* Full-Duplex, need to poll RXP event to know if there are remaining
* data, before disabling SPI.
* DXPIE is set in Full-Duplex, one IT will be raised if TXP and RXP
* are set. So in case of Full-Duplex, need to poll TXP and RXP event.
*/
if (spi->rx_buf && !spi->cur_usedma)
mask |= STM32H7_SPI_SR_RXP;
if ((spi->cur_comm == SPI_FULL_DUPLEX) && !spi->cur_usedma)
mask |= STM32H7_SPI_SR_TXP | STM32H7_SPI_SR_RXP;

if (!(sr & mask)) {
dev_warn(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n",
Expand Down Expand Up @@ -1925,6 +1928,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
master->can_dma = stm32_spi_can_dma;

pm_runtime_set_active(&pdev->dev);
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_enable(&pdev->dev);

ret = spi_register_master(master);
Expand All @@ -1940,6 +1944,8 @@ static int stm32_spi_probe(struct platform_device *pdev)

err_pm_disable:
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
err_dma_release:
if (spi->dma_tx)
dma_release_channel(spi->dma_tx);
Expand All @@ -1956,17 +1962,21 @@ 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);

pm_runtime_get_sync(&pdev->dev);

spi_unregister_master(master);
spi->cfg->disable(spi);

pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
if (master->dma_tx)
dma_release_channel(master->dma_tx);
if (master->dma_rx)
dma_release_channel(master->dma_rx);

clk_disable_unprepare(spi->clk);

pm_runtime_disable(&pdev->dev);

pinctrl_pm_select_sleep_state(&pdev->dev);

Expand Down

0 comments on commit 7b6ae47

Please sign in to comment.