summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Robinson Jr <rrobinson@phytec.com>2013-08-09 16:58:01 -0700
committerAnthony Felice <tony.felice@timesys.com>2013-09-17 14:22:18 -0400
commit734200d17cf5e8b20e50ecf24f682ff233a20554 (patch)
tree9f8cbad536c6786b0f2c700478b257e40456f9a1
parent31c2750be324136ea634cdb5eded0b673119f6dd (diff)
pcl052: revert usb0 to device mode
Signed-off-by: Russell Robinson Jr <rrobinson@phytec.com>
-rw-r--r--arch/arm/mach-mvf/board-pcl052.c4
-rw-r--r--arch/arm/mach-mvf/usb_dr.c228
-rw-r--r--drivers/usb/core/hub.c33
3 files changed, 119 insertions, 146 deletions
diff --git a/arch/arm/mach-mvf/board-pcl052.c b/arch/arm/mach-mvf/board-pcl052.c
index 08a59470d434..eab9492b8ace 100644
--- a/arch/arm/mach-mvf/board-pcl052.c
+++ b/arch/arm/mach-mvf/board-pcl052.c
@@ -334,9 +334,11 @@ static void __init pcl052_init_usb(void)
gpio_set_value(USB_VBUS_ENABLE_PIN, 1);
#ifdef CONFIG_USB_EHCI_ARC
- mvf_usb_dr_init();
mvf_usb_dr2_init();
#endif
+#ifdef CONFIG_USB_GADGET_ARC
+ mvf_usb_dr_init();
+#endif
}
/*!
diff --git a/arch/arm/mach-mvf/usb_dr.c b/arch/arm/mach-mvf/usb_dr.c
index 34377c4c19b3..ba89e9346927 100644
--- a/arch/arm/mach-mvf/usb_dr.c
+++ b/arch/arm/mach-mvf/usb_dr.c
@@ -20,7 +20,6 @@
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
-#include <linux/pm_wakeup.h>
#include <linux/fsl_devices.h>
#include <linux/delay.h>
#include <linux/io.h>
@@ -38,6 +37,10 @@ static void usbotg_clock_gate(bool on);
static void _dr_discharge_line(bool enable);
static void usbotg_wakeup_event_clear(void);
+/* The usb_phy0_clk do not have enable/disable function at clock.c
+ * and PLL output for usb0's phy should be always enabled.
+ * usb_phy0_clk only stands for usb uses pll3 as its parent.
+ */
static struct clk *usb_phy0_clk;
static u8 otg_used;
@@ -62,22 +65,24 @@ static struct fsl_usb2_platform_data dr_utmi_config = {
/* Platform data for wakeup operation */
static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = {
- .name = "Host wakeup",
+ .name = "Gadget wakeup",
.usb_clock_for_pm = usbotg_clock_gate,
.usb_wakeup_exhandle = usbotg_wakeup_event_clear,
};
static void usbotg_internal_phy_clock_gate(bool on)
{
+ u32 reg;
+
void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR);
+ reg = __raw_readl(phy_reg + HW_USBPHY_CTRL);
if (on)
- __raw_writel(BM_USBPHY_CTRL_CLKGATE,
- phy_reg + HW_USBPHY_CTRL_CLR);
+ reg &= ~BM_USBPHY_CTRL_CLKGATE;
else
- __raw_writel(BM_USBPHY_CTRL_CLKGATE,
- phy_reg + HW_USBPHY_CTRL_SET);
+ reg |= BM_USBPHY_CTRL_CLKGATE;
+ __raw_writel(reg, phy_reg + HW_USBPHY_CTRL);
}
static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
@@ -109,13 +114,6 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
/* Power up the PHY */
__raw_writel(0, phy_reg + HW_USBPHY_PWD);
- if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
- (pdata->operating_mode == FSL_USB2_DR_OTG)) {
- /* enable FS/LS device */
- __raw_writel(
- BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3,
- phy_reg + HW_USBPHY_CTRL_SET);
- }
return 0;
}
@@ -138,8 +136,8 @@ static int usbotg_init_ext(struct platform_device *pdev)
usbotg_internal_phy_clock_gate(true);
usb_phy_enable(pdev->dev.platform_data);
/*
- * after the phy reset,can't read the value for id/vbus at
- * the register of otgsc at once ,need delay 3 ms
+ * after the phy reset,can not read the value for id/vbus at
+ * the register of otgsc ,cannot read at once ,need delay 3 ms
*/
mdelay(3);
}
@@ -161,18 +159,21 @@ static void usbotg_uninit_ext(struct platform_device *pdev)
static void usbotg_clock_gate(bool on)
{
-
+ pr_debug("%s: on is %d\n", __func__, on);
if (on)
clk_enable(usb_phy0_clk);
else
clk_disable(usb_phy0_clk);
-
}
-
+/*
+void mvf_set_otghost_vbus_func(driver_vbus_func driver_vbus)
+{
+ dr_utmi_config.platform_driver_vbus = driver_vbus;
+}
+*/
static void _dr_discharge_line(bool enable)
{
void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR);
-
if (enable) {
__raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x3),
phy_reg + HW_USBPHY_DEBUG_SET);
@@ -190,6 +191,7 @@ static void _dr_discharge_line(bool enable)
/* Below two macros are used at otg mode to indicate usb mode*/
#define ENABLED_BY_HOST (0x1 << 0)
#define ENABLED_BY_DEVICE (0x1 << 1)
+static u32 low_power_enable_src; /* only useful at otg mode */
static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata,
bool enable)
{
@@ -231,11 +233,12 @@ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata,
static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata,
bool enable, int source)
{
- if (enable)
+ if (enable) {
+ low_power_enable_src |= source;
enter_phy_lowpower_suspend(pdata, enable);
- else {
- pr_debug("phy lowpower disable\n");
+ } else {
enter_phy_lowpower_suspend(pdata, enable);
+ low_power_enable_src &= ~source;
}
}
@@ -267,9 +270,10 @@ static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata,
static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata,
bool on, int source)
{
- pr_debug("USB Host %s,on=%d\n", __func__, on);
- mdelay(3);
- if (on) {
+ /* otg host and device share the OWIE bit, only when host and device
+ * all enable the wakeup irq, we can enable the OWIE bit
+ */
+ if (on) {
otg_wake_up_enable(pdata, on);
} else {
otg_wake_up_enable(pdata, on);
@@ -298,167 +302,125 @@ static void usbotg_wakeup_event_clear(void)
}
/* End of Common operation for DR port */
-
#ifdef CONFIG_USB_EHCI_ARC_OTG
-/* Beginning of host related operation for DR port */
-static void _host_platform_suspend(struct fsl_usb2_platform_data *pdata)
-{
- void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR);
- u32 tmp;
-
- tmp = (BM_USBPHY_PWD_TXPWDFS
- | BM_USBPHY_PWD_TXPWDIBIAS
- | BM_USBPHY_PWD_TXPWDV2I
- | BM_USBPHY_PWD_RXPWDENV
- | BM_USBPHY_PWD_RXPWD1PT1
- | BM_USBPHY_PWD_RXPWDDIFF
- | BM_USBPHY_PWD_RXPWDRX);
- __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
-}
-
-static void _host_platform_resume(struct fsl_usb2_platform_data *pdata)
-{
- void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR);
- u32 tmp;
+#endif /* CONFIG_USB_EHCI_ARC_OTG */
- tmp = (BM_USBPHY_PWD_TXPWDFS
- | BM_USBPHY_PWD_TXPWDIBIAS
- | BM_USBPHY_PWD_TXPWDV2I
- | BM_USBPHY_PWD_RXPWDENV
- | BM_USBPHY_PWD_RXPWD1PT1
- | BM_USBPHY_PWD_RXPWDDIFF
- | BM_USBPHY_PWD_RXPWDRX);
- __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
-}
-static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata,
+#ifdef CONFIG_USB_GADGET_ARC
+/* Beginning of device related operation for DR port */
+static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata,
bool enable)
{
- __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST);
+ __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE);
}
-static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata,
+static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata,
bool enable)
{
- __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST);
-
- if (enable)
+ __wakeup_irq_enable(pdata, enable, ENABLED_BY_DEVICE);
+ if (enable) {
+ pr_debug("device wakeup enable\n");
device_wakeup_enable(&pdata->pdev->dev);
- else
+ } else {
+ pr_debug("device wakeup disable\n");
device_wakeup_disable(&pdata->pdev->dev);
+ }
}
static enum usb_wakeup_event
-_is_host_wakeup(struct fsl_usb2_platform_data *pdata)
+_is_device_wakeup(struct fsl_usb2_platform_data *pdata)
{
- u32 wakeup_req = USBC0_CTRL & UCTRL_OWIR;
- u32 otgsc = UOG_OTGSC;
+ int wakeup_req = USBC0_CTRL & UCTRL_OWIR;
- if (wakeup_req) {
- pr_debug("the otgsc is 0x%x, usbsts is 0x%x,"
- " portsc is 0x%x, wakeup_irq is 0x%x\n",
- UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, wakeup_req);
- }
- /* if ID change sts, it is a host wakeup event */
- if (wakeup_req && (otgsc & OTGSC_IS_USB_ID)) {
- pr_debug("otg host ID wakeup\n");
- /* if host ID wakeup, we must clear the b session change sts */
- otgsc &= (~OTGSC_IS_USB_ID);
- return WAKEUP_EVENT_ID;
+ /* if ID=1, it is a device wakeup event */
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) &&
+ (UOG_USBSTS & USBSTS_URI)) {
+ printk(KERN_INFO "otg udc wakeup, host sends reset signal\n");
+ return WAKEUP_EVENT_DPDM;
}
- if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) {
- pr_debug("otg host Remote wakeup\n");
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && \
+ ((UOG_USBSTS & USBSTS_PCI) ||
+ (UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME))) {
+ /*
+ * When the line state from J to K, the Port Change Detect bit
+ * in the USBSTS register is also set to '1'.
+ */
+ printk(KERN_INFO "otg udc wakeup, host sends resume signal\n");
return WAKEUP_EVENT_DPDM;
}
- return WAKEUP_EVENT_INVALID;
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) &&
+ (UOG_OTGSC & OTGSC_STS_A_VBUS_VALID) &&
+ (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) {
+ printk(KERN_INFO "otg udc vbus rising wakeup\n");
+ return WAKEUP_EVENT_VBUS;
+ }
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) &&
+ !(UOG_OTGSC & OTGSC_STS_A_VBUS_VALID)) {
+ printk(KERN_INFO "otg udc vbus falling wakeup\n");
+ return WAKEUP_EVENT_VBUS;
+ }
+
+ return WAKEUP_EVENT_DPDM;
}
-static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata)
{
- _host_phy_lowpower_suspend(pdata, false);
- _host_wakeup_enable(pdata, false);
+ _device_phy_lowpower_suspend(pdata, false);
+ _device_wakeup_enable(pdata, false);
}
-
-/* End of host related operation for DR port */
-#endif /* CONFIG_USB_EHCI_ARC_OTG */
-
+/* end of device related operation for DR port */
+#endif /* CONFIG_USB_GADGET_ARC */
void __init mvf_usb_dr_init(void)
{
struct platform_device *pdev, *pdev_wakeup;
u32 reg;
-
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- dr_utmi_config.operating_mode = DR_HOST_MODE;
- dr_utmi_config.wake_up_enable = _host_wakeup_enable;
- dr_utmi_config.platform_suspend = _host_platform_suspend;
- dr_utmi_config.platform_resume = _host_platform_resume;
- dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend;
- dr_utmi_config.is_wakeup_event = _is_host_wakeup;
+#ifdef CONFIG_USB_GADGET_ARC
+ dr_utmi_config.operating_mode = DR_UDC_MODE;
+ dr_utmi_config.wake_up_enable = _device_wakeup_enable;
+ dr_utmi_config.platform_suspend = NULL;
+ dr_utmi_config.platform_resume = NULL;
+ dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend;
+ dr_utmi_config.is_wakeup_event = _is_device_wakeup;
dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
- dr_utmi_config.wakeup_handler = host_wakeup_handler;
+ dr_utmi_config.wakeup_handler = device_wakeup_handler;
- pdev = mvf_add_fsl_ehci_otg(0, &dr_utmi_config);
+ pdev = mvf_add_fsl_usb2_udc(0, &dr_utmi_config);
- dr_wakeup_config.usb_pdata[0] = pdev->dev.platform_data;
+ dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data;
/* register wakeup device */
- pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(0, &dr_wakeup_config);
+ pdev_wakeup = mvf_add_fsl_usb2_udc_wakeup(0, &dr_wakeup_config);
if (pdev != NULL)
((struct fsl_usb2_platform_data *)
(pdev->dev.platform_data))->wakeup_pdata =
(struct fsl_usb2_wakeup_platform_data *)
(pdev_wakeup->dev.platform_data);
- __raw_writel(0x0220C802, USBPHY1_CTRL);
- udelay(20);
+ device_set_wakeup_capable(&pdev->dev, true);
+ __raw_writel(((0x01 << 30) | 0x2), ANADIG_USB1_MISC);
+
+ __raw_writel(0x00000894, USBPHY1_CTRL);
+ udelay(10);
__raw_writel(0x0, USBPHY1_PWD);
+ __raw_writel(0x1, USBPHY1_IP);
+ udelay(20);
+ __raw_writel(0x7, USBPHY1_IP);
reg = __raw_readl(USBPHY1_DEBUG);
- reg &= ~0x40000000; /* clear clock gate */
+ reg &= ~0x40000000; /* clear gate clock */
__raw_writel(reg, USBPHY1_DEBUG);
- reg = __raw_readl(ANADIG_USB1_MISC);
- reg |= (0x01 << 30); /* Enable CLK_TO_UTMI */
- __raw_writel(reg, ANADIG_USB1_MISC);
-
__raw_writel(0x10000007, USBPHY1_TX);
- /*__raw_writel(0x100F0F07, USBPHY1_TX);*/
-
- /* Enable disconnect detect */
reg = __raw_readl(USBPHY1_CTRL);
- reg &= ~0x040; /* clear OTG ID change IRQ */
- reg |= (0x1 << 14); /* Enable UTMI+ level2 */
- reg |= (0x1 << 9);
- reg |= (0x1 << 15); /* Enable UTMI+ level3 */
- reg &= ~((0xD1 << 11) | 0x6);
+ reg |= ((0xD1 << 11) | 0x6);
__raw_writel(reg, USBPHY1_CTRL);
- __raw_writel(0x1 << 3, USBPHY1_CTRL + 0x8);
- /* Disable VBUS and CHARGER detect */
reg = __raw_readl(ANADIG_USB1_VBUS_DETECT);
reg |= 0xE8;
__raw_writel(reg, ANADIG_USB1_VBUS_DETECT);
__raw_writel(0x001c0000, ANADIG_USB1_CHRG_DETECT);
-
#endif
-}
-
-/* USB HIGH_SPEED disconnect detect on/off */
-void fsl_platform_set_usb0_phy_dis(struct fsl_usb2_platform_data *pdata,
- bool enable)
-{
- u32 reg;
- reg = __raw_readl(USBPHY1_CTRL);
-
- if (enable)
- reg |= ((0xD1 << 11) | 0x6);
- else
- reg &= ~((0xD1 << 11) | 0x6);
-
- __raw_writel(reg, USBPHY1_CTRL);
-
- __raw_writel(0x1 << 3, USBPHY1_CTRL + 0x8);
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 5fa3206886df..ef1b40c69986 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -43,11 +43,16 @@ extern void fsl_platform_set_usb_phy_dis(struct fsl_usb2_platform_data *pdata,
#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);
+#if (defined(CONFIG_MACH_PCM052) || defined(CONFIG_MACH_PCL052))
extern void fsl_platform_set_usb1_phy_dis(struct fsl_usb2_platform_data *pdata,
bool enable);
#endif
+#if defined(CONFIG_MACH_PCM052)
+extern void fsl_platform_set_usb0_phy_dis(struct fsl_usb2_platform_data *pdata,
+ bool enable);
+#endif
+#endif
+
/* if we are in debug mode, always announce new devices */
#ifdef DEBUG
#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
@@ -1674,14 +1679,16 @@ void usb_disconnect(struct usb_device **pdev)
udev->devnum);
#ifdef MVF_USB_HOST_HACK
if (udev->speed == USB_SPEED_HIGH && udev->level == 1)
-#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052)
- {
- fsl_platform_set_usb0_phy_dis(NULL, 0);
- fsl_platform_set_usb1_phy_dis(NULL, 0);
- }
+ {
+#if (defined(CONFIG_MACH_PCM052) || defined(CONFIG_MACH_PCL052))
+ fsl_platform_set_usb1_phy_dis(NULL, 0);
+#if defined(CONFIG_MACH_PCM052)
+ fsl_platform_set_usb0_phy_dis(NULL, 0);
+#endif
#else
fsl_platform_set_usb_phy_dis(NULL, 0);
#endif
+ }
#endif
usb_lock_device(udev);
@@ -2929,14 +2936,16 @@ 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)
-#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052)
- {
- fsl_platform_set_usb0_phy_dis(NULL, 1);
- fsl_platform_set_usb1_phy_dis(NULL, 1);
- }
+ {
+#if (defined(CONFIG_MACH_PCM052) || defined(CONFIG_MACH_PCL052))
+ fsl_platform_set_usb1_phy_dis(NULL, 1);
+#if defined(CONFIG_MACH_PCM052)
+ fsl_platform_set_usb0_phy_dis(NULL, 1);
+#endif
#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