]> Pileus Git - ~andy/linux/blobdiff - drivers/spi/spi-pl022.c
Merge remote-tracking branch 'asoc/topic/tlv320dac33' into asoc-next
[~andy/linux] / drivers / spi / spi-pl022.c
index a1db91a99b89a670cb7979c5fd758c90796aa2a9..b0fe393c882ced538ef9f098daf885a736796469 100644 (file)
@@ -371,6 +371,7 @@ struct pl022 {
        /* Two optional pin states - default & sleep */
        struct pinctrl                  *pinctrl;
        struct pinctrl_state            *pins_default;
+       struct pinctrl_state            *pins_idle;
        struct pinctrl_state            *pins_sleep;
        struct spi_master               *master;
        struct pl022_ssp_controller     *master_info;
@@ -1088,7 +1089,7 @@ err_alloc_rx_sg:
        return -ENOMEM;
 }
 
-static int __devinit pl022_dma_probe(struct pl022 *pl022)
+static int pl022_dma_probe(struct pl022 *pl022)
 {
        dma_cap_mask_t mask;
 
@@ -2057,8 +2058,7 @@ pl022_platform_data_dt_get(struct device *dev)
        return pd;
 }
 
-static int __devinit
-pl022_probe(struct amba_device *adev, const struct amba_id *id)
+static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
        struct device *dev = &adev->dev;
        struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
@@ -2116,6 +2116,11 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        } else
                dev_err(dev, "could not get default pinstate\n");
 
+       pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl,
+                                             PINCTRL_STATE_IDLE);
+       if (IS_ERR(pl022->pins_idle))
+               dev_dbg(dev, "could not get idle pinstate\n");
+
        pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl,
                                               PINCTRL_STATE_SLEEP);
        if (IS_ERR(pl022->pins_sleep))
@@ -2246,10 +2251,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
                pm_runtime_set_autosuspend_delay(dev,
                        platform_info->autosuspend_delay);
                pm_runtime_use_autosuspend(dev);
-               pm_runtime_put_autosuspend(dev);
-       } else {
-               pm_runtime_put(dev);
        }
+       pm_runtime_put(dev);
+
        return 0;
 
  err_spi_register:
@@ -2270,7 +2274,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        return status;
 }
 
-static int __devexit
+static int
 pl022_remove(struct amba_device *adev)
 {
        struct pl022 *pl022 = amba_get_drvdata(adev);
@@ -2303,35 +2307,47 @@ pl022_remove(struct amba_device *adev)
  * the runtime counterparts to handle external resources like
  * clocks, pins and regulators when going to sleep.
  */
-static void pl022_suspend_resources(struct pl022 *pl022)
+static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
 {
        int ret;
+       struct pinctrl_state *pins_state;
 
        clk_disable(pl022->clk);
 
+       pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep;
        /* Optionally let pins go into sleep states */
-       if (!IS_ERR(pl022->pins_sleep)) {
-               ret = pinctrl_select_state(pl022->pinctrl,
-                                          pl022->pins_sleep);
+       if (!IS_ERR(pins_state)) {
+               ret = pinctrl_select_state(pl022->pinctrl, pins_state);
                if (ret)
-                       dev_err(&pl022->adev->dev,
-                               "could not set pins to sleep state\n");
+                       dev_err(&pl022->adev->dev, "could not set %s pins\n",
+                               runtime ? "idle" : "sleep");
        }
 }
 
-static void pl022_resume_resources(struct pl022 *pl022)
+static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
 {
        int ret;
 
        /* Optionaly enable pins to be muxed in and configured */
+       /* First go to the default state */
        if (!IS_ERR(pl022->pins_default)) {
-               ret = pinctrl_select_state(pl022->pinctrl,
-                                          pl022->pins_default);
+               ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default);
                if (ret)
                        dev_err(&pl022->adev->dev,
                                "could not set default pins\n");
        }
 
+       if (!runtime) {
+               /* Then let's idle the pins until the next transfer happens */
+               if (!IS_ERR(pl022->pins_idle)) {
+                       ret = pinctrl_select_state(pl022->pinctrl,
+                                       pl022->pins_idle);
+               if (ret)
+                       dev_err(&pl022->adev->dev,
+                               "could not set idle pins\n");
+               }
+       }
+
        clk_enable(pl022->clk);
 }
 #endif
@@ -2347,7 +2363,9 @@ static int pl022_suspend(struct device *dev)
                dev_warn(dev, "cannot suspend master\n");
                return ret;
        }
-       pl022_suspend_resources(pl022);
+
+       pm_runtime_get_sync(dev);
+       pl022_suspend_resources(pl022, false);
 
        dev_dbg(dev, "suspended\n");
        return 0;
@@ -2358,7 +2376,8 @@ static int pl022_resume(struct device *dev)
        struct pl022 *pl022 = dev_get_drvdata(dev);
        int ret;
 
-       pl022_resume_resources(pl022);
+       pl022_resume_resources(pl022, false);
+       pm_runtime_put(dev);
 
        /* Start the queue running */
        ret = spi_master_resume(pl022->master);
@@ -2376,7 +2395,7 @@ static int pl022_runtime_suspend(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       pl022_suspend_resources(pl022);
+       pl022_suspend_resources(pl022, true);
        return 0;
 }
 
@@ -2384,7 +2403,7 @@ static int pl022_runtime_resume(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       pl022_resume_resources(pl022);
+       pl022_resume_resources(pl022, true);
        return 0;
 }
 #endif
@@ -2464,7 +2483,7 @@ static struct amba_driver pl022_driver = {
        },
        .id_table       = pl022_ids,
        .probe          = pl022_probe,
-       .remove         = __devexit_p(pl022_remove),
+       .remove         = pl022_remove,
 };
 
 static int __init pl022_init(void)