]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge remote-tracking branches 'spi/topic/imx', 'spi/topic/mxs', 'spi/topic/orion...
authorMark Brown <broonie@kernel.org>
Fri, 10 Nov 2017 21:33:47 +0000 (21:33 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 10 Nov 2017 21:33:47 +0000 (21:33 +0000)
Documentation/devicetree/bindings/spi/spi-rspi.txt
drivers/spi/spi-imx.c
drivers/spi/spi-mxs.c
drivers/spi/spi-orion.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c64xx.c

index 8f4169f6393648c7741911620f12327985c0d750..3b02b3a7cfb28858dc4eaf7ad9fa8f9404832779 100644 (file)
@@ -5,11 +5,14 @@ Required properties:
                     "renesas,rspi-<soctype>", "renesas,rspi" as fallback.
                     For Renesas Serial Peripheral Interface on RZ/A1H:
                     "renesas,rspi-<soctype>", "renesas,rspi-rz" as fallback.
-                    For Quad Serial Peripheral Interface on R-Car Gen2:
+                    For Quad Serial Peripheral Interface on R-Car Gen2 and
+                    RZ/G1 devices:
                     "renesas,qspi-<soctype>", "renesas,qspi" as fallback.
                     Examples with soctypes are:
                        - "renesas,rspi-sh7757" (SH)
                        - "renesas,rspi-r7s72100" (RZ/A1H)
+                       - "renesas,qspi-r8a7743" (RZ/G1M)
+                       - "renesas,qspi-r8a7745" (RZ/G1E)
                        - "renesas,qspi-r8a7790" (R-Car H2)
                        - "renesas,qspi-r8a7791" (R-Car M2-W)
                        - "renesas,qspi-r8a7792" (R-Car V2H)
index babb15f079951021ca2669e68898adcc44fb646c..79ddefe4180d6ccd643afd36e003af8997a8fa39 100644 (file)
 /* generic defines to abstract from the different register layouts */
 #define MXC_INT_RR     (1 << 0) /* Receive data ready interrupt */
 #define MXC_INT_TE     (1 << 1) /* Transmit FIFO empty interrupt */
+#define MXC_INT_RDR    BIT(4) /* Receive date threshold interrupt */
 
 /* The maximum  bytes that a sdma BD can transfer.*/
 #define MAX_SDMA_BD_BYTES  (1 << 15)
 #define MX51_ECSPI_CTRL_MAX_BURST      512
+/* The maximum bytes that IMX53_ECSPI can transfer in slave mode.*/
+#define MX53_MAX_TRANSFER_BYTES                512
 
 enum spi_imx_devtype {
        IMX1_CSPI,
@@ -76,7 +79,9 @@ struct spi_imx_devtype_data {
        void (*trigger)(struct spi_imx_data *);
        int (*rx_available)(struct spi_imx_data *);
        void (*reset)(struct spi_imx_data *);
+       void (*disable)(struct spi_imx_data *);
        bool has_dmamode;
+       bool has_slavemode;
        unsigned int fifo_size;
        bool dynamic_burst;
        enum spi_imx_devtype devtype;
@@ -108,6 +113,11 @@ struct spi_imx_data {
        unsigned int dynamic_burst, read_u32;
        unsigned int word_mask;
 
+       /* Slave mode */
+       bool slave_mode;
+       bool slave_aborted;
+       unsigned int slave_burst;
+
        /* DMA */
        bool usedma;
        u32 wml;
@@ -221,6 +231,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
        if (!master->dma_rx)
                return false;
 
+       if (spi_imx->slave_mode)
+               return false;
+
        bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word);
 
        if (bytes_per_word != 1 && bytes_per_word != 2 && bytes_per_word != 4)
@@ -262,6 +275,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_INT         0x10
 #define MX51_ECSPI_INT_TEEN            (1 <<  0)
 #define MX51_ECSPI_INT_RREN            (1 <<  3)
+#define MX51_ECSPI_INT_RDREN           (1 <<  4)
 
 #define MX51_ECSPI_DMA      0x14
 #define MX51_ECSPI_DMA_TX_WML(wml)     ((wml) & 0x3f)
@@ -378,6 +392,44 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
                spi_imx_buf_tx_u16(spi_imx);
 }
 
+static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
+{
+       u32 val = be32_to_cpu(readl(spi_imx->base + MXC_CSPIRXDATA));
+
+       if (spi_imx->rx_buf) {
+               int n_bytes = spi_imx->slave_burst % sizeof(val);
+
+               if (!n_bytes)
+                       n_bytes = sizeof(val);
+
+               memcpy(spi_imx->rx_buf,
+                      ((u8 *)&val) + sizeof(val) - n_bytes, n_bytes);
+
+               spi_imx->rx_buf += n_bytes;
+               spi_imx->slave_burst -= n_bytes;
+       }
+}
+
+static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx)
+{
+       u32 val = 0;
+       int n_bytes = spi_imx->count % sizeof(val);
+
+       if (!n_bytes)
+               n_bytes = sizeof(val);
+
+       if (spi_imx->tx_buf) {
+               memcpy(((u8 *)&val) + sizeof(val) - n_bytes,
+                      spi_imx->tx_buf, n_bytes);
+               val = cpu_to_be32(val);
+               spi_imx->tx_buf += n_bytes;
+       }
+
+       spi_imx->count -= n_bytes;
+
+       writel(val, spi_imx->base + MXC_CSPITXDATA);
+}
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
                                      unsigned int fspi, unsigned int *fres)
