summaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorCorentin Labbe <clabbe.montjoie@gmail.com>2018-09-03 12:01:56 +0200
committerJens Axboe <axboe@kernel.dk>2018-09-03 16:17:13 +0200
commitf20fb266e77a8af8a6e42eecfb5981178cc4d8a1 (patch)
tree5cd13dc53c3ed624c68bc91337759c5c96294d65 /drivers/ata
parentdt-bindings: ata: ahci-platform: document ahci-supply (diff)
downloadlinux-f20fb266e77a8af8a6e42eecfb5981178cc4d8a1.tar.xz
linux-f20fb266e77a8af8a6e42eecfb5981178cc4d8a1.zip
ata: ahci_platform: add support for PHY controller regulator
The SoC R40 AHCI controller need a PHY regulator to work. But since the PHY is embedded in the controller, we cannot do a DT node for it, since phy-supply works only in node with a PHY compatible. So this patch adds a way to add an optional phy-supply regulator on AHCI controller node. Acked-by: Maxime Ripard <maxime.ripard@bootlin.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.h1
-rw-r--r--drivers/ata/libahci_platform.c20
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 1415f1012de5..ef356e70e6de 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -353,6 +353,7 @@ struct ahci_host_priv {
struct reset_control *rsts; /* Optional */
struct regulator **target_pwrs; /* Optional */
struct regulator *ahci_regulator;/* Optional */
+ struct regulator *phy_regulator;/* Optional */
/*
* If platform uses PHYs. There is a 1:1 relation between the port number and
* the PHY position in this array.
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index e56f3a9fc7d4..4b900fc659f7 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -157,6 +157,12 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
return rc;
}
+ if (hpriv->phy_regulator) {
+ rc = regulator_enable(hpriv->phy_regulator);
+ if (rc)
+ goto disable_ahci_pwrs;
+ }
+
for (i = 0; i < hpriv->nports; i++) {
if (!hpriv->target_pwrs[i])
continue;
@@ -173,6 +179,9 @@ disable_target_pwrs:
if (hpriv->target_pwrs[i])
regulator_disable(hpriv->target_pwrs[i]);
+ if (hpriv->phy_regulator)
+ regulator_disable(hpriv->phy_regulator);
+disable_ahci_pwrs:
if (hpriv->ahci_regulator)
regulator_disable(hpriv->ahci_regulator);
return rc;
@@ -198,6 +207,8 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv)
if (hpriv->ahci_regulator)
regulator_disable(hpriv->ahci_regulator);
+ if (hpriv->phy_regulator)
+ regulator_disable(hpriv->phy_regulator);
}
EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
/**
@@ -430,6 +441,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
hpriv->ahci_regulator = NULL;
}
+ hpriv->phy_regulator = devm_regulator_get_optional(dev, "phy");
+ if (IS_ERR(hpriv->phy_regulator)) {
+ rc = PTR_ERR(hpriv->phy_regulator);
+ if (rc == -EPROBE_DEFER)
+ goto err_out;
+ rc = 0;
+ hpriv->phy_regulator = NULL;
+ }
+
if (flags & AHCI_PLATFORM_GET_RESETS) {
hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
if (IS_ERR(hpriv->rsts)) {