diff mbox

[3/5] usb: phy: twl4030-usb: Move code from twl4030_phy_power to the runtime PM calls

Message ID 1409182091-31191-4-git-send-email-tony@atomide.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tony Lindgren Aug. 27, 2014, 11:28 p.m. UTC
We don't need twl4030_phy_power() any longer now that we have
the runtime PM calls. Let's get rid of it as it's confusing.
No functional changes, just move the code and use res instead
of ret as we are not returning that value.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/phy/phy-twl4030-usb.c | 72 +++++++++++++++++++------------------------
 1 file changed, 31 insertions(+), 41 deletions(-)

Comments

Kishon Vijay Abraham I Sept. 4, 2014, 1:50 p.m. UTC | #1
Hi Tony,

On Thursday 28 August 2014 04:58 AM, Tony Lindgren wrote:
> We don't need twl4030_phy_power() any longer now that we have
> the runtime PM calls. Let's get rid of it as it's confusing.
> No functional changes, just move the code and use res instead
> of ret as we are not returning that value.

Now that you are doing pm_runtime_get_sync in twl4030_phy_init, won't it power
on the phy even before initializing it (since runtime_resume will be invoked
even before doing phy_init)?

Even if pm_runtime_get_sync in not done in twl4030_phy_init, phy-core itself
does pm_runtime_get_sync in phy_init().

Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren Sept. 4, 2014, 5:07 p.m. UTC | #2
* Kishon Vijay Abraham I <kishon@ti.com> [140904 06:51]:
> Hi Tony,
> 
> On Thursday 28 August 2014 04:58 AM, Tony Lindgren wrote:
> > We don't need twl4030_phy_power() any longer now that we have
> > the runtime PM calls. Let's get rid of it as it's confusing.
> > No functional changes, just move the code and use res instead
> > of ret as we are not returning that value.
> 
> Now that you are doing pm_runtime_get_sync in twl4030_phy_init, won't it power
> on the phy even before initializing it (since runtime_resume will be invoked
> even before doing phy_init)?

Yes. The logic being that it should not matter as we are not
configuring the phy until in twl4030_phy_power_on(). Maybe we
should add code to make sure the phy is deconfigured initially
though :)

In twl4030_phy_init() we just want to check the ID pin state to get
things right initially. In the twl4030-usb case the I2C chip is
always on, but let's try to get the runtime PM set up like any
standard Linux driver would do it to avoid confusion.

> Even if pm_runtime_get_sync in not done in twl4030_phy_init, phy-core itself
> does pm_runtime_get_sync in phy_init().

Hmm OK. Looking at that, looks like we don't neeed any of these
custom exports though:

$ git grep phy_pm_runtime | grep EXPORT_SYMBOL
drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_get);
drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_put);
drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync);
drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_allow);
drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid);

The reasons why I think we don't need the above at all is:

1. We already have a framework for that in Linux runtime PM and we
   can follow the standard Linux runtime PM calls and not proxy
   them in phy-core.c

2. We can allow idling the phy properly on the bus it's connected
   to, in this case I2C, even if USB driver is not loaded. We
   eventually should idle the phy even if usb_add_phy_dev()
   failed

3. There's no actual need for phy-core.c to proxy the runtime
   PM calls

So we can and should just let the phy drivers do their own runtime PM
as needed based on just the phy init, power_on and power_off calls.

Probably the same goes for the regulator_enable in phy-core.c. That
should be handled in the phy driver as phy-core is already unable
to handle it properly. For example, for phy-twl4030-usb.c we have
three regulators to deal with and the phy framework won't have any
idea how to deal with those.

And the phy-core won't be able to deal with the phy driver interrupts
anyways, so any attempt of doing finer grained runtime PM in phy-core
or handling of separate wake-up interrupts will be doomed to fail.

I think the changes above would simplify the phy handling quite
a bit, what do you think?

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kishon Vijay Abraham I Sept. 8, 2014, 2:25 p.m. UTC | #3
Hi Tony,

On Thursday 04 September 2014 10:37 PM, Tony Lindgren wrote:
> * Kishon Vijay Abraham I <kishon@ti.com> [140904 06:51]:
>> Hi Tony,
>>
>> On Thursday 28 August 2014 04:58 AM, Tony Lindgren wrote:
>>> We don't need twl4030_phy_power() any longer now that we have
>>> the runtime PM calls. Let's get rid of it as it's confusing.
>>> No functional changes, just move the code and use res instead
>>> of ret as we are not returning that value.
>>
>> Now that you are doing pm_runtime_get_sync in twl4030_phy_init, won't it power
>> on the phy even before initializing it (since runtime_resume will be invoked
>> even before doing phy_init)?
> 
> Yes. The logic being that it should not matter as we are not
> configuring the phy until in twl4030_phy_power_on(). Maybe we
> should add code to make sure the phy is deconfigured initially
> though :)
> 
> In twl4030_phy_init() we just want to check the ID pin state to get
> things right initially. In the twl4030-usb case the I2C chip is
> always on, but let's try to get the runtime PM set up like any
> standard Linux driver would do it to avoid confusion.
> 
>> Even if pm_runtime_get_sync in not done in twl4030_phy_init, phy-core itself
>> does pm_runtime_get_sync in phy_init().
> 
> Hmm OK. Looking at that, looks like we don't neeed any of these
> custom exports though:
> 
> $ git grep phy_pm_runtime | grep EXPORT_SYMBOL
> drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_get);
> drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
> drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_put);
> drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync);
> drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_allow);
> drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid);
> 
> The reasons why I think we don't need the above at all is:
> 
> 1. We already have a framework for that in Linux runtime PM and we
>    can follow the standard Linux runtime PM calls and not proxy
>    them in phy-core.c

