aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManu Gautam <mgautam@codeaurora.org>2018-01-18 06:24:30 -0500
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-02-12 03:50:16 -0500
commitc4a5153e87fdf6805f63ff57556260e2554155a5 (patch)
tree5ca6f6f3995b3a864f76a11918e8f0f0a5596fde
parent00b42170c86f90ac9dea83a7dfcd3f0c38098fe2 (diff)
usb: dwc3: core: Power-off core/PHYs on system_suspend in host mode
Commit 689bf72c6e0d ("usb: dwc3: Don't reinitialize core during host bus-suspend/resume") updated suspend/resume routines to not power_off and reinit PHYs/core for host mode. It broke platforms that rely on DWC3 core to power_off PHYs to enter low power state on system suspend. Perform dwc3_core_exit/init only during host mode system_suspend/ resume to addresses power regression from above mentioned patch and also allow USB session to stay connected across runtime_suspend/resume in host mode. While at it also replace existing checks for HOST only dr_mode with current_dr_role to have similar core driver behavior for both Host-only and DRD+Host configurations. Fixes: 689bf72c6e0d ("usb: dwc3: Don't reinitialize core during host bus-suspend/resume") Reviewed-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Manu Gautam <mgautam@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc3/core.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index bc2467f0e6a7..59511f2cd3ac 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -100,6 +100,8 @@ static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
100 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 100 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
101 reg |= DWC3_GCTL_PRTCAPDIR(mode); 101 reg |= DWC3_GCTL_PRTCAPDIR(mode);
102 dwc3_writel(dwc->regs, DWC3_GCTL, reg); 102 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
103
104 dwc->current_dr_role = mode;
103} 105}
104 106
105static void __dwc3_set_mode(struct work_struct *work) 107static void __dwc3_set_mode(struct work_struct *work)
@@ -133,8 +135,6 @@ static void __dwc3_set_mode(struct work_struct *work)
133 135
134 dwc3_set_prtcap(dwc, dwc->desired_dr_role); 136 dwc3_set_prtcap(dwc, dwc->desired_dr_role);
135 137
136 dwc->current_dr_role = dwc->desired_dr_role;
137
138 spin_unlock_irqrestore(&dwc->lock, flags); 138 spin_unlock_irqrestore(&dwc->lock, flags);
139 139
140 switch (dwc->desired_dr_role) { 140 switch (dwc->desired_dr_role) {
@@ -219,7 +219,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
219 * XHCI driver will reset the host block. If dwc3 was configured for 219 * XHCI driver will reset the host block. If dwc3 was configured for
220 * host-only mode, then we can return early. 220 * host-only mode, then we can return early.
221 */ 221 */
222 if (dwc->dr_mode == USB_DR_MODE_HOST) 222 if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
223 return 0; 223 return 0;
224 224
225 reg = dwc3_readl(dwc->regs, DWC3_DCTL); 225 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -919,7 +919,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
919 919
920 switch (dwc->dr_mode) { 920 switch (dwc->dr_mode) {
921 case USB_DR_MODE_PERIPHERAL: 921 case USB_DR_MODE_PERIPHERAL:
922 dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE;
923 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 922 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
924 923
925 if (dwc->usb2_phy) 924 if (dwc->usb2_phy)
@@ -935,7 +934,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
935 } 934 }
936 break; 935 break;
937 case USB_DR_MODE_HOST: 936 case USB_DR_MODE_HOST:
938 dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST;
939 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 937 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
940 938
941 if (dwc->usb2_phy) 939 if (dwc->usb2_phy)
@@ -1287,7 +1285,7 @@ static int dwc3_remove(struct platform_device *pdev)
1287} 1285}
1288 1286
1289#ifdef CONFIG_PM 1287#ifdef CONFIG_PM
1290static int dwc3_suspend_common(struct dwc3 *dwc) 1288static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
1291{ 1289{
1292 unsigned long flags; 1290 unsigned long flags;
1293 1291
@@ -1299,6 +1297,10 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
1299 dwc3_core_exit(dwc); 1297 dwc3_core_exit(dwc);
1300 break; 1298 break;
1301 case DWC3_GCTL_PRTCAP_HOST: 1299 case DWC3_GCTL_PRTCAP_HOST:
1300 /* do nothing during host runtime_suspend */
1301 if (!PMSG_IS_AUTO(msg))
1302 dwc3_core_exit(dwc);
1303 break;
1302 default: 1304 default:
1303 /* do nothing */ 1305 /* do nothing */
1304 break; 1306 break;
@@ -1307,7 +1309,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
1307 return 0; 1309 return 0;
1308} 1310}
1309 1311
1310static int dwc3_resume_common(struct dwc3 *dwc) 1312static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
1311{ 1313{
1312 unsigned long flags; 1314 unsigned long flags;
1313 int ret; 1315 int ret;
@@ -1323,6 +1325,13 @@ static int dwc3_resume_common(struct dwc3 *dwc)
1323 spin_unlock_irqrestore(&dwc->lock, flags); 1325 spin_unlock_irqrestore(&dwc->lock, flags);
1324 break; 1326 break;
1325 case DWC3_GCTL_PRTCAP_HOST: 1327 case DWC3_GCTL_PRTCAP_HOST:
1328 /* nothing to do on host runtime_resume */
1329 if (!PMSG_IS_AUTO(msg)) {
1330 ret = dwc3_core_init(dwc);
1331 if (ret)
1332 return ret;
1333 }
1334 break;
1326 default: 1335 default:
1327 /* do nothing */ 1336 /* do nothing */
1328 break; 1337 break;
@@ -1334,12 +1343,11 @@ static int dwc3_resume_common(struct dwc3 *dwc)
1334static int dwc3_runtime_checks(struct dwc3 *dwc) 1343static int dwc3_runtime_checks(struct dwc3 *dwc)
1335{ 1344{
1336 switch (dwc->current_dr_role) { 1345 switch (dwc->current_dr_role) {
1337 case USB_DR_MODE_PERIPHERAL: 1346 case DWC3_GCTL_PRTCAP_DEVICE:
1338 case USB_DR_MODE_OTG:
1339 if (dwc->connected) 1347 if (dwc->connected)
1340 return -EBUSY; 1348 return -EBUSY;
1341 break; 1349 break;
1342 case USB_DR_MODE_HOST: 1350 case DWC3_GCTL_PRTCAP_HOST:
1343 default: 1351 default:
1344 /* do nothing */ 1352 /* do nothing */
1345 break; 1353 break;
@@ -1356,7 +1364,7 @@ static int dwc3_runtime_suspend(struct device *dev)
1356 if (dwc3_runtime_checks(dwc)) 1364 if (dwc3_runtime_checks(dwc))
1357 return -EBUSY; 1365 return -EBUSY;
1358 1366
1359 ret = dwc3_suspend_common(dwc); 1367 ret = dwc3_suspend_common(dwc, PMSG_AUTO_SUSPEND);
1360 if (ret) 1368 if (ret)
1361 return ret; 1369 return ret;
1362 1370
@@ -1372,7 +1380,7 @@ static int dwc3_runtime_resume(struct device *dev)
1372 1380
1373 device_init_wakeup(dev, false); 1381 device_init_wakeup(dev, false);
1374 1382
1375 ret = dwc3_resume_common(dwc); 1383 ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);
1376 if (ret) 1384 if (ret)
1377 return ret; 1385 return ret;
1378 1386
@@ -1419,7 +1427,7 @@ static int dwc3_suspend(struct device *dev)
1419 struct dwc3 *dwc = dev_get_drvdata(dev); 1427 struct dwc3 *dwc = dev_get_drvdata(dev);
1420 int ret; 1428 int ret;
1421 1429
1422 ret = dwc3_suspend_common(dwc); 1430 ret = dwc3_suspend_common(dwc, PMSG_SUSPEND);
1423 if (ret) 1431 if (ret)
1424 return ret; 1432 return ret;
1425 1433
@@ -1435,7 +1443,7 @@ static int dwc3_resume(struct device *dev)
1435 1443
1436 pinctrl_pm_select_default_state(dev); 1444 pinctrl_pm_select_default_state(dev);
1437 1445
1438 ret = dwc3_resume_common(dwc); 1446 ret = dwc3_resume_common(dwc, PMSG_RESUME);
1439 if (ret) 1447 if (ret)
1440 return ret; 1448 return ret;
1441 1449