diff options
Diffstat (limited to 'target/linux/sunxi/patches-4.4/144-usb-ehci-plat-support-multiple-reset-ctrllines.patch')
-rw-r--r-- | target/linux/sunxi/patches-4.4/144-usb-ehci-plat-support-multiple-reset-ctrllines.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/target/linux/sunxi/patches-4.4/144-usb-ehci-plat-support-multiple-reset-ctrllines.patch b/target/linux/sunxi/patches-4.4/144-usb-ehci-plat-support-multiple-reset-ctrllines.patch new file mode 100644 index 0000000000..faafa1f0a3 --- /dev/null +++ b/target/linux/sunxi/patches-4.4/144-usb-ehci-plat-support-multiple-reset-ctrllines.patch @@ -0,0 +1,131 @@ +From 957e8f96c67052ca843ea9ffc5223662b973e5de Mon Sep 17 00:00:00 2001 +From: Reinder de Haan <patchesrdh@mveas.com> +Date: Sun, 15 Nov 2015 14:24:46 +0100 +Subject: [PATCH] ehci-platform: Add support for controllers with multiple + reset lines + +At least the EHCI/OHCI found on the Allwinnner H3 SoC needs multiple +reset lines, the controller will not initialize while the reset for +its companion is still asserted, which means we need to de-assert +2 resets for the controller to work. + +Signed-off-by: Reinder de Haan <patchesrdh@mveas.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- +Changes in v2: +-Use the new reset_control_[de]assert_shared reset-controller functions +--- + Documentation/devicetree/bindings/usb/usb-ehci.txt | 2 +- + drivers/usb/host/ehci-platform.c | 47 +++++++++++++--------- + 2 files changed, 30 insertions(+), 19 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt +index a12d601..0701812 100644 +--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt +@@ -18,7 +18,7 @@ Optional properties: + - clocks : a list of phandle + clock specifier pairs + - phys : phandle + phy specifier pair + - phy-names : "usb" +- - resets : phandle + reset specifier pair ++ - resets : a list of phandle + reset specifier pairs + + Example (Sequoia 440EPx): + ehci@e0000300 { +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index bd7082f2..6fbf32a 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -39,11 +39,12 @@ + + #define DRIVER_DESC "EHCI generic platform driver" + #define EHCI_MAX_CLKS 3 ++#define EHCI_MAX_RESETS 2 + #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) + + struct ehci_platform_priv { + struct clk *clks[EHCI_MAX_CLKS]; +- struct reset_control *rst; ++ struct reset_control *resets[EHCI_MAX_RESETS]; + struct phy **phys; + int num_phys; + bool reset_on_resume; +@@ -149,7 +150,7 @@ static int ehci_platform_probe(struct platform_device *dev) + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ehci_platform_priv *priv; + struct ehci_hcd *ehci; +- int err, irq, phy_num, clk = 0; ++ int err, irq, phy_num, clk = 0, rst = 0; + + if (usb_disabled()) + return -ENODEV; +@@ -232,18 +233,24 @@ static int ehci_platform_probe(struct platform_device *dev) + break; + } + } +- } + +- priv->rst = devm_reset_control_get_optional(&dev->dev, NULL); +- if (IS_ERR(priv->rst)) { +- err = PTR_ERR(priv->rst); +- if (err == -EPROBE_DEFER) +- goto err_put_clks; +- priv->rst = NULL; +- } else { +- err = reset_control_deassert(priv->rst); +- if (err) +- goto err_put_clks; ++ for (rst = 0; rst < EHCI_MAX_RESETS; rst++) { ++ priv->resets[rst] = ++ of_reset_control_get_by_index(dev->dev.of_node, ++ rst); ++ if (IS_ERR(priv->resets[rst])) { ++ err = PTR_ERR(priv->resets[rst]); ++ if (err == -EPROBE_DEFER) ++ goto err_reset; ++ priv->resets[rst] = NULL; ++ break; ++ } ++ err = reset_control_deassert_shared(priv->resets[rst]); ++ if (err) { ++ reset_control_put(priv->resets[rst]); ++ goto err_reset; ++ } ++ } + } + + if (pdata->big_endian_desc) +@@ -300,8 +307,10 @@ static int ehci_platform_probe(struct platform_device *dev) + if (pdata->power_off) + pdata->power_off(dev); + err_reset: +- if (priv->rst) +- reset_control_assert(priv->rst); ++ while (--rst >= 0) { ++ reset_control_assert_shared(priv->resets[rst]); ++ reset_control_put(priv->resets[rst]); ++ } + err_put_clks: + while (--clk >= 0) + clk_put(priv->clks[clk]); +@@ -319,15 +328,17 @@ static int ehci_platform_remove(struct platform_device *dev) + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); +- int clk; ++ int clk, rst; + + usb_remove_hcd(hcd); + + if (pdata->power_off) + pdata->power_off(dev); + +- if (priv->rst) +- reset_control_assert(priv->rst); ++ for (rst = 0; rst < EHCI_MAX_RESETS && priv->resets[rst]; rst++) { ++ reset_control_assert_shared(priv->resets[rst]); ++ reset_control_put(priv->resets[rst]); ++ } + + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) + clk_put(priv->clks[clk]); |