summaryrefslogtreecommitdiff
path: root/drivers/usb/otg
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2011-11-18 14:01:06 +0800
committerJason Liu <r64343@freescale.com>2012-01-09 21:07:22 +0800
commit4ecfcfd2a9abc3bcca35056a2e077352c70c6daa (patch)
tree8bcb7803dc4ea1e313aa1c639eabeb4831e27ad7 /drivers/usb/otg
parenta7dacc3fc8231ba21d2b5f1b95b7a40c1ba3c0f6 (diff)
ENGR00162583-2 usb driver: avoid class driver access register after usb is off
- An well-behavior class driver should disable their endpoints after being notified disconnect with host, we use all endpoints are stopped (ep->stopped) to indicates the class driver will not visit device driver any more. the ep-stopped will be initialized as 1 for non-control endpoint it will be 0 after fsl_ep_enable, and be 1 after fsl_ep_disable. Where is a non-sleep wait routine at disconnect event for waiting all endpoints are stopped - Some controller's (like i.mx6q) DP will change from J to SE0 slowly after the cable disconnects with host, in that case there will be a wakeup interrupt after driver enables the wakeup interrupt. For i.mx6q, there is a discharge routine for DP after the disconnection. - Should not wait vbus to low during first otg switch, as the wait will be timeout when the usb cable is connecting to host. Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers/usb/otg')
-rwxr-xr-xdrivers/usb/otg/fsl_otg.c18
-rwxr-xr-xdrivers/usb/otg/fsl_otg.h2
2 files changed, 15 insertions, 5 deletions
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index a30815cba3f1..be8e0160a197 100755
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -168,11 +168,11 @@ static void fsl_otg_wait_stable_vbus(bool on)
fsl_otg_clk_gate(true);
/* Wait for vbus change to B_SESSION_VALID complete */
timeout = jiffies + FSL_VBUS_CHANGE_TIMEOUT;
- while ((le32_to_cpu(usb_dr_regs->otgsc)&OTGSC_INTSTS_B_SESSION_VALID) == !on) {
+ while ((le32_to_cpu(usb_dr_regs->otgsc)&OTGSC_STS_B_SESSION_VALID) != (on << 11)) {
if (time_after(jiffies, timeout)) {
printk(KERN_ERR"wait otg vbus change timeout! \n");
fsl_otg_clk_gate(false);
- break;
+ return;
}
msleep(10);
}
@@ -619,8 +619,11 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host)
* so suspend the host after a short delay.
*/
otg_dev->host_working = 1;
- if (otg_dev->fsm.id)
+
+ if (otg_dev->fsm.id) {
+ otg_dev->host_first_call = true;
schedule_otg_work(&otg_dev->otg_event, 100);
+ }
else {
/* if the device is already at the port */
otg_drv_vbus(&otg_dev->fsm, 1);
@@ -733,8 +736,12 @@ static void fsl_otg_event(struct work_struct *work)
if (fsm->id) { /* switch to gadget */
fsl_otg_start_host(fsm, 0);
otg_drv_vbus(fsm, 0);
- fsl_otg_wait_stable_vbus(false);
- fsl_otg_wait_dischrg_vbus();
+ if (og->host_first_call == false) {
+ fsl_otg_wait_dischrg_vbus();
+ fsl_otg_wait_stable_vbus(false);
+ } else {
+ og->host_first_call = false;
+ }
b_session_irq_enable(false);
fsl_otg_start_gadget(fsm, 1);
} else { /* switch to host */
@@ -943,6 +950,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp;
fsl_otg_tc->otg.start_srp = fsl_otg_start_srp;
fsl_otg_tc->otg.dev = &pdev->dev;
+ fsl_otg_tc->host_first_call = false;
fsl_otg_dev = fsl_otg_tc;
diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h
index a8536815d0bf..d3d382bd8e32 100755
--- a/drivers/usb/otg/fsl_otg.h
+++ b/drivers/usb/otg/fsl_otg.h
@@ -385,6 +385,8 @@ struct fsl_otg {
/*used for usb host */
struct work_struct work_wq;
u8 host_working;
+ /*Used for host init call,we need to avoid discharge Vbus when usb cable connect to PC*/
+ bool host_first_call;
int irq;
};