|
@@ -42,6 +42,12 @@
|
|
|
|
|
|
#define DRIVER_DESC "EHCI orion driver"
|
|
|
|
|
|
+#define hcd_to_orion_priv(h) ((struct orion_ehci_hcd *)hcd_to_ehci(h)->priv)
|
|
|
+
|
|
|
+struct orion_ehci_hcd {
|
|
|
+ struct clk *clk;
|
|
|
+};
|
|
|
+
|
|
|
static const char hcd_name[] = "ehci-orion";
|
|
|
|
|
|
static struct hc_driver __read_mostly ehci_orion_hc_driver;
|
|
@@ -137,6 +143,10 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static const struct ehci_driver_overrides orion_overrides __initconst = {
|
|
|
+ .extra_priv_size = sizeof(struct orion_ehci_hcd),
|
|
|
+};
|
|
|
+
|
|
|
static int ehci_orion_drv_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct orion_ehci_data *pd = dev_get_platdata(&pdev->dev);
|
|
@@ -144,10 +154,10 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
|
|
|
struct resource *res;
|
|
|
struct usb_hcd *hcd;
|
|
|
struct ehci_hcd *ehci;
|
|
|
- struct clk *clk;
|
|
|
void __iomem *regs;
|
|
|
int irq, err;
|
|
|
enum orion_ehci_phy_ver phy_version;
|
|
|
+ struct orion_ehci_hcd *priv;
|
|
|
|
|
|
if (usb_disabled())
|
|
|
return -ENODEV;
|
|
@@ -187,17 +197,11 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- /* Not all platforms can gate the clock, so it is not
|
|
|
- an error if the clock does not exists. */
|
|
|
- clk = devm_clk_get(&pdev->dev, NULL);
|
|
|
- if (!IS_ERR(clk))
|
|
|
- clk_prepare_enable(clk);
|
|
|
-
|
|
|
hcd = usb_create_hcd(&ehci_orion_hc_driver,
|
|
|
&pdev->dev, dev_name(&pdev->dev));
|
|
|
if (!hcd) {
|
|
|
err = -ENOMEM;
|
|
|
- goto err_create_hcd;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
hcd->rsrc_start = res->start;
|
|
@@ -208,6 +212,15 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
|
|
|
ehci->caps = hcd->regs + 0x100;
|
|
|
hcd->has_tt = 1;
|
|
|
|
|
|
+ priv = hcd_to_orion_priv(hcd);
|
|
|
+ /*
|
|
|
+ * Not all platforms can gate the clock, so it is not an error if
|
|
|
+ * the clock does not exists.
|
|
|
+ */
|
|
|
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
|
|
|
+ if (!IS_ERR(priv->clk))
|
|
|
+ clk_prepare_enable(priv->clk);
|
|
|
+
|
|
|
/*
|
|
|
* (Re-)program MBUS remapping windows if we are asked to.
|
|
|
*/
|
|
@@ -243,10 +256,9 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
|
|
|
return 0;
|
|
|
|
|
|
err_add_hcd:
|
|
|
+ if (!IS_ERR(priv->clk))
|
|
|
+ clk_disable_unprepare(priv->clk);
|
|
|
usb_put_hcd(hcd);
|
|
|
-err_create_hcd:
|
|
|
- if (!IS_ERR(clk))
|
|
|
- clk_disable_unprepare(clk);
|
|
|
err:
|
|
|
dev_err(&pdev->dev, "init %s fail, %d\n",
|
|
|
dev_name(&pdev->dev), err);
|
|
@@ -257,14 +269,15 @@ err:
|
|
|
static int ehci_orion_drv_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
|
|
- struct clk *clk;
|
|
|
+ struct orion_ehci_hcd *priv = hcd_to_orion_priv(hcd);
|
|
|
|
|
|
usb_remove_hcd(hcd);
|
|
|
+
|
|
|
+ if (!IS_ERR(priv->clk))
|
|
|
+ clk_disable_unprepare(priv->clk);
|
|
|
+
|
|
|
usb_put_hcd(hcd);
|
|
|
|
|
|
- clk = devm_clk_get(&pdev->dev, NULL);
|
|
|
- if (!IS_ERR(clk))
|
|
|
- clk_disable_unprepare(clk);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -292,7 +305,7 @@ static int __init ehci_orion_init(void)
|
|
|
|
|
|
pr_info("%s: " DRIVER_DESC "\n", hcd_name);
|
|
|
|
|
|
- ehci_init_driver(&ehci_orion_hc_driver, NULL);
|
|
|
+ ehci_init_driver(&ehci_orion_hc_driver, &orion_overrides);
|
|
|
return platform_driver_register(&ehci_orion_driver);
|
|
|
}
|
|
|
module_init(ehci_orion_init);
|