aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2016-09-22 16:58:30 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-09-23 06:26:07 -0400
commit2b9a8c40836930a45f42f06f98731eb9614ba86b (patch)
treeca5ac79d869486fec68ec3e214d03aa74104bbcf /drivers/usb
parent4e719183667e1363b0d81add5212aee2f149d727 (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.c13
-rw-r--r--drivers/usb/musb/musb_core.h1
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)
1855 MUSB_DEVCTL_HR; 1855 MUSB_DEVCTL_HR;
1856 switch (devctl & ~s) { 1856 switch (devctl & ~s) {
1857 case MUSB_QUIRK_B_INVALID_VBUS_91: 1857 case MUSB_QUIRK_B_INVALID_VBUS_91:
1858 if (musb->session) 1858 if (!musb->session && !musb->quirk_invalid_vbus) {
1859 break; 1859 musb->quirk_invalid_vbus = true;
1860 musb_dbg(musb, "Allow PM as device with invalid vbus: %02x", 1860 musb_dbg(musb,
1861 devctl); 1861 "First invalid vbus, assume no session");
1862 return; 1862 return;
1863 }
1864 break;
1863 case MUSB_QUIRK_A_DISCONNECT_19: 1865 case MUSB_QUIRK_A_DISCONNECT_19:
1864 if (!musb->session) 1866 if (!musb->session)
1865 break; 1867 break;
@@ -1886,6 +1888,7 @@ static void musb_pm_runtime_check_session(struct musb *musb)
1886 error); 1888 error);
1887 } else { 1889 } else {
1888 musb_dbg(musb, "Allow PM with no session: %02x", devctl); 1890 musb_dbg(musb, "Allow PM with no session: %02x", devctl);
1891 musb->quirk_invalid_vbus = false;
1889 pm_runtime_mark_last_busy(musb->controller); 1892 pm_runtime_mark_last_busy(musb->controller);
1890 pm_runtime_put_autosuspend(musb->controller); 1893 pm_runtime_put_autosuspend(musb->controller);
1891 } 1894 }
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 {
379 379
380 int port_mode; /* MUSB_PORT_MODE_* */ 380 int port_mode; /* MUSB_PORT_MODE_* */
381 bool session; 381 bool session;
382 bool quirk_invalid_vbus;
382 bool is_host; 383 bool is_host;
383 384
384 int a_wait_bcon; /* VBUS timeout in msecs */ 385 int a_wait_bcon; /* VBUS timeout in msecs */