prevents getting clocks that don't exist on the platform.
Signed-off-by: Roger Quadros <[email protected]>
---
drivers/mfd/omap-usb-host.c | 47 ++++++++++++++++++++++++++++++++-----------
1 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 44772ae..ad89939 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -94,6 +94,7 @@ struct usbhs_port {
};
struct usbhs_hcd_omap {
+ int nports;
struct usbhs_port port[MAX_HS_USB_PORTS];
struct clk *xclk60mhsp1_ck;
@@ -291,7 +292,7 @@ static int usbhs_runtime_resume(struct device *dev)
if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
clk_enable(omap->ehci_logic_fck);
- for (i = 0; i < MAX_HS_USB_PORTS; i++) {
+ for (i = 0; i < omap->nports; i++) {
if (is_ehci_tll_mode(pdata->port_mode[i])) {
if (omap->port[i].utmi_clk) {
r = clk_enable(omap->port[i].utmi_clk);
@@ -320,7 +321,7 @@ static int usbhs_runtime_suspend(struct device *dev)
spin_lock_irqsave(&omap->lock, flags);
- for (i = 0; i < MAX_HS_USB_PORTS; i++) {
+ for (i = 0; i < omap->nports; i++) {
if (is_ehci_tll_mode(pdata->port_mode[i])) {
if (omap->port[i].utmi_clk)
clk_disable(omap->port[i].utmi_clk);
@@ -360,8 +361,6 @@ static void omap_usbhs_init(struct device *dev)
pm_runtime_get_sync(dev);
spin_lock_irqsave(&omap->lock, flags);
- omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
- dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
/* setup ULPI bypass and burst configurations */
@@ -502,8 +501,32 @@ static int __devinit usbhs_omap_probe(struct
platform_device *pdev)
omap->pdata = pdata;
platform_set_drvdata(pdev, omap);
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+ omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
+
+ /* we need to call runtime suspend before we update omap->nports
+ * to prevent unbalanced clk_disable()
+ */
+ pm_runtime_put_sync(dev);
+
+ switch (omap->usbhs_rev) {
+ case OMAP_USBHS_REV1:
+ omap->nports = 3;
+ break;
+ case OMAP_USBHS_REV2:
+ omap->nports = 2;
+ break;
+ default:
+ omap->nports = MAX_HS_USB_PORTS;
+ dev_info(dev,
+ "USB HOST Rev : 0x%d not recognized, assuming %d ports\n",
+ omap->usbhs_rev, omap->nports);
+ break;
+ }
+
need_logic_fck = false;
- for (i = 0; i < MAX_HS_USB_PORTS; i++) {
+ for (i = 0; i < omap->nports; i++) {
if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
is_ehci_hsic_mode(i))
need_logic_fck |= true;
@@ -538,7 +561,7 @@ static int __devinit usbhs_omap_probe(struct
platform_device *pdev)
goto err_init60m;
}
- for (i = 0; i < MAX_HS_USB_PORTS; i++) {
+ for (i = 0; i < omap->nports; i++) {
struct clk *pclk;
char utmi_clk[] = "usb_host_hs_utmi_px_clk";
@@ -588,8 +611,6 @@ static int __devinit usbhs_omap_probe(struct
platform_device *pdev)
}
- pm_runtime_enable(dev);
-
omap_usbhs_init(dev);
ret = omap_usbhs_alloc_children(pdev);
if (ret) {
@@ -597,15 +618,15 @@ static int __devinit usbhs_omap_probe(struct
platform_device *pdev)
goto err_alloc;
}
+ pr_info("OMAP USB HOST : revision 0x%x, ports %d\n",
+ omap->usbhs_rev, omap->nports);
return 0;
err_alloc:
omap_usbhs_deinit(&pdev->dev);
-
- pm_runtime_disable(dev);
iounmap(omap->uhh_base);
- for (i = 0; i < MAX_HS_USB_PORTS; i++)
+ for (i = 0; i < omap->nports; i++)
clk_put(omap->port[i].utmi_clk);
clk_put(omap->init_60m_fclk);
@@ -619,6 +640,8 @@ err_xclk60mhsp2:
err_xclk60mhsp1:
clk_put(omap->ehci_logic_fck);
+ pm_runtime_disable(dev);
+
err_remap:
kfree(omap);
return ret;
@@ -639,7 +662,7 @@ static int __devexit usbhs_omap_remove(struct
platform_device *pdev)
pm_runtime_disable(&pdev->dev);
iounmap(omap->uhh_base);
- for (i = 0; i < MAX_HS_USB_PORTS; i++)
+ for (i = 0; i < omap->nports; i++)
clk_put(omap->port[i].utmi_clk);
clk_put(omap->init_60m_fclk);
--
1.7.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html