i40iw: Correct status check on i40iw_get_pble
[cascardo/linux.git] / drivers / spi / spi-cadence.c
index 97a3bf6..1c57ce6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
 
 /* Name of this driver */
@@ -37,6 +38,7 @@
 #define CDNS_SPI_SICR  0x24 /* Slave Idle Count Register, RW */
 #define CDNS_SPI_THLD  0x28 /* Transmit FIFO Watermark Register,RW */
 
+#define SPI_AUTOSUSPEND_TIMEOUT                3000
 /*
  * SPI Configuration Register bit Masks
  *
@@ -169,7 +171,7 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi)
 /**
  * cdns_spi_chipselect - Select or deselect the chip select line
  * @spi:       Pointer to the spi_device structure
- * @is_on:     Select(0) or deselect (1) the chip select line
+ * @is_high:   Select(0) or deselect (1) the chip select line
  */
 static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
 {
@@ -207,7 +209,8 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi)
        struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
        u32 ctrl_reg, new_ctrl_reg;
 
-       new_ctrl_reg = ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
+       new_ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
+       ctrl_reg = new_ctrl_reg;
 
        /* Set the SPI clock phase and clock polarity */
        new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA | CDNS_SPI_CR_CPOL);
@@ -244,7 +247,7 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi)
  * controller.
  */
 static void cdns_spi_config_clock_freq(struct spi_device *spi,
-                                 struct spi_transfer *transfer)
+                                      struct spi_transfer *transfer)
 {
        struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
        u32 ctrl_reg, baud_rate_val;
@@ -378,6 +381,7 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
 
        return status;
 }
+
 static int cdns_prepare_message(struct spi_master *master,
                                struct spi_message *msg)
 {
@@ -509,6 +513,11 @@ static int cdns_spi_probe(struct platform_device *pdev)
                goto clk_dis_apb;
        }
 
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
+       pm_runtime_set_active(&pdev->dev);
+
        ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
        if (ret < 0)
                master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
@@ -523,11 +532,14 @@ static int cdns_spi_probe(struct platform_device *pdev)
        /* SPI controller initializations */
        cdns_spi_init_hw(xspi);
 
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(&pdev->dev);
+
        irq = platform_get_irq(pdev, 0);
        if (irq <= 0) {
                ret = -ENXIO;
                dev_err(&pdev->dev, "irq number is invalid\n");
-               goto remove_master;
+               goto clk_dis_all;
        }
 
        ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq,
@@ -535,7 +547,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
        if (ret != 0) {
                ret = -ENXIO;
                dev_err(&pdev->dev, "request_irq failed\n");
-               goto remove_master;
+               goto clk_dis_all;
        }
 
        master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
@@ -543,6 +555,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
        master->transfer_one = cdns_transfer_one;
        master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
        master->set_cs = cdns_spi_chipselect;
+       master->auto_runtime_pm = true;
        master->mode_bits = SPI_CPOL | SPI_CPHA;
 
        /* Set to default valid value */
@@ -560,6 +573,8 @@ static int cdns_spi_probe(struct platform_device *pdev)
        return ret;
 
 clk_dis_all:
+       pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        clk_disable_unprepare(xspi->ref_clk);
 clk_dis_apb:
        clk_disable_unprepare(xspi->pclk);
@@ -587,6 +602,8 @@ static int cdns_spi_remove(struct platform_device *pdev)
 
        clk_disable_unprepare(xspi->ref_clk);
        clk_disable_unprepare(xspi->pclk);
+       pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
 
        spi_unregister_master(master);
 
@@ -600,21 +617,14 @@ static int cdns_spi_remove(struct platform_device *pdev)
  * This function disables the SPI controller and
  * changes the driver state to "suspend"
  *
- * Return:     Always 0
+ * Return:     0 on success and error value on error
  */
 static int __maybe_unused cdns_spi_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct spi_master *master = platform_get_drvdata(pdev);
-       struct cdns_spi *xspi = spi_master_get_devdata(master);
-
-       spi_master_suspend(master);
 
-       clk_disable_unprepare(xspi->ref_clk);
-
-       clk_disable_unprepare(xspi->pclk);
-
-       return 0;
+       return spi_master_suspend(master);
 }
 
 /**
@@ -629,8 +639,23 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct spi_master *master = platform_get_drvdata(pdev);
+
+       return spi_master_resume(master);
+}
+
+/**
+ * cdns_spi_runtime_resume - Runtime resume method for the SPI driver
+ * @dev:       Address of the platform_device structure
+ *
+ * This function enables the clocks
+ *
+ * Return:     0 on success and error value on error
+ */
+static int __maybe_unused cnds_runtime_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
        struct cdns_spi *xspi = spi_master_get_devdata(master);
-       int ret = 0;
+       int ret;
 
        ret = clk_prepare_enable(xspi->pclk);
        if (ret) {
@@ -644,13 +669,33 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
                clk_disable(xspi->pclk);
                return ret;
        }
-       spi_master_resume(master);
+       return 0;
+}
+
+/**
+ * cdns_spi_runtime_suspend - Runtime suspend method for the SPI driver
+ * @dev:       Address of the platform_device structure
+ *
+ * This function disables the clocks
+ *
+ * Return:     Always 0
+ */
+static int __maybe_unused cnds_runtime_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct cdns_spi *xspi = spi_master_get_devdata(master);
+
+       clk_disable_unprepare(xspi->ref_clk);
+       clk_disable_unprepare(xspi->pclk);
 
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend,
-                        cdns_spi_resume);
+static const struct dev_pm_ops cdns_spi_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(cnds_runtime_suspend,
+                          cnds_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(cdns_spi_suspend, cdns_spi_resume)
+};
 
 static const struct of_device_id cdns_spi_of_match[] = {
        { .compatible = "xlnx,zynq-spi-r1p6" },