Skip to content

Commit 421255a

Browse files
Xu Yanggregkh
authored andcommitted
usb: chipidea: imx: improve usbmisc_imx7d_pullup()
When add workaround for ERR051725, the usbmisc will put PHY to Non-driving mode (OPMODE = 01) after stopping the device controller and put PHY back to Normal mode (OPMODE = 00) after starting the device controller. However, this will bring issue for host controller. Because the PHY may stay in Non-driving mode after switching the role from device to host. Then the port will not work if USB device is attached. To fix this issue, improving the workaround by putting PHY to Non-driving mode for a certain period and back to Normal mode finally. To make host detect a disconnect signal, the period should be at least 125us (a micro-frame time) for high-speed link. And only working as high-speed mode will need workaround for ERR051725. So this will also filter the pullup event for high-speed. Fixes: 11992b4 ("usb: chipidea: imx: implement workaround for ERR051725") Reviewed-by: Jun Li <[email protected]> Signed-off-by: Xu Yang <[email protected]> Acked-by: Peter Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9528d32 commit 421255a

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

drivers/usb/chipidea/ci_hdrc_imx.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
338338
schedule_work(&ci->usb_phy->chg_work);
339339
break;
340340
case CI_HDRC_CONTROLLER_PULLUP_EVENT:
341-
if (ci->role == CI_ROLE_GADGET)
341+
if (ci->role == CI_ROLE_GADGET &&
342+
ci->gadget.speed == USB_SPEED_HIGH)
342343
imx_usbmisc_pullup(data->usbmisc_data,
343344
ci->gadget.connected);
344345
break;

drivers/usb/chipidea/usbmisc_imx.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,15 +1068,24 @@ static void usbmisc_imx7d_pullup(struct imx_usbmisc_data *data, bool on)
10681068
unsigned long flags;
10691069
u32 val;
10701070

1071+
if (on)
1072+
return;
1073+
10711074
spin_lock_irqsave(&usbmisc->lock, flags);
10721075
val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
1073-
if (!on) {
1074-
val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
1075-
val |= MX7D_USBNC_USB_CTRL2_OPMODE(1);
1076-
val |= MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN;
1077-
} else {
1078-
val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN;
1079-
}
1076+
val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
1077+
val |= MX7D_USBNC_USB_CTRL2_OPMODE(1);
1078+
val |= MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN;
1079+
writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
1080+
spin_unlock_irqrestore(&usbmisc->lock, flags);
1081+
1082+
/* Last for at least 1 micro-frame to let host see disconnect signal */
1083+
usleep_range(125, 150);
1084+
1085+
spin_lock_irqsave(&usbmisc->lock, flags);
1086+
val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
1087+
val |= MX7D_USBNC_USB_CTRL2_OPMODE(0);
1088+
val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN;
10801089
writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
10811090
spin_unlock_irqrestore(&usbmisc->lock, flags);
10821091
}

0 commit comments

Comments
 (0)