On Thu, Apr 17, 2014 at 04:40:06PM +0800, Peter Chen wrote:
> After the PHY has powered and initialized, it needs some delay
> for controller to reflect PHY's status. Some status and values
> for id, vbus, dp/dm are only stable after this delay. The current
> code tries to clear id/vbus status without enough delay, it
> causes the status are not cleared properly.
> 
> This patch add 2ms delay after phy has initialized, and clear the
> unexpected status after that.
> 
> Signed-off-by: Peter Chen <peter.c...@freescale.com>
> ---
>  drivers/usb/chipidea/core.c |   26 +++++++++++++-------------
>  1 files changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> index ff38cf3..d506f34 100644
> --- a/drivers/usb/chipidea/core.c
> +++ b/drivers/usb/chipidea/core.c
> @@ -199,11 +199,10 @@ static void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool 
> enable)
>               hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm),
>                               0);
>               /* 
> -              * The controller needs at least 1ms to reflect
> -              * PHY's status, the PHY also needs some time (less
> +              * the PHY needs some time (less
>                * than 1ms) to leave low power mode.
>                */
> -             usleep_range(1500, 2000);
> +             usleep_range(1000, 1100);
>       }
>  }
>  
> @@ -555,12 +554,8 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
>               ci->is_otg = (hw_read(ci, CAP_DCCPARAMS,
>                               DCCPARAMS_DC | DCCPARAMS_HC)
>                                       == (DCCPARAMS_DC | DCCPARAMS_HC));
> -     if (ci->is_otg) {
> +     if (ci->is_otg)
>               dev_dbg(ci->dev, "It is OTG capable controller\n");
> -             /* Disable and clear all OTG irq */
> -             hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
> -                                                     OTGSC_INT_STATUS_BITS);
> -     }
>  }
>  
>  static int ci_hdrc_probe(struct platform_device *pdev)
> @@ -622,6 +617,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
>       if (ret) {
>               dev_err(dev, "unable to init phy: %d\n", ret);
>               return ret;
> +     } else {
> +             /* 
> +              * The delay to sync PHY's status, the maximum delay is
> +              * 2ms since the otgsc uses 1ms timer to debounce the
> +              * PHY's input
> +              */
> +             usleep_range(2000, 2500);
>       }
>  
>       ci->hw_bank.phys = res->start;
> @@ -656,6 +658,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
>       }
>  
>       if (ci->is_otg) {
> +             /* Disable and clear all OTG irq */
> +             hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
> +                                                     OTGSC_INT_STATUS_BITS);
>               ret = ci_hdrc_otg_init(ci);
>               if (ret) {
>                       dev_err(dev, "init otg fails, ret = %d\n", ret);
> @@ -665,11 +670,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
>  
>       if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
>               if (ci->is_otg) {
> -                     /*
> -                      * ID pin needs 1ms debouce time,
> -                      * we delay 2ms for safe.
> -                      */
> -                     mdelay(2);
>                       ci->role = ci_otg_role(ci);
>                       /* Enable ID change irq */
>                       hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
> -- 
> 1.7.8
> 
> 

Tested on i.MX6SL EVK HW, works as expectation.

Li Jun

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

Reply via email to