summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/arcotg_udc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/arcotg_udc.c')
-rw-r--r--drivers/usb/gadget/arcotg_udc.c77
1 files changed, 40 insertions, 37 deletions
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index 1577c93c35bb..abba4d2ae8d4 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -177,6 +177,25 @@ static inline void dump_ep_queue(struct fsl_ep *ep)
}
#endif
+#if (defined CONFIG_ARCH_MX35 || defined CONFIG_ARCH_MX25)
+/*
+ * The Phy at MX35 and MX25 have bugs, it must disable, and re-eable phy
+ * if the phy clock is disabled before
+ */
+static void reset_phy(void)
+{
+ u32 phyctrl;
+ phyctrl = fsl_readl(&dr_regs->phyctrl1);
+ phyctrl &= ~PHY_CTRL0_USBEN;
+ fsl_writel(phyctrl, &dr_regs->phyctrl1);
+
+ phyctrl = fsl_readl(&dr_regs->phyctrl1);
+ phyctrl |= PHY_CTRL0_USBEN;
+ fsl_writel(phyctrl, &dr_regs->phyctrl1);
+}
+#else
+static void reset_phy(void){; }
+#endif
/*-----------------------------------------------------------------
* done() - retire a request; caller blocked irqs
* @status : request status to be set, only works when
@@ -300,6 +319,8 @@ static void dr_phy_low_power_mode(struct fsl_udc *udc, bool enable)
if (udc_controller->pdata->usb_clock_for_pm)
udc_controller->pdata->usb_clock_for_pm(true);
+ /* Due to mx35/mx25's phy's bug */
+ reset_phy();
temp = fsl_readl(&dr_regs->portsc1);
temp &= ~PORTSCX_PHY_LOW_POWER_SPD;
fsl_writel(temp, &dr_regs->portsc1);
@@ -445,12 +466,14 @@ static void dr_controller_run(struct fsl_udc *udc)
dr_phy_low_power_mode(udc, true);
printk(KERN_INFO "udc enter low power mode \n");
} else {
+#ifdef CONFIG_ARCH_MX37
/*
add some delay for USB timing issue. USB may be
recognize as FS device
during USB gadget remote wake up function
*/
mdelay(100);
+#endif
/* Clear stopped bit */
udc->stopped = 0;
/* Set controller to Run */
@@ -680,7 +703,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
case USB_ENDPOINT_XFER_ISOC:
/* Calculate transactions needed for high bandwidth iso */
mult = (unsigned char)(1 + ((max >> 11) & 0x03));
- max = max & 0x8ff; /* bit 0~10 */
+ max = max & 0x7ff; /* bit 0~10 */
/* 3 transactions at most */
if (mult > 3)
goto en_done;
@@ -2018,29 +2041,12 @@ static void reset_irq(struct fsl_udc *udc)
/* Write 1s to the flush register */
fsl_writel(0xffffffff, &dr_regs->endptflush);
- if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
- VDBG("Bus reset");
- /* Bus is reseting */
- udc->bus_reset = 1;
- /* Reset all the queues, include XD, dTD, EP queue
- * head and TR Queue */
- reset_queues(udc);
- udc->usb_state = USB_STATE_DEFAULT;
- } else {
- VDBG("Controller reset");
- /* initialize usb hw reg except for regs for EP, not
- * touch usbintr reg */
- dr_controller_setup(udc);
-
- /* Reset all internal used Queues */
- reset_queues(udc);
-
- ep0_setup(udc);
-
- /* Enable DR IRQ reg, Set Run bit, change udc state */
- dr_controller_run(udc);
- udc->usb_state = USB_STATE_ATTACHED;
- }
+ /* Bus is reseting */
+ udc->bus_reset = 1;
+ /* Reset all the queues, include XD, dTD, EP queue
+ * head and TR Queue */
+ reset_queues(udc);
+ udc->usb_state = USB_STATE_DEFAULT;
}
/* if wakup udc, return true; else return false*/
@@ -2176,9 +2182,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
int retval = -ENODEV;
unsigned long flags = 0;
-#ifndef CONFIG_USB_OTG
u32 portsc;
-#endif
if (!udc_controller)
return -ENODEV;
@@ -2200,14 +2204,14 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc_controller->driver = driver;
udc_controller->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc_controller->lock, flags);
-#ifndef CONFIG_USB_OTG
+
if (udc_controller->pdata->usb_clock_for_pm)
udc_controller->pdata->usb_clock_for_pm(true);
portsc = fsl_readl(&dr_regs->portsc1);
portsc &= ~PORTSCX_PHY_LOW_POWER_SPD;
fsl_writel(portsc, &dr_regs->portsc1);
-#endif
+
/* bind udc driver to gadget driver */
retval = driver->bind(&udc_controller->gadget);
if (retval) {
@@ -2705,14 +2709,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
int ret = -ENODEV;
unsigned int i;
u32 dccparams;
-#ifndef CONFIG_USB_OTG
- u32 portsc;
-#endif
-
- if (strcmp(pdev->name, driver_name)) {
- VDBG("Wrong device\n");
- return -ENODEV;
- }
udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
if (udc_controller == NULL) {
@@ -2768,6 +2764,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err2a;
}
+ /* Due to mx35/mx25's phy's bug */
+ reset_phy();
+
if (pdata->have_sysif_regs)
usb_sys_regs = (struct usb_sys_interface *)
((u32)dr_regs + USB_DR_SYS_OFFSET);
@@ -2881,10 +2880,14 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
dr_wake_up_enable(udc_controller, false);
udc_controller->stopped = 1;
+#if !(defined CONFIG_ARCH_MX35 || defined CONFIG_ARCH_MX25)
+{
+ u32 portsc;
portsc = fsl_readl(&dr_regs->portsc1);
portsc |= PORTSCX_PHY_LOW_POWER_SPD;
fsl_writel(portsc, &dr_regs->portsc1);
-
+}
+#endif
if (udc_controller->pdata->usb_clock_for_pm)
udc_controller->pdata->usb_clock_for_pm(false);
#endif