summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-07-23 15:06:03 +0100
committerMark Brown <broonie@kernel.org>2026-07-23 15:06:03 +0100
commite6ac02baf8864fad4d1fd52e070d5ebd94296af7 (patch)
tree5807d00978eac4fd2252205c65046dbe150743ab /drivers
parent70b506cadb7409cad6a4f331c689244d605b16e8 (diff)
parentf3783a591419ad74afe0beb0b81bca249b20d90b (diff)
downloadlinux-next-e6ac02baf8864fad4d1fd52e070d5ebd94296af7.tar.gz
linux-next-e6ac02baf8864fad4d1fd52e070d5ebd94296af7.zip
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/atmel-quadspi.c132
-rw-r--r--drivers/spi/spi-altera-platform.c13
-rw-r--r--drivers/spi/spi-atcspi200.c5
-rw-r--r--drivers/spi/spi-axiado.c20
-rw-r--r--drivers/spi/spi-axiado.h5
-rw-r--r--drivers/spi/spi-bcm-qspi.c6
-rw-r--r--drivers/spi/spi-bcm2835.c2
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c6
-rw-r--r--drivers/spi/spi-bcm63xx.c5
-rw-r--r--drivers/spi/spi-bcmbca-hsspi.c6
-rw-r--r--drivers/spi/spi-fsl-dspi.c21
-rw-r--r--drivers/spi/spi-geni-qcom.c105
-rw-r--r--drivers/spi/spi-npcm-fiu.c15
-rw-r--r--drivers/spi/spi-nxp-fspi.c31
-rw-r--r--drivers/spi/spi-orion.c25
-rw-r--r--drivers/spi/spi-qpic-snand.c6
-rw-r--r--drivers/spi/spi-realtek-rtl.c26
-rw-r--r--drivers/spi/spi-rpc-if.c4
19 files changed, 272 insertions, 163 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8782514bb89b..bb3773f99ad9 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -189,7 +189,7 @@ config SPI_AT91_USART
config SPI_ATMEL_QUADSPI
tristate "Atmel Quad SPI Controller"
- depends on ARCH_AT91 || COMPILE_TEST
+ depends on ARCH_MICROCHIP || COMPILE_TEST
depends on OF && HAS_IOMEM
help
This enables support for the Quad SPI controller in master mode.
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index aaf7f4c46b22..98369091eef7 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -256,8 +256,11 @@ static const struct atmel_qspi_pcal pcal[ATMEL_QSPI_PCAL_ARRAY_SIZE] = {
{200000000, 7},
};
+struct atmel_qspi;
+
struct atmel_qspi_caps {
u32 max_speed_hz;
+ int (*init)(struct atmel_qspi *aq);
bool has_qspick;
bool has_gclk;
bool has_ricr;
@@ -1149,6 +1152,58 @@ static int atmel_qspi_sama7g5_init(struct atmel_qspi *aq)
return ret;
}
+static int atmel_qspi_lan969x_init(struct atmel_qspi *aq)
+{
+ u32 val;
+ int ret;
+
+ atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
+ ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
+ !(val & QSPI_SR2_DLOCK), 40,
+ ATMEL_QSPI_TIMEOUT);
+ if (ret)
+ return ret;
+
+ ret = atmel_qspi_set_gclk(aq);
+ if (ret)
+ return ret;
+
+ /* Start the DLL before resetting the controller. */
+ atmel_qspi_write(QSPI_CR_DLLON | QSPI_CR_STPCAL, aq, QSPI_CR);
+ ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
+ (val & QSPI_SR2_DLOCK) &&
+ !(val & QSPI_SR2_CALBSY), 40,
+ ATMEL_QSPI_TIMEOUT);
+ if (ret)
+ return ret;
+
+ atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR);
+ ret = atmel_qspi_reg_sync(aq);
+ if (ret)
+ return ret;
+
+ atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
+ ret = atmel_qspi_reg_sync(aq);
+ if (ret)
+ return ret;
+
+ ret = atmel_qspi_set_pad_calibration(aq);
+ if (ret)
+ return ret;
+
+ aq->mr = 0;
+ aq->scr = 0;
+
+ ret = atmel_qspi_set_serial_memory_mode(aq);
+ if (ret)
+ return ret;
+
+ atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);
+ return readl_poll_timeout(aq->regs + QSPI_SR2, val,
+ (val & QSPI_SR2_QSPIENS), 40,
+ ATMEL_QSPI_TIMEOUT);
+}
+
static int atmel_qspi_sama7g5_setup(struct spi_device *spi)
{
struct atmel_qspi *aq = spi_controller_get_devdata(spi->controller);
@@ -1156,7 +1211,7 @@ static int atmel_qspi_sama7g5_setup(struct spi_device *spi)
/* The controller can communicate with a single peripheral device (target). */
aq->target_max_speed_hz = spi->max_speed_hz;
- return atmel_qspi_sama7g5_init(aq);
+ return aq->caps->init(aq);
}
static int atmel_qspi_setup(struct spi_device *spi)
@@ -1347,20 +1402,21 @@ static const struct atmel_qspi_ops atmel_qspi_sama7g5_ops = {
static int atmel_qspi_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct spi_controller *ctrl;
struct atmel_qspi *aq;
struct resource *res;
int irq, err = 0;
- ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*aq));
+ ctrl = devm_spi_alloc_host(dev, sizeof(*aq));
if (!ctrl)
return -ENOMEM;
aq = spi_controller_get_devdata(ctrl);
- aq->caps = of_device_get_match_data(&pdev->dev);
+ aq->caps = of_device_get_match_data(dev);
if (!aq->caps) {
- dev_err(&pdev->dev, "Could not retrieve QSPI caps\n");
+ dev_err(dev, "Could not retrieve QSPI caps\n");
return -EINVAL;
}
@@ -1387,45 +1443,40 @@ static int atmel_qspi_probe(struct platform_device *pdev)
/* Map the registers */
aq->regs = devm_platform_ioremap_resource_byname(pdev, "qspi_base");
if (IS_ERR(aq->regs))
- return dev_err_probe(&pdev->dev, PTR_ERR(aq->regs),
+ return dev_err_probe(dev, PTR_ERR(aq->regs),
"missing registers\n");
/* Map the AHB memory */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mmap");
- aq->mem = devm_ioremap_resource(&pdev->dev, res);
+ aq->mem = devm_ioremap_resource(dev, res);
if (IS_ERR(aq->mem))
- return dev_err_probe(&pdev->dev, PTR_ERR(aq->mem),
+ return dev_err_probe(dev, PTR_ERR(aq->mem),
"missing AHB memory\n");
aq->mmap_size = resource_size(res);
aq->mmap_phys_base = (dma_addr_t)res->start;
/* Get the peripheral clock */
- aq->pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
+ aq->pclk = devm_clk_get_enabled(dev, "pclk");
if (IS_ERR(aq->pclk))
- aq->pclk = devm_clk_get_enabled(&pdev->dev, NULL);
+ aq->pclk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(aq->pclk))
- return dev_err_probe(&pdev->dev, PTR_ERR(aq->pclk),
+ return dev_err_probe(dev, PTR_ERR(aq->pclk),
"missing peripheral clock\n");
if (aq->caps->has_qspick) {
/* Get the QSPI system clock */
- aq->qspick = devm_clk_get_enabled(&pdev->dev, "qspick");
- if (IS_ERR(aq->qspick)) {
- dev_err(&pdev->dev, "missing system clock\n");
- err = PTR_ERR(aq->qspick);
- return err;
- }
-
+ aq->qspick = devm_clk_get_enabled(dev, "qspick");
+ if (IS_ERR(aq->qspick))
+ return dev_err_probe(dev, PTR_ERR(aq->qspick),
+ "missing system clock\n");
} else if (aq->caps->has_gclk) {
/* Get the QSPI generic clock */
- aq->gclk = devm_clk_get(&pdev->dev, "gclk");
- if (IS_ERR(aq->gclk)) {
- dev_err(&pdev->dev, "missing Generic clock\n");
- err = PTR_ERR(aq->gclk);
- return err;
- }
+ aq->gclk = devm_clk_get(dev, "gclk");
+ if (IS_ERR(aq->gclk))
+ return dev_err_probe(dev, PTR_ERR(aq->gclk),
+ "missing Generic clock\n");
}
if (aq->caps->has_dma) {
@@ -1439,15 +1490,15 @@ static int atmel_qspi_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt,
- 0, dev_name(&pdev->dev), aq);
+ err = devm_request_irq(dev, irq, atmel_qspi_interrupt,
+ 0, dev_name(dev), aq);
if (err)
return err;
- pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
- pm_runtime_use_autosuspend(&pdev->dev);
- devm_pm_runtime_set_active_enabled(&pdev->dev);
- devm_pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(dev, 500);
+ pm_runtime_use_autosuspend(dev);
+ devm_pm_runtime_set_active_enabled(dev);
+ devm_pm_runtime_get_noresume(dev);
err = atmel_qspi_init(aq);
if (err)
@@ -1457,7 +1508,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
if (err)
return err;
- pm_runtime_put_autosuspend(&pdev->dev);
+ pm_runtime_put_autosuspend(dev);
return 0;
}
@@ -1571,7 +1622,7 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
}
if (aq->caps->has_gclk)
- return atmel_qspi_sama7g5_init(aq);
+ return aq->caps->init(aq);
ret = pm_runtime_force_resume(dev);
if (ret < 0)
@@ -1629,6 +1680,7 @@ static const struct atmel_qspi_caps atmel_sam9x60_qspi_caps = {
static const struct atmel_qspi_caps atmel_sam9x7_ospi_caps = {
.max_speed_hz = SAM9X7_QSPI_MAX_SPEED_HZ,
+ .init = atmel_qspi_sama7g5_init,
.has_gclk = true,
.octal = true,
.has_dma = true,
@@ -1639,6 +1691,7 @@ static const struct atmel_qspi_caps atmel_sam9x7_ospi_caps = {
static const struct atmel_qspi_caps atmel_sama7d65_ospi_caps = {
.max_speed_hz = SAMA7G5_QSPI0_MAX_SPEED_HZ,
+ .init = atmel_qspi_sama7g5_init,
.has_gclk = true,
.octal = true,
.has_dma = true,
@@ -1649,6 +1702,7 @@ static const struct atmel_qspi_caps atmel_sama7d65_ospi_caps = {
static const struct atmel_qspi_caps atmel_sama7d65_qspi_caps = {
.max_speed_hz = SAMA7G5_QSPI1_SDR_MAX_SPEED_HZ,
+ .init = atmel_qspi_sama7g5_init,
.has_gclk = true,
.has_dma = true,
.has_2xgclk = true,
@@ -1657,6 +1711,7 @@ static const struct atmel_qspi_caps atmel_sama7d65_qspi_caps = {
static const struct atmel_qspi_caps atmel_sama7g5_ospi_caps = {
.max_speed_hz = SAMA7G5_QSPI0_MAX_SPEED_HZ,
+ .init = atmel_qspi_sama7g5_init,
.has_gclk = true,
.octal = true,
.has_dma = true,
@@ -1666,11 +1721,21 @@ static const struct atmel_qspi_caps atmel_sama7g5_ospi_caps = {
static const struct atmel_qspi_caps atmel_sama7g5_qspi_caps = {
.max_speed_hz = SAMA7G5_QSPI1_SDR_MAX_SPEED_HZ,
+ .init = atmel_qspi_sama7g5_init,
.has_gclk = true,
.has_dma = true,
.has_dllon = true,
};
+static const struct atmel_qspi_caps atmel_lan969x_qspi_caps = {
+ .max_speed_hz = SAM9X7_QSPI_MAX_SPEED_HZ,
+ .init = atmel_qspi_lan969x_init,
+ .has_gclk = true,
+ .has_dma = true,
+ .has_padcalib = true,
+ .has_dllon = true,
+};
+
static const struct of_device_id atmel_qspi_dt_ids[] = {
{
.compatible = "atmel,sama5d2-qspi",
@@ -1700,7 +1765,10 @@ static const struct of_device_id atmel_qspi_dt_ids[] = {
.compatible = "microchip,sama7d65-qspi",
.data = &atmel_sama7d65_qspi_caps,
},
-
+ {
+ .compatible = "microchip,lan9691-qspi",
+ .data = &atmel_lan969x_qspi_caps,
+ },
{ /* sentinel */ }
};
diff --git a/drivers/spi/spi-altera-platform.c b/drivers/spi/spi-altera-platform.c
index 3de7df73f216..4fe69ce9da16 100644
--- a/drivers/spi/spi-altera-platform.c
+++ b/drivers/spi/spi-altera-platform.c
@@ -77,10 +77,8 @@ static int altera_spi_probe(struct platform_device *pdev)
struct resource *regoff;
hw->regmap = dev_get_regmap(pdev->dev.parent, NULL);
- if (!hw->regmap) {
- dev_err(&pdev->dev, "get regmap failed\n");
- return -ENODEV;
- }
+ if (!hw->regmap)
+ return dev_err_probe(&pdev->dev, -ENODEV, "get regmap failed\n");
regoff = platform_get_resource(pdev, IORESOURCE_REG, 0);
if (regoff)
@@ -94,10 +92,9 @@ static int altera_spi_probe(struct platform_device *pdev)
hw->regmap = devm_regmap_init_mmio(&pdev->dev, res,
&spi_altera_config);
- if (IS_ERR(hw->regmap)) {
- dev_err(&pdev->dev, "regmap mmio init failed\n");
- return PTR_ERR(hw->regmap);
- }
+ if (IS_ERR(hw->regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(hw->regmap),
+ "regmap mmio init failed\n");
}
altera_spi_init_host(host);
diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c
index 3c5098421ba3..b6ea8e556335 100644
--- a/drivers/spi/spi-atcspi200.c
+++ b/drivers/spi/spi-atcspi200.c
@@ -598,8 +598,11 @@ static int atcspi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct atcspi_dev *spi = spi_controller_get_devdata(host);
+ int ret;
- spi_controller_suspend(host);
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
clk_disable_unprepare(spi->clk);
diff --git a/drivers/spi/spi-axiado.c b/drivers/spi/spi-axiado.c
index 649f149617ce..25561aa9f76f 100644
--- a/drivers/spi/spi-axiado.c
+++ b/drivers/spi/spi-axiado.c
@@ -213,7 +213,7 @@ static void ax_spi_fill_tx_fifo(struct ax_spi *xspi)
}
/**
- * ax_spi_get_rx_byte - Gets a byte from the RX FIFO buffer
+ * ax_spi_get_rx_byte_for_irq - Gets a byte from the RX FIFO buffer
* @xspi: Controller private data (struct ax_spi *)
*
* This function handles the logic of extracting bytes from the 32-bit RX FIFO.
@@ -246,9 +246,13 @@ static u8 ax_spi_get_rx_byte_for_irq(struct ax_spi *xspi)
}
/**
+ * ax_spi_process_rx_and_finalize - Process RX bytes and check for completion
+ * @ctlr: Pointer to spi_controller structure
+ *
* Helper function to process received bytes and check for transfer completion.
* This avoids code duplication and centralizes the completion logic.
- * Returns true if the transfer was finalized.
+ *
+ * Return: true if the transfer was finalized.
*/
static bool ax_spi_process_rx_and_finalize(struct spi_controller *ctlr)
{
@@ -430,15 +434,11 @@ static int ax_transfer_one(struct spi_controller *ctlr,
/* TX mode: discard all received data */
xspi->rx_discard = transfer->len;
xspi->rx_copy_remaining = 0;
- } else if ((!transfer->tx_buf && transfer->rx_buf) ||
- (transfer->tx_buf && transfer->rx_buf)) {
- /* RX mode: generate clock by filling TX FIFO with dummy bytes
- * Full-duplex mode: generate clock by filling TX FIFO
- */
- xspi->rx_discard = 0;
- xspi->rx_copy_remaining = transfer->len;
} else {
- /* No TX and RX */
+ /* RX-only or full-duplex mode: copy received data, with the
+ * clock generated by filling the TX FIFO (with dummy bytes
+ * in RX-only mode)
+ */
xspi->rx_discard = 0;
xspi->rx_copy_remaining = transfer->len;
}
diff --git a/drivers/spi/spi-axiado.h b/drivers/spi/spi-axiado.h
index 6cf0e5bf5879..d24d31c3a446 100644
--- a/drivers/spi/spi-axiado.h
+++ b/drivers/spi/spi-axiado.h
@@ -98,9 +98,10 @@
* @regs: Virtual address of the SPI controller registers
* @ref_clk: Pointer to the peripheral clock
* @pclk: Pointer to the APB clock
+ * @clk_rate: Reference clock rate in Hz
* @speed_hz: Current SPI bus clock speed in Hz
- * @txbuf: Pointer to the TX buffer
- * @rxbuf: Pointer to the RX buffer
+ * @tx_buf: Pointer to the TX buffer
+ * @rx_buf: Pointer to the RX buffer
* @tx_bytes: Number of bytes left to transfer
* @rx_bytes: Number of bytes requested
* @tx_fifo_depth: Depth of the TX FIFO
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index dcade7b99cef..ae1ffe13fa46 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -1692,13 +1692,17 @@ EXPORT_SYMBOL_GPL(bcm_qspi_remove);
static int __maybe_unused bcm_qspi_suspend(struct device *dev)
{
struct bcm_qspi *qspi = dev_get_drvdata(dev);
+ int ret;
/* store the override strap value */
if (!bcm_qspi_bspi_ver_three(qspi))
qspi->s3_strap_override_ctrl =
bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
- spi_controller_suspend(qspi->host);
+ ret = spi_controller_suspend(qspi->host);
+ if (ret)
+ return ret;
+
clk_disable_unprepare(qspi->clk);
bcm_qspi_hw_uninit(qspi);
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index ff94482fefcc..8f8715809c7c 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -1226,7 +1226,7 @@ static int bcm2835_spi_setup(struct spi_device *spi)
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
struct bcm2835_spidev *target = spi_get_ctldata(spi);
struct gpiod_lookup_table *lookup __free(kfree) = NULL;
- const char *pinctrl_compats[] = {
+ static const char * const pinctrl_compats[] = {
"brcm,bcm2835-gpio",
"brcm,bcm2711-gpio",
"brcm,bcm7211-gpio",
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 58012e1b5ae7..37b3534d0b0a 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -889,8 +889,12 @@ static int bcm63xx_hsspi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
+ int ret;
+
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
- spi_controller_suspend(host);
clk_disable_unprepare(bs->pll_clk);
clk_disable_unprepare(bs->clk);
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 43d7b54e3ae8..8cef725aab26 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -632,8 +632,11 @@ static int bcm63xx_spi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
+ int ret;
- spi_controller_suspend(host);
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
clk_disable_unprepare(bs->clk);
diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c
index 09c1472ae4fa..af88ce04948b 100644
--- a/drivers/spi/spi-bcmbca-hsspi.c
+++ b/drivers/spi/spi-bcmbca-hsspi.c
@@ -568,8 +568,12 @@ static int bcmbca_hsspi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct bcmbca_hsspi *bs = spi_controller_get_devdata(host);
+ int ret;
+
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
- spi_controller_suspend(host);
clk_disable_unprepare(bs->pll_clk);
clk_disable_unprepare(bs->clk);
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 019d05cdefe6..c2d283876ef8 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1464,10 +1464,18 @@ static int dspi_init(struct fsl_dspi *dspi)
static int dspi_suspend(struct device *dev)
{
struct fsl_dspi *dspi = dev_get_drvdata(dev);
+ int ret;
if (dspi->irq)
disable_irq(dspi->irq);
- spi_controller_suspend(dspi->ctlr);
+
+ ret = spi_controller_suspend(dspi->ctlr);
+ if (ret) {
+ if (dspi->irq)
+ enable_irq(dspi->irq);
+ return ret;
+ }
+
clk_disable_unprepare(dspi->clk);
pinctrl_pm_select_sleep_state(dev);
@@ -1485,12 +1493,15 @@ static int dspi_resume(struct device *dev)
ret = clk_prepare_enable(dspi->clk);
if (ret)
return ret;
- spi_controller_resume(dspi->ctlr);
+
+ ret = spi_controller_resume(dspi->ctlr);
+ if (ret)
+ goto disable_clk;
ret = dspi_init(dspi);
if (ret) {
dev_err(dev, "failed to initialize dspi during resume\n");
- return ret;
+ goto disable_clk;
}
dspi_set_mtf(dspi);
@@ -1499,6 +1510,10 @@ static int dspi_resume(struct device *dev)
enable_irq(dspi->irq);
return 0;
+
+disable_clk:
+ clk_disable_unprepare(dspi->clk);
+ return ret;
}
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 26e723cfea61..d262206ed663 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -78,6 +78,13 @@
#define GSI_CPHA BIT(4)
#define GSI_CPOL BIT(5)
+struct geni_spi_desc {
+ int (*resources_init)(struct geni_se *se);
+ int (*set_rate)(struct geni_se *se, unsigned long clk_freq);
+ int (*power_on)(struct geni_se *se);
+ int (*power_off)(struct geni_se *se);
+};
+
struct spi_geni_master {
struct geni_se se;
struct device *dev;
@@ -105,6 +112,7 @@ struct spi_geni_master {
struct dma_chan *tx;
struct dma_chan *rx;
int cur_xfer_mode;
+ const struct geni_spi_desc *dev_data;
};
static void spi_slv_setup(struct spi_geni_master *mas)
@@ -305,11 +313,12 @@ static void spi_setup_word_len(struct spi_geni_master *mas, u16 mode,
writel(word_len, se->base + SE_SPI_WORD_LEN);
}
-static int geni_spi_set_clock_and_bw(struct spi_geni_master *mas,
- unsigned long clk_hz)
+static int geni_spi_set_clock_and_bw(struct geni_se *se,
+ unsigned long clk_hz)
{
+ struct spi_controller *spi = dev_get_drvdata(se->dev);
+ struct spi_geni_master *mas = spi_controller_get_devdata(spi);
u32 clk_sel, m_clk_cfg, idx, div;
- struct geni_se *se = &mas->se;
int ret;
if (clk_hz == mas->cur_speed_hz)
@@ -613,25 +622,30 @@ static int spi_geni_init(struct spi_geni_master *mas)
u32 spi_tx_cfg, fifo_disable;
int ret = -ENXIO;
- pm_runtime_get_sync(mas->dev);
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(mas->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret < 0) {
+ dev_err(mas->dev, "Failed to resume and get %d\n", ret);
+ return ret;
+ }
proto = geni_se_read_proto(se);
if (spi->target) {
if (proto != GENI_SE_SPI_SLAVE) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
- goto out_pm;
+ return -EINVAL;
}
spi_slv_setup(mas);
} else if (proto == GENI_SE_INVALID_PROTO) {
ret = geni_load_se_firmware(se, GENI_SE_SPI);
if (ret) {
dev_err(mas->dev, "spi master firmware load failed ret: %d\n", ret);
- goto out_pm;
+ return ret;
}
} else if (proto != GENI_SE_SPI) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
- goto out_pm;
+ return -EINVAL;
}
mas->tx_fifo_depth = geni_se_get_tx_fifo_depth(se);
@@ -664,7 +678,7 @@ static int spi_geni_init(struct spi_geni_master *mas)
dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n");
break;
} else if (ret == -EPROBE_DEFER) {
- goto out_pm;
+ return ret;
}
/*
* in case of failure to get gpi dma channel, we can still do the
@@ -693,8 +707,6 @@ static int spi_geni_init(struct spi_geni_master *mas)
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
}
-out_pm:
- pm_runtime_put(mas->dev);
return ret;
}
@@ -825,7 +837,7 @@ static int setup_se_xfer(struct spi_transfer *xfer,
}
/* Speed and bits per word can be overridden per transfer */
- ret = geni_spi_set_clock_and_bw(mas, xfer->speed_hz);
+ ret = mas->dev_data->set_rate(&mas->se, xfer->speed_hz);
if (ret)
return ret;
@@ -1045,7 +1057,6 @@ static int spi_geni_probe(struct platform_device *pdev)
struct spi_controller *spi;
struct spi_geni_master *mas;
void __iomem *base;
- struct clk *clk;
struct device *dev = &pdev->dev;
irq = platform_get_irq(pdev, 0);
@@ -1060,10 +1071,6 @@ static int spi_geni_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- clk = devm_clk_get(dev, "se");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
if (device_property_read_bool(dev, "spi-slave"))
spi = devm_spi_alloc_target(dev, sizeof(*mas));
else
@@ -1079,17 +1086,14 @@ static int spi_geni_probe(struct platform_device *pdev)
mas->se.dev = dev;
mas->se.wrapper = dev_get_drvdata(dev->parent);
mas->se.base = base;
- mas->se.clk = clk;
- ret = devm_pm_opp_set_clkname(&pdev->dev, "se");
+ mas->dev_data = device_get_match_data(&pdev->dev);
+ if (!mas->dev_data)
+ return -EINVAL;
+
+ ret = mas->dev_data->resources_init(&mas->se);
if (ret)
return ret;
- /* OPP table is optional */
- ret = devm_pm_opp_of_add_table(&pdev->dev);
- if (ret && ret != -ENODEV) {
- dev_err(&pdev->dev, "invalid OPP table in device tree\n");
- return ret;
- }
spi->bus_num = -1;
spi->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH;
@@ -1115,24 +1119,12 @@ static int spi_geni_probe(struct platform_device *pdev)
if (spi->target)
spi->target_abort = spi_geni_target_abort;
- ret = geni_icc_get(&mas->se, NULL);
- if (ret)
- return ret;
-
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
- /* Set the bus quota to a reasonable value for register access */
- mas->se.icc_paths[GENI_TO_CORE].avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
- mas->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
-
- ret = geni_icc_set_bw(&mas->se);
- if (ret)
- return ret;
-
ret = spi_geni_init(mas);
if (ret)
return ret;
@@ -1154,16 +1146,9 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev)
{
struct spi_controller *spi = dev_get_drvdata(dev);
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
- int ret;
-
- /* Drop the performance state vote */
- dev_pm_opp_set_rate(dev, 0);
-
- ret = geni_se_resources_off(&mas->se);
- if (ret)
- return ret;
- return geni_icc_disable(&mas->se);
+ return mas->dev_data->power_off ?
+ mas->dev_data->power_off(&mas->se) : 0;
}
static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
@@ -1172,15 +1157,16 @@ static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
int ret;
- ret = geni_icc_enable(&mas->se);
- if (ret)
- return ret;
+ if (mas->dev_data->power_on) {
+ ret = mas->dev_data->power_on(&mas->se);
+ if (ret)
+ return ret;
+ }
- ret = geni_se_resources_on(&mas->se);
- if (ret)
- return ret;
+ if (mas->se.has_opp)
+ return dev_pm_opp_set_rate(mas->dev, mas->cur_sclk_hz);
- return dev_pm_opp_set_rate(mas->dev, mas->cur_sclk_hz);
+ return 0;
}
static int __maybe_unused spi_geni_suspend(struct device *dev)
@@ -1221,8 +1207,21 @@ static const struct dev_pm_ops spi_geni_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(spi_geni_suspend, spi_geni_resume)
};
+static const struct geni_spi_desc geni_spi = {
+ .resources_init = geni_se_resources_init,
+ .set_rate = geni_spi_set_clock_and_bw,
+ .power_on = geni_se_resources_activate,
+ .power_off = geni_se_resources_deactivate,
+};
+
+static const struct geni_spi_desc sa8255p_geni_spi = {
+ .resources_init = geni_se_domain_attach,
+ .set_rate = geni_se_set_perf_opp,
+};
+
static const struct of_device_id spi_geni_dt_match[] = {
- { .compatible = "qcom,geni-spi" },
+ { .compatible = "qcom,geni-spi", .data = &geni_spi },
+ { .compatible = "qcom,sa8255p-geni-spi", .data = &sa8255p_geni_spi },
{}
};
MODULE_DEVICE_TABLE(of, spi_geni_dt_match);
diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c
index 4b825044038b..96dfef4d9067 100644
--- a/drivers/spi/spi-npcm-fiu.c
+++ b/drivers/spi/spi-npcm-fiu.c
@@ -393,7 +393,7 @@ static int npcm_fiu_uma_write(struct spi_mem *mem,
{
struct npcm_fiu_spi *fiu =
spi_controller_get_devdata(mem->spi->controller);
- u32 uma_cfg = BIT(10);
+ u32 uma_cfg = cmd ? BIT(10) : 0;
u32 data_reg[4] = {0};
u32 val;
u32 i;
@@ -403,8 +403,11 @@ static int npcm_fiu_uma_write(struct spi_mem *mem,
(spi_get_chipselect(mem->spi, 0) <<
NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
- regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD,
- NPCM_FIU_UMA_CMD_CMD, cmd);
+ if (cmd)
+ regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD,
+ NPCM_FIU_UMA_CMD_CMD, cmd);
+ else
+ uma_cfg |= ilog2(op->data.buswidth) << NPCM_FIU_UMA_CFG_WDBPCK_SHIFT;
if (data_size) {
memcpy(data_reg, data, data_size);
@@ -464,8 +467,7 @@ static int npcm_fiu_manualwrite(struct spi_mem *mem,
/* Starting the data writing loop in multiples of 8 */
for (idx = 0; idx < num_data_chunks; ++idx) {
- ret = npcm_fiu_uma_write(mem, op, data[0], false,
- &data[1], CHUNK_SIZE - 1);
+ ret = npcm_fiu_uma_write(mem, op, 0, false, &data[0], CHUNK_SIZE);
if (ret)
return ret;
@@ -474,8 +476,7 @@ static int npcm_fiu_manualwrite(struct spi_mem *mem,
/* Handling chunk remains */
if (remain_data > 0) {
- ret = npcm_fiu_uma_write(mem, op, data[0], false,
- &data[1], remain_data - 1);
+ ret = npcm_fiu_uma_write(mem, op, 0, false, &data[0], remain_data);
if (ret)
return ret;
}
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
index 1e36ae084dd8..d94a2a7b98d4 100644
--- a/drivers/spi/spi-nxp-fspi.c
+++ b/drivers/spi/spi-nxp-fspi.c
@@ -1350,9 +1350,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
/* enable clock */
- ret = pm_runtime_get_sync(f->dev);
- if (ret < 0)
- return dev_err_probe(dev, ret, "Failed to enable clock");
+ ret = pm_runtime_resume_and_get(f->dev);
+ if (ret < 0) {
+ ret = dev_err_probe(dev, ret, "Failed to enable clock");
+ goto err_disable_pm;
+ }
/* Clear potential interrupts */
reg = fspi_readl(f, f->iobase + FSPI_INTR);
@@ -1362,18 +1364,24 @@ static int nxp_fspi_probe(struct platform_device *pdev)
nxp_fspi_default_setup(f);
ret = pm_runtime_put_sync(dev);
- if (ret < 0)
- return dev_err_probe(dev, ret, "Failed to disable clock");
+ if (ret < 0) {
+ ret = dev_err_probe(dev, ret, "Failed to disable clock");
+ goto err_disable_pm;
+ }
init_completion(&f->c);
ret = devm_request_irq(dev, irq,
nxp_fspi_irq_handler, 0, pdev->name, f);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to request irq\n");
+ if (ret) {
+ ret = dev_err_probe(dev, ret, "Failed to request irq\n");
+ goto err_disable_pm;
+ }
ret = devm_mutex_init(dev, &f->lock);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to initialize lock\n");
+ if (ret) {
+ ret = dev_err_probe(dev, ret, "Failed to initialize lock\n");
+ goto err_disable_pm;
+ }
ctlr->bus_num = -1;
ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
@@ -1389,6 +1397,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
return ret;
return devm_spi_register_controller(&pdev->dev, ctlr);
+
+err_disable_pm:
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+ return ret;
}
static int nxp_fspi_runtime_suspend(struct device *dev)
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 265708a94984..e5e05512a1fd 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -691,12 +691,9 @@ static int orion_spi_probe(struct platform_device *pdev)
return PTR_ERR(spi->clk);
/* The following clock is only used by some SoCs */
- spi->axi_clk = devm_clk_get(&pdev->dev, "axi");
- if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- if (!IS_ERR(spi->axi_clk))
- clk_prepare_enable(spi->axi_clk);
+ spi->axi_clk = devm_clk_get_optional_enabled(&pdev->dev, "axi");
+ if (IS_ERR(spi->axi_clk))
+ return PTR_ERR(spi->axi_clk);
tclk_hz = clk_get_rate(spi->clk);
@@ -719,10 +716,8 @@ static int orion_spi_probe(struct platform_device *pdev)
host->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor);
spi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
- if (IS_ERR(spi->base)) {
- status = PTR_ERR(spi->base);
- goto out_rel_axi_clk;
- }
+ if (IS_ERR(spi->base))
+ return PTR_ERR(spi->base);
for_each_available_child_of_node(pdev->dev.of_node, np) {
struct orion_direct_acc *dir_acc;
@@ -757,9 +752,8 @@ static int orion_spi_probe(struct platform_device *pdev)
dir_acc = &spi->child[cs].direct_access;
dir_acc->vaddr = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
if (!dir_acc->vaddr) {
- status = -ENOMEM;
of_node_put(np);
- goto out_rel_axi_clk;
+ return -ENOMEM;
}
dir_acc->size = PAGE_SIZE;
@@ -789,8 +783,6 @@ out_rel_pm:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
-out_rel_axi_clk:
- clk_disable_unprepare(spi->axi_clk);
return status;
}
@@ -799,12 +791,10 @@ out_rel_axi_clk:
static void orion_spi_remove(struct platform_device *pdev)
{
struct spi_controller *host = platform_get_drvdata(pdev);
- struct orion_spi *spi = spi_controller_get_devdata(host);
spi_unregister_controller(host);
pm_runtime_get_sync(&pdev->dev);
- clk_disable_unprepare(spi->axi_clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
@@ -830,8 +820,7 @@ static int orion_spi_runtime_resume(struct device *dev)
struct spi_controller *host = dev_get_drvdata(dev);
struct orion_spi *spi = spi_controller_get_devdata(host);
- if (!IS_ERR(spi->axi_clk))
- clk_prepare_enable(spi->axi_clk);
+ clk_prepare_enable(spi->axi_clk);
return clk_prepare_enable(spi->clk);
}
#endif
diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c
index 66f2d1b78ade..6cc53586b8a8 100644
--- a/drivers/spi/spi-qpic-snand.c
+++ b/drivers/spi/spi-qpic-snand.c
@@ -394,14 +394,19 @@ static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand)
return 0;
err_free_ecc_cfg:
+ kfree(snandc->qspi->oob_buf);
+ snandc->qspi->oob_buf = NULL;
kfree(ecc_cfg);
return ret;
}
static void qcom_spi_ecc_cleanup_ctx_pipelined(struct nand_device *nand)
{
+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand);
struct qpic_ecc *ecc_cfg = nand_to_ecc_ctx(nand);
+ kfree(snandc->qspi->oob_buf);
+ snandc->qspi->oob_buf = NULL;
kfree(ecc_cfg);
}
@@ -1645,4 +1650,3 @@ module_platform_driver(qcom_spi_driver);
MODULE_DESCRIPTION("SPI driver for QPIC QSPI cores");
MODULE_AUTHOR("Md Sadre Alam <quic_mdalam@quicinc.com>");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/spi/spi-realtek-rtl.c b/drivers/spi/spi-realtek-rtl.c
index 73065c8934dc..e1c40ff2e49d 100644
--- a/drivers/spi/spi-realtek-rtl.c
+++ b/drivers/spi/spi-realtek-rtl.c
@@ -35,58 +35,58 @@ static void rt_set_cs(struct spi_device *spi, bool active)
u32 value;
/* CS0 bit is active low */
- value = readl(REG(RTL_SPI_SFCSR));
+ value = __raw_readl(REG(RTL_SPI_SFCSR));
if (active)
value |= RTL_SPI_SFCSR_CSB0;
else
value &= ~RTL_SPI_SFCSR_CSB0;
- writel(value, REG(RTL_SPI_SFCSR));
+ __raw_writel(value, REG(RTL_SPI_SFCSR));
}
static void set_size(struct rtspi *rtspi, int size)
{
u32 value;
- value = readl(REG(RTL_SPI_SFCSR));
+ value = __raw_readl(REG(RTL_SPI_SFCSR));
value &= RTL_SPI_SFCSR_LEN_MASK;
if (size == 4)
value |= RTL_SPI_SFCSR_LEN4;
else if (size == 1)
value |= RTL_SPI_SFCSR_LEN1;
- writel(value, REG(RTL_SPI_SFCSR));
+ __raw_writel(value, REG(RTL_SPI_SFCSR));
}
static inline void wait_ready(struct rtspi *rtspi)
{
- while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
+ while (!(__raw_readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
cpu_relax();
}
static void send4(struct rtspi *rtspi, const u32 *buf)
{
wait_ready(rtspi);
set_size(rtspi, 4);
- writel(*buf, REG(RTL_SPI_SFDR));
+ __raw_writel(*buf, REG(RTL_SPI_SFDR));
}
static void send1(struct rtspi *rtspi, const u8 *buf)
{
wait_ready(rtspi);
set_size(rtspi, 1);
- writel(buf[0] << 24, REG(RTL_SPI_SFDR));
+ __raw_writel(buf[0] << 24, REG(RTL_SPI_SFDR));
}
static void rcv4(struct rtspi *rtspi, u32 *buf)
{
wait_ready(rtspi);
set_size(rtspi, 4);
- *buf = readl(REG(RTL_SPI_SFDR));
+ *buf = __raw_readl(REG(RTL_SPI_SFDR));
}
static void rcv1(struct rtspi *rtspi, u8 *buf)
{
wait_ready(rtspi);
set_size(rtspi, 1);
- *buf = readl(REG(RTL_SPI_SFDR)) >> 24;
+ *buf = __raw_readl(REG(RTL_SPI_SFDR)) >> 24;
}
static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
@@ -134,16 +134,16 @@ static void init_hw(struct rtspi *rtspi)
u32 value;
/* Turn on big-endian byte ordering */
- value = readl(REG(RTL_SPI_SFCR));
+ value = __raw_readl(REG(RTL_SPI_SFCR));
value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
- writel(value, REG(RTL_SPI_SFCR));
+ __raw_writel(value, REG(RTL_SPI_SFCR));
- value = readl(REG(RTL_SPI_SFCSR));
+ value = __raw_readl(REG(RTL_SPI_SFCSR));
/* Permanently disable CS1, since it's never used */
value |= RTL_SPI_SFCSR_CSB1;
/* Select CS0 for use */
value &= RTL_SPI_SFCSR_CS;
- writel(value, REG(RTL_SPI_SFCSR));
+ __raw_writel(value, REG(RTL_SPI_SFCSR));
}
static int realtek_rtl_spi_probe(struct platform_device *pdev)
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index b63c7856e758..9a740342d0f7 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -161,6 +161,8 @@ static int rpcif_spi_probe(struct platform_device *pdev)
ctlr->dev.of_node = parent->of_node;
+ pm_runtime_set_autosuspend_delay(rpc->dev, 200);
+ pm_runtime_use_autosuspend(rpc->dev);
pm_runtime_enable(rpc->dev);
ctlr->num_chipselect = 1;
@@ -183,6 +185,7 @@ static int rpcif_spi_probe(struct platform_device *pdev)
return 0;
out_disable_rpm:
+ pm_runtime_dont_use_autosuspend(rpc->dev);
pm_runtime_disable(rpc->dev);
return error;
}
@@ -193,6 +196,7 @@ static void rpcif_spi_remove(struct platform_device *pdev)
struct rpcif *rpc = spi_controller_get_devdata(ctlr);
spi_unregister_controller(ctlr);
+ pm_runtime_dont_use_autosuspend(rpc->dev);
pm_runtime_disable(rpc->dev);
}