@@ -427,6 +479,9 @@ static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
        if (enable & MXC_INT_RR)
                val |= MX51_ECSPI_INT_RREN;
 
+       if (enable & MXC_INT_RDR)
+               val |= MX51_ECSPI_INT_RDREN;
+
        writel(val, spi_imx->base + MX51_ECSPI_INT);
 }
 
@@ -439,6 +494,15 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
        writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
 }
 
+static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
+{
+       u32 ctrl;
+
+       ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
+       ctrl &= ~MX51_ECSPI_CTRL_ENABLE;
+       writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+}
+
 static int mx51_ecspi_config(struct spi_device *spi)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
@@ -446,14 +510,11 @@ static int mx51_ecspi_config(struct spi_device *spi)
        u32 clk = spi_imx->speed_hz, delay, reg;
        u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
 
-       /*
-        * The hardware seems to have a race condition when changing modes. The
-        * current assumption is that the selection of the channel arrives
-        * earlier in the hardware than the mode bits when they are written at
-        * the same time.
-        * So set master mode for all channels as we do not support slave mode.
-        */
-       ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
+       /* set Master or Slave mode */
+       if (spi_imx->slave_mode)
+               ctrl &= ~MX51_ECSPI_CTRL_MODE_MASK;
+       else
+               ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
        /*
         * Enable SPI_RDY handling (falling edge/level triggered).
@@ -468,9 +529,22 @@ static int mx51_ecspi_config(struct spi_device *spi)
        /* set chip select to use */
        ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
 
-       ctrl |= (spi_imx->bits_per_word - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
+       if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
+               ctrl |= (spi_imx->slave_burst * 8 - 1)
+                       << MX51_ECSPI_CTRL_BL_OFFSET;
+       else
+               ctrl |= (spi_imx->bits_per_word - 1)
+                       << MX51_ECSPI_CTRL_BL_OFFSET;
 
-       cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
+       /*
+        * eCSPI burst completion by Chip Select signal in Slave mode
+        * is not functional for imx53 Soc, config SPI burst completed when
+        * BURST_LENGTH + 1 bits are received
+        */
+       if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
+               cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
+       else
+               cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
 
        if (spi->mode & SPI_CPHA)
                cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
@@ -805,6 +879,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
        .fifo_size = 8,
        .has_dmamode = false,
        .dynamic_burst = false,
+       .has_slavemode = false,
        .devtype = IMX1_CSPI,
 };
 
@@ -817,6 +892,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
        .fifo_size = 8,
        .has_dmamode = false,
        .dynamic_burst = false,
+       .has_slavemode = false,
        .devtype = IMX21_CSPI,
 };
 
@@ -830,6 +906,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
        .fifo_size = 8,
        .has_dmamode = false,
        .dynamic_burst = false,
+       .has_slavemode = false,
        .devtype = IMX27_CSPI,
 };
 
@@ -842,6 +919,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
        .fifo_size = 8,
        .has_dmamode = false,
        .dynamic_burst = false,
