diff options
-rw-r--r-- | drivers/usb/core/hub.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5acf9757b09a..b3f934af7f22 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -37,6 +37,16 @@ #endif #endif +#ifdef CONFIG_ARCH_STMP3XXX +#define STMP3XXX_USB_HOST_HACK +#endif + +#ifdef STMP3XXX_USB_HOST_HACK +#include <linux/fsl_devices.h> +#include <mach/regs-usbphy.h> +#include <mach/platform.h> +#endif + struct usb_hub { struct device *intfdev; /* the "interface" device */ struct usb_device *hdev; @@ -2704,6 +2714,19 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, break; } } + +#ifdef STMP3XXX_USB_HOST_HACK + { /*Must enable HOSTDISCONDETECT after second reset*/ + if (port1 == 1) { + if (udev->speed == USB_SPEED_HIGH) { + stmp3xxx_setl( + BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + REGS_USBPHY_BASE + HW_USBPHY_CTRL); + } + } + } +#endif + if (retval) goto fail; @@ -2831,6 +2854,35 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, "port %d, status %04x, change %04x, %s\n", port1, portstatus, portchange, portspeed (portstatus)); +#ifdef STMP3XXX_USB_HOST_HACK + { + /* + * FIXME: the USBPHY of STMP3xxx SoC has bug. The usb port power + * is never enabled during standard ehci reset procedure if the + * external device once passed plug/unplug procedure. This work- + * around resets and reinitiates USBPHY before the ehci port reset + * sequence started. + */ + struct device *dev = hcd->self.controller; + struct fsl_usb2_platform_data *pdata; + + pdata = (struct fsl_usb2_platform_data *)dev->platform_data; + if (dev->parent && dev->type) { + if (port1 == 1 && pdata->platform_init) + pdata->platform_init(NULL); + } + if (port1 == 1) { + if (!(portstatus&USB_PORT_STAT_CONNECTION)) { + /* Must clear HOSTDISCONDETECT when disconnect*/ + stmp3xxx_clearl( + BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + REGS_USBPHY_BASE + HW_USBPHY_CTRL); + } + } + } +#endif + + if (hub->has_indicators) { set_port_led(hub, port1, HUB_LED_AUTO); hub->indicator[port1-1] = INDICATOR_AUTO; |