|
@@ -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 @@ err_p2_fck:
|
|
|
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);
|
|
|
|