diff mbox

[v8,05/22] mfd: omap-usb-tll: Clean up clock handling

Message ID 1358511445-26656-6-git-send-email-rogerq@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Roger Quadros Jan. 18, 2013, 12:17 p.m. UTC
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>
---
 drivers/mfd/omap-usb-tll.c |   89 +++++++++++++++++++++++++++----------------
 1 files changed, 56 insertions(+), 33 deletions(-)

Comments

Russell King - ARM Linux Jan. 18, 2013, 2:59 p.m. UTC | #1
On Fri, Jan 18, 2013 at 02:17:08PM +0200, Roger Quadros wrote:
> +	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";
> +		struct clk *fck;
> +
> +		snprintf(clkname, sizeof(clkname),
> +					"usb_tll_hs_usb_ch%d_clk", i);
> +		fck = clk_get(dev, clkname);
> +
> +		if (IS_ERR(fck))
> +			dev_dbg(dev, "can't get clock : %s\n", clkname);
> +		else
> +			tll->ch_clk[i] = fck;

Hmm.  I'd actually suggest that this becomes:

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

so that tll->ch_clk is always written to.

>  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++)
> +		clk_put(tll->ch_clk[i]);

And change this to:

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

so that you're not passing a NULL pointer in.

> +	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 (!tll->ch_clk[i])

			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);
> +			}
> +		}
> +	}

> @@ -387,11 +409,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 (tll->ch_clk[i])

			if (!IS_ERR(tll->ch_clk[i]))

> +				clk_disable(tll->ch_clk[i]);
> +		}
> +	}
>  
>  	spin_unlock_irqrestore(&tll->lock, flags);
>  
> -- 
> 1.7.4.1
>
Roger Quadros Jan. 18, 2013, 3:04 p.m. UTC | #2
On 01/18/2013 04:59 PM, Russell King - ARM Linux wrote:
> On Fri, Jan 18, 2013 at 02:17:08PM +0200, Roger Quadros wrote:
>> +	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";
>> +		struct clk *fck;
>> +
>> +		snprintf(clkname, sizeof(clkname),
>> +					"usb_tll_hs_usb_ch%d_clk", i);
>> +		fck = clk_get(dev, clkname);
>> +
>> +		if (IS_ERR(fck))
>> +			dev_dbg(dev, "can't get clock : %s\n", clkname);
>> +		else
>> +			tll->ch_clk[i] = fck;
> 
> Hmm.  I'd actually suggest that this becomes:
> 
> 		tll->ch_clk[i] = fck;
> 		if (IS_ERR(fck)
> 			dev_dbg(dev, "can't get clock: %s\n", clkname);
> 
> so that tll->ch_clk is always written to.

Yes, I'll fix this.

> 
>>  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++)
>> +		clk_put(tll->ch_clk[i]);
> 
> And change this to:
> 
> 	for (i = 0; i < tll->nch; i++)
> 		if (!IS_ERR(tll->ch_clk[i]))
> 			clk_put(tll->ch_clk[i]);
> 
> so that you're not passing a NULL pointer in.
>
ok.

>> +	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 (!tll->ch_clk[i])
> 
> 			if (IS_ERR(tll->ch_clk[i]))
ok.
> 
>> +				continue;
>> +
>> +			r = clk_enable(tll->ch_clk[i]);
>> +			if (r) {
>> +				dev_err(dev,
>> +				 "Error enabling ch %d clock: %d\n", i, r);
>> +			}
>> +		}
>> +	}
> 
>> @@ -387,11 +409,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 (tll->ch_clk[i])
> 
> 			if (!IS_ERR(tll->ch_clk[i]))
ok.

> 
>> +				clk_disable(tll->ch_clk[i]);
>> +		}
>> +	}
>>  
>>  	spin_unlock_irqrestore(&tll->lock, flags);
>>  

--
cheers,
-roger
diff mbox

Patch

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 9a19cc7..4ce134b 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -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,32 @@  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";
+		struct clk *fck;
+
+		snprintf(clkname, sizeof(clkname),
+					"usb_tll_hs_usb_ch%d_clk", i);
+		fck = clk_get(dev, clkname);
+
+		if (IS_ERR(fck))
+			dev_dbg(dev, "can't get clock : %s\n", clkname);
+		else
+			tll->ch_clk[i] = fck;
+	}
+
+	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 +332,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 +348,11 @@  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++)
+		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 +362,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 +373,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 (!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 +398,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 +409,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 (tll->ch_clk[i])
+				clk_disable(tll->ch_clk[i]);
+		}
+	}
 
 	spin_unlock_irqrestore(&tll->lock, flags);