summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:17:26 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:17:26 +0200
commitb62ed4c93ad71374b54d2c3a72cbc67b506f580c (patch)
tree6ca6ab974bbce902fc9de300fea6aa056170850f /drivers/spi
parent5895db67c12464003afd16c08049b73aa09e58ea (diff)
parent221fc2f4d0eda59d02af2e751a9282fa013a8e97 (diff)
Merge v6.18.40linux-rolling-lts
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-atmel.c133
-rw-r--r--drivers/spi/spi-dw.h1
-rw-r--r--drivers/spi/spi-ep93xx.c1
-rw-r--r--drivers/spi/spi-hisi-kunpeng.c6
-rw-r--r--drivers/spi/spi-meson-spifc.c1
-rw-r--r--drivers/spi/spi-rpc-if.c6
-rw-r--r--drivers/spi/spi-sh-msiof.c10
-rw-r--r--drivers/spi/spi-uniphier.c4
-rw-r--r--drivers/spi/spi-xilinx.c11
-rw-r--r--drivers/spi/spi.c5
10 files changed, 95 insertions, 83 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 586e2fd357ed..a9499b51b8cc 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -559,6 +559,38 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, u8 bits_per_word)
return err;
}
+static void atmel_spi_release_dma(void *data)
+{
+ struct spi_controller *host = data;
+ struct atmel_spi *as = spi_controller_get_devdata(host);
+ struct device *dev = &as->pdev->dev;
+
+ if (host->dma_tx) {
+ dma_release_channel(host->dma_tx);
+ host->dma_tx = NULL;
+ }
+
+ if (host->dma_rx) {
+ dma_release_channel(host->dma_rx);
+ host->dma_rx = NULL;
+ }
+
+ if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+ if (as->addr_tx_bbuf) {
+ dma_free_coherent(dev, SPI_MAX_DMA_XFER,
+ as->addr_tx_bbuf,
+ as->dma_addr_tx_bbuf);
+ as->addr_tx_bbuf = NULL;
+ }
+ if (as->addr_rx_bbuf) {
+ dma_free_coherent(dev, SPI_MAX_DMA_XFER,
+ as->addr_rx_bbuf,
+ as->dma_addr_rx_bbuf);
+ as->addr_rx_bbuf = NULL;
+ }
+ }
+}
+
static int atmel_spi_configure_dma(struct spi_controller *host,
struct atmel_spi *as)
{
@@ -569,7 +601,8 @@ static int atmel_spi_configure_dma(struct spi_controller *host,
if (IS_ERR(host->dma_tx)) {
err = PTR_ERR(host->dma_tx);
dev_dbg(dev, "No TX DMA channel, DMA is disabled\n");
- goto error_clear;
+ host->dma_tx = NULL;
+ return err;
}
host->dma_rx = dma_request_chan(dev, "rx");
@@ -580,26 +613,45 @@ static int atmel_spi_configure_dma(struct spi_controller *host,
* requested tx channel.
*/
dev_dbg(dev, "No RX DMA channel, DMA is disabled\n");
- goto error;
+ host->dma_rx = NULL;
+ goto err_release_dma;
}
err = atmel_spi_dma_slave_config(as, 8);
if (err)
- goto error;
+ goto err_release_dma;
+
+ if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
+ as->addr_tx_bbuf = dma_alloc_coherent(dev, SPI_MAX_DMA_XFER,
+ &as->dma_addr_tx_bbuf,
+ GFP_KERNEL | GFP_DMA);
+ if (!as->addr_tx_bbuf) {
+ err = -ENOMEM;
+ goto err_release_dma;
+ }
+
+ as->addr_rx_bbuf = dma_alloc_coherent(dev, SPI_MAX_DMA_XFER,
+ &as->dma_addr_rx_bbuf,
+ GFP_KERNEL | GFP_DMA);
+ if (!as->addr_rx_bbuf) {
+ err = -ENOMEM;
+ goto err_release_dma;
+ }
+ }
+
+ err = devm_add_action_or_reset(dev, atmel_spi_release_dma, host);
+ if (err)
+ return err;
dev_info(&as->pdev->dev,
- "Using %s (tx) and %s (rx) for DMA transfers\n",
- dma_chan_name(host->dma_tx),
- dma_chan_name(host->dma_rx));
+ "Using %s (tx) and %s (rx) for DMA transfers\n",
+ dma_chan_name(host->dma_tx), dma_chan_name(host->dma_rx));
return 0;
-error:
- if (!IS_ERR(host->dma_rx))
- dma_release_channel(host->dma_rx);
- if (!IS_ERR(host->dma_tx))
- dma_release_channel(host->dma_tx);
-error_clear:
- host->dma_tx = host->dma_rx = NULL;
+
+err_release_dma:
+ atmel_spi_release_dma(host);
+
return err;
}
@@ -611,18 +663,6 @@ static void atmel_spi_stop_dma(struct spi_controller *host)
dmaengine_terminate_all(host->dma_tx);
}
-static void atmel_spi_release_dma(struct spi_controller *host)
-{
- if (host->dma_rx) {
- dma_release_channel(host->dma_rx);
- host->dma_rx = NULL;
- }
- if (host->dma_tx) {
- dma_release_channel(host->dma_tx);
- host->dma_tx = NULL;
- }
-}
-
/* This function is called by the DMA driver from tasklet context */
static void dma_callback(void *data)
{
@@ -1586,30 +1626,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
as->use_pdc = true;
}
- if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
- as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
- SPI_MAX_DMA_XFER,
- &as->dma_addr_rx_bbuf,
- GFP_KERNEL | GFP_DMA);
- if (!as->addr_rx_bbuf) {
- as->use_dma = false;
- } else {
- as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
- SPI_MAX_DMA_XFER,
- &as->dma_addr_tx_bbuf,
- GFP_KERNEL | GFP_DMA);
- if (!as->addr_tx_bbuf) {
- as->use_dma = false;
- dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
- as->addr_rx_bbuf,
- as->dma_addr_rx_bbuf);
- }
- }
- if (!as->use_dma)
- dev_info(host->dev.parent,
- " can not allocate dma coherent memory\n");
- }
-
if (as->caps.has_dma_support && !as->use_dma)
dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
@@ -1669,13 +1685,10 @@ static int atmel_spi_probe(struct platform_device *pdev)
out_free_dma:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
-
- if (as->use_dma)
- atmel_spi_release_dma(host);
-
spi_writel(as, CR, SPI_BIT(SWRST));
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
- clk_disable_unprepare(as->gclk);
+ if (as->gclk)
+ clk_disable_unprepare(as->gclk);
out_disable_clk:
clk_disable_unprepare(clk);
out_free_irq:
@@ -1696,18 +1709,8 @@ static void atmel_spi_remove(struct platform_device *pdev)
spi_unregister_controller(host);
/* reset the hardware and block queue progress */
- if (as->use_dma) {
+ if (as->use_dma)
atmel_spi_stop_dma(host);
- atmel_spi_release_dma(host);
- if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
- dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
- as->addr_tx_bbuf,
- as->dma_addr_tx_bbuf);
- dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
- as->addr_rx_bbuf,
- as->dma_addr_rx_bbuf);
- }
- }
spin_lock_irq(&as->lock);
spi_writel(as, CR, SPI_BIT(SWRST));
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index fc267c6437ae..8a3c085c85e0 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -282,6 +282,7 @@ static inline void dw_spi_shutdown_chip(struct dw_spi *dws)
{
dw_spi_enable_chip(dws, 0);
dw_spi_set_clk(dws, 0);
+ dws->current_freq = 0;
}
extern void dw_spi_set_cs(struct spi_device *spi, bool enable);
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index 52d2f8920cd7..a8ddd3d388de 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -600,6 +600,7 @@ fail_release_rx:
espi->dma_rx = NULL;
fail_free_page:
free_page((unsigned long)espi->zeropage);
+ espi->zeropage = NULL;
return ret;
}
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
index a38dcae6271f..f004920600ae 100644
--- a/drivers/spi/spi-hisi-kunpeng.c
+++ b/drivers/spi/spi-hisi-kunpeng.c
@@ -518,10 +518,8 @@ static int hisi_spi_probe(struct platform_device *pdev)
}
ret = spi_register_controller(host);
- if (ret) {
- dev_err(dev, "failed to register spi host, ret=%d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register spi host\n");
if (hisi_spi_debugfs_init(hs))
dev_info(dev, "failed to create debugfs dir\n");
diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c
index ef7efeaeee97..e19ca48a2b65 100644
--- a/drivers/spi/spi-meson-spifc.c
+++ b/drivers/spi/spi-meson-spifc.c
@@ -352,6 +352,7 @@ static void meson_spifc_remove(struct platform_device *pdev)
{
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index 6edc0c4db854..c2f9c86c1d8d 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -206,8 +206,12 @@ static int rpcif_spi_suspend(struct device *dev)
static int rpcif_spi_resume(struct device *dev)
{
struct spi_controller *ctlr = dev_get_drvdata(dev);
+ struct rpcif *rpc = spi_controller_get_devdata(ctlr);
+ int ret;
- rpcif_hw_init(dev, false);
+ ret = rpcif_hw_init(rpc->dev, false);
+ if (ret)
+ return ret;
return spi_controller_resume(ctlr);
}
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 7f4135a3bda2..a4ae96290aa2 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -114,7 +114,7 @@ static irqreturn_t sh_msiof_spi_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static void sh_msiof_spi_reset_regs(struct sh_msiof_spi_priv *p)
+static int sh_msiof_spi_reset_regs(struct sh_msiof_spi_priv *p)
{
u32 mask = SICTR_TXRST | SICTR_RXRST;
u32 data;
@@ -123,8 +123,8 @@ static void sh_msiof_spi_reset_regs(struct sh_msiof_spi_priv *p)
data |= mask;
sh_msiof_write(p, SICTR, data);
- readl_poll_timeout_atomic(p->mapbase + SICTR, data, !(data & mask), 1,
- 100);
+ return readl_poll_timeout_atomic(p->mapbase + SICTR, data,
+ !(data & mask), 1, 100);
}
static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
@@ -834,7 +834,9 @@ static int sh_msiof_transfer_one(struct spi_controller *ctlr,
int ret;
/* reset registers */
- sh_msiof_spi_reset_regs(p);
+ ret = sh_msiof_spi_reset_regs(p);
+ if (ret)
+ return ret;
/* setup clocks (clock already enabled in chipselect()) */
if (!spi_controller_is_target(p->ctlr))
diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c
index 75b7a0d3f865..2126f46cb14e 100644
--- a/drivers/spi/spi-uniphier.c
+++ b/drivers/spi/spi-uniphier.c
@@ -659,6 +659,8 @@ static int uniphier_spi_probe(struct platform_device *pdev)
priv->host = host;
priv->is_save_param = false;
+ init_completion(&priv->xfer_done);
+
priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base);
@@ -686,8 +688,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
goto out_host_put;
}
- init_completion(&priv->xfer_done);
-
clk_rate = clk_get_rate(priv->clk);
host->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER);
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index c86dc56f38b4..8085571913c8 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -371,11 +371,18 @@ static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi)
xspi->regs + XIPIF_V123B_RESETR_OFFSET);
/* Fill the Tx FIFO with as many words as possible */
- do {
+ while (1) {
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+ if (sr & XSPI_SR_TX_FULL_MASK)
+ break;
+
n_words++;
- } while (!(sr & XSPI_SR_TX_FULL_MASK));
+ }
+
+ /* Handle the NO FIFO case separately */
+ if (!n_words)
+ return 1;
return n_words;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index ac4de4703a6f..6ea9ac2931cd 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -4810,11 +4810,6 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
return NOTIFY_OK;
}
- /*
- * Clear the flag before adding the device so that fw_devlink
- * doesn't skip adding consumers to this device.
- */
- fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
spi = of_register_spi_device(ctlr, rd->dn);
put_device(&ctlr->dev);