diff options
author | Kunihiko Hayashi <hayashi.kunihiko@socionext.com> | 2018-03-23 10:30:53 +0900 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2018-03-26 07:40:01 -0700 |
commit | f0f56716fc3e5d547fd7811eb218a30ed0695605 (patch) | |
tree | 98e855715735d806bdc2dfec4836decb8799ef50 /drivers/ata | |
parent | 3d6f22b74d919a5f32a6093666e85be110cc06de (diff) |
ata: ahci-platform: add reset control support
Add support to get and control a list of resets for the device
as optional and shared. These resets must be kept de-asserted until
the device is enabled.
This is specified as shared because some SoCs like UniPhier series
have common reset controls with all ahci controller instances.
Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Reviewed-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 | 1 | ||||
-rw-r--r-- | drivers/ata/libahci_platform.c | 24 |
2 files changed, 22 insertions, 3 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index a9d996e17d75..4356ef1d28a8 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -350,6 +350,7 @@ struct ahci_host_priv { u32 em_msg_type; /* EM message type */ bool got_runtime_pm; /* Did we do pm_runtime_get? */ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + struct reset_control *rsts; /* Optional */ struct regulator **target_pwrs; /* Optional */ /* * If platform uses PHYs. There is a 1:1 relation between the port number and diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 30cc8f1a31e1..46a762442dc5 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -25,6 +25,7 @@ #include <linux/phy/phy.h> #include <linux/pm_runtime.h> #include <linux/of_platform.h> +#include <linux/reset.h> #include "ahci.h" static void ahci_host_stop(struct ata_host *host); @@ -195,7 +196,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators); * following order: * 1) Regulator * 2) Clocks (through ahci_platform_enable_clks) - * 3) Phys + * 3) Resets + * 4) Phys * * If resource enabling fails at any point the previous enabled resources * are disabled in reverse order. @@ -215,12 +217,19 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) if (rc) goto disable_regulator; - rc = ahci_platform_enable_phys(hpriv); + rc = reset_control_deassert(hpriv->rsts); if (rc) goto disable_clks; + rc = ahci_platform_enable_phys(hpriv); + if (rc) + goto disable_resets; + return 0; +disable_resets: + reset_control_assert(hpriv->rsts); + disable_clks: ahci_platform_disable_clks(hpriv); @@ -239,12 +248,15 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); * following order: * 1) Phys * 2) Clocks (through ahci_platform_disable_clks) - * 3) Regulator + * 3) Resets + * 4) Regulator */ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) { ahci_platform_disable_phys(hpriv); + reset_control_assert(hpriv->rsts); + ahci_platform_disable_clks(hpriv); ahci_platform_disable_regulators(hpriv); @@ -393,6 +405,12 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) hpriv->clks[i] = clk; } + hpriv->rsts = devm_reset_control_array_get_optional_shared(dev); + if (IS_ERR(hpriv->rsts)) { + rc = PTR_ERR(hpriv->rsts); + goto err_out; + } + hpriv->nports = child_nodes = of_get_child_count(dev->of_node); /* |