diff options
author | Tony Lindgren <tony@atomide.com> | 2016-09-22 15:58:30 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-09-23 12:26:07 +0200 |
commit | 2b9a8c40836930a45f42f06f98731eb9614ba86b (patch) | |
tree | ca5ac79d869486fec68ec3e214d03aa74104bbcf /drivers/usb | |
parent | 4e719183667e1363b0d81add5212aee2f149d727 (diff) |
usb: musb: Fix session based PM for first invalid VBUS
With the session bit based PM runtime working on musb, we've
implemented few quirks to attempt to detect the current state of
the hardware. One of the quirks is for invalid VBUS as peripheral,
but it is not working in all cases.
If we start musb on dm3730 as a peripheral with no cable connected,
we will get the devctl 91 state once and will never idle as there
are not further interrupts from musb. So we need to ignore the first
devctl 91 state as there will be more interrupts if we're connected.
The invalid VBUS state also can happen always when connected to
certain USB hubs. Looks like musb on dm3730 can claim invalid VBUS
with some hubs while 3717-evm and BeagleBone don't. This causes
session as peripheral to fail for dm3730 with some hubs.
This too is fixed by ignoring only the first invalid VBUS. When
connected, we can just look at the session bit as that will clear
automatically when the session ends.
Fixes: 467d5c980709 ("usb: musb: Implement session bit based runtime PM for musb-core")
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 13 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 1 |
2 files changed, 9 insertions, 5 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0319ea67e5a1..27dadc0d9114 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1855,11 +1855,13 @@ static void musb_pm_runtime_check_session(struct musb *musb) MUSB_DEVCTL_HR; switch (devctl & ~s) { case MUSB_QUIRK_B_INVALID_VBUS_91: - if (musb->session) - break; - musb_dbg(musb, "Allow PM as device with invalid vbus: %02x", - devctl); - return; + if (!musb->session && !musb->quirk_invalid_vbus) { + musb->quirk_invalid_vbus = true; + musb_dbg(musb, + "First invalid vbus, assume no session"); + return; + } + break; case MUSB_QUIRK_A_DISCONNECT_19: if (!musb->session) break; @@ -1886,6 +1888,7 @@ static void musb_pm_runtime_check_session(struct musb *musb) error); } else { musb_dbg(musb, "Allow PM with no session: %02x", devctl); + musb->quirk_invalid_vbus = false; pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 65288a53c19b..2cb88a498f8a 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -379,6 +379,7 @@ struct musb { int port_mode; /* MUSB_PORT_MODE_* */ bool session; + bool quirk_invalid_vbus; bool is_host; int a_wait_bcon; /* VBUS timeout in msecs */ |