From 051e157a7bcacf3d4f84289c2e8cc561ecb4a3c3 Mon Sep 17 00:00:00 2001 From: Jingchang Lu <b35083@freescale.com> Date: Fri, 7 Dec 2012 17:28:16 +0800 Subject: ENGR00216081-1:Add USB host and gadget PM support Handle usb suspend/resume, currently the BSP doesn't support usb plug/unplug wakeup. Signed-off-by: Jingchang Lu <b35083@freescale.com> --- drivers/usb/gadget/arcotg_udc.c | 12 ++++++++-- drivers/usb/host/ehci-arc.c | 51 ++++++----------------------------------- 2 files changed, 17 insertions(+), 46 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index 5a1aab94b405..c7c99cd9f3cb 100755 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -3356,9 +3356,15 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) (udc_controller->usb_state > USB_STATE_POWERED) && (udc_controller->usb_state < USB_STATE_SUSPENDED)) { return -EBUSY;/* keep the clk on */ - } else + } else { + if (udc_controller->pdata->wake_up_enable) + udc_controller->pdata->wake_up_enable( + udc_controller->pdata, true); ret = udc_suspend(udc_controller); - dr_clk_gate(false); + } + + if (udc_controller->stopped) + dr_clk_gate(false); printk(KERN_DEBUG "USB Gadget suspend ends\n"); return ret; @@ -3408,6 +3414,8 @@ static int fsl_udc_resume(struct platform_device *pdev) /* prevent the quirk interrupts from resuming */ disable_irq_nosync(udc_controller->irq); + if (pdata->wake_up_enable) + pdata->wake_up_enable(pdata, false); /* * If the controller was stopped at suspend time, then * don't resume it now. diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index 81ab1cffe374..0f5335d6381e 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -670,28 +670,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; printk(KERN_DEBUG "USB Host suspend begins\n"); -#ifdef CONFIG_ARCH_MVF - if (pdata->suspended) { - pr_debug("%s: already suspended, leaving early\n", __func__); - pdata->already_suspended = 1; - return 0; - } - - pr_debug("%s: suspending...\n", __func__); - - hcd->state = HC_STATE_SUSPENDED; - pdev->dev.power.power_state = PMSG_SUSPEND; - - /* ignore non-host interrupts */ - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* stop the controller */ - tmp = ehci_readl(ehci, &ehci->regs->command); - tmp &= ~CMD_RUN; - ehci_writel(ehci, tmp, &ehci->regs->command); - pdata->suspended = 1; -#else /* Only handles OTG mode switch event, system suspend event will be done in bus suspend */ if (pdata->pmflags == 0) { printk(KERN_DEBUG "%s, pm event\n", __func__); @@ -706,7 +685,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, printk(KERN_DEBUG "host suspend ends\n"); return 0; } - +#ifndef CONFIG_ARCH_MVF /* only the otg host can go here */ /* wait for all usb device on the hcd dettached */ usb_lock_device(roothub); @@ -740,7 +719,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, fsl_usb_clk_gate(hcd->self.controller->platform_data, true); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); } -#endif + port_status = ehci_readl(ehci, &ehci->regs->port_status[0]); /* save EHCI registers */ pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); @@ -772,6 +751,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, } pdata->pmflags = 0; printk(KERN_DEBUG "host suspend ends\n"); +#endif return 0; } @@ -786,27 +766,13 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) struct fsl_usb2_wakeup_platform_data *wake_up_pdata = pdata->wakeup_pdata; /* Only handles OTG mode switch event */ printk(KERN_DEBUG "ehci fsl drv resume begins: %s\n", pdata->name); -#ifdef CONFIG_ARCH_MVF - if (pdata->already_suspended) { - pr_debug("already suspended, leaving early\n"); - pdata->already_suspended = 0; - return 0; - } - if (!pdata->suspended) { - pr_debug("not suspended, leaving early\n"); - return 0; - } - - pdata->suspended = 0; - - pr_debug("%s resuming...\n", __func__); -#else if (pdata->pmflags == 0) { printk(KERN_DEBUG "%s,pm event, wait for wakeup irq if needed\n", __func__); wait_event_interruptible(wake_up_pdata->wq, !wake_up_pdata->usb_wakeup_is_pending); return 0; } +#ifndef CONFIG_ARCH_MVF if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); fsl_usb_clk_gate(hcd->self.controller->platform_data, true); @@ -815,7 +781,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) fsl_usb_lowpower_mode(pdata, false); spin_unlock_irqrestore(&ehci->lock, flags); } -#endif + spin_lock_irqsave(&ehci->lock, flags); /* set host mode */ fsl_platform_set_host_mode(hcd); @@ -837,19 +803,16 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) ehci_writel(ehci, tmp, &ehci->regs->command); spin_unlock_irqrestore(&ehci->lock, flags); -#ifdef CONFIG_ARCH_MVF - usb_hcd_resume_root_hub(hcd); -#else if ((hcd->state & HC_STATE_SUSPENDED)) { printk(KERN_DEBUG "will resume roothub and its children\n"); usb_lock_device(roothub); usb_resume(&roothub->dev, PMSG_USER_RESUME); usb_unlock_device(roothub); } -#endif + pdata->pmflags = 0; printk(KERN_DEBUG "ehci fsl drv resume ends: %s\n", pdata->name); - +#endif return 0; } #endif -- cgit v1.2.3 From 74e4dd3713a06947ac42aed73c822d7641735239 Mon Sep 17 00:00:00 2001 From: Jingchang Lu <b35083@freescale.com> Date: Mon, 10 Dec 2012 13:55:03 +0800 Subject: ENGR00216081-2:Errata workaround for usb suspend and resume Toggle PHYPWD.PWD after set PORTSC.SUSP with 8ms to trigger the LS_SE0/LS_EOP append flag after resume within UTM block. Signed-off-by: Jingchang Lu <b35083@freescale.com> --- drivers/usb/host/ehci-hub.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d6a80d9731a2..544ed44ef28c 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -29,8 +29,9 @@ /*-------------------------------------------------------------------------*/ #include <linux/usb/otg.h> -#ifdef CONFIG_ARCH_MX6 +#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MVF) #define MX6_USB_HOST_HACK +#define MVF_USB_HOST_HACK #include <linux/fsl_devices.h> #endif #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) @@ -1081,6 +1082,14 @@ static int ehci_hub_control ( pdata = hcd->self.controller->platform_data; if (pdata->platform_suspend) pdata->platform_suspend(pdata); +#ifdef MVF_USB_HOST_HACK + /* workaround: + * Toggle HW_USBPHY_PWD to flag controller + * generating LS-SE0/LS-EOP after resume + */ + if (pdata->platform_resume) + pdata->platform_resume(pdata); +#endif } #endif if (hostpc_reg) { -- cgit v1.2.3 From fd5b59f7d6fc1736c2b00f306dcfeb574fea4512 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr <rrobinson@phytec.com> Date: Mon, 11 Feb 2013 15:33:19 -0800 Subject: mvf: usb: create modular defines for ehci and some hardware address changes. ehci changes are currently only used with phyCORE-Vybrid (pcm052) Signed-off-by: Russell Robinson Jr <rrobinson@phytec.com> --- drivers/usb/core/hub.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 694476ea22ac..f056707d0986 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -42,6 +42,11 @@ extern void fsl_platform_set_usb_phy_dis(struct fsl_usb2_platform_data *pdata, #ifdef CONFIG_ARCH_MVF #define MVF_USB_HOST_HACK #include <linux/fsl_devices.h> + +extern void fsl_platform_set_usb0_phy_dis(struct fsl_usb2_platform_data *pdata, + bool enable); +extern void fsl_platform_set_usb1_phy_dis(struct fsl_usb2_platform_data *pdata, + bool enable); #endif /* if we are in debug mode, always announce new devices */ #ifdef DEBUG @@ -1669,7 +1674,14 @@ void usb_disconnect(struct usb_device **pdev) udev->devnum); #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) +#ifdef CONFIG_MACH_PCM052 + { + fsl_platform_set_usb0_phy_dis(NULL, 0); + fsl_platform_set_usb1_phy_dis(NULL, 0); + } +#else fsl_platform_set_usb_phy_dis(NULL, 0); +#endif #endif usb_lock_device(udev); @@ -2917,7 +2929,14 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) +#ifdef CONFIG_MACH_PCM052 + { + fsl_platform_set_usb0_phy_dis(NULL, 1); + fsl_platform_set_usb1_phy_dis(NULL, 1); + } +#else fsl_platform_set_usb_phy_dis(NULL, 1); +#endif #endif /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? * Because device hardware and firmware is sometimes buggy in -- cgit v1.2.3