The reason for adding these are for providing fine grained control of the PHY
by the controller drivers. In most cases the controller driver determines when
the PHY should be active or idle.
> 
> 2. We can allow idling the phy properly on the bus it's connected
>    to, in this case I2C, even if USB driver is not loaded. We
>    eventually should idle the phy even if usb_add_phy_dev()
>    failed

yes.. that's why we have ops like phy_power_on to tell when the PHY should be
active. So these PHYs can be idled in probe.
> 
> 3. There's no actual need for phy-core.c to proxy the runtime
>    PM calls
> 
> So we can and should just let the phy drivers do their own runtime PM
> as needed based on just the phy init, power_on and power_off calls.
> 
> Probably the same goes for the regulator_enable in phy-core.c. That
> should be handled in the phy driver as phy-core is already unable
> to handle it properly. For example, for phy-twl4030-usb.c we have
> three regulators to deal with and the phy framework won't have any
> idea how to deal with those.

hmm.. It was modelled for basic PHY drivers that have a single regulator (e.g.,
TI PIPE3 PHY). The idea is not to duplicate getting and enabling regulator in
each of the PHY drivers when it can be abstracted in phy-core.

Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren Sept. 8, 2014, 4:34 p.m. UTC | #4
* Kishon Vijay Abraham I <kishon@ti.com> [140908 07:26]:
> Hi Tony,
> 
> On Thursday 04 September 2014 10:37 PM, Tony Lindgren wrote:
> > * Kishon Vijay Abraham I <kishon@ti.com> [140904 06:51]:
> >> Hi Tony,
> >>
> >> On Thursday 28 August 2014 04:58 AM, Tony Lindgren wrote:
> >>> We don't need twl4030_phy_power() any longer now that we have
> >>> the runtime PM calls. Let's get rid of it as it's confusing.
> >>> No functional changes, just move the code and use res instead
> >>> of ret as we are not returning that value.
> >>
> >> Now that you are doing pm_runtime_get_sync in twl4030_phy_init, won't it power
> >> on the phy even before initializing it (since runtime_resume will be invoked
> >> even before doing phy_init)?
> > 
> > Yes. The logic being that it should not matter as we are not
> > configuring the phy until in twl4030_phy_power_on(). Maybe we
> > should add code to make sure the phy is deconfigured initially
> > though :)
> > 
> > In twl4030_phy_init() we just want to check the ID pin state to get
> > things right initially. In the twl4030-usb case the I2C chip is
> > always on, but let's try to get the runtime PM set up like any
> > standard Linux driver would do it to avoid confusion.
> > 
> >> Even if pm_runtime_get_sync in not done in twl4030_phy_init, phy-core itself
> >> does pm_runtime_get_sync in phy_init().
> > 
> > Hmm OK. Looking at that, looks like we don't neeed any of these
> > custom exports though:
> > 
> > $ git grep phy_pm_runtime | grep EXPORT_SYMBOL
> > drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_get);
> > drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
> > drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_put);
> > drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync);
> > drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_allow);
> > drivers/phy/phy-core.c:EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid);
> > 
> > The reasons why I think we don't need the above at all is:
> > 
> > 1. We already have a framework for that in Linux runtime PM and we
> >    can follow the standard Linux runtime PM calls and not proxy
> >    them in phy-core.c
> 
> The reason for adding these are for providing fine grained control of the PHY
> by the controller drivers. In most cases the controller driver determines when
> the PHY should be active or idle.

Yeah but having the USB controller driver attempt to manage the
PHY did not work well. That all had to be ripped out of musb driver
in commits 30a70b026b4c and 8b2bc2c9351b.

I took a brief look at trying to fix musb + twl4030-usb runtime PM
so the USB controller driver would manage it. And that's probably
so far the only USB driver and PHY controller combo where we've had
runtime PM working in various forms in the mainline kernel.

Attempting to make the USB controller driver manage the runtime PM
for the PHY would make things unnecesarily complicated. The PHY can
sleep since it's on the I2C bus. So we'd have to implement some kind
of completion checking all over the place to attempt to keep things
in sync.

Meanwhile, having independent PHY drivers doing their own runtime
PM avoids all these issues. At minimum, it just means the PHY
driver needs to implement PHY init, power_on and power_off functions
like they already do. Then as needed, the PHY driver can implement
it's runtime PM calls.

I think what does make sense to do in the PHY framework is to keep
track of the PHY state in a generic way, and have a generic way of
telling the USB controller driver of the PHY state. That might allow
us eventually remove things like omap_musb_mailbox() calls.

And the custom exported functions above are unused AFAIK, so let's
just remove them.

> > 2. We can allow idling the phy properly on the bus it's connected
> >    to, in this case I2C, even if USB driver is not loaded. We
> >    eventually should idle the phy even if usb_add_phy_dev()
> >    failed
> 
> yes.. that's why we have ops like phy_power_on to tell when the PHY should be
> active. So these PHYs can be idled in probe.

Yeah phy_power_on et al are good, and needed. But the runtime PM
should be implemented in the actual PHY drivers because of the
reasons above.
 
> > 3. There's no actual need for phy-core.c to proxy the runtime
> >    PM calls
> > 
> > So we can and should just let the phy drivers do their own runtime PM
> > as needed based on just the phy init, power_on and power_off calls.
> > 
> > Probably the same goes for the regulator_enable in phy-core.c. That
> > should be handled in the phy driver as phy-core is already unable
> > to handle it properly. For example, for phy-twl4030-usb.c we have
> > three regulators to deal with and the phy framework won't have any
> > idea how to deal with those.
> 
> hmm.. It was modelled for basic PHY drivers that have a single regulator (e.g.,
> TI PIPE3 PHY). The idea is not to duplicate getting and enabling regulator in
> each of the PHY drivers when it can be abstracted in phy-core.

There's no need to for that AFAIK. That too can be implemented in the
PHY driver as part of runtime PM as needed.

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index a292db0..519cc90 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -383,45 +383,6 @@  static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
 	WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
 }
 
-static void twl4030_phy_power(struct twl4030_usb *twl, int on)
-{
-	int ret;
-
-	if (on) {
-		ret = regulator_enable(twl->usb3v1);
-		if (ret)
-			dev_err(twl->dev, "Failed to enable usb3v1\n");
-
-		ret = regulator_enable(twl->usb1v8);
-		if (ret)
-			dev_err(twl->dev, "Failed to enable usb1v8\n");
-
-		/*
-		 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
-		 * in twl4030) resets the VUSB_DEDICATED2 register. This reset
-		 * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
-		 * SLEEP. We work around this by clearing the bit after usv3v1
-		 * is re-activated. This ensures that VUSB3V1 is really active.
-		 */
-		twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
-
-		ret = regulator_enable(twl->usb1v5);
-		if (ret)
-			dev_err(twl->dev, "Failed to enable usb1v5\n");
-
-		__twl4030_phy_power(twl, 1);
-		twl4030_usb_write(twl, PHY_CLK_CTRL,
-				  twl4030_usb_read(twl, PHY_CLK_CTRL) |
-					(PHY_CLK_CTRL_CLOCKGATING_EN |
-						PHY_CLK_CTRL_CLK32K_EN));
-	} else {
-		__twl4030_phy_power(twl, 0);
-		regulator_disable(twl->usb1v5);
-		regulator_disable(twl->usb1v8);
-		regulator_disable(twl->usb3v1);
-	}
-}
-
 static int twl4030_usb_runtime_suspend(struct device *dev)
 {
 	struct twl4030_usb *twl = dev_get_drvdata(dev);
@@ -430,7 +391,10 @@  static int twl4030_usb_runtime_suspend(struct device *dev)
 	if (twl->asleep)
 		return 0;
 
-	twl4030_phy_power(twl, 0);
+	__twl4030_phy_power(twl, 0);
+	regulator_disable(twl->usb1v5);
+	regulator_disable(twl->usb1v8);
+	regulator_disable(twl->usb3v1);
 	twl->asleep = 1;
 
 	return 0;
@@ -439,12 +403,38 @@  static int twl4030_usb_runtime_suspend(struct device *dev)
 static int twl4030_usb_runtime_resume(struct device *dev)
 {
 	struct twl4030_usb *twl = dev_get_drvdata(dev);
+	int res;
 
 	dev_dbg(twl->dev, "%s\n", __func__);
 	if (!twl->asleep)
 		return 0;
 
-	twl4030_phy_power(twl, 1);
+	res = regulator_enable(twl->usb3v1);
+	if (res)
+		dev_err(twl->dev, "Failed to enable usb3v1\n");
+
+	res = regulator_enable(twl->usb1v8);
+	if (res)
+		dev_err(twl->dev, "Failed to enable usb1v8\n");
+
+	/*
+	 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
+	 * in twl4030) resets the VUSB_DEDICATED2 register. This reset
+	 * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
+	 * SLEEP. We work around this by clearing the bit after usv3v1
+	 * is re-activated. This ensures that VUSB3V1 is really active.
+	 */
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
+
+	res = regulator_enable(twl->usb1v5);
+	if (res)
+		dev_err(twl->dev, "Failed to enable usb1v5\n");
+
+	__twl4030_phy_power(twl, 1);
+	twl4030_usb_write(twl, PHY_CLK_CTRL,
+			  twl4030_usb_read(twl, PHY_CLK_CTRL) |
+			  (PHY_CLK_CTRL_CLOCKGATING_EN |
+			   PHY_CLK_CTRL_CLK32K_EN));
 	twl->asleep = 0;
 
 	return 0;