Commit a37da918 authored by Corentin Labbe's avatar Corentin Labbe Committed by Jens Axboe

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: default avatarMaxime Ripard <maxime.ripard@bootlin.com>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarCorentin Labbe <clabbe.montjoie@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 15fd6ec9
...@@ -352,6 +352,7 @@ struct ahci_host_priv { ...@@ -352,6 +352,7 @@ struct ahci_host_priv {
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
struct reset_control *rsts; /* Optional */ struct reset_control *rsts; /* Optional */
struct regulator **target_pwrs; /* 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 * If platform uses PHYs. There is a 1:1 relation between the port number and
* the PHY position in this array. * the PHY position in this array.
......
...@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); ...@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
* ahci_platform_enable_regulators - Enable regulators * ahci_platform_enable_regulators - Enable regulators
* @hpriv: host private area to store config values * @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 * hpriv->target_pwrs, if any. If a regulator fails to be enabled, it
* disables all the regulators already enabled in reverse order and * disables all the regulators already enabled in reverse order and
* returns an error. * returns an error.
...@@ -151,6 +151,12 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) ...@@ -151,6 +151,12 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
{ {
int rc, i; int rc, i;
if (hpriv->ahci_regulator) {
rc = regulator_enable(hpriv->ahci_regulator);
if (rc)
return rc;
}
for (i = 0; i < hpriv->nports; i++) { for (i = 0; i < hpriv->nports; i++) {
if (!hpriv->target_pwrs[i]) if (!hpriv->target_pwrs[i])
continue; continue;
...@@ -167,6 +173,8 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) ...@@ -167,6 +173,8 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
if (hpriv->target_pwrs[i]) if (hpriv->target_pwrs[i])
regulator_disable(hpriv->target_pwrs[i]); regulator_disable(hpriv->target_pwrs[i]);
if (hpriv->ahci_regulator)
regulator_disable(hpriv->ahci_regulator);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators); EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators);
...@@ -175,7 +183,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators); ...@@ -175,7 +183,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators);
* ahci_platform_disable_regulators - Disable regulators * ahci_platform_disable_regulators - Disable regulators
* @hpriv: host private area to store config values * @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) void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv)
{ {
...@@ -186,6 +195,9 @@ 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; continue;
regulator_disable(hpriv->target_pwrs[i]); regulator_disable(hpriv->target_pwrs[i]);
} }
if (hpriv->ahci_regulator)
regulator_disable(hpriv->ahci_regulator);
} }
EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators); EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
/** /**
...@@ -351,6 +363,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, ...@@ -351,6 +363,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
* *
* 1) mmio registers (IORESOURCE_MEM 0, mandatory) * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
* 2) regulator for controlling the targets power (optional) * 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, * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
* or for non devicetree enabled platforms a single clock * or for non devicetree enabled platforms a single clock
* 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional) * 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, ...@@ -408,6 +421,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
hpriv->clks[i] = clk; 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) { if (flags & AHCI_PLATFORM_GET_RESETS) {
hpriv->rsts = devm_reset_control_array_get_optional_shared(dev); hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
if (IS_ERR(hpriv->rsts)) { if (IS_ERR(hpriv->rsts)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment