]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00234722 USB: fix Kernel dump issue after USB driver loadable
authormake shi <b15407@freescale.com>
Thu, 29 Nov 2012 08:28:25 +0000 (16:28 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:47 +0000 (08:35 +0200)
- It is better to disable otgsc and wake up interrupt to avoid an
  abnormal interrupt happen during USB driver being removed.
- If the USB host is already at low power mode, only need turn on
  the clock, no need turn off the clock.
- Need discharge dp and dm during USB driver being removed ,in order
  to avoid a wakeup interrupt happen. And if the USB otg is in host
  mode, we should clear discharge dp and dm in fsl_otg_set_host()
  during system boot up.

Signed-off-by: make shi <b15407@freescale.com>
drivers/usb/gadget/arcotg_udc.c
drivers/usb/host/ehci-arc.c
drivers/usb/otg/fsl_otg.c

index ae0daac1f2ef5d90048f426be2e8f7f7db17134a..89bd9a3b7decfbb460b4ef604e2524a39bf1f1e3 100755 (executable)
@@ -3248,7 +3248,7 @@ err1a:
 static int  fsl_udc_remove(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-
+       u32 temp;
        DECLARE_COMPLETION(done);
 
        if (!udc_controller)
@@ -3258,6 +3258,13 @@ static int  fsl_udc_remove(struct platform_device *pdev)
        if (udc_controller->stopped)
                dr_clk_gate(true);
 
+       /* disable wake up and otgsc interrupt for safely remove udc driver*/
+       temp = fsl_readl(&dr_regs->otgsc);
+       temp &= ~(0x7f << 24);
+       fsl_writel(temp, &dr_regs->otgsc);
+       dr_wake_up_enable(udc_controller, false);
+
+       dr_discharge_line(pdata, true);
        /* DR has been stopped in usb_gadget_unregister_driver() */
        remove_proc_file();
 
index cf9d9e1612f08c37516d79efb4be4e22d6ce0eed..8c703b9a33d4d55b451eebba1896c7c95a1c91af 100755 (executable)
@@ -339,14 +339,14 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
                if (pdata->usb_clock_for_pm)
                        pdata->usb_clock_for_pm(true);
 
+               /*disable the wakeup to avoid an abnormal wakeup interrupt*/
+               usb_host_set_wakeup(hcd->self.controller, false);
+
                tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);
                if (tmp & PORT_PTS_PHCD) {
                        tmp &= ~PORT_PTS_PHCD;
                        ehci_writel(ehci, tmp, &ehci->regs->port_status[0]);
                        msleep(100);
-
-                       if (pdata->usb_clock_for_pm)
-                               pdata->usb_clock_for_pm(false);
                }
        }
 
index d728cf92457d327232ad397f526ec168048d5c70..292c2e930b5d9ad3f0047792f6e34ba248c97e6d 100755 (executable)
@@ -607,6 +607,9 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
 static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host)
 {
        struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg);
+       struct fsl_usb2_platform_data *pdata;
+
+       pdata = otg_dev->otg.dev->platform_data;
 
        if (!otg_p || otg_dev != fsl_otg_dev)
                return -ENODEV;
@@ -633,6 +636,8 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host)
                else {
                        /* if the device is already at the port */
                        otg_drv_vbus(&otg_dev->fsm, 1);
+                       if (pdata->dr_discharge_line)
+                               pdata->dr_discharge_line(false);
                        fsl_otg_wait_stable_vbus(true);
                        b_session_irq_enable(false);
                        fsl_otg_start_host(&otg_dev->fsm, 1);