Skip to content

Commit

Permalink
mfd: omap-usb-host: cleanup clock management code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Roger Quadros committed Feb 13, 2013
1 parent ccac71a commit 06ba7dc
Showing 1 changed file with 106 additions and 80 deletions.
186 changes: 106 additions & 80 deletions drivers/mfd/omap-usb-host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);

Expand All @@ -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);

clk_disable(omap->utmi_p2_fck);
clk_disable(omap->utmi_p1_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]);
}

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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -516,90 +518,105 @@ static int usbhs_omap_probe(struct platform_device *pdev)
}
}

for (i = 0; i < omap->nports; i++)
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;
}

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)) {
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;
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_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;
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"
"failed error:%d\n", ret);
}

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"
Expand All @@ -617,28 +634,30 @@ static int usbhs_omap_probe(struct platform_device *pdev)

err_alloc:
omap_usbhs_deinit(&pdev->dev);
clk_put(omap->init_60m_fclk);

err_usbhost_p2_fck:
clk_put(omap->usbhost_p2_fck);
for (i = 0; i < omap->nports; i++)
if (!IS_ERR(omap->utmi_clk[i]))
clk_put(omap->utmi_clk[i]);

err_usbhost_p1_fck:
clk_put(omap->usbhost_p1_fck);
clk_put(omap->init_60m_fclk);

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;
Expand All @@ -653,16 +672,23 @@ static int usbhs_omap_probe(struct platform_device *pdev)
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;
Expand Down

0 comments on commit 06ba7dc

Please sign in to comment.