diff options
author | Corentin Labbe <clabbe.montjoie@gmail.com> | 2018-09-03 12:01:54 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-09-03 08:17:12 -0600 |
commit | a37da9180f42c953416c8aa3be2fbedf59fc4e3b (patch) | |
tree | c8b9e6e03546c1ca75449cddc30486c9fdcd46dc | |
parent | 15fd6ec97d4c6277ddfa170718ca277f044524d6 (diff) | |
download | linux-a37da9180f42c953416c8aa3be2fbedf59fc4e3b.tar.bz2 |
ata: ahci_platform: add support for AHCI controller regulator
The SoC R40 AHCI controller need a regulator to work.
So this patch add a way to add an optional regulator on AHCI controller.
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>
-rw-r--r-- | drivers/ata/ahci.h | 1 | ||||
-rw-r--r-- | drivers/ata/libahci_platform.c | 26 |
2 files changed, 25 insertions, 2 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 6a1515f0da40..1415f1012de5 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -352,6 +352,7 @@ struct ahci_host_priv { struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ struct reset_control *rsts; /* Optional */ struct regulator **target_pwrs; /* Optional */ + struct regulator *ahci_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 8ac2be869dd9..e56f3a9fc7d4 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); * ahci_platform_enable_regulators - Enable regulators * @hpriv: host private area to store config values * - * This function enables all the regulators found in + * This function enables all the regulators found in controller and * hpriv->target_pwrs, if any. If a regulator fails to be enabled, it * disables all the regulators already enabled in reverse order and * returns an error. @@ -151,6 +151,12 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) { int rc, i; + if (hpriv->ahci_regulator) { + rc = regulator_enable(hpriv->ahci_regulator); + if (rc) + return rc; + } + for (i = 0; i < hpriv->nports; i++) { if (!hpriv->target_pwrs[i]) continue; @@ -167,6 +173,8 @@ disable_target_pwrs: if (hpriv->target_pwrs[i]) regulator_disable(hpriv->target_pwrs[i]); + if (hpriv->ahci_regulator) + regulator_disable(hpriv->ahci_regulator); return rc; } EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators); @@ -175,7 +183,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators); * ahci_platform_disable_regulators - Disable regulators * @hpriv: host private area to store config values * - * This function disables all regulators found in hpriv->target_pwrs. + * This function disables all regulators found in hpriv->target_pwrs and + * AHCI controller. */ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv) { @@ -186,6 +195,9 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv) continue; regulator_disable(hpriv->target_pwrs[i]); } + + if (hpriv->ahci_regulator) + regulator_disable(hpriv->ahci_regulator); } EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators); /** @@ -351,6 +363,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, * * 1) mmio registers (IORESOURCE_MEM 0, mandatory) * 2) regulator for controlling the targets power (optional) + * regulator for controlling the AHCI controller (optional) * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, * or for non devicetree enabled platforms a single clock * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional) @@ -408,6 +421,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, hpriv->clks[i] = clk; } + hpriv->ahci_regulator = devm_regulator_get_optional(dev, "ahci"); + if (IS_ERR(hpriv->ahci_regulator)) { + rc = PTR_ERR(hpriv->ahci_regulator); + if (rc == -EPROBE_DEFER) + goto err_out; + rc = 0; + hpriv->ahci_regulator = NULL; + } + if (flags & AHCI_PLATFORM_GET_RESETS) { hpriv->rsts = devm_reset_control_array_get_optional_shared(dev); if (IS_ERR(hpriv->rsts)) { |