Skip to content

Commit

Permalink
mfd: omap-usb-tll: Clean up clock handling
Browse files Browse the repository at this point in the history
Every channel has a functional clock that is similarly named.
It makes sense to use a for loop to manage these clocks as OMAPs
can come with up to 3 channels.

Dynamically allocate and get channel clocks depending on the
number of clocks avaiable on the platform.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Roger Quadros committed Feb 13, 2013
1 parent 1a7a8d7 commit 0bde3e9
Showing 1 changed file with 54 additions and 33 deletions.
87 changes: 54 additions & 33 deletions drivers/mfd/omap-usb-tll.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,9 @@
#define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL)

struct usbtll_omap {
struct clk *usbtll_p1_fck;
struct clk *usbtll_p2_fck;
int nch; /* num. of channels */
struct usbhs_omap_platform_data *pdata;
struct clk **ch_clk;
/* secure the register updates */
spinlock_t lock;
};
Expand Down Expand Up @@ -225,26 +224,12 @@ static int usbtll_omap_probe(struct platform_device *pdev)

tll->pdata = pdata;

tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
if (IS_ERR(tll->usbtll_p1_fck)) {
ret = PTR_ERR(tll->usbtll_p1_fck);
dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
return ret;
}

tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
if (IS_ERR(tll->usbtll_p2_fck)) {
ret = PTR_ERR(tll->usbtll_p2_fck);
dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
goto err_p2_fck;
}

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_request_and_ioremap(dev, res);
if (!base) {
ret = -EADDRNOTAVAIL;
dev_err(dev, "Resource request/ioremap failed:%d\n", ret);
goto err_res;
return ret;
}

platform_set_drvdata(pdev, tll);
Expand All @@ -270,6 +255,29 @@ static int usbtll_omap_probe(struct platform_device *pdev)
break;
}

spin_unlock_irqrestore(&tll->lock, flags);

tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk * [tll->nch]),
GFP_KERNEL);
if (!tll->ch_clk) {
ret = -ENOMEM;
dev_err(dev, "Couldn't allocate memory for channel clocks\n");
goto err_clk_alloc;
}

for (i = 0; i < tll->nch; i++) {
char clkname[] = "usb_tll_hs_usb_chx_clk";

snprintf(clkname, sizeof(clkname),
"usb_tll_hs_usb_ch%d_clk", i);
tll->ch_clk[i] = clk_get(dev, clkname);

if (IS_ERR(tll->ch_clk[i]))
dev_dbg(dev, "can't get clock : %s\n", clkname);
}

spin_lock_irqsave(&tll->lock, flags);

if (is_ehci_tll_mode(pdata->port_mode[0]) ||
is_ehci_tll_mode(pdata->port_mode[1]) ||
is_ehci_tll_mode(pdata->port_mode[2]) ||
Expand Down Expand Up @@ -321,11 +329,9 @@ static int usbtll_omap_probe(struct platform_device *pdev)

return 0;

err_res:
clk_put(tll->usbtll_p2_fck);

err_p2_fck:
clk_put(tll->usbtll_p1_fck);
err_clk_alloc:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);

return ret;
}
Expand All @@ -339,9 +345,12 @@ static int usbtll_omap_probe(struct platform_device *pdev)
static int usbtll_omap_remove(struct platform_device *pdev)
{
struct usbtll_omap *tll = platform_get_drvdata(pdev);
int i;

for (i = 0; i < tll->nch; i++)
if (!IS_ERR(tll->ch_clk[i]))
clk_put(tll->ch_clk[i]);

clk_put(tll->usbtll_p2_fck);
clk_put(tll->usbtll_p1_fck);
pm_runtime_disable(&pdev->dev);
return 0;
}
Expand All @@ -351,6 +360,7 @@ static int usbtll_runtime_resume(struct device *dev)
struct usbtll_omap *tll = dev_get_drvdata(dev);
struct usbhs_omap_platform_data *pdata = tll->pdata;
unsigned long flags;
int i;

dev_dbg(dev, "usbtll_runtime_resume\n");

Expand All @@ -361,11 +371,20 @@ static int usbtll_runtime_resume(struct device *dev)

spin_lock_irqsave(&tll->lock, flags);

if (is_ehci_tll_mode(pdata->port_mode[0]))
clk_enable(tll->usbtll_p1_fck);
for (i = 0; i < tll->nch; i++) {
if (is_ehci_tll_mode(pdata->port_mode[i])) {
int r;

if (is_ehci_tll_mode(pdata->port_mode[1]))
clk_enable(tll->usbtll_p2_fck);
if (IS_ERR(tll->ch_clk[i]))
continue;

r = clk_enable(tll->ch_clk[i]);
if (r) {
dev_err(dev,
"Error enabling ch %d clock: %d\n", i, r);
}
}
}

spin_unlock_irqrestore(&tll->lock, flags);

Expand All @@ -377,6 +396,7 @@ static int usbtll_runtime_suspend(struct device *dev)
struct usbtll_omap *tll = dev_get_drvdata(dev);
struct usbhs_omap_platform_data *pdata = tll->pdata;
unsigned long flags;
int i;

dev_dbg(dev, "usbtll_runtime_suspend\n");

Expand All @@ -387,11 +407,12 @@ static int usbtll_runtime_suspend(struct device *dev)

spin_lock_irqsave(&tll->lock, flags);

if (is_ehci_tll_mode(pdata->port_mode[0]))
clk_disable(tll->usbtll_p1_fck);

if (is_ehci_tll_mode(pdata->port_mode[1]))
clk_disable(tll->usbtll_p2_fck);
for (i = 0; i < tll->nch; i++) {
if (is_ehci_tll_mode(pdata->port_mode[i])) {
if (!IS_ERR(tll->ch_clk[i]))
clk_disable(tll->ch_clk[i]);
}
}

spin_unlock_irqrestore(&tll->lock, flags);

Expand Down

0 comments on commit 0bde3e9

Please sign in to comment.