+       .has_slavemode = false,
        .devtype = IMX31_CSPI,
 };
 
@@ -855,6 +933,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
        .fifo_size = 8,
        .has_dmamode = true,
        .dynamic_burst = false,
+       .has_slavemode = false,
        .devtype = IMX35_CSPI,
 };
 
@@ -867,6 +946,8 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
        .fifo_size = 64,
        .has_dmamode = true,
        .dynamic_burst = true,
+       .has_slavemode = true,
+       .disable = mx51_ecspi_disable,
        .devtype = IMX51_ECSPI,
 };
 
@@ -878,6 +959,8 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
        .reset = mx51_ecspi_reset,
        .fifo_size = 64,
        .has_dmamode = true,
+       .has_slavemode = true,
+       .disable = mx51_ecspi_disable,
        .devtype = IMX53_ECSPI,
 };
 
@@ -945,14 +1028,16 @@ static void spi_imx_push(struct spi_imx_data *spi_imx)
                spi_imx->txfifo++;
        }
 
-       spi_imx->devtype_data->trigger(spi_imx);
+       if (!spi_imx->slave_mode)
+               spi_imx->devtype_data->trigger(spi_imx);
 }
 
 static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 {
        struct spi_imx_data *spi_imx = dev_id;
 
-       while (spi_imx->devtype_data->rx_available(spi_imx)) {
+       while (spi_imx->txfifo &&
+              spi_imx->devtype_data->rx_available(spi_imx)) {
                spi_imx->rx(spi_imx);
                spi_imx->txfifo--;
        }
@@ -1034,7 +1119,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
        spi_imx->speed_hz  = t->speed_hz;
 
        /* Initialize the functions for transfer */
-       if (spi_imx->devtype_data->dynamic_burst) {
+       if (spi_imx->devtype_data->dynamic_burst && !spi_imx->slave_mode) {
                u32 mask;
 
                spi_imx->dynamic_burst = 0;
@@ -1078,6 +1163,12 @@ static int spi_imx_setupxfer(struct spi_device *spi,
                        return ret;
        }
 
+       if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
+               spi_imx->rx = mx53_ecspi_rx_slave;
+               spi_imx->tx = mx53_ecspi_tx_slave;
+               spi_imx->slave_burst = t->len;
+       }
+
        spi_imx->devtype_data->config(spi);
 
        return 0;
@@ -1262,11 +1353,61 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
        return transfer->len;
 }
 
+static int spi_imx_pio_transfer_slave(struct spi_device *spi,
+                                     struct spi_transfer *transfer)
+{
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+       int ret = transfer->len;
+
+       if (is_imx53_ecspi(spi_imx) &&
+           transfer->len > MX53_MAX_TRANSFER_BYTES) {
+               dev_err(&spi->dev, "Transaction too big, max size is %d bytes\n",
+                       MX53_MAX_TRANSFER_BYTES);
+               return -EMSGSIZE;
+       }
+
+       spi_imx->tx_buf = transfer->tx_buf;
+       spi_imx->rx_buf = transfer->rx_buf;
+       spi_imx->count = transfer->len;
+       spi_imx->txfifo = 0;
+
+       reinit_completion(&spi_imx->xfer_done);
+       spi_imx->slave_aborted = false;
+
+       spi_imx_push(spi_imx);
+
+       spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE | MXC_INT_RDR);
+
+       if (wait_for_completion_interruptible(&spi_imx->xfer_done) ||
+           spi_imx->slave_aborted) {
+               dev_dbg(&spi->dev, "interrupted\n");
+               ret = -EINTR;
+       }
+
+       /* ecspi has a HW issue when works in Slave mode,
+        * after 64 words writtern to TXFIFO, even TXFIFO becomes empty,
+        * ECSPI_TXDATA keeps shift out the last word data,
+        * so we have to disable ECSPI when in slave mode after the
+        * transfer completes
+        */
+       if (spi_imx->devtype_data->disable)
+               spi_imx->devtype_data->disable(spi_imx);
+
+       return ret;
+}
+
 static int spi_imx_transfer(struct spi_device *spi,
                                struct spi_transfer *transfer)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
 
+       /* flush rxfifo before transfer */
+       while (spi_imx->devtype_data->rx_available(spi_imx))
+               spi_imx->rx(spi_imx);
+
+       if (spi_imx->slave_mode)
+               return spi_imx_pio_transfer_slave(spi, transfer);
+
        if (spi_imx->usedma)
                return spi_imx_dma_transfer(spi_imx, transfer);
        else
@@ -1323,6 +1464,16 @@ spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
        return 0;
 }
 
