mfd: omap-usb-tll: Clean up clock handling

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>
This commit is contained in:
Roger Quadros 2012-11-08 13:07:09 +02:00
parent 1a7a8d70cd
commit 0bde3e9fee

View File

@ -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;
};
@ -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);
@ -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]) ||
@ -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;
}
@ -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;
}
@ -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");
@ -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);
@ -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");
@ -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);