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-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html