+static int spi_imx_slave_abort(struct spi_master *master)
+{
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+       spi_imx->slave_aborted = true;
+       complete(&spi_imx->xfer_done);
+
+       return 0;
+}
+
 static int spi_imx_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1334,13 +1485,23 @@ static int spi_imx_probe(struct platform_device *pdev)
        struct spi_imx_data *spi_imx;
        struct resource *res;
        int i, ret, irq, spi_drctl;
+       const struct spi_imx_devtype_data *devtype_data = of_id ? of_id->data :
+               (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
+       bool slave_mode;
 
        if (!np && !mxc_platform_info) {
                dev_err(&pdev->dev, "can't get the platform data\n");
                return -EINVAL;
        }
 
-       master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
+       slave_mode = devtype_data->has_slavemode &&
+                       of_property_read_bool(np, "spi-slave");
+       if (slave_mode)
+               master = spi_alloc_slave(&pdev->dev,
+                                        sizeof(struct spi_imx_data));
+       else
+               master = spi_alloc_master(&pdev->dev,
+                                         sizeof(struct spi_imx_data));
        if (!master)
                return -ENOMEM;
 
@@ -1358,20 +1519,29 @@ static int spi_imx_probe(struct platform_device *pdev)
        spi_imx = spi_master_get_devdata(master);
        spi_imx->bitbang.master = master;
        spi_imx->dev = &pdev->dev;
+       spi_imx->slave_mode = slave_mode;
 
-       spi_imx->devtype_data = of_id ? of_id->data :
-               (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
+       spi_imx->devtype_data = devtype_data;
 
+       /* Get number of chip selects, either platform data or OF */
        if (mxc_platform_info) {
                master->num_chipselect = mxc_platform_info->num_chipselect;
-               master->cs_gpios = devm_kzalloc(&master->dev,
-                       sizeof(int) * master->num_chipselect, GFP_KERNEL);
-               if (!master->cs_gpios)
-                       return -ENOMEM;
+               if (mxc_platform_info->chipselect) {
+                       master->cs_gpios = devm_kzalloc(&master->dev,
+                               sizeof(int) * master->num_chipselect, GFP_KERNEL);
+                       if (!master->cs_gpios)
+                               return -ENOMEM;
+
+                       for (i = 0; i < master->num_chipselect; i++)
+                               master->cs_gpios[i] = mxc_platform_info->chipselect[i];
+               }
+       } else {
+               u32 num_cs;
 
-               for (i = 0; i < master->num_chipselect; i++)
-                       master->cs_gpios[i] = mxc_platform_info->chipselect[i];
-       }
+               if (!of_property_read_u32(np, "num-cs", &num_cs))
+                       master->num_chipselect = num_cs;
+               /* If not preset, default value of 1 is used */
+       }
 
        spi_imx->bitbang.chipselect = spi_imx_chipselect;
        spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
@@ -1380,6 +1550,7 @@ static int spi_imx_probe(struct platform_device *pdev)
        spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
        spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
        spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
+       spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
        spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
                                             | SPI_NO_CS;
        if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
@@ -1451,37 +1622,38 @@ static int spi_imx_probe(struct platform_device *pdev)
        spi_imx->devtype_data->intctrl(spi_imx, 0);
 
        master->dev.of_node = pdev->dev.of_node;
+
+       /* Request GPIO CS lines, if any */
+       if (!spi_imx->slave_mode && master->cs_gpios) {
+               for (i = 0; i < master->num_chipselect; i++) {
+                       if (!gpio_is_valid(master->cs_gpios[i]))
+                               continue;
+
+                       ret = devm_gpio_request(&pdev->dev,
+                                               master->cs_gpios[i],
+                                               DRIVER_NAME);
+                       if (ret) {
+                               dev_err(&pdev->dev, "Can't get CS GPIO %i\n",
+                                       master->cs_gpios[i]);
+                               goto out_spi_bitbang;
+                       }
+               }
+       }
+
        ret = spi_bitbang_start(&spi_imx->bitbang);
        if (ret) {
                dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
                goto out_clk_put;
        }
 
-       if (!master->cs_gpios) {
-               dev_err(&pdev->dev, "No CS GPIOs available\n");
-               ret = -EINVAL;
-               goto out_clk_put;
-       }
-
-       for (i = 0; i < master->num_chipselect; i++) {
-               if (!gpio_is_valid(master->cs_gpios[i]))
-                       continue;
-
-               ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
-                                       DRIVER_NAME);
-               if (ret) {
-                       dev_err(&pdev->dev, "Can't get CS GPIO %i\n",
-                               master->cs_gpios[i]);
-                       goto out_clk_put;
-               }
-       }
-
        dev_info(&pdev->dev, "probed\n");
 
        clk_disable(spi_imx->clk_ipg);
        clk_disable(spi_imx->clk_per);
        return ret;
 
