mfd: omap-usb-host: cleanup clock management code

All ports have similarly named port clocks so we can
bunch them into a port data structure and use for loop
to enable/disable the clocks.

Dynamically allocate and get clocks based on number of ports
available on the platform

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Roger Quadros 2012-11-08 17:40:25 +02:00
parent ccac71a7f0
commit 06ba7dc75f

View File

@ -92,13 +92,12 @@
struct usbhs_hcd_omap { struct usbhs_hcd_omap {
int nports; int nports;
struct clk **utmi_clk;
struct clk *xclk60mhsp1_ck; struct clk *xclk60mhsp1_ck;
struct clk *xclk60mhsp2_ck; struct clk *xclk60mhsp2_ck;
struct clk *utmi_p1_fck; struct clk *utmi_p1_gfclk;
struct clk *usbhost_p1_fck; struct clk *utmi_p2_gfclk;
struct clk *utmi_p2_fck;
struct clk *usbhost_p2_fck;
struct clk *init_60m_fclk; struct clk *init_60m_fclk;
struct clk *ehci_logic_fck; struct clk *ehci_logic_fck;
@ -276,22 +275,25 @@ static int usbhs_runtime_resume(struct device *dev)
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
struct usbhs_omap_platform_data *pdata = omap->pdata; struct usbhs_omap_platform_data *pdata = omap->pdata;
unsigned long flags; unsigned long flags;
int i, r;
dev_dbg(dev, "usbhs_runtime_resume\n"); dev_dbg(dev, "usbhs_runtime_resume\n");
omap_tll_enable(); omap_tll_enable();
spin_lock_irqsave(&omap->lock, flags); spin_lock_irqsave(&omap->lock, flags);
if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) if (!IS_ERR(omap->ehci_logic_fck))
clk_enable(omap->ehci_logic_fck); clk_enable(omap->ehci_logic_fck);
if (is_ehci_tll_mode(pdata->port_mode[0])) for (i = 0; i < omap->nports; i++) {
clk_enable(omap->usbhost_p1_fck); if (!is_ehci_tll_mode(pdata->port_mode[i]) ||
if (is_ehci_tll_mode(pdata->port_mode[1])) IS_ERR(omap->utmi_clk[i]))
clk_enable(omap->usbhost_p2_fck); continue;
clk_enable(omap->utmi_p1_fck); r = clk_enable(omap->utmi_clk[i]);
clk_enable(omap->utmi_p2_fck); if (r)
dev_err(dev, "Can't enable port %d clk : %d\n", i, r);
}
spin_unlock_irqrestore(&omap->lock, flags); spin_unlock_irqrestore(&omap->lock, flags);
@ -303,20 +305,19 @@ static int usbhs_runtime_suspend(struct device *dev)
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
struct usbhs_omap_platform_data *pdata = omap->pdata; struct usbhs_omap_platform_data *pdata = omap->pdata;
unsigned long flags; unsigned long flags;
int i;
dev_dbg(dev, "usbhs_runtime_suspend\n"); dev_dbg(dev, "usbhs_runtime_suspend\n");
spin_lock_irqsave(&omap->lock, flags); spin_lock_irqsave(&omap->lock, flags);
if (is_ehci_tll_mode(pdata->port_mode[0])) for (i = 0; i < omap->nports; i++) {
clk_disable(omap->usbhost_p1_fck); if (is_ehci_tll_mode(pdata->port_mode[i]) &&
if (is_ehci_tll_mode(pdata->port_mode[1])) !IS_ERR(omap->utmi_clk[i]))
clk_disable(omap->usbhost_p2_fck); clk_disable(omap->utmi_clk[i]);
}
clk_disable(omap->utmi_p2_fck); if (!IS_ERR(omap->ehci_logic_fck))
clk_disable(omap->utmi_p1_fck);
if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
clk_disable(omap->ehci_logic_fck); clk_disable(omap->ehci_logic_fck);
spin_unlock_irqrestore(&omap->lock, flags); spin_unlock_irqrestore(&omap->lock, flags);
@ -458,6 +459,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int ret = 0; int ret = 0;
int i; int i;
bool need_logic_fck;
if (!pdata) { if (!pdata) {
dev_err(dev, "Missing platform data\n"); dev_err(dev, "Missing platform data\n");
@ -516,76 +518,91 @@ static int usbhs_omap_probe(struct platform_device *pdev)
} }
} }
for (i = 0; i < omap->nports; i++) i = sizeof(struct clk *) * omap->nports;
if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL);
is_ehci_hsic_mode(i)) { if (!omap->utmi_clk) {
omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); dev_err(dev, "Memory allocation failed\n");
if (IS_ERR(omap->ehci_logic_fck)) { ret = -ENOMEM;
ret = PTR_ERR(omap->ehci_logic_fck); goto err_mem;
dev_warn(dev, "ehci_logic_fck failed:%d\n", }
ret);
}
break;
}
omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); need_logic_fck = false;
if (IS_ERR(omap->utmi_p1_fck)) { for (i = 0; i < omap->nports; i++) {
ret = PTR_ERR(omap->utmi_p1_fck); if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); is_ehci_hsic_mode(i))
goto err_end; need_logic_fck |= true;
}
omap->ehci_logic_fck = ERR_PTR(-EINVAL);
if (need_logic_fck) {
omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck");
if (IS_ERR(omap->ehci_logic_fck)) {
ret = PTR_ERR(omap->ehci_logic_fck);
dev_dbg(dev, "ehci_logic_fck failed:%d\n", ret);
}
}
omap->utmi_p1_gfclk = clk_get(dev, "utmi_p1_gfclk");
if (IS_ERR(omap->utmi_p1_gfclk)) {
ret = PTR_ERR(omap->utmi_p1_gfclk);
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
goto err_p1_gfclk;
}
omap->utmi_p2_gfclk = clk_get(dev, "utmi_p2_gfclk");
if (IS_ERR(omap->utmi_p2_gfclk)) {
ret = PTR_ERR(omap->utmi_p2_gfclk);
dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
goto err_p2_gfclk;
} }
omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
if (IS_ERR(omap->xclk60mhsp1_ck)) { if (IS_ERR(omap->xclk60mhsp1_ck)) {
ret = PTR_ERR(omap->xclk60mhsp1_ck); ret = PTR_ERR(omap->xclk60mhsp1_ck);
dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
goto err_utmi_p1_fck; goto err_xclk60mhsp1;
}
omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
if (IS_ERR(omap->utmi_p2_fck)) {
ret = PTR_ERR(omap->utmi_p2_fck);
dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
goto err_xclk60mhsp1_ck;
} }
omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
if (IS_ERR(omap->xclk60mhsp2_ck)) { if (IS_ERR(omap->xclk60mhsp2_ck)) {
ret = PTR_ERR(omap->xclk60mhsp2_ck); ret = PTR_ERR(omap->xclk60mhsp2_ck);
dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
goto err_utmi_p2_fck; goto err_xclk60mhsp2;
}
omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
if (IS_ERR(omap->usbhost_p1_fck)) {
ret = PTR_ERR(omap->usbhost_p1_fck);
dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
goto err_xclk60mhsp2_ck;
}
omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
if (IS_ERR(omap->usbhost_p2_fck)) {
ret = PTR_ERR(omap->usbhost_p2_fck);
dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
goto err_usbhost_p1_fck;
} }
omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
if (IS_ERR(omap->init_60m_fclk)) { if (IS_ERR(omap->init_60m_fclk)) {
ret = PTR_ERR(omap->init_60m_fclk); ret = PTR_ERR(omap->init_60m_fclk);
dev_err(dev, "init_60m_fclk failed error:%d\n", ret); dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
goto err_usbhost_p2_fck; goto err_init60m;
}
for (i = 0; i < omap->nports; i++) {
char clkname[] = "usb_host_hs_utmi_px_clk";
/* clock names are indexed from 1*/
snprintf(clkname, sizeof(clkname),
"usb_host_hs_utmi_p%d_clk", i + 1);
/* If a clock is not found we won't bail out as not all
* platforms have all clocks and we can function without
* them
*/
omap->utmi_clk[i] = clk_get(dev, clkname);
if (IS_ERR(omap->utmi_clk[i]))
dev_dbg(dev, "Failed to get clock : %s : %ld\n",
clkname, PTR_ERR(omap->utmi_clk[i]));
} }
if (is_ehci_phy_mode(pdata->port_mode[0])) { if (is_ehci_phy_mode(pdata->port_mode[0])) {
/* for OMAP3 , the clk set paretn fails */ /* for OMAP3 , the clk set paretn fails */
ret = clk_set_parent(omap->utmi_p1_fck, ret = clk_set_parent(omap->utmi_p1_gfclk,
omap->xclk60mhsp1_ck); omap->xclk60mhsp1_ck);
if (ret != 0) if (ret != 0)
dev_err(dev, "xclk60mhsp1_ck set parent" dev_err(dev, "xclk60mhsp1_ck set parent"
"failed error:%d\n", ret); "failed error:%d\n", ret);
} else if (is_ehci_tll_mode(pdata->port_mode[0])) { } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
ret = clk_set_parent(omap->utmi_p1_fck, ret = clk_set_parent(omap->utmi_p1_gfclk,
omap->init_60m_fclk); omap->init_60m_fclk);
if (ret != 0) if (ret != 0)
dev_err(dev, "init_60m_fclk set parent" dev_err(dev, "init_60m_fclk set parent"
@ -593,13 +610,13 @@ static int usbhs_omap_probe(struct platform_device *pdev)
} }
if (is_ehci_phy_mode(pdata->port_mode[1])) { if (is_ehci_phy_mode(pdata->port_mode[1])) {
ret = clk_set_parent(omap->utmi_p2_fck, ret = clk_set_parent(omap->utmi_p2_gfclk,
omap->xclk60mhsp2_ck); omap->xclk60mhsp2_ck);
if (ret != 0) if (ret != 0)
dev_err(dev, "xclk60mhsp2_ck set parent" dev_err(dev, "xclk60mhsp2_ck set parent"
"failed error:%d\n", ret); "failed error:%d\n", ret);
} else if (is_ehci_tll_mode(pdata->port_mode[1])) { } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
ret = clk_set_parent(omap->utmi_p2_fck, ret = clk_set_parent(omap->utmi_p2_gfclk,
omap->init_60m_fclk); omap->init_60m_fclk);
if (ret != 0) if (ret != 0)
dev_err(dev, "init_60m_fclk set parent" dev_err(dev, "init_60m_fclk set parent"
@ -617,28 +634,30 @@ static int usbhs_omap_probe(struct platform_device *pdev)
err_alloc: err_alloc:
omap_usbhs_deinit(&pdev->dev); omap_usbhs_deinit(&pdev->dev);
for (i = 0; i < omap->nports; i++)
if (!IS_ERR(omap->utmi_clk[i]))
clk_put(omap->utmi_clk[i]);
clk_put(omap->init_60m_fclk); clk_put(omap->init_60m_fclk);
err_usbhost_p2_fck: err_init60m:
clk_put(omap->usbhost_p2_fck);
err_usbhost_p1_fck:
clk_put(omap->usbhost_p1_fck);
err_xclk60mhsp2_ck:
clk_put(omap->xclk60mhsp2_ck); clk_put(omap->xclk60mhsp2_ck);
err_utmi_p2_fck: err_xclk60mhsp2:
clk_put(omap->utmi_p2_fck);
err_xclk60mhsp1_ck:
clk_put(omap->xclk60mhsp1_ck); clk_put(omap->xclk60mhsp1_ck);
err_utmi_p1_fck: err_xclk60mhsp1:
clk_put(omap->utmi_p1_fck); clk_put(omap->utmi_p2_gfclk);
err_end: err_p2_gfclk:
clk_put(omap->ehci_logic_fck); clk_put(omap->utmi_p1_gfclk);
err_p1_gfclk:
if (!IS_ERR(omap->ehci_logic_fck))
clk_put(omap->ehci_logic_fck);
err_mem:
pm_runtime_disable(dev); pm_runtime_disable(dev);
return ret; return ret;
@ -653,16 +672,23 @@ err_end:
static int usbhs_omap_remove(struct platform_device *pdev) static int usbhs_omap_remove(struct platform_device *pdev)
{ {
struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
int i;
omap_usbhs_deinit(&pdev->dev); omap_usbhs_deinit(&pdev->dev);
for (i = 0; i < omap->nports; i++)
if (!IS_ERR(omap->utmi_clk[i]))
clk_put(omap->utmi_clk[i]);
clk_put(omap->init_60m_fclk); clk_put(omap->init_60m_fclk);
clk_put(omap->usbhost_p2_fck); clk_put(omap->utmi_p1_gfclk);
clk_put(omap->usbhost_p1_fck); clk_put(omap->utmi_p2_gfclk);
clk_put(omap->xclk60mhsp2_ck); clk_put(omap->xclk60mhsp2_ck);
clk_put(omap->utmi_p2_fck);
clk_put(omap->xclk60mhsp1_ck); clk_put(omap->xclk60mhsp1_ck);
clk_put(omap->utmi_p1_fck);
clk_put(omap->ehci_logic_fck); if (!IS_ERR(omap->ehci_logic_fck))
clk_put(omap->ehci_logic_fck);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;