summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/spi/fsl,spi.yaml6
-rw-r--r--MAINTAINERS4
-rw-r--r--drivers/spi/spi-axiado.c31
-rw-r--r--drivers/spi/spi-cadence-quadspi.c4
-rw-r--r--drivers/spi/spi-cadence.c6
-rw-r--r--drivers/spi/spi-imx.c1
-rw-r--r--drivers/spi/spi-mpc52xx.c9
-rw-r--r--drivers/spi/spi-mtk-snfi.c8
-rw-r--r--drivers/spi/spi-mxic.c3
-rw-r--r--drivers/spi/spi-orion.c20
-rw-r--r--drivers/spi/spi-topcliff-pch.c11
-rw-r--r--drivers/spi/spi.c61
-rw-r--r--include/linux/spi/spi.h4
13 files changed, 110 insertions, 58 deletions
diff --git a/Documentation/devicetree/bindings/spi/fsl,spi.yaml b/Documentation/devicetree/bindings/spi/fsl,spi.yaml
index d74792fc9bf2..6a359488dd41 100644
--- a/Documentation/devicetree/bindings/spi/fsl,spi.yaml
+++ b/Documentation/devicetree/bindings/spi/fsl,spi.yaml
@@ -59,7 +59,7 @@ unevaluatedProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
spi@4c0 {
compatible = "fsl,spi";
@@ -67,8 +67,8 @@ examples:
cell-index = <0>;
interrupts = <82 0>;
mode = "cpu";
- cs-gpios = <&gpio 18 IRQ_TYPE_EDGE_RISING // device reg=<0>
- &gpio 19 IRQ_TYPE_EDGE_RISING>; // device reg=<1>
+ cs-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>, // device reg=<0>
+ <&gpio 19 GPIO_ACTIVE_HIGH>; // device reg=<1>
};
...
diff --git a/MAINTAINERS b/MAINTAINERS
index 6b456089ef40..9922adc1f493 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24655,8 +24655,8 @@ F: Documentation/devicetree/bindings/net/socionext,synquacer-netsec.yaml
F: drivers/net/ethernet/socionext/netsec.c
SOCIONEXT (SNI) Synquacer SPI DRIVER
-M: Masahisa Kojima <masahisa.kojima@linaro.org>
-M: Jassi Brar <jaswinder.singh@linaro.org>
+M: Masahisa Kojima <kojima.masahisa@socionext.com>
+M: Jassi Brar <jassisinghbrar@gmail.com>
L: linux-spi@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml
diff --git a/drivers/spi/spi-axiado.c b/drivers/spi/spi-axiado.c
index dc55c55ae63c..9057a0a8df4a 100644
--- a/drivers/spi/spi-axiado.c
+++ b/drivers/spi/spi-axiado.c
@@ -751,9 +751,9 @@ static const struct spi_controller_mem_ops ax_spi_mem_ops = {
*/
static int ax_spi_probe(struct platform_device *pdev)
{
- int ret = 0, irq;
struct spi_controller *ctlr;
struct ax_spi *xspi;
+ int ret, irq;
u32 num_cs;
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*xspi));
@@ -785,7 +785,7 @@ static int ax_spi_probe(struct platform_device *pdev)
ret = clk_prepare_enable(xspi->ref_clk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable device clock.\n");
- goto clk_dis_apb;
+ goto err_disable_apb;
}
pm_runtime_use_autosuspend(&pdev->dev);
@@ -815,7 +815,7 @@ static int ax_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
ret = -ENXIO;
- goto clk_dis_all;
+ goto err_disable_rpm;
}
ret = devm_request_irq(&pdev->dev, irq, ax_spi_irq,
@@ -823,7 +823,7 @@ static int ax_spi_probe(struct platform_device *pdev)
if (ret != 0) {
ret = -ENXIO;
dev_err(&pdev->dev, "request_irq failed\n");
- goto clk_dis_all;
+ goto err_disable_rpm;
}
ctlr->use_gpio_descriptors = true;
@@ -842,23 +842,26 @@ static int ax_spi_probe(struct platform_device *pdev)
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
- pm_runtime_put_autosuspend(&pdev->dev);
-
ctlr->mem_ops = &ax_spi_mem_ops;
ret = spi_register_controller(ctlr);
if (ret) {
dev_err(&pdev->dev, "spi_register_controller failed\n");
- goto clk_dis_all;
+ goto err_disable_rpm;
}
- return ret;
+ pm_runtime_put_autosuspend(&pdev->dev);
-clk_dis_all:
- pm_runtime_set_suspended(&pdev->dev);
+ return 0;
+
+err_disable_rpm:
pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+
clk_disable_unprepare(xspi->ref_clk);
-clk_dis_apb:
+err_disable_apb:
clk_disable_unprepare(xspi->pclk);
return ret;
@@ -877,10 +880,14 @@ static void ax_spi_remove(struct platform_device *pdev)
struct spi_controller *ctlr = platform_get_drvdata(pdev);
struct ax_spi *xspi = spi_controller_get_devdata(ctlr);
+ pm_runtime_get_sync(&pdev->dev);
+
spi_unregister_controller(ctlr);
- pm_runtime_set_suspended(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
clk_disable_unprepare(xspi->ref_clk);
clk_disable_unprepare(xspi->pclk);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index b6f7f95e8bd3..65aff2e70265 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -2016,13 +2016,13 @@ static void cqspi_remove(struct platform_device *pdev)
ddata = of_device_get_match_data(dev);
+ spi_unregister_controller(cqspi->host);
+
refcount_set(&cqspi->refcount, 0);
if (!refcount_dec_and_test(&cqspi->inflight_ops))
cqspi_wait_idle(cqspi);
- spi_unregister_controller(cqspi->host);
-
if (cqspi->rx_chan)
dma_release_channel(cqspi->rx_chan);
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index caa7a57e6d27..08d7dabe818d 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -777,6 +777,10 @@ static void cdns_spi_remove(struct platform_device *pdev)
struct spi_controller *ctlr = platform_get_drvdata(pdev);
struct cdns_spi *xspi = spi_controller_get_devdata(ctlr);
+ spi_controller_get(ctlr);
+
+ spi_unregister_controller(ctlr);
+
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
if (!spi_controller_is_target(ctlr)) {
@@ -784,7 +788,7 @@ static void cdns_spi_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
}
- spi_unregister_controller(ctlr);
+ spi_controller_put(ctlr);
}
/**
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 4747899e0646..e5c907c45b87 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -2373,6 +2373,7 @@ out_register_controller:
out_runtime_pm_put:
pm_runtime_dont_use_autosuspend(spi_imx->dev);
pm_runtime_disable(spi_imx->dev);
+ pm_runtime_put_noidle(spi_imx->dev);
pm_runtime_set_suspended(&pdev->dev);
clk_disable_unprepare(spi_imx->clk_ipg);
diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c
index 05bbd3795e7d..924d820448fb 100644
--- a/drivers/spi/spi-mpc52xx.c
+++ b/drivers/spi/spi-mpc52xx.c
@@ -498,6 +498,9 @@ static int mpc52xx_spi_probe(struct platform_device *op)
err_register:
dev_err(&ms->host->dev, "initialization failed\n");
+ free_irq(ms->irq0, ms);
+ free_irq(ms->irq1, ms);
+ cancel_work_sync(&ms->work);
err_gpio:
while (i-- > 0)
gpiod_put(ms->gpio_cs[i]);
@@ -517,15 +520,17 @@ static void mpc52xx_spi_remove(struct platform_device *op)
struct mpc52xx_spi *ms = spi_controller_get_devdata(host);
int i;
- cancel_work_sync(&ms->work);
+ spi_unregister_controller(host);
+
free_irq(ms->irq0, ms);
free_irq(ms->irq1, ms);
+ cancel_work_sync(&ms->work);
+
for (i = 0; i < ms->gpio_cs_count; i++)
gpiod_put(ms->gpio_cs[i]);
kfree(ms->gpio_cs);
- spi_unregister_controller(host);
iounmap(ms->regs);
spi_controller_put(host);
}
diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c
index 73fa84475f0e..e616e6800e92 100644
--- a/drivers/spi/spi-mtk-snfi.c
+++ b/drivers/spi/spi-mtk-snfi.c
@@ -1447,14 +1447,14 @@ static int mtk_snand_probe(struct platform_device *pdev)
ret = nand_ecc_register_on_host_hw_engine(&ms->ecc_eng);
if (ret) {
dev_err(&pdev->dev, "failed to register ecc engine.\n");
- goto release_ecc;
+ goto free_buf;
}
ret = devm_add_action_or_reset(&pdev->dev, mtk_unregister_ecc_engine,
&ms->ecc_eng);
if (ret) {
dev_err_probe(&pdev->dev, ret, "failed to add ECC unregister action\n");
- goto release_ecc;
+ goto free_buf;
}
ctlr->num_chipselect = 1;
@@ -1465,10 +1465,12 @@ static int mtk_snand_probe(struct platform_device *pdev)
ret = spi_register_controller(ctlr);
if (ret) {
dev_err(&pdev->dev, "spi_register_controller failed.\n");
- goto release_ecc;
+ goto free_buf;
}
return 0;
+free_buf:
+ kfree(ms->buf);
release_ecc:
mtk_ecc_release(ms->ecc);
return ret;
diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index f9369c69911c..b0e7fc828a50 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -832,9 +832,10 @@ static void mxic_spi_remove(struct platform_device *pdev)
struct spi_controller *host = platform_get_drvdata(pdev);
struct mxic_spi *mxic = spi_controller_get_devdata(host);
+ spi_unregister_controller(host);
+
pm_runtime_disable(&pdev->dev);
mxic_spi_mem_ecc_remove(mxic);
- spi_unregister_controller(host);
}
static const struct of_device_id mxic_spi_of_ids[] = {
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 7a2186b51b4c..64bf215c1804 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -648,8 +648,8 @@ static int orion_spi_probe(struct platform_device *pdev)
struct orion_spi *spi;
struct resource *r;
unsigned long tclk_hz;
- int status = 0;
struct device_node *np;
+ int status;
host = spi_alloc_host(&pdev->dev, sizeof(*spi));
if (host == NULL) {
@@ -774,6 +774,7 @@ static int orion_spi_probe(struct platform_device *pdev)
pm_runtime_set_active(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_get_noresume(&pdev->dev);
pm_runtime_enable(&pdev->dev);
status = orion_spi_reset(spi);
@@ -784,10 +785,15 @@ static int orion_spi_probe(struct platform_device *pdev)
if (status < 0)
goto out_rel_pm;
- return status;
+ pm_runtime_put_autosuspend(&pdev->dev);
+
+ return 0;
out_rel_pm:
pm_runtime_disable(&pdev->dev);
+ 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);
out:
@@ -801,11 +807,19 @@ 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_controller_get(host);
+
+ spi_unregister_controller(host);
+
pm_runtime_get_sync(&pdev->dev);
clk_disable_unprepare(spi->axi_clk);
- spi_unregister_controller(host);
+ spi_controller_put(host);
+
pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
}
MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index cae2dcefabea..14d11450e86d 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1406,8 +1406,9 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev)
dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
__func__, plat_dev->id, board_dat->pdev->irq);
- if (use_dma)
- pch_free_dma_buf(board_dat, data);
+ spi_controller_get(data->host);
+
+ spi_unregister_controller(data->host);
/* check for any pending messages; no action is taken if the queue
* is still full; but at least we tried. Unload anyway */
@@ -1432,8 +1433,12 @@ static void pch_spi_pd_remove(struct platform_device *plat_dev)
free_irq(board_dat->pdev->irq, data);
}
+ if (use_dma)
+ pch_free_dma_buf(board_dat, data);
+
pci_iounmap(board_dat->pdev, data->io_remap_addr);
- spi_unregister_controller(data->host);
+
+ spi_controller_put(data->host);
}
#ifdef CONFIG_PM
static int pch_spi_pd_suspend(struct platform_device *pd_dev,
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 7001f5dce8bd..104279858f56 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
#include "internals.h"
+static int __spi_setup(struct spi_device *spi, bool initial_setup);
+
static DEFINE_IDR(spi_controller_idr);
static void spidev_release(struct device *dev)
@@ -743,7 +745,7 @@ static int __spi_add_device(struct spi_device *spi, struct spi_device *parent)
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
- status = spi_setup(spi);
+ status = __spi_setup(spi, true);
if (status < 0) {
dev_err(dev, "can't setup %s, status %d\n",
dev_name(&spi->dev), status);
@@ -4049,27 +4051,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
return status;
}
-/**
- * spi_setup - setup SPI mode and clock rate
- * @spi: the device whose settings are being modified
- * Context: can sleep, and no requests are queued to the device
- *
- * SPI protocol drivers may need to update the transfer mode if the
- * device doesn't work with its default. They may likewise need
- * to update clock rates or word sizes from initial values. This function
- * changes those settings, and must be called from a context that can sleep.
- * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
- * effect the next time the device is selected and data is transferred to
- * or from it. When this function returns, the SPI device is deselected.
- *
- * Note that this call will fail if the protocol driver specifies an option
- * that the underlying controller or its driver does not support. For
- * example, not all hardware supports wire transfers using nine bit words,
- * LSB-first wire encoding, or active-high chipselects.
- *
- * Return: zero on success, else a negative error code.
- */
-int spi_setup(struct spi_device *spi)
+static int __spi_setup(struct spi_device *spi, bool initial_setup)
{
unsigned bad_bits, ugly_bits;
int status;
@@ -4154,7 +4136,7 @@ int spi_setup(struct spi_device *spi)
status = spi_set_cs_timing(spi);
if (status) {
mutex_unlock(&spi->controller->io_mutex);
- return status;
+ goto err_cleanup;
}
if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
@@ -4163,7 +4145,7 @@ int spi_setup(struct spi_device *spi)
mutex_unlock(&spi->controller->io_mutex);
dev_err(&spi->controller->dev, "Failed to power device: %d\n",
status);
- return status;
+ goto err_cleanup;
}
/*
@@ -4199,6 +4181,37 @@ int spi_setup(struct spi_device *spi)
status);
return status;
+
+err_cleanup:
+ if (initial_setup)
+ spi_cleanup(spi);
+
+ return status;
+}
+
+/**
+ * spi_setup - setup SPI mode and clock rate
+ * @spi: the device whose settings are being modified
+ * Context: can sleep, and no requests are queued to the device
+ *
+ * SPI protocol drivers may need to update the transfer mode if the
+ * device doesn't work with its default. They may likewise need
+ * to update clock rates or word sizes from initial values. This function
+ * changes those settings, and must be called from a context that can sleep.
+ * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
+ * effect the next time the device is selected and data is transferred to
+ * or from it. When this function returns, the SPI device is deselected.
+ *
+ * Note that this call will fail if the protocol driver specifies an option
+ * that the underlying controller or its driver does not support. For
+ * example, not all hardware supports wire transfers using nine bit words,
+ * LSB-first wire encoding, or active-high chipselects.
+ *
+ * Return: zero on success, else a negative error code.
+ */
+int spi_setup(struct spi_device *spi)
+{
+ return __spi_setup(spi, false);
}
EXPORT_SYMBOL_GPL(spi_setup);
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 7587b1c5d7ec..79513f5941cc 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -701,7 +701,7 @@ struct spi_controller {
int (*transfer)(struct spi_device *spi,
struct spi_message *mesg);
- /* Called on release() to free memory provided by spi_controller */
+ /* Called on deregistration to free memory provided by spi_controller */
void (*cleanup)(struct spi_device *spi);
/*
@@ -1019,7 +1019,7 @@ struct spi_res {
* this value may have changed compared to what was requested, depending
* on the available snapshotting resolution (DMA transfer,
* @ptp_sts_supported is false, etc).
- * @ptp_sts_word_post: See @ptp_sts_word_post. The two can be equal (meaning
+ * @ptp_sts_word_post: See @ptp_sts_word_pre. The two can be equal (meaning
* that a single byte should be snapshotted).
* If the core takes care of the timestamp (if @ptp_sts_supported is false
* for this controller), it will set @ptp_sts_word_pre to 0, and