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
Родитель ccac71a7f0
Коммит 06ba7dc75f
1 изменённых файлов: 109 добавлений и 83 удалений

Просмотреть файл

@ -92,13 +92,12 @@
struct usbhs_hcd_omap {
int nports;
struct clk **utmi_clk;
struct clk *xclk60mhsp1_ck;
struct clk *xclk60mhsp2_ck;
struct clk *utmi_p1_fck;
struct clk *usbhost_p1_fck;
struct clk *utmi_p2_fck;
struct clk *usbhost_p2_fck;
struct clk *utmi_p1_gfclk;
struct clk *utmi_p2_gfclk;
struct clk *init_60m_fclk;
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_omap_platform_data *pdata = omap->pdata;
unsigned long flags;
int i, r;
dev_dbg(dev, "usbhs_runtime_resume\n");
omap_tll_enable();
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);
if (is_ehci_tll_mode(pdata->port_mode[0]))
clk_enable(omap->usbhost_p1_fck);
if (is_ehci_tll_mode(pdata->port_mode[1]))
clk_enable(omap->usbhost_p2_fck);
for (i = 0; i < omap->nports; i++) {
if (!is_ehci_tll_mode(pdata->port_mode[i]) ||
IS_ERR(omap->utmi_clk[i]))
continue;
clk_enable(omap->utmi_p1_fck);
clk_enable(omap->utmi_p2_fck);
r = clk_enable(omap->utmi_clk[i]);
if (r)
dev_err(dev, "Can't enable port %d clk : %d\n", i, r);
}
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_omap_platform_data *pdata = omap->pdata;
unsigned long flags;
int i;
dev_dbg(dev, "usbhs_runtime_suspend\n");
spin_lock_irqsave(&omap->lock, flags);
if (is_ehci_tll_mode(pdata->port_mode[0]))
clk_disable(omap->usbhost_p1_fck);
if (is_ehci_tll_mode(pdata->port_mode[1]))
clk_disable(omap->usbhost_p2_fck);
for (i = 0; i < omap->nports; i++) {
if (is_ehci_tll_mode(pdata->port_mode[i]) &&
!IS_ERR(omap->utmi_clk[i]))
clk_disable(omap->utmi_clk[i]);
}
clk_disable(omap->utmi_p2_fck);
clk_disable(omap->utmi_p1_fck);
if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
if (!IS_ERR(omap->ehci_logic_fck))
clk_disable(omap->ehci_logic_fck);
spin_unlock_irqrestore(&omap->lock, flags);
@ -458,6 +459,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
struct resource *res;
int ret = 0;
int i;
bool need_logic_fck;
if (!pdata) {
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++)
if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
is_ehci_hsic_mode(i)) {
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_warn(dev, "ehci_logic_fck failed:%d\n",
ret);
}
break;
}
i = sizeof(struct clk *) * omap->nports;
omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL);
if (!omap->utmi_clk) {
dev_err(dev, "Memory allocation failed\n");
ret = -ENOMEM;
goto err_mem;
}
omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
if (IS_ERR(omap->utmi_p1_fck)) {
ret = PTR_ERR(omap->utmi_p1_fck);
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
goto err_end;
need_logic_fck = false;
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;
}
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");
if (IS_ERR(omap->xclk60mhsp1_ck)) {
ret = PTR_ERR(omap->xclk60mhsp1_ck);
dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
goto err_utmi_p1_fck;
}
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;
goto err_xclk60mhsp1;
}
omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
if (IS_ERR(omap->xclk60mhsp2_ck)) {
ret = PTR_ERR(omap->xclk60mhsp2_ck);
dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
goto err_utmi_p2_fck;
}
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;
goto err_xclk60mhsp2;
}
omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
if (IS_ERR(omap->init_60m_fclk)) {
ret = PTR_ERR(omap->init_60m_fclk);
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])) {
/* 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);
if (ret != 0)
dev_err(dev, "xclk60mhsp1_ck set parent"
"failed error:%d\n", ret);
} 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);
if (ret != 0)
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])) {
ret = clk_set_parent(omap->utmi_p2_fck,
ret = clk_set_parent(omap->utmi_p2_gfclk,
omap->xclk60mhsp2_ck);
if (ret != 0)
dev_err(dev, "xclk60mhsp2_ck set parent"
"failed error:%d\n", ret);
} 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);
if (ret != 0)
dev_err(dev, "init_60m_fclk set parent"
@ -617,28 +634,30 @@ static int usbhs_omap_probe(struct platform_device *pdev)
err_alloc:
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);
err_usbhost_p2_fck:
clk_put(omap->usbhost_p2_fck);
err_usbhost_p1_fck:
clk_put(omap->usbhost_p1_fck);
err_xclk60mhsp2_ck:
err_init60m:
clk_put(omap->xclk60mhsp2_ck);
err_utmi_p2_fck:
clk_put(omap->utmi_p2_fck);
err_xclk60mhsp1_ck:
err_xclk60mhsp2:
clk_put(omap->xclk60mhsp1_ck);
err_utmi_p1_fck:
clk_put(omap->utmi_p1_fck);
err_xclk60mhsp1:
clk_put(omap->utmi_p2_gfclk);
err_end:
clk_put(omap->ehci_logic_fck);
err_p2_gfclk:
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);
return ret;
@ -653,16 +672,23 @@ err_end:
static int usbhs_omap_remove(struct platform_device *pdev)
{
struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
int i;
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->usbhost_p2_fck);
clk_put(omap->usbhost_p1_fck);
clk_put(omap->utmi_p1_gfclk);
clk_put(omap->utmi_p2_gfclk);
clk_put(omap->xclk60mhsp2_ck);
clk_put(omap->utmi_p2_fck);
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);
return 0;