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