The wakeup issue has been identified as a fake wakeup issue which is caused by static discharge. It can be from air or on contact. The following are the changes need to be made.
1. In ../arch/arm/mach-mx28/usb_dr.c, add the following code.
static void usbotg_wakeup_event_clear(void)
{
void __iomem *phy_reg = IO_ADDRESS(USBPHY0_PHYS_ADDR);
u32 wakeup_irq_bits;
wakeup_irq_bits = BM_USBPHY_CTRL_RESUME_IRQ | BM_USBPHY_CTRL_WAKEUP_IRQ;
if (__raw_readl(phy_reg + HW_USBPHY_CTRL) && wakeup_irq_bits) {
/* clear the wakeup interrupt status */
__raw_writel(wakeup_irq_bits, phy_reg + HW_USBPHY_CTRL_CLR);
}
}
static struct fsl_usb2_wakeup_platform_data usbdr_wakeup_config = {
.name = "DR wakeup",
.usb_clock_for_pm = usbotg_clock_gate,
.usb_wakeup_exhandle = usbotg_wakeup_event_clear,
};
2. In ../linux/ include/linux/fsl_devices.h, add the following changes.
struct fsl_usb2_wakeup_platform_data {
char *name;
void (*usb_clock_for_pm) (bool);
void (*usb_wakeup_exhandle) (void);
struct fsl_usb2_platform_data *usb_pdata[3];
/* This waitqueue is used to wait "usb_wakeup thread" to finish
* during system resume routine. "usb_wakeup theard" should be finished
* prior to usb resume routine.
*/
wait_queue_head_t wq;
/* This flag is used to indicate the "usb_wakeup thread" is finished during
* usb wakeup routine.
*/
bool usb_wakeup_is_pending;
/* Store ctrl ptr so that usb_wakeup.c knows who should die at
* wakeup_dev_exit() */
void * ctrl;
};
3. In ../arch/arm/plat-mxs/usb_wakeup.c, add the following changes.
static void wakeup_event_handler(struct wakeup_ctrl *ctrl)
{
struct fsl_usb2_wakeup_platform_data *pdata = ctrl->pdata;
int already_waked = 0;
int i;
wakeup_clk_gate(ctrl->pdata, true);
/* if this is an wakeup event, we should debounce ID pin
* so we can get the correct ID value(ID status) here
* */
if (usb_event_is_otg_wakeup())
usb_debounce_id_pin();
for (i = 0; i < 3; i++) {
struct fsl_usb2_platform_data *usb_pdata = pdata->usb_pdata[i];
if (usb_pdata) {
if (is_wakeup(usb_pdata)) {
usb_pdata->wakeup_event = 1;
if (usb2_is_in_lowpower(ctrl))
if (usb_pdata->usb_clock_for_pm)
usb_pdata->usb_clock_for_pm(true);
usb_pdata->lowpower = 0;
already_waked = 1;
}
}
}
if (already_waked == 0)
{ /* If nothing to wakeup, clear wakeup event */
/* It's a fake wakeup caused by static discharge. */
pdata->usb_wakeup_exhandle();
}
else
{
/* Normal wakeup caused by shorting USB ID pin to ground or plug in a USB drive. */
wakeup_clk_gate(ctrl->pdata, false);
pdata->usb_wakeup_is_pending = false;
wake_up(&pdata->wq);
}
}