Hi, 

>-----Original Message-----
>From: Kevin Hilman [mailto:[email protected]] 
>Sent: Tuesday, August 31, 2010 8:49 PM
>To: Kalliguddi, Hema
>Cc: [email protected]; [email protected]; 
>Mankad, Maulik Ojas; Felipe Balbi; Tony Lindgren; Cousson, 
>Benoit; Paul Walmsley
>Subject: Re: [PATCH 6/8 v2] usb: musb: Offmode fix for idle path
>
>"Kalliguddi, Hema" <[email protected]> writes:
>
>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:[email protected]] 
>>>Sent: Thursday, August 26, 2010 5:40 AM
>>>To: Kalliguddi, Hema
>>>Cc: [email protected]; [email protected]; 
>>>Mankad, Maulik Ojas; Felipe Balbi; Tony Lindgren; Cousson, 
>>>Benoit; Paul Walmsley
>>>Subject: Re: [PATCH 6/8 v2] usb: musb: Offmode fix for idle path
>>>
>>>Hema HK <[email protected]> writes:
>>>
>>>> With OMAP core-off support musb was not functional as 
>>>context was getting
>>>> lost after wakeup from core-off. And also musb was blocking 
>>>the core-off
>>>> after loading the gadget driver even with no cable connected 
>>>sometimes.
>>>>
>>>> Added the conext save/restore api in the platform layer which will
>>>> be called in the idle and wakeup path.
>>>>
>>>> Changed the usb sysconfig settings as per the usbotg 
>functional spec.
>>>> When the device is not used, configure to force idle and 
>>>force standby mode.
>>>> When it is being used, configure in smart standby and smart 
>>>idle mode.
>>>> So while attempting to coreoff the usb is configured to 
>>>force standby and
>>>> force idle mode, after wakeup configured in smart idle and 
>>>smart standby.
>>>
>>>You don't describe the new .clk_autogated field added here.  
>That part
>>>should be a separate patch as it's not directly related to 
>>>$SUBJECT patch.
>>>
>>
>> In OMAP for USB there is no need to disable the interface 
>clock. But for the other 
>> platforms like davinci which uses mentor USB IP clock is not 
>auto gated so 
>> There is a need to disbale the clock when .suspend API 
>defined in the driver is called. 
>> So introduced a flag in the platform to enable/disable the clock
>> In .supend and .resume APIs appropriately in the driver code.
>
>Yes, I understand why it's there, and just suggested that it should be
>documented and done as a separate patch.
>
>> Yes. It may not be directly related to $SUBJECT patch, but I 
>am reusing  
>> .suspend and .resume APIs for context save and restore 
>during idle path. 
>> Because of that this fix as part of the patch.
>>
>>>> Signed-off-by: Hema HK <[email protected]>
>>>> Signed-off-by: Maulik Mankad <[email protected]>
>>>>
>>>> Cc: Felipe Balbi <[email protected]>
>>>> Cc: Tony Lindgren <[email protected]>
>>>> Cc: Kevin Hilman <[email protected]>
>>>> Cc: Cousson, Benoit <[email protected]>
>>>> Cc: Paul Walmsley <[email protected]>
>>>> ---
>>>>  arch/arm/mach-omap2/pm34xx.c          |    5 +++
>>>>  arch/arm/mach-omap2/usb-musb.c        |   42 
>>>++++++++++++++++++++++++++++-
>>>>  arch/arm/plat-omap/include/plat/usb.h |    2 +
>>>>  drivers/usb/musb/musb_core.c          |   10 +++----
>>>>  drivers/usb/musb/musb_core.h          |    1 -
>>>>  drivers/usb/musb/omap2430.c           |   48 
>>>++++++++++++++++++++++++++++++---
>>>>  include/linux/usb/musb.h              |    6 ++++
>>>>  7 files changed, 102 insertions(+), 12 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-omap2/pm34xx.c 
>>>b/arch/arm/mach-omap2/pm34xx.c
>>>> index fb4994a..7b34201 100644
>>>> --- a/arch/arm/mach-omap2/pm34xx.c
>>>> +++ b/arch/arm/mach-omap2/pm34xx.c
>>>> @@ -39,6 +39,7 @@
>>>>  #include <plat/gpmc.h>
>>>>  #include <plat/dma.h>
>>>>  #include <plat/dmtimer.h>
>>>> +#include <plat/usb.h>
>>>>  
>>>>  #include <asm/tlbflush.h>
>>>>  
>>>> @@ -416,6 +417,8 @@ void omap_sram_idle(void)
>>>>            if (core_next_state == PWRDM_POWER_OFF) {
>>>>                    omap3_core_save_context();
>>>>                    omap3_prcm_save_context();
>>>> +                  /* Save MUSB context */
>>>> +                  musb_context_save_restore(1);
>>>>            }
>>>>    }
>>>>  
>>>> @@ -458,6 +461,8 @@ void omap_sram_idle(void)
>>>>                    omap3_prcm_restore_context();
>>>>                    omap3_sram_restore_context();
>>>>                    omap2_sms_restore_context();
>>>> +                  /* restore MUSB context */
>>>> +                  musb_context_save_restore(0);
>>>>            }
>>>>            omap_uart_resume_idle(0);
>>>>            omap_uart_resume_idle(1);
>>>> diff --git a/arch/arm/mach-omap2/usb-musb.c 
>>>b/arch/arm/mach-omap2/usb-musb.c
>>>> index c228cc0..9d10440 100644
>>>> --- a/arch/arm/mach-omap2/usb-musb.c
>>>> +++ b/arch/arm/mach-omap2/usb-musb.c
>>>> @@ -35,6 +35,7 @@
>>>>  
>>>>  static const char name[] = "musb_hdrc";
>>>>  #define MAX_OMAP_MUSB_HWMOD_NAME_LEN      16
>>>> +struct omap_hwmod *oh_p =NULL;
>>>>  
>>>>  static struct musb_hdrc_config musb_config = {
>>>>    .multipoint     = 1,
>>>> @@ -59,6 +60,9 @@ static struct musb_hdrc_platform_data 
>musb_plat = {
>>>>     * "mode", and should be passed to usb_musb_init().
>>>>     */
>>>>    .power          = 50,                   /* up to 100 mA */
>>>> +
>>>> +  /* supports clock autogating */
>>>> +  .clk_autogated  = 1,
>>>
>>>This appears unrelated, and should be a separate patch.
>>>
>>>>  };
>>>>  
>>>>  static u64 musb_dmamask = DMA_BIT_MASK(32);
>>>> @@ -97,7 +101,7 @@ void __init usb_musb_init(struct 
>>>omap_musb_board_data *board_data)
>>>>    musb_plat.mode = board_data->mode;
>>>>    musb_plat.extvbus = board_data->extvbus;
>>>>    pdata = &musb_plat;
>>>> -
>>>> +  oh_p = oh;
>>>>    od = omap_device_build(name, bus_id, oh, pdata,
>>>>                           sizeof(struct musb_hdrc_platform_data),
>>>>                                            omap_musb_latency,
>>>> @@ -116,8 +120,44 @@ void __init usb_musb_init(struct 
>>>omap_musb_board_data *board_data)
>>>>  
>>>>  }
>>>>  
>>>> +void musb_context_save_restore(int save)
>>>> +{
>>>> +  struct omap_hwmod *oh = oh_p;
>>>> +  struct omap_device *od;
>>>> +  struct platform_device *pdev;
>>>> +  struct device *dev;
>>>> +  struct device_driver *drv;
>>>> +  struct musb_hdrc_platform_data *pdata;
>>>> +  const struct dev_pm_ops *pm;
>>>> +
>>>> +  if (!oh)
>>>> +          return;
>>>> +  od = oh->od;
>>>> +  pdev = &od->pdev;
>>>> +  if (!pdev)
>>>> +          return;
>>>> +  dev = &pdev->dev;
>>>> +  drv = dev->driver;
>>>> +
>>>> +  if (drv) {
>>>> +          pdata = dev->platform_data;
>>>> +          pm = drv->pm;
>>>> +
>>>> +          if (!pdata->is_usb_active(dev)) {
>>>> +
>>>> +                  if (save)
>>>> +                          pm->suspend(dev);
>>>> +                  else
>>>> +                          pm->resume_noirq(dev);
>>>
>>>-ECONFUSED
>>>
>>>First, this 'save_restore' function neither saves or 
>restores anything.
>>>
>>
>> There are musb_save/restore APIs defined in the driver code 
>and called in a system suspend/resume APIs.
>> I am just making use of these apis in the idle path aswell.
>
>Please don't.  This is not and intended use of the driver model hooks.
>
I am using this hooks because the save/restore API is not a exported API 
And it needs a musb structure parameter which will not be available in the 
platform layer.
Once I move o runtime PM api usage and use the runtime suspend/resume APIs need 
not use these
hooks. But for this patch we will have live with these hooks.

>Instead, we need to move the musb idle management out of the
>interrupts-disabled section of the idle loop and use the 
>runtime PM APIs
>as intended.

As part of the runtime PM patch I will take care of this.
>
>Kevin
>
>>>Second, I'm thoroughly confused about why you are simulating a system
>>>suspend/resume here? 
>>
>> As said, instead of exporting the internal save/restore 
>APIs, I am making use of the pm_ops function pointers
>> To do the same job.
>>
>>>
>>>Kevin
>>>
>>>> +          }
>>>> +  }
>>>> +}
>>>> +
>>>>  #else
>>>>  void __init usb_musb_init(struct omap_musb_board_data *board_data)
>>>>  {
>>>>  }
>>>> +void musb_context_save_restore(int save)
>>>> +{
>>>> +}
>>>>  #endif /* CONFIG_USB_MUSB_SOC */
>>>> diff --git a/arch/arm/plat-omap/include/plat/usb.h 
>>>b/arch/arm/plat-omap/include/plat/usb.h
>>>> index 2a9427c..ed2b41a 100644
>>>> --- a/arch/arm/plat-omap/include/plat/usb.h
>>>> +++ b/arch/arm/plat-omap/include/plat/usb.h
>>>> @@ -79,6 +79,8 @@ extern void usb_ehci_init(const struct 
>>>ehci_hcd_omap_platform_data *pdata);
>>>>  
>>>>  extern void usb_ohci_init(const struct 
>>>ohci_hcd_omap_platform_data *pdata);
>>>>  
>>>> +/* For saving and restoring the musb context during off/wakeup*/
>>>> +extern void musb_context_save_restore(int save);
>>>>  #endif
>>>>  
>>>>  
>>>> diff --git a/drivers/usb/musb/musb_core.c 
>>>b/drivers/usb/musb/musb_core.c
>>>> index 2a50d12..8510e55 100644
>>>> --- a/drivers/usb/musb/musb_core.c
>>>> +++ b/drivers/usb/musb/musb_core.c
>>>> @@ -2410,6 +2410,7 @@ static int musb_suspend(struct device *dev)
>>>>    struct platform_device *pdev = to_platform_device(dev);
>>>>    unsigned long   flags;
>>>>    struct musb     *musb = dev_to_musb(&pdev->dev);
>>>> +  struct musb_hdrc_platform_data *plat = dev->platform_data;
>>>>  
>>>>    if (!musb->clock)
>>>>            return 0;
>>>> @@ -2428,9 +2429,7 @@ static int musb_suspend(struct device *dev)
>>>>  
>>>>    musb_save_context(musb);
>>>>  
>>>> -  if (musb->set_clock)
>>>> -          musb->set_clock(musb->clock, 0);
>>>> -  else
>>>> +  if (!plat->clk_autogated)
>>>>            clk_disable(musb->clock);
>>>>    spin_unlock_irqrestore(&musb->lock, flags);
>>>>    return 0;
>>>> @@ -2440,13 +2439,12 @@ static int musb_resume_noirq(struct 
>>>device *dev)
>>>>  {
>>>>    struct platform_device *pdev = to_platform_device(dev);
>>>>    struct musb     *musb = dev_to_musb(&pdev->dev);
>>>> +  struct musb_hdrc_platform_data *plat = dev->platform_data;
>>>>  
>>>>    if (!musb->clock)
>>>>            return 0;
>>>>  
>>>> -  if (musb->set_clock)
>>>> -          musb->set_clock(musb->clock, 1);
>>>> -  else
>>>> +  if (!plat->clk_autogated)
>>>>            clk_enable(musb->clock);
>>>>  
>>>>    musb_restore_context(musb);
>>>> diff --git a/drivers/usb/musb/musb_core.h 
>>>b/drivers/usb/musb/musb_core.h
>>>> index 85a92fd..bfdf54d 100644
>>>> --- a/drivers/usb/musb/musb_core.h
>>>> +++ b/drivers/usb/musb/musb_core.h
>>>> @@ -472,7 +472,6 @@ struct musb_context_registers {
>>>>  
>>>>  #if defined(CONFIG_ARCH_OMAP2430) || 
>defined(CONFIG_ARCH_OMAP3) || \
>>>>      defined(CONFIG_ARCH_OMAP4)
>>>> -  u32 otg_sysconfig, otg_forcestandby;
>>>>  #endif
>>>>    u8 power;
>>>>    u16 intrtxe, intrrxe;
>>>> diff --git a/drivers/usb/musb/omap2430.c 
>>>b/drivers/usb/musb/omap2430.c
>>>> index 3bae428..dcba935 100644
>>>> --- a/drivers/usb/musb/omap2430.c
>>>> +++ b/drivers/usb/musb/omap2430.c
>>>> @@ -188,6 +188,18 @@ int musb_platform_set_mode(struct musb 
>>>*musb, u8 musb_mode)
>>>>  
>>>>    return 0;
>>>>  }
>>>> +int is_musb_active(struct device *dev)
>>>> +{
>>>> +  struct musb *musb;
>>>> +
>>>> +#ifdef CONFIG_USB_MUSB_HDRC_HCD
>>>> +  /* usbcore insists dev->driver_data is a "struct hcd *" */
>>>> +  musb = hcd_to_musb(dev_get_drvdata(dev));
>>>> +#else
>>>> +  musb = dev_get_drvdata(dev);
>>>> +#endif
>>>> +  return musb->is_active;
>>>> +}
>>>>  
>>>>  int __init musb_platform_init(struct musb *musb)
>>>>  {
>>>> @@ -246,6 +258,7 @@ int __init musb_platform_init(struct 
>musb *musb)
>>>>    if (is_host_enabled(musb))
>>>>            musb->board_set_vbus = omap_set_vbus;
>>>>  
>>>> +  plat->is_usb_active = is_musb_active;
>>>>    setup_timer(&musb_idle_timer, musb_do_idle, (unsigned 
>>>long) musb);
>>>>  
>>>>    return 0;
>>>> @@ -255,15 +268,42 @@ int __init musb_platform_init(struct 
>>>musb *musb)
>>>>  void musb_platform_save_context(struct musb *musb,
>>>>            struct musb_context_registers *musb_context)
>>>>  {
>>>> -  musb_context->otg_sysconfig = musb_readl(musb->mregs, 
>>>OTG_SYSCONFIG);
>>>> -  musb_context->otg_forcestandby = 
>>>musb_readl(musb->mregs, OTG_FORCESTDBY);
>>>> +  /*
>>>> +   * As per the omap-usbotg specification, configure it 
>>>to forced standby
>>>> +   * and  force idle mode when no activity on usb.
>>>> +   */
>>>> +  void __iomem *musb_base = musb->mregs;
>>>> +
>>>> +  musb_writel(musb_base, OTG_FORCESTDBY, 0);
>>>> +
>>>> +  musb_writel(musb_base, OTG_SYSCONFIG, musb_readl(musb_base,
>>>> +                          OTG_SYSCONFIG) & ~(NOSTDBY | 
>>>SMARTSTDBY));
>>>> +
>>>> +  musb_writel(musb_base, OTG_SYSCONFIG, musb_readl(musb_base,
>>>> +                                  OTG_SYSCONFIG) & ~AUTOIDLE);
>>>> +
>>>> +  musb_writel(musb_base, OTG_SYSCONFIG, musb_readl(musb_base,
>>>> +                          OTG_SYSCONFIG) & ~(NOIDLE | SMARTIDLE));
>>>> +
>>>> +  musb_writel(musb_base, OTG_FORCESTDBY, 1);
>>>>  }
>>>>  
>>>>  void musb_platform_restore_context(struct musb *musb,
>>>>            struct musb_context_registers *musb_context)
>>>>  {
>>>> -  musb_writel(musb->mregs, OTG_SYSCONFIG, 
>>>musb_context->otg_sysconfig);
>>>> -  musb_writel(musb->mregs, OTG_FORCESTDBY, 
>>>musb_context->otg_forcestandby);
>>>> +  /*
>>>> +   * As per the omap-usbotg specification, configure it 
>>>smart standby
>>>> +   * and smart idle during operation.
>>>> +   */
>>>> +  void __iomem *musb_base = musb->mregs;
>>>> +
>>>> +  musb_writel(musb_base, OTG_FORCESTDBY, 0);
>>>> +
>>>> +  musb_writel(musb_base, OTG_SYSCONFIG, musb_readl(musb_base,
>>>> +                          OTG_SYSCONFIG) | SMARTSTDBY);
>>>> +
>>>> +  musb_writel(musb_base, OTG_SYSCONFIG, musb_readl(musb_base,
>>>> +                          OTG_SYSCONFIG) | SMARTIDLE | 
>>>ENABLEWAKEUP);
>>>>  }
>>>>  #endif
>>>>  
>>>> diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
>>>> index ee2dd1d..da134ab 100644
>>>> --- a/include/linux/usb/musb.h
>>>> +++ b/include/linux/usb/musb.h
>>>> @@ -126,6 +126,12 @@ struct musb_hdrc_platform_data {
>>>>  
>>>>    /* Architecture specific board data     */
>>>>    void            *board_data;
>>>> +
>>>> +  /* check usb device active state*/
>>>> +  int             (*is_usb_active)(struct device *dev);
>>>> +
>>>> +  /*  indiates whether clock is autogated */
>>>> +  int             clk_autogated;
>>>>  };
>>>
>--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to