From patchwork Fri Aug 6 17:29:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kalliguddi, Hema" X-Patchwork-Id: 117877 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o76HTOok004533 for ; Fri, 6 Aug 2010 17:29:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761633Ab0HFR3S (ORCPT ); Fri, 6 Aug 2010 13:29:18 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:60558 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751713Ab0HFR3R (ORCPT ); Fri, 6 Aug 2010 13:29:17 -0400 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id o76HTBl4010488 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 6 Aug 2010 12:29:13 -0500 Received: from linfarm476.india.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id o76HTAwG009486; Fri, 6 Aug 2010 22:59:10 +0530 (IST) Received: from linfarm476.india.ti.com (localhost [127.0.0.1]) by linfarm476.india.ti.com (8.12.11/8.12.11) with ESMTP id o76HT9RL001727; Fri, 6 Aug 2010 22:59:09 +0530 Received: (from a0876481@localhost) by linfarm476.india.ti.com (8.12.11/8.12.11/Submit) id o76HT9gE001725; Fri, 6 Aug 2010 22:59:09 +0530 From: Hema HK To: linux-usb@vger.kernel.org, linux-omap@vger.kernel.org Cc: Hema HK , "Basak, Partha" , Felipe Balbi , Tony Lindgren , Kevin Hilman Subject: [PATCH 8/8 ]usb : musb:Using runtime pm apis for musb. Date: Fri, 6 Aug 2010 22:59:09 +0530 Message-Id: <1281115749-1601-1-git-send-email-hemahk@ti.com> X-Mailer: git-send-email 1.5.6.6 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 06 Aug 2010 17:29:25 +0000 (UTC) Index: linux-omap-pm/arch/arm/mach-omap2/pm34xx.c =================================================================== --- linux-omap-pm.orig/arch/arm/mach-omap2/pm34xx.c 2010-08-06 10:44:06.000000000 -0400 +++ linux-omap-pm/arch/arm/mach-omap2/pm34xx.c 2010-08-06 10:44:42.942112875 -0400 @@ -418,7 +418,9 @@ omap3_core_save_context(); omap3_prcm_save_context(); /* Save MUSB context */ - musb_context_save_restore(1); + musb_context_save_restore(save_context); + } else { + musb_context_save_restore(disable_clk); } } @@ -462,8 +464,10 @@ omap3_sram_restore_context(); omap2_sms_restore_context(); /* restore MUSB context */ - musb_context_save_restore(0); - } + musb_context_save_restore(restore_context); + } else { + musb_context_save_restore(enable_clk); + } omap_uart_resume_idle(0); omap_uart_resume_idle(1); if (core_next_state == PWRDM_POWER_OFF) Index: linux-omap-pm/arch/arm/mach-omap2/usb-musb.c =================================================================== --- linux-omap-pm.orig/arch/arm/mach-omap2/usb-musb.c 2010-08-06 10:44:06.000000000 -0400 +++ linux-omap-pm/arch/arm/mach-omap2/usb-musb.c 2010-08-06 10:44:42.942112875 -0400 @@ -25,11 +25,13 @@ #include #include +#include #include #include #include #include +#include #ifdef CONFIG_USB_MUSB_SOC @@ -99,6 +101,18 @@ musb_plat.board_data = board_data; musb_plat.power = board_data->power >> 1; musb_plat.mode = board_data->mode; + musb_plat.device_enable = omap_device_enable; + musb_plat.device_idle = omap_device_idle; + musb_plat.enable_wakeup = omap_device_enable_wakeup; + musb_plat.disable_wakeup = omap_device_disable_wakeup; + /* + * Errata 1.166 idle_req/ack is broken in omap3430 + * workaround is to disable the autodile bit for omap3430. + */ + if (cpu_is_omap3430()) + oh->flags |= HWMOD_NO_OCP_AUTOIDLE; + + musb_plat.oh = oh; pdata = &musb_plat; od = omap_device_build(name, bus_id, oh, pdata, @@ -120,7 +134,7 @@ } } -void musb_context_save_restore(int save) +void musb_context_save_restore(enum musb_state state) { struct omap_hwmod *oh = omap_hwmod_lookup("usb_otg_hs"); struct omap_device *od = oh->od; @@ -129,14 +143,64 @@ struct device_driver *drv = dev->driver; if (drv) { +#ifdef CONFIG_PM_RUNTIME struct musb_hdrc_platform_data *pdata = dev->platform_data; const struct dev_pm_ops *pm = drv->pm; - if (!pdata->is_usb_active(dev)) { - if (save) + if (!pdata->is_usb_active(dev)) { + switch (state) { + case save_context: + /* If the usb device not active then Save + * the context,set the sysconfig setting to + * force standby force idle during idle and + * disable the clock. + */ + oh->flags |= HWMOD_SWSUP_SIDLE + | HWMOD_SWSUP_MSTANDBY; pm->suspend(dev); - else + pdata->device_idle(pdev); + + break; + case disable_clk: + /* If the usb device not active then + * Save the context, set the sysconfig setting + * to force standby force idle during idle and + * disable the clock. + */ + + oh->flags |= HWMOD_SWSUP_SIDLE + | HWMOD_SWSUP_MSTANDBY; + pdata->device_idle(pdev); + + break; + + case restore_context: + /* Enable the clock, set the sysconfig + * back to smart idle and smart stndby after + * wakeup. restore the context. + */ + oh->flags &= ~(HWMOD_SWSUP_SIDLE + | HWMOD_SWSUP_MSTANDBY); + pdata->device_enable(pdev); pm->resume_noirq(dev); + + break; + + case enable_clk: + /* Set the sysconfig back to smart + * idle and smart stndby after wakeup and + * enable the clock + */ + oh->flags &= ~(HWMOD_SWSUP_SIDLE + | HWMOD_SWSUP_MSTANDBY); + pdata->device_enable(pdev); + + break; + + default: + break; + } +#endif } } } Index: linux-omap-pm/arch/arm/plat-omap/include/plat/usb.h =================================================================== --- linux-omap-pm.orig/arch/arm/plat-omap/include/plat/usb.h 2010-08-06 10:44:06.000000000 -0400 +++ linux-omap-pm/arch/arm/plat-omap/include/plat/usb.h 2010-08-06 10:44:42.942112875 -0400 @@ -71,6 +71,13 @@ unsigned extvbus:1; }; +enum musb_state { + save_context = 1, + disable_clk, + restore_context, + enable_clk, + }; + enum musb_interface {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI}; extern void usb_musb_init(struct omap_musb_board_data *board_data); @@ -80,7 +87,7 @@ 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); +extern void musb_context_save_restore(enum musb_state state); #endif Index: linux-omap-pm/drivers/usb/musb/musb_core.c =================================================================== --- linux-omap-pm.orig/drivers/usb/musb/musb_core.c 2010-08-06 10:44:06.000000000 -0400 +++ linux-omap-pm/drivers/usb/musb/musb_core.c 2010-08-06 10:44:42.942112875 -0400 @@ -2447,9 +2447,21 @@ return 0; } +static int musb_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int musb_runtime_resume(struct device *dev) +{ + return 0; +} + static const struct dev_pm_ops musb_dev_pm_ops = { .suspend = musb_suspend, .resume_noirq = musb_resume_noirq, + .runtime_suspend = musb_runtime_suspend, + .runtime_resume = musb_runtime_resume, }; #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) Index: linux-omap-pm/drivers/usb/musb/omap2430.c =================================================================== --- linux-omap-pm.orig/drivers/usb/musb/omap2430.c 2010-08-06 10:44:30.093914217 -0400 +++ linux-omap-pm/drivers/usb/musb/omap2430.c 2010-08-06 10:44:42.942112875 -0400 @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -209,10 +210,6 @@ struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; -#if defined(CONFIG_ARCH_OMAP2430) - omap_cfg_reg(AE5_2430_USB0HS_STP); -#endif - /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. @@ -224,22 +221,6 @@ } musb_platform_resume(musb); - - l = musb_readl(musb->mregs, OTG_SYSCONFIG); - l &= ~ENABLEWAKEUP; /* disable wakeup */ - l &= ~NOSTDBY; /* remove possible nostdby */ - l |= SMARTSTDBY; /* enable smart standby */ - l &= ~AUTOIDLE; /* disable auto idle */ - l &= ~NOIDLE; /* remove possible noidle */ - l |= SMARTIDLE; /* enable smart idle */ - /* - * MUSB AUTOIDLE don't work in 3430. - * Workaround by Richard Woodruff/TI - */ - if (!cpu_is_omap3430()) - l |= AUTOIDLE; /* enable auto idle */ - musb_writel(musb->mregs, OTG_SYSCONFIG, l); - l = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { @@ -273,48 +254,26 @@ void musb_platform_save_context(struct musb *musb, struct musb_context_registers *musb_context) { - /* - * 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) { - /* - * 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)); } #endif static int musb_platform_suspend(struct musb *musb) { u32 l; + struct device *dev = musb->controller; + struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct omap_hwmod *oh = pdata->oh; if (!musb->clock) return 0; @@ -324,16 +283,9 @@ l |= ENABLEFORCE; /* enable MSTANDBY */ musb_writel(musb->mregs, OTG_FORCESTDBY, l); - l = musb_readl(musb->mregs, OTG_SYSCONFIG); - l |= ENABLEWAKEUP; /* enable wakeup */ - musb_writel(musb->mregs, OTG_SYSCONFIG, l); - + pdata->enable_wakeup(oh->od); otg_set_suspend(musb->xceiv, 1); - - if (musb->set_clock) - musb->set_clock(musb->clock, 0); - else - clk_disable(musb->clock); + pm_runtime_put_sync(dev); return 0; } @@ -341,21 +293,18 @@ static int musb_platform_resume(struct musb *musb) { u32 l; + struct device *dev = musb->controller; + struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct omap_hwmod *oh = pdata->oh; if (!musb->clock) return 0; otg_set_suspend(musb->xceiv, 0); - - if (musb->set_clock) - musb->set_clock(musb->clock, 1); - else - clk_enable(musb->clock); - - l = musb_readl(musb->mregs, OTG_SYSCONFIG); - l &= ~ENABLEWAKEUP; /* disable wakeup */ - musb_writel(musb->mregs, OTG_SYSCONFIG, l); - + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + pdata->disable_wakeup(oh->od); + pdata->enable_wakeup(oh->od); l = musb_readl(musb->mregs, OTG_FORCESTDBY); l &= ~ENABLEFORCE; /* disable MSTANDBY */ musb_writel(musb->mregs, OTG_FORCESTDBY, l); Index: linux-omap-pm/include/linux/usb/musb.h =================================================================== --- linux-omap-pm.orig/include/linux/usb/musb.h 2010-08-06 10:44:06.000000000 -0400 +++ linux-omap-pm/include/linux/usb/musb.h 2010-08-06 10:44:42.946115274 -0400 @@ -10,6 +10,9 @@ #ifndef __LINUX_USB_MUSB_H #define __LINUX_USB_MUSB_H +#include +#include + /* The USB role is defined by the connector used on the board, so long as * standards are being followed. (Developer boards sometimes won't.) */ @@ -129,6 +132,21 @@ /* check usb device active state*/ int (*is_usb_active)(struct device *dev); + + /* omap hwmod data structure */ + struct omap_hwmod *oh; + + /* enable clocks and set sysconfig register*/ + int (*device_enable)(struct platform_device *pdev); + + /* Disable clock and reset the sysconfig register settings*/ + int (*device_idle)(struct platform_device *pdev); + + /* set the enable wakeup bit of sysconfig register */ + int (*enable_wakeup)(struct omap_device *od); + + /* Clear the enable wakeup bit of sysconfig register */ + int (*disable_wakeup)(struct omap_device *od); };