diff options
author | Hans de Goede <hdegoede@redhat.com> | 2014-02-22 16:53:32 +0100 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-02-22 15:35:42 -0500 |
commit | 4b3e603a298db26c6c37e8b08adcce24d014df13 (patch) | |
tree | ee83e07b60a9fc55e3882c826ee9804223ebaf3a /drivers/ata | |
parent | 156c5887948cd191417f18026aab9ce26e5a95da (diff) | |
download | blackbird-op-linux-4b3e603a298db26c6c37e8b08adcce24d014df13.tar.gz blackbird-op-linux-4b3e603a298db26c6c37e8b08adcce24d014df13.zip |
ahci-platform: Add support for an optional regulator for sata-target power
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/ahci.h | 2 | ||||
-rw-r--r-- | drivers/ata/ahci_platform.c | 36 |
2 files changed, 36 insertions, 2 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index c12862bd48ee..bf8100c51142 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -37,6 +37,7 @@ #include <linux/clk.h> #include <linux/libata.h> +#include <linux/regulator/consumer.h> /* Enclosure Management Control */ #define EM_CTRL_MSG_TYPE 0x000f0000 @@ -323,6 +324,7 @@ struct ahci_host_priv { u32 em_buf_sz; /* EM buffer size in byte */ u32 em_msg_type; /* EM message type */ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + struct regulator *target_pwr; /* Optional */ void *plat_data; /* Other platform data */ /* * Optional ahci_start_engine override, if not set this gets set to the diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 8d5a9a7ce958..4befd78133ad 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -185,6 +185,14 @@ static int ahci_probe(struct platform_device *pdev) return -ENOMEM; } + hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); + if (IS_ERR(hpriv->target_pwr)) { + rc = PTR_ERR(hpriv->target_pwr); + if (rc == -EPROBE_DEFER) + return -EPROBE_DEFER; + hpriv->target_pwr = NULL; + } + for (i = 0; i < AHCI_MAX_CLKS; i++) { /* * For now we must use clk_get(dev, NULL) for the first clock, @@ -206,9 +214,15 @@ static int ahci_probe(struct platform_device *pdev) hpriv->clks[i] = clk; } + if (hpriv->target_pwr) { + rc = regulator_enable(hpriv->target_pwr); + if (rc) + goto free_clk; + } + rc = ahci_enable_clks(dev, hpriv); if (rc) - goto free_clk; + goto disable_regulator; /* * Some platforms might need to prepare for mmio region access, @@ -291,6 +305,9 @@ pdata_exit: pdata->exit(dev); disable_unprepare_clk: ahci_disable_clks(hpriv); +disable_regulator: + if (hpriv->target_pwr) + regulator_disable(hpriv->target_pwr); free_clk: ahci_put_clks(hpriv); return rc; @@ -307,6 +324,9 @@ static void ahci_host_stop(struct ata_host *host) ahci_disable_clks(hpriv); ahci_put_clks(hpriv); + + if (hpriv->target_pwr) + regulator_disable(hpriv->target_pwr); } #ifdef CONFIG_PM_SLEEP @@ -343,6 +363,9 @@ static int ahci_suspend(struct device *dev) ahci_disable_clks(hpriv); + if (hpriv->target_pwr) + regulator_disable(hpriv->target_pwr); + return 0; } @@ -353,9 +376,15 @@ static int ahci_resume(struct device *dev) struct ahci_host_priv *hpriv = host->private_data; int rc; + if (hpriv->target_pwr) { + rc = regulator_enable(hpriv->target_pwr); + if (rc) + return rc; + } + rc = ahci_enable_clks(dev, hpriv); if (rc) - return rc; + goto disable_regulator; if (pdata && pdata->resume) { rc = pdata->resume(dev); @@ -377,6 +406,9 @@ static int ahci_resume(struct device *dev) disable_unprepare_clk: ahci_disable_clks(hpriv); +disable_regulator: + if (hpriv->target_pwr) + regulator_disable(hpriv->target_pwr); return rc; } |