+out_spi_bitbang:
+       spi_bitbang_stop(&spi_imx->bitbang);
 out_clk_put:
        clk_disable_unprepare(spi_imx->clk_ipg);
 out_put_per:
index 5b0e9a3e83f6944d90f23de597a3a9ff504e3a7b..3d216b950b415192309d8a6947387e92fec1d87d 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/completion.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 #include <linux/module.h>
 #include <linux/stmp_device.h>
 #include <linux/spi/spi.h>
@@ -442,6 +443,85 @@ static int mxs_spi_transfer_one(struct spi_master *master,
        return status;
 }
 
+static int mxs_spi_runtime_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mxs_spi *spi = spi_master_get_devdata(master);
+       struct mxs_ssp *ssp = &spi->ssp;
+       int ret;
+
+       clk_disable_unprepare(ssp->clk);
+
+       ret = pinctrl_pm_select_idle_state(dev);
+       if (ret) {
+               int ret2 = clk_prepare_enable(ssp->clk);
+
+               if (ret2)
+                       dev_warn(dev, "Failed to reenable clock after failing pinctrl request (pinctrl: %d, clk: %d)\n",
+                                ret, ret2);
+       }
+
+       return ret;
+}
+
+static int mxs_spi_runtime_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mxs_spi *spi = spi_master_get_devdata(master);
+       struct mxs_ssp *ssp = &spi->ssp;
+       int ret;
+
+       ret = pinctrl_pm_select_default_state(dev);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(ssp->clk);
+       if (ret)
+               pinctrl_pm_select_idle_state(dev);
+
+       return ret;
+}
+
+static int __maybe_unused mxs_spi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       int ret;
+
+       ret = spi_master_suspend(master);
+       if (ret)
+               return ret;
+
+       if (!pm_runtime_suspended(dev))
+               return mxs_spi_runtime_suspend(dev);
+       else
+               return 0;
+}
+
+static int __maybe_unused mxs_spi_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       int ret;
+
+       if (!pm_runtime_suspended(dev))
+               ret = mxs_spi_runtime_resume(dev);
+       else
+               ret = 0;
+       if (ret)
+               return ret;
+
+       ret = spi_master_resume(master);
+       if (ret < 0 && !pm_runtime_suspended(dev))
+               mxs_spi_runtime_suspend(dev);
+
+       return ret;
+}
+
+static const struct dev_pm_ops mxs_spi_pm = {
+       SET_RUNTIME_PM_OPS(mxs_spi_runtime_suspend,
+                          mxs_spi_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(mxs_spi_suspend, mxs_spi_resume)
+};
+
 static const struct of_device_id mxs_spi_dt_ids[] = {
        { .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, },
        { .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, },
@@ -493,12 +573,15 @@ static int mxs_spi_probe(struct platform_device *pdev)
        if (!master)
                return -ENOMEM;
 
+       platform_set_drvdata(pdev, master);
+
        master->transfer_one_message = mxs_spi_transfer_one;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->mode_bits = SPI_CPOL | SPI_CPHA;
        master->num_chipselect = 3;
        master->dev.of_node = np;
        master->flags = SPI_MASTER_HALF_DUPLEX;
+       master->auto_runtime_pm = true;
 
        spi = spi_master_get_devdata(master);
        ssp = &spi->ssp;
@@ -521,28 +604,41 @@ static int mxs_spi_probe(struct platform_device *pdev)
                goto out_master_free;
        }
 
-       ret = clk_prepare_enable(ssp->clk);
-       if (ret)
-               goto out_dma_release;
+       pm_runtime_enable(ssp->dev);
+       if (!pm_runtime_enabled(ssp->dev)) {
+               ret = mxs_spi_runtime_resume(ssp->dev);
+               if (ret < 0) {
+                       dev_err(ssp->dev, "runtime resume failed\n");
+                       goto out_dma_release;
+               }
+       }
+
+       ret = pm_runtime_get_sync(ssp->dev);
+       if (ret < 0) {
+               dev_err(ssp->dev, "runtime_get_sync failed\n");
+               goto out_pm_runtime_disable;
+       }
 
        clk_set_rate(ssp->clk, clk_freq);
 
        ret = stmp_reset_block(ssp->base);
        if (ret)
-               goto out_disable_clk;
-
-       platform_set_drvdata(pdev, master);
+               goto out_pm_runtime_put;
 
        ret = devm_spi_register_master(&pdev->dev, master);
        if (ret) {
                dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
-               goto out_disable_clk;
+               goto out_pm_runtime_put;
        }
 
+       pm_runtime_put(ssp->dev);
+
        return 0;
 
-out_disable_clk:
-       clk_disable_unprepare(ssp->clk);
+out_pm_runtime_put:
+       pm_runtime_put(ssp->dev);
+out_pm_runtime_disable:
+       pm_runtime_disable(ssp->dev);
 out_dma_release:
        dma_release_channel(ssp->dmach);
 out_master_free:
@@ -560,7 +656,10 @@ static int mxs_spi_remove(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
        ssp = &spi->ssp;
 
-       clk_disable_unprepare(ssp->clk);
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev))
+               mxs_spi_runtime_suspend(&pdev->dev);
+
        dma_release_channel(ssp->dmach);
 
        return 0;
