Re: [PATCH 6/8 v2] usb: musb: Offmode fix for idle path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hema HK <hemahk@xxxxxx> 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.

> Signed-off-by: Hema HK <hemahk@xxxxxx>
> Signed-off-by: Maulik Mankad <x0082077@xxxxxx>
>
> Cc: Felipe Balbi <felipe.balbi@xxxxxxxxx>
> Cc: Tony Lindgren <tony@xxxxxxxxxxx>
> Cc: Kevin Hilman <khilman@xxxxxxxxxxxxxxxxxxx>
> Cc: Cousson, Benoit <b-cousson@xxxxxx>
> Cc: Paul Walmsley <paul@xxxxxxxxx>
> ---
>  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.

Second, I'm thoroughly confused about why you are simulating a system
suspend/resume here? 

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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux