diff options
| author | Mark Brown <broonie@kernel.org> | 2026-07-23 15:06:03 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-07-23 15:06:03 +0100 |
| commit | e6ac02baf8864fad4d1fd52e070d5ebd94296af7 (patch) | |
| tree | 5807d00978eac4fd2252205c65046dbe150743ab /drivers | |
| parent | 70b506cadb7409cad6a4f331c689244d605b16e8 (diff) | |
| parent | f3783a591419ad74afe0beb0b81bca249b20d90b (diff) | |
| download | linux-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/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/spi/atmel-quadspi.c | 132 | ||||
| -rw-r--r-- | drivers/spi/spi-altera-platform.c | 13 | ||||
| -rw-r--r-- | drivers/spi/spi-atcspi200.c | 5 | ||||
| -rw-r--r-- | drivers/spi/spi-axiado.c | 20 | ||||
| -rw-r--r-- | drivers/spi/spi-axiado.h | 5 | ||||
| -rw-r--r-- | drivers/spi/spi-bcm-qspi.c | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-bcm2835.c | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-bcm63xx-hsspi.c | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-bcm63xx.c | 5 | ||||
| -rw-r--r-- | drivers/spi/spi-bcmbca-hsspi.c | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 21 | ||||
| -rw-r--r-- | drivers/spi/spi-geni-qcom.c | 105 | ||||
| -rw-r--r-- | drivers/spi/spi-npcm-fiu.c | 15 | ||||
| -rw-r--r-- | drivers/spi/spi-nxp-fspi.c | 31 | ||||
| -rw-r--r-- | drivers/spi/spi-orion.c | 25 | ||||
| -rw-r--r-- | drivers/spi/spi-qpic-snand.c | 6 | ||||
| -rw-r--r-- | drivers/spi/spi-realtek-rtl.c | 26 | ||||
| -rw-r--r-- | drivers/spi/spi-rpc-if.c | 4 |
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); } |