@@ -572,6 +671,7 @@ static struct platform_driver mxs_spi_driver = {
        .driver = {
                .name   = DRIVER_NAME,
                .of_match_table = mxs_spi_dt_ids,
+               .pm = &mxs_spi_pm,
        },
 };
 
index 4b6dd73b80da0f034976e5781dd34089377e408c..8974bb340b3abe40a438df71545396aa5c095f2d 100644 (file)
@@ -671,7 +671,6 @@ static int orion_spi_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "%pOF has no valid 'reg' property (%d)\n",
                                np, status);
-                       status = 0;
                        continue;
                }
 
index 2a10b3f94ff72a4ea3d6924a082ef6d2db174528..2ce875764ca646a2bdfb803cae33465ab8fa1786 100644 (file)
@@ -1221,7 +1221,6 @@ static int rspi_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct rspi_data *rspi;
        int ret;
-       const struct of_device_id *of_id;
        const struct rspi_plat_data *rspi_pd;
        const struct spi_ops *ops;
 
@@ -1229,9 +1228,8 @@ static int rspi_probe(struct platform_device *pdev)
        if (master == NULL)
                return -ENOMEM;
 
-       of_id = of_match_device(rspi_of_match, &pdev->dev);
-       if (of_id) {
-               ops = of_id->data;
+       ops = of_device_get_match_data(&pdev->dev);
+       if (ops) {
                ret = rspi_parse_dt(&pdev->dev, master);
                if (ret)
                        goto error1;
index b392cca8fa4f5ba3c1c499ea8b1bc228fcabdbee..de7df20f8712dd74dc074e763555891f076b820f 100644 (file)
@@ -752,7 +752,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 {
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
        struct s3c64xx_spi_driver_data *sdd;
-       struct s3c64xx_spi_info *sci;
        int err;
 
        sdd = spi_master_get_devdata(spi->master);
@@ -788,8 +787,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                spi_set_ctldata(spi, cs);
        }
 
-       sci = sdd->cntrlr_info;
-
        pm_runtime_get_sync(&sdd->pdev->dev);
 
        /* Check if we can provide the requested rate */