From 6f82ccd186e246786909fe032be53b8dc0e593ba Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Tue, 18 Sep 2018 17:43:02 +0200 Subject: [PATCH] Adding R40 SATA driver --- ...-support-except-for-existing-drivers.patch | 444 ++++++++++++++++++ .../sunxi-dev/board-r40-sata-support.patch | 382 +++++++++++++++ 2 files changed, 826 insertions(+) create mode 100644 patch/kernel/sunxi-dev/0001-general-ata-ahci-platform-add-reset-control-support-except-for-existing-drivers.patch create mode 100644 patch/kernel/sunxi-dev/board-r40-sata-support.patch diff --git a/patch/kernel/sunxi-dev/0001-general-ata-ahci-platform-add-reset-control-support-except-for-existing-drivers.patch b/patch/kernel/sunxi-dev/0001-general-ata-ahci-platform-add-reset-control-support-except-for-existing-drivers.patch new file mode 100644 index 000000000..1317bfafe --- /dev/null +++ b/patch/kernel/sunxi-dev/0001-general-ata-ahci-platform-add-reset-control-support-except-for-existing-drivers.patch @@ -0,0 +1,444 @@ +Add an extra argument to ahci_platform_get_resources(), that is +for the bitmap representing the resource to get in this function. + +Currently there is no resources to be defined, so all the callers set +'0' to the argument. + +Suggested-by: Hans de Goede +Cc: Thierry Reding +Cc: Matthias Brugger +Cc: Patrice Chotard +Cc: Maxime Ripard +Signed-off-by: Kunihiko Hayashi +--- + drivers/ata/ahci_brcm.c | 2 +- + drivers/ata/ahci_ceva.c | 2 +- + drivers/ata/ahci_da850.c | 2 +- + drivers/ata/ahci_dm816.c | 2 +- + drivers/ata/ahci_imx.c | 2 +- + drivers/ata/ahci_mtk.c | 2 +- + drivers/ata/ahci_mvebu.c | 2 +- + drivers/ata/ahci_platform.c | 2 +- + drivers/ata/ahci_qoriq.c | 2 +- + drivers/ata/ahci_seattle.c | 2 +- + drivers/ata/ahci_st.c | 2 +- + drivers/ata/ahci_sunxi.c | 2 +- + drivers/ata/ahci_tegra.c | 2 +- + drivers/ata/ahci_xgene.c | 2 +- + drivers/ata/libahci_platform.c | 4 +++- + include/linux/ahci_platform.h | 2 +- + 16 files changed, 18 insertions(+), 16 deletions(-) + +diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c +index ea43081..f3d5577 100644 +--- a/drivers/ata/ahci_brcm.c ++++ b/drivers/ata/ahci_brcm.c +@@ -425,7 +425,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) + + brcm_sata_phys_enable(priv); + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + hpriv->plat_data = priv; +diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c +index 5ecc9d4..dc78c98 100644 +--- a/drivers/ata/ahci_ceva.c ++++ b/drivers/ata/ahci_ceva.c +@@ -213,7 +213,7 @@ static int ceva_ahci_probe(struct platform_device *pdev) + + cevapriv->ahci_pdev = pdev; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c +index 9b34dff..ebaa657 100644 +--- a/drivers/ata/ahci_da850.c ++++ b/drivers/ata/ahci_da850.c +@@ -171,7 +171,7 @@ static int ahci_da850_probe(struct platform_device *pdev) + u32 mpy; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c +index fbd827c..89509c3 100644 +--- a/drivers/ata/ahci_dm816.c ++++ b/drivers/ata/ahci_dm816.c +@@ -148,7 +148,7 @@ static int ahci_dm816_probe(struct platform_device *pdev) + struct ahci_host_priv *hpriv; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c +index 6822e2f..b00799d 100644 +--- a/drivers/ata/ahci_imx.c ++++ b/drivers/ata/ahci_imx.c +@@ -1127,7 +1127,7 @@ static int imx_ahci_probe(struct platform_device *pdev) + return ret; + } + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c +index 0ae6971..8bc1a26 100644 +--- a/drivers/ata/ahci_mtk.c ++++ b/drivers/ata/ahci_mtk.c +@@ -142,7 +142,7 @@ static int mtk_ahci_probe(struct platform_device *pdev) + if (!plat) + return -ENOMEM; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c +index 72d90b4..f9cb51b 100644 +--- a/drivers/ata/ahci_mvebu.c ++++ b/drivers/ata/ahci_mvebu.c +@@ -158,7 +158,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev) + const struct mbus_dram_target_info *dram; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 99f9a89..5709273 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -43,7 +43,7 @@ static int ahci_probe(struct platform_device *pdev) + struct ahci_host_priv *hpriv; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c +index cfdef4d..ce59253 100644 +--- a/drivers/ata/ahci_qoriq.c ++++ b/drivers/ata/ahci_qoriq.c +@@ -250,7 +250,7 @@ static int ahci_qoriq_probe(struct platform_device *pdev) + struct resource *res; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c +index 1d31c0c..e57b6f9 100644 +--- a/drivers/ata/ahci_seattle.c ++++ b/drivers/ata/ahci_seattle.c +@@ -164,7 +164,7 @@ static int ahci_seattle_probe(struct platform_device *pdev) + int rc; + struct ahci_host_priv *hpriv; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c +index bc345f2..21c5c44 100644 +--- a/drivers/ata/ahci_st.c ++++ b/drivers/ata/ahci_st.c +@@ -156,7 +156,7 @@ static int st_ahci_probe(struct platform_device *pdev) + if (!drv_data) + return -ENOMEM; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + hpriv->plat_data = drv_data; +diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c +index b264374..631610b 100644 +--- a/drivers/ata/ahci_sunxi.c ++++ b/drivers/ata/ahci_sunxi.c +@@ -181,7 +181,7 @@ static int ahci_sunxi_probe(struct platform_device *pdev) + struct ahci_host_priv *hpriv; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c +index 64d8484..004f260 100644 +--- a/drivers/ata/ahci_tegra.c ++++ b/drivers/ata/ahci_tegra.c +@@ -494,7 +494,7 @@ static int tegra_ahci_probe(struct platform_device *pdev) + int ret; + unsigned int i; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c +index ad58da7..7e157e1 100644 +--- a/drivers/ata/ahci_xgene.c ++++ b/drivers/ata/ahci_xgene.c +@@ -759,7 +759,7 @@ static int xgene_ahci_probe(struct platform_device *pdev) + &xgene_ahci_v2_port_info }; + int rc; + +- hpriv = ahci_platform_get_resources(pdev); ++ hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c +index 30cc8f1..6abc1cd 100644 +--- a/drivers/ata/libahci_platform.c ++++ b/drivers/ata/libahci_platform.c +@@ -332,6 +332,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, + /** + * ahci_platform_get_resources - Get platform resources + * @pdev: platform device to get resources for ++ * @flags: bitmap representing the resource to get + * + * This function allocates an ahci_host_priv struct, and gets the following + * resources, storing a reference to them inside the returned struct: +@@ -345,7 +346,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, + * RETURNS: + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value + */ +-struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) ++struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, ++ unsigned int flags) + { + struct device *dev = &pdev->dev; + struct ahci_host_priv *hpriv; +diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h +index 1b0a17b..6490be1 100644 +--- a/include/linux/ahci_platform.h ++++ b/include/linux/ahci_platform.h +@@ -30,7 +30,7 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv); + int ahci_platform_enable_resources(struct ahci_host_priv *hpriv); + void ahci_platform_disable_resources(struct ahci_host_priv *hpriv); + struct ahci_host_priv *ahci_platform_get_resources( +- struct platform_device *pdev); ++ struct platform_device *pdev, unsigned int flags); + int ahci_platform_init_host(struct platform_device *pdev, + struct ahci_host_priv *hpriv, + const struct ata_port_info *pi_template, + +From patchwork Wed Aug 22 12:13:02 2018 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2,2/3] ata: libahci_platform: add reset control support +X-Patchwork-Submitter: Kunihiko Hayashi +X-Patchwork-Id: 960932 +X-Patchwork-Delegate: davem@davemloft.net +Message-Id: <1534939983-16264-3-git-send-email-hayashi.kunihiko@socionext.com> +To: Tejun Heo , Hans de Goede , + Rob Herring , + Mark Rutland , linux-ide@vger.kernel.org +Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + Kunihiko Hayashi , + Thierry Reding +Date: Wed, 22 Aug 2018 21:13:02 +0900 +From: Kunihiko Hayashi +List-Id: + +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. + +However, according to Thierry's view, +https://www.spinics.net/lists/linux-ide/msg55357.html +some hardware-specific drivers already use their own resets, +and the common reset make a path to occur double controls of resets. + +The ahci_platform_get_resources() can get and control the reset +only when the second argument includes AHCI_PLATFORM_GET_RESETS bit. + +Suggested-by: Hans de Goede +Cc: Thierry Reding +Signed-off-by: Kunihiko Hayashi +Acked-by: Rob Herring +--- + .../devicetree/bindings/ata/ahci-platform.txt | 1 + + drivers/ata/ahci.h | 1 + + drivers/ata/libahci_platform.c | 31 ++++++++++++++++++---- + include/linux/ahci_platform.h | 2 ++ + 4 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index c760ecb..f4006d3 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -30,6 +30,7 @@ compatible: + Optional properties: + - dma-coherent : Present if dma operations are coherent + - clocks : a list of phandle + clock specifier pairs ++- resets : a list of phandle + reset specifier pairs + - target-supply : regulator for SATA target power + - phys : reference to the SATA PHY node + - phy-names : must be "sata-phy" +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 1609eba..6a1515f 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 6abc1cd..6817143 100644 +--- a/drivers/ata/libahci_platform.c ++++ b/drivers/ata/libahci_platform.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #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); + +@@ -238,13 +247,16 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); + * This function disables all ahci_platform managed resources in the + * following order: + * 1) Phys +- * 2) Clocks (through ahci_platform_disable_clks) +- * 3) Regulator ++ * 2) Resets ++ * 3) Clocks (through ahci_platform_disable_clks) ++ * 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); +@@ -341,7 +353,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, + * 2) regulator for controlling the targets power (optional) + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, + * or for non devicetree enabled platforms a single clock +- * 4) phys (optional) ++ * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional) ++ * 5) phys (optional) + * + * RETURNS: + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value +@@ -395,6 +408,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, + hpriv->clks[i] = clk; + } + ++ if (flags & AHCI_PLATFORM_GET_RESETS) { ++ 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); + + /* +diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h +index 6490be1..eaedca5f 100644 +--- a/include/linux/ahci_platform.h ++++ b/include/linux/ahci_platform.h +@@ -43,4 +43,6 @@ int ahci_platform_resume_host(struct device *dev); + int ahci_platform_suspend(struct device *dev); + int ahci_platform_resume(struct device *dev); + ++#define AHCI_PLATFORM_GET_RESETS 0x01 ++ + #endif /* _AHCI_PLATFORM_H */ + +Unlike SoC-specific driver, generic ahci_platform driver doesn't +have any chances to control resets. + +This adds AHCI_PLATFORM_GET_RESETS to ahci_platform_get_resources() +on the generic driver to enable reset control support. + +Suggested-by: Hans de Goede +Cc: Thierry Reding +Signed-off-by: Kunihiko Hayashi +--- + drivers/ata/ahci_platform.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 5709273..ddd9308 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -43,7 +43,8 @@ static int ahci_probe(struct platform_device *pdev) + struct ahci_host_priv *hpriv; + int rc; + +- hpriv = ahci_platform_get_resources(pdev, 0); ++ hpriv = ahci_platform_get_resources(pdev, ++ AHCI_PLATFORM_GET_RESETS); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + diff --git a/patch/kernel/sunxi-dev/board-r40-sata-support.patch b/patch/kernel/sunxi-dev/board-r40-sata-support.patch new file mode 100644 index 000000000..12f59fa17 --- /dev/null +++ b/patch/kernel/sunxi-dev/board-r40-sata-support.patch @@ -0,0 +1,382 @@ +This patch fix the indentation of target-supply's ':'. + +Signed-off-by: Corentin Labbe +--- + Documentation/devicetree/bindings/ata/ahci-platform.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index 5d5bd456d9d9..b88820b4c01e 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -47,7 +47,7 @@ Sub-nodes required properties: + - reg : the port number + And at least one of the following properties: + - phys : reference to the SATA PHY node +-- target-supply : regulator for SATA target power ++- target-supply : regulator for SATA target power + + Examples: + sata@ffe08000 { + +The SoC R40 AHCI controller need a regulator to work. +So this patch add a way to add an optional regulator on AHCI controller. + +Signed-off-by: Corentin Labbe +--- + drivers/ata/ahci.h | 1 + + 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 c92c10d55374..a886b61476a3 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 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) + 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)) { + +This patch document the new optional ahci-supply. + +Signed-off-by: Corentin Labbe +Reviewed-by: Rob Herring +--- + Documentation/devicetree/bindings/ata/ahci-platform.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index b88820b4c01e..f495774c8af9 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -33,6 +33,7 @@ Optional properties: + - target-supply : regulator for SATA target power + - phys : reference to the SATA PHY node + - phy-names : must be "sata-phy" ++- ahci-supply : regulator for AHCI controller + - ports-implemented : Mask that indicates which ports that the HBA supports + are available for software to use. Useful if PORTS_IMPL + is not programmed by the BIOS, which is true with + + +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. + +Signed-off-by: Corentin Labbe +--- + drivers/ata/ahci.h | 1 + + drivers/ata/libahci_platform.c | 20 ++++++++++++++++++++ + 2 files changed, 21 insertions(+) + +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 a886b61476a3..dc4d79b1c9ae 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 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) + 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)) { + +This patch document the new optional phy-supply. + +Signed-off-by: Corentin Labbe +--- + Documentation/devicetree/bindings/ata/ahci-platform.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index f495774c8af9..45b451961612 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -31,6 +31,7 @@ Optional properties: + - clocks : a list of phandle + clock specifier pairs + - resets : a list of phandle + reset specifier pairs + - target-supply : regulator for SATA target power ++- phy-supply : regulator for PHY power + - phys : reference to the SATA PHY node + - phy-names : must be "sata-phy" + - ahci-supply : regulator for AHCI controller + +This patch add the r40 compatible to the ahci_sunxi's supported list of +compatible. + +Since R40 need ahci_platform to handle the reset controller, we also add +the new AHCI_PLATFORM_GET_RESETS flag for ahci_platform_get_resources(). +This has no consequence for older platform (a10, a20) since the reset is +optional. + +Signed-off-by: Corentin Labbe +--- + drivers/ata/ahci_sunxi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c +index 631610b72aa5..911710643305 100644 +--- a/drivers/ata/ahci_sunxi.c ++++ b/drivers/ata/ahci_sunxi.c +@@ -181,7 +181,7 @@ static int ahci_sunxi_probe(struct platform_device *pdev) + struct ahci_host_priv *hpriv; + int rc; + +- hpriv = ahci_platform_get_resources(pdev, 0); ++ hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +@@ -250,6 +250,7 @@ static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend, + + static const struct of_device_id ahci_sunxi_of_match[] = { + { .compatible = "allwinner,sun4i-a10-ahci", }, ++ { .compatible = "allwinner,sun8i-r40-ahci", }, + { }, + }; + MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match); + +This patch update binding with the new R40 compatible. + +Signed-off-by: Corentin Labbe +Reviewed-by: Rob Herring +--- + Documentation/devicetree/bindings/ata/ahci-platform.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index 45b451961612..e30fd106df4f 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -10,6 +10,7 @@ PHYs. + Required properties: + - compatible : compatible string, one of: + - "allwinner,sun4i-a10-ahci" ++ - "allwinner,sun8i-r40-ahci" + - "brcm,iproc-ahci" + - "hisilicon,hisi-ahci" + - "cavium,octeon-7130-ahci" +@@ -44,6 +45,7 @@ Required properties when using sub-nodes: + - #address-cells : number of cells to encode an address + - #size-cells : number of cells representing the size of an address + ++For allwinner,sun8i-r40-ahci, the reset propertie must be present. + + Sub-nodes required properties: + - reg : the port number + +R40 have a sata controller which is the same as A20. +This patch adds a DT node for it. + +Signed-off-by: Icenowy Zheng +Signed-off-by: Corentin Labbe +--- + arch/arm/boot/dts/sun8i-r40.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi +index 852c2ccc3268..d27c522e1918 100644 +--- a/arch/arm/boot/dts/sun8i-r40.dtsi ++++ b/arch/arm/boot/dts/sun8i-r40.dtsi +@@ -550,6 +550,19 @@ + #size-cells = <0>; + }; + ++ ahci: sata@1c18000 { ++ compatible = "allwinner,sun8i-r40-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>; ++ resets = <&ccu RST_BUS_SATA>; ++ resets-name = "ahci"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ }; ++ + gmac: ethernet@1c50000 { + compatible = "allwinner,sun8i-r40-gmac"; + syscon = <&ccu>; + +This patch enable the AHCI controller. +Since this controller need two regulator, this patch add them. + +Signed-off-by: Corentin Labbe +--- + arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts +index a891a387e8f1..438b7b44dab3 100644 +--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts ++++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts +@@ -105,6 +105,12 @@ + }; + }; + ++&ahci { ++ ahci-supply = <®_dldo4>; ++ phy-supply = <®_eldo3>; ++ status = "okay"; ++}; ++ + &de { + status = "okay"; + }; +@@ -257,6 +257,18 @@ + regulator-name = "vcc-wifi"; + }; + ++®_dldo4 { ++ regulator-min-microvolt = <2500000>; ++ regulator-max-microvolt = <2500000>; ++ regulator-name = "vdd2v5-sata"; ++}; ++ ++®_eldo3 { ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-name = "vdd1v2-sata"; ++}; ++ + &tcon_top_hdmi_in_tcon_tv0 { + remote-endpoint = <&tcon_tv0_out_tcon_top>; + };