public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
From: Felipe Balbi <me@felipebalbi.com>
To: tom.leiming@gmail.com
Cc: greg@kroah.com, linux-usb@vger.kernel.org,
	linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
	David Brownell <dbrownell@users.sourceforge.net>,
	Felipe Balbi <felipe.balbi@nokia.com>,
	Anand Gadiyar <gadiyar@ti.com>,
	Mike Frysinger <vapier@gentoo.org>,
	Sergei Shtylyov <sshtylyov@ru.mvista.com>
Subject: Re: [PATCH] USB: otg: twl4030: fix phy initialization
Date: Thu, 02 Sep 2010 13:28:39 -0500	[thread overview]
Message-ID: <ee6a42fe148f72518d475ff3838fc32a@secure211.sgcpanel.com> (raw)
In-Reply-To: <1283443098-15262-1-git-send-email-tom.leiming@gmail.com>

Hi,

On Thu,  2 Sep 2010 23:58:18 +0800, tom.leiming@gmail.com wrote:
> From: Ming Lei <tom.leiming@gmail.com>
> 
> Commit 461c317705eca5cac09a360f488715927fd0a927(into 2.6.36-v3)
> is put forward to power down phy if no usb cable is connected,
> but does introduce the two issues below:
> 
> 1), phy is not into work state if usb cable is connected
> with PC during poweron, so musb device mode is not usable
> in such case, follows the reasons:

I'm pretty sure I verified both cases.

> 	-twl4030_phy_resume is not called, so
> 		regulators are not enabled
> 		i2c access are not enabled
> 		usb mode not configurated
> 
> 2), The kernel warings[1] of regulators 'unbalanced disables'
> is caused if poweron without usb cable connected
> with PC or b-device.
> 
> This patch fixes the two issues above:
> 	-power down phy only if no usb cable is connected with PC
> and b-device
> 	-do phy initialization(via __twl4030_phy_resume) if usb cable
> is connected with PC(vbus event) or another b-device(ID event) in
> twl4030_usb_probe.
> 
> This patch is verified OK on Beagle board either connected with
> usb cable or not when poweron.

I kinda doubt it, would have to test it myself, but I'm without
enough gear to test it again.

> [1]. warnings of 'unbalanced disables' of regulators.
> [root@OMAP3EVM /]# dmesg
> ------------[ cut here ]------------
> WARNING: at drivers/regulator/core.c:1357
_regulator_disable+0x38/0x128()

this should not have been caused by that patch, though.


> Cc: Felipe Balbi <felipe.balbi@nokia.com>

this email doesn't exist anymore... I'm yet to subscribe the new one,
for now keep this one in Cc, sorry for that.

> diff --git a/drivers/usb/otg/twl4030-usb.c
b/drivers/usb/otg/twl4030-usb.c
> index 05aaac1..df6381f 100644
> --- a/drivers/usb/otg/twl4030-usb.c
> +++ b/drivers/usb/otg/twl4030-usb.c
> @@ -347,11 +347,22 @@ static void twl4030_i2c_access(struct twl4030_usb
> *twl, int on)
>  	}
>  }
>  
> -static void twl4030_phy_power(struct twl4030_usb *twl, int on)
> +static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
>  {
> +	u8 old_pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
>  	u8 pwr;
>  
> -	pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
> +	if (on)
> +		pwr = old_pwr & ~PHY_PWR_PHYPWD;
> +	else
> +		pwr = old_pwr | PHY_PWR_PHYPWD;
> +
> +	if (pwr != old_pwr)
> +		WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);

writing 1 if register is one won't cause any problems, you're just
wasting a variable.

> +static void twl4030_phy_power(struct twl4030_usb *twl, int on)
> +{
>  	if (on) {
>  		regulator_enable(twl->usb3v1);
>  		regulator_enable(twl->usb1v8);
> @@ -365,15 +376,13 @@ static void twl4030_phy_power(struct twl4030_usb
> *twl, int on)
>  		twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
>  							VUSB_DEDICATED2);
>  		regulator_enable(twl->usb1v5);
> -		pwr &= ~PHY_PWR_PHYPWD;
> -		WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
> +		__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  {
> -		pwr |= PHY_PWR_PHYPWD;
> -		WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
> +		__twl4030_phy_power(twl, 0);
>  		regulator_disable(twl->usb1v5);
>  		regulator_disable(twl->usb1v8);
>  		regulator_disable(twl->usb3v1);
> @@ -387,19 +396,25 @@ static void twl4030_phy_suspend(struct twl4030_usb
> *twl, int controller_off)
>  
>  	twl4030_phy_power(twl, 0);
>  	twl->asleep = 1;
> +	dev_dbg(twl->dev, "%s\n", __func__);

this is noise.

>  }
>  
> -static void twl4030_phy_resume(struct twl4030_usb *twl)
> +static void __twl4030_phy_resume(struct twl4030_usb *twl)
>  {
> -	if (!twl->asleep)
> -		return;
> -
>  	twl4030_phy_power(twl, 1);
>  	twl4030_i2c_access(twl, 1);
>  	twl4030_usb_set_mode(twl, twl->usb_mode);
>  	if (twl->usb_mode == T2_USB_MODE_ULPI)
>  		twl4030_i2c_access(twl, 0);
> +}
> +
> +static void twl4030_phy_resume(struct twl4030_usb *twl)
> +{
> +	if (!twl->asleep)
> +		return;
> +	__twl4030_phy_resume(twl);
>  	twl->asleep = 0;
> +	dev_dbg(twl->dev, "%s\n", __func__);

this is noise.

> @@ -502,6 +517,26 @@ static irqreturn_t twl4030_usb_irq(int irq, void
> *_twl)
>  	return IRQ_HANDLED;
>  }
>  
> +static void twl4030_usb_phy_init(struct twl4030_usb *twl)
> +{
> +	int status;
> +
> +	status = twl4030_usb_linkstat(twl);
> +	if (status >= 0) {
> +		if (status == USB_EVENT_NONE) {
> +			__twl4030_phy_power(twl, 0);
> +			twl->asleep = 1;
> +		} else {
> +			__twl4030_phy_resume(twl);

this might break people who are using charger detection, although I
would have to revisit some code to be sure.

> +			twl->asleep = 0;
> +		}
> +
> +		blocking_notifier_call_chain(&twl->otg.notifier, status,
> +				twl->otg.gadget);
> +	}
> +	sysfs_notify(&twl->dev->kobj, NULL, "vbus");

thís should only be called from IRQ handler and is duplicating
code.

> @@ -550,7 +585,6 @@ static int __devinit twl4030_usb_probe(struct
> platform_device *pdev)
>  	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
>  	struct twl4030_usb	*twl;
>  	int			status, err;
> -	u8			pwr;
>  
>  	if (!pdata) {
>  		dev_dbg(&pdev->dev, "platform_data not available\n");
> @@ -569,10 +603,7 @@ static int __devinit twl4030_usb_probe(struct
> platform_device *pdev)
>  	twl->otg.set_peripheral	= twl4030_set_peripheral;
>  	twl->otg.set_suspend	= twl4030_set_suspend;
>  	twl->usb_mode		= pdata->usb_mode;
> -
> -	pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
> -
> -	twl->asleep		= (pwr & PHY_PWR_PHYPWD);
> +	twl->asleep = 1;

and now you're lying to the driver again. What happens if
bootloader has put transceiver to sleep ??

> @@ -610,15 +641,10 @@ static int __devinit twl4030_usb_probe(struct
> platform_device *pdev)
>  		return status;
>  	}
>  
> -	/* The IRQ handler just handles changes from the previous states
> -	 * of the ID and VBUS pins ... in probe() we must initialize that
> -	 * previous state.  The easy way:  fake an IRQ.
> -	 *
> -	 * REVISIT:  a real IRQ might have happened already, if PREEMPT is
> -	 * enabled.  Else the IRQ may not yet be configured or enabled,
> -	 * because of scheduling delays.
> +	/* Power down phy or make it work according to
> +	 * current link state.

if you're changing the comment you might as well fix the comment style.

>  	 */
> -	twl4030_usb_irq(twl->irq, twl);
> +	twl4030_usb_phy_init(twl);

now I see, this doesn't care about that flag, so why even setting
it above ??

-- 
balbi

  reply	other threads:[~2010-09-02 18:28 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-02 15:58 [PATCH] USB: otg: twl4030: fix phy initialization tom.leiming
2010-09-02 18:28 ` Felipe Balbi [this message]
2010-09-03  0:43   ` Ming Lei
     [not found]     ` <AANLkTimts7SjE9EKrmsSkynWsQc_VtJUVVigrFs2VtrK-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-09-04 15:36       ` Ming Lei
2010-09-04 21:24         ` Felipe Balbi
     [not found]           ` <1fb6fc37cd0f017043d5c124bca4bb1a-WEDJutINlwSqfKURHDCIgFDQ4js95KgL@public.gmane.org>
2010-09-05  6:42             ` Ming Lei
     [not found]               ` <AANLkTi=4J5u4SEh5jSPxObceWdAom51R+H_j8oApG5PG-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-09-05  9:51                 ` Felipe Balbi
2010-09-05 16:00                   ` Ming Lei

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ee6a42fe148f72518d475ff3838fc32a@secure211.sgcpanel.com \
    --to=me@felipebalbi.com \
    --cc=dbrownell@users.sourceforge.net \
    --cc=felipe.balbi@nokia.com \
    --cc=gadiyar@ti.com \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=sshtylyov@ru.mvista.com \
    --cc=tom.leiming@gmail.com \
    --cc=vapier@gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox