diff options
author | Peter Chen <peter.chen@freescale.com> | 2012-02-17 15:22:07 +0800 |
---|---|---|
committer | Peter Chen <peter.chen@freescale.com> | 2012-02-22 14:51:06 +0800 |
commit | e9d2ee66faef002a10f3e5540bcff5939215f7cf (patch) | |
tree | 827a3329312f2aab1489b4a84998d4913366013c | |
parent | 6a082d2d9dd3f6cc53bc7b603094d586b3b5d1db (diff) |
ENGR00174734-2 usb: fix bugs that dp and dm are floating at device mode
At i.mx6x, the data line (dp and dm) are floating at device mode,
that is to say data line will be any values (0-3.6v).
So if the usb wakeup is enabled, there will be a wakeup interrupt
that causes usb to active mode.
In order to fix this problem well, we need to do below things:
- Need to discharge both dp and dm
- It needs to discharge data line when we switch to device mode and
usb cable is disconnected from the host, but not to disable discharge
after line state is SE0, the reason is that if we do not pulldown
the data line, the line state will be floating again, and possible cause
the wakeup interrupt.
- It needs to disable discharge data line when the usb cable connects at
device mode and usb device is connected at host mode, otherwise it will
affect signal quality.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
-rwxr-xr-x | drivers/usb/gadget/arcotg_udc.c | 30 | ||||
-rwxr-xr-x | drivers/usb/otg/fsl_otg.c | 7 |
2 files changed, 23 insertions, 14 deletions
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index 1cc50da4c9c2..5a1aab94b405 100755 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -295,21 +295,21 @@ static void nuke(struct fsl_ep *ep, int status) /*------------------------------------------------------------------ Internal Hardware related function ------------------------------------------------------------------*/ -static void dr_discharge_dp(struct fsl_usb2_platform_data *pdata) +static void dr_discharge_line(struct fsl_usb2_platform_data *pdata, bool enable) { - /* enable pulldown dp */ - if (pdata->gadget_discharge_dp) - pdata->gadget_discharge_dp(true); + /* enable/disable pulldown dp and dm */ + if (pdata->dr_discharge_line) { + pdata->dr_discharge_line(enable); /* - * Some boards are very slow change line state from J to SE0 for DP, - * So, we need to discharge DP, otherwise there is a wakeup interrupt + * Some platforms, like mx6x, are very slow change line state + * to SE0 for dp and dm. + * So, we need to discharge dp and dm, otherwise there is a wakeup interrupt * after we enable the wakeup function. */ - gadget_wait_line_to_se0(); + if (enable) + gadget_wait_line_to_se0(); + } - /* Disable pulldown dp */ - if (pdata->gadget_discharge_dp) - pdata->gadget_discharge_dp(false); } static inline void @@ -400,7 +400,7 @@ static int dr_controller_setup(struct fsl_udc *udc) tmp |= USB_MODE_ES; fsl_writel(tmp, &dr_regs->usbmode); /* wait dp to 0v */ - dr_discharge_dp(pdata); + dr_discharge_line(pdata, true); fsl_platform_set_device_mode(pdata); @@ -506,6 +506,8 @@ static void dr_controller_run(struct fsl_udc *udc) /* Clear stopped bit */ udc->stopped = 0; + /* disable pulldown dp and dm */ + dr_discharge_line(udc->pdata, false); /* The usb line has already been connected to pc */ temp = fsl_readl(&dr_regs->usbcmd); temp |= USB_CMD_RUN_STOP; @@ -2169,8 +2171,8 @@ static void fsl_gadget_disconnect_event(struct work_struct *work) pdata = udc->pdata; - /* wait dp to 0v */ - dr_discharge_dp(pdata); + /* wait line to se0 */ + dr_discharge_line(pdata, true); /* * Wait class drivers finish, an well-behaviour class driver should @@ -2226,6 +2228,8 @@ bool try_wake_up_udc(struct fsl_udc *udc) if (udc->suspended) /*let the system pm resume the udc */ return true; udc->stopped = 0; + /* disable pulldown dp and dm */ + dr_discharge_line(pdata, false); fsl_writel(tmp | USB_CMD_RUN_STOP, &dr_regs->usbcmd); printk(KERN_DEBUG "%s: udc out low power mode\n", __func__); } else { diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index 7ee9fcad8d5e..b797161f798d 100755 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * Author: Li Yang <LeoLi@freescale.com> * Jerry Huang <Chang-Ming.Huang@freescale.com> @@ -722,6 +722,8 @@ static void fsl_otg_event(struct work_struct *work) struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work); struct otg_fsm *fsm = &og->fsm; struct otg_transceiver *otg = &og->otg; + struct fsl_usb2_platform_data *pdata; + pdata = og->otg.dev->platform_data; mutex_lock(&pm_mutex); b_session_irq_enable(false); @@ -749,6 +751,9 @@ static void fsl_otg_event(struct work_struct *work) fsl_otg_wait_stable_vbus(true); b_session_irq_enable(false); fsl_otg_start_host(fsm, 1); + if (pdata->dr_discharge_line) + pdata->dr_discharge_line(false); + } mutex_unlock(&pm_mutex); } |