aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-platform.c
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2014-05-13 11:44:19 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 18:53:01 -0400
commit2d87bbd634b0fe5aa2285fd2a095867158fb2cc3 (patch)
tree4ed108676d751e68b09ec2a81816e543bc4ca695 /drivers/usb/host/ehci-platform.c
parent4615f3bd089fc4c549ed90e14982b360779feb50 (diff)
usb: ehci-platform: add optional reset controller retrieval
On the Allwinner's A31 SoC the reset line connected to the EHCI IP has to be deasserted for the EHCI block to be usable. Add support for an optional reset controller that will be deasserted on power off and asserted on power on. Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-platform.c')
-rw-r--r--drivers/usb/host/ehci-platform.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index c7dd93aad20c..2f5b9ce3e042 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -29,6 +29,7 @@
29#include <linux/of.h> 29#include <linux/of.h>
30#include <linux/phy/phy.h> 30#include <linux/phy/phy.h>
31#include <linux/platform_device.h> 31#include <linux/platform_device.h>
32#include <linux/reset.h>
32#include <linux/usb.h> 33#include <linux/usb.h>
33#include <linux/usb/hcd.h> 34#include <linux/usb/hcd.h>
34#include <linux/usb/ehci_pdriver.h> 35#include <linux/usb/ehci_pdriver.h>
@@ -41,6 +42,7 @@
41 42
42struct ehci_platform_priv { 43struct ehci_platform_priv {
43 struct clk *clks[EHCI_MAX_CLKS]; 44 struct clk *clks[EHCI_MAX_CLKS];
45 struct reset_control *rst;
44 struct phy *phy; 46 struct phy *phy;
45}; 47};
46 48
@@ -208,6 +210,18 @@ static int ehci_platform_probe(struct platform_device *dev)
208 } 210 }
209 } 211 }
210 212
213 priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
214 if (IS_ERR(priv->rst)) {
215 err = PTR_ERR(priv->rst);
216 if (err == -EPROBE_DEFER)
217 goto err_put_clks;
218 priv->rst = NULL;
219 } else {
220 err = reset_control_deassert(priv->rst);
221 if (err)
222 goto err_put_clks;
223 }
224
211 if (pdata->big_endian_desc) 225 if (pdata->big_endian_desc)
212 ehci->big_endian_desc = 1; 226 ehci->big_endian_desc = 1;
213 if (pdata->big_endian_mmio) 227 if (pdata->big_endian_mmio)
@@ -218,7 +232,7 @@ static int ehci_platform_probe(struct platform_device *dev)
218 dev_err(&dev->dev, 232 dev_err(&dev->dev,
219 "Error: CONFIG_USB_EHCI_BIG_ENDIAN_MMIO not set\n"); 233 "Error: CONFIG_USB_EHCI_BIG_ENDIAN_MMIO not set\n");
220 err = -EINVAL; 234 err = -EINVAL;
221 goto err_put_clks; 235 goto err_reset;
222 } 236 }
223#endif 237#endif
224#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC 238#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
@@ -226,14 +240,14 @@ static int ehci_platform_probe(struct platform_device *dev)
226 dev_err(&dev->dev, 240 dev_err(&dev->dev,
227 "Error: CONFIG_USB_EHCI_BIG_ENDIAN_DESC not set\n"); 241 "Error: CONFIG_USB_EHCI_BIG_ENDIAN_DESC not set\n");
228 err = -EINVAL; 242 err = -EINVAL;
229 goto err_put_clks; 243 goto err_reset;
230 } 244 }
231#endif 245#endif
232 246
233 if (pdata->power_on) { 247 if (pdata->power_on) {
234 err = pdata->power_on(dev); 248 err = pdata->power_on(dev);
235 if (err < 0) 249 if (err < 0)
236 goto err_put_clks; 250 goto err_reset;
237 } 251 }
238 252
239 hcd->rsrc_start = res_mem->start; 253 hcd->rsrc_start = res_mem->start;
@@ -256,6 +270,9 @@ static int ehci_platform_probe(struct platform_device *dev)
256err_power: 270err_power:
257 if (pdata->power_off) 271 if (pdata->power_off)
258 pdata->power_off(dev); 272 pdata->power_off(dev);
273err_reset:
274 if (priv->rst)
275 reset_control_assert(priv->rst);
259err_put_clks: 276err_put_clks:
260 while (--clk >= 0) 277 while (--clk >= 0)
261 clk_put(priv->clks[clk]); 278 clk_put(priv->clks[clk]);
@@ -280,6 +297,9 @@ static int ehci_platform_remove(struct platform_device *dev)
280 if (pdata->power_off) 297 if (pdata->power_off)
281 pdata->power_off(dev); 298 pdata->power_off(dev);
282 299
300 if (priv->rst)
301 reset_control_assert(priv->rst);
302
283 for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) 303 for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
284 clk_put(priv->clks[clk]); 304 clk_put(priv->clks[clk]);
285 305