Skip to content

Commit 6f6d705

Browse files
diandersFelipe Balbi
authored andcommitted
usb: dwc2: bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE
This is an attempt to rehash commit 0cf884e ("usb: dwc2: add bus suspend/resume for dwc2") on ToT. That commit was reverted in commit b0bb9bb ("Revert "usb: dwc2: add bus suspend/resume for dwc2"") because apparently it broke the Altera SOCFPGA. With all the changes that have happened to dwc2 in the meantime, it's possible that the Altera SOCFPGA will just magically work with this change now. ...and it would be good to get bus suspend/resume implemented. This change is a forward port of one that's been living in the Chrome OS 3.14 kernel tree. Signed-off-by: Douglas Anderson <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent c999933 commit 6f6d705

File tree

1 file changed

+53
-31
lines changed

1 file changed

+53
-31
lines changed

drivers/usb/dwc2/hcd.c

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4471,6 +4471,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
44714471
unsigned long flags;
44724472
int ret = 0;
44734473
u32 hprt0;
4474+
u32 pcgctl;
44744475

44754476
spin_lock_irqsave(&hsotg->lock, flags);
44764477

@@ -4486,7 +4487,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
44864487
if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
44874488
goto unlock;
44884489

4489-
if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
4490+
if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL)
44904491
goto skip_power_saving;
44914492

44924493
/*
@@ -4495,21 +4496,35 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
44954496
*/
44964497
if (!hsotg->bus_suspended) {
44974498
hprt0 = dwc2_read_hprt0(hsotg);
4498-
hprt0 |= HPRT0_SUSP;
4499-
hprt0 &= ~HPRT0_PWR;
4500-
dwc2_writel(hsotg, hprt0, HPRT0);
4501-
spin_unlock_irqrestore(&hsotg->lock, flags);
4502-
dwc2_vbus_supply_exit(hsotg);
4503-
spin_lock_irqsave(&hsotg->lock, flags);
4499+
if (hprt0 & HPRT0_CONNSTS) {
4500+
hprt0 |= HPRT0_SUSP;
4501+
if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL)
4502+
hprt0 &= ~HPRT0_PWR;
4503+
dwc2_writel(hsotg, hprt0, HPRT0);
4504+
}
4505+
if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {
4506+
spin_unlock_irqrestore(&hsotg->lock, flags);
4507+
dwc2_vbus_supply_exit(hsotg);
4508+
spin_lock_irqsave(&hsotg->lock, flags);
4509+
} else {
4510+
pcgctl = readl(hsotg->regs + PCGCTL);
4511+
pcgctl |= PCGCTL_STOPPCLK;
4512+
writel(pcgctl, hsotg->regs + PCGCTL);
4513+
}
45044514
}
45054515

4506-
/* Enter partial_power_down */
4507-
ret = dwc2_enter_partial_power_down(hsotg);
4508-
if (ret) {
4509-
if (ret != -ENOTSUPP)
4510-
dev_err(hsotg->dev,
4511-
"enter partial_power_down failed\n");
4512-
goto skip_power_saving;
4516+
if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {
4517+
/* Enter partial_power_down */
4518+
ret = dwc2_enter_partial_power_down(hsotg);
4519+
if (ret) {
4520+
if (ret != -ENOTSUPP)
4521+
dev_err(hsotg->dev,
4522+
"enter partial_power_down failed\n");
4523+
goto skip_power_saving;
4524+
}
4525+
4526+
/* After entering partial_power_down, hardware is no more accessible */
4527+
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
45134528
}
45144529

45154530
/* Ask phy to be suspended */
@@ -4519,9 +4534,6 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
45194534
spin_lock_irqsave(&hsotg->lock, flags);
45204535
}
45214536

4522-
/* After entering partial_power_down, hardware is no more accessible */
4523-
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
4524-
45254537
skip_power_saving:
45264538
hsotg->lx_state = DWC2_L2;
45274539
unlock:
@@ -4534,6 +4546,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
45344546
{
45354547
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
45364548
unsigned long flags;
4549+
u32 pcgctl;
45374550
int ret = 0;
45384551

45394552
spin_lock_irqsave(&hsotg->lock, flags);
@@ -4544,17 +4557,11 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
45444557
if (hsotg->lx_state != DWC2_L2)
45454558
goto unlock;
45464559

4547-
if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
4560+
if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) {
45484561
hsotg->lx_state = DWC2_L0;
45494562
goto unlock;
45504563
}
45514564

4552-
/*
4553-
* Set HW accessible bit before powering on the controller
4554-
* since an interrupt may rise.
4555-
*/
4556-
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
4557-
45584565
/*
45594566
* Enable power if not already done.
45604567
* This must not be spinlocked since duration
@@ -4566,10 +4573,23 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
45664573
spin_lock_irqsave(&hsotg->lock, flags);
45674574
}
45684575

4569-
/* Exit partial_power_down */
4570-
ret = dwc2_exit_partial_power_down(hsotg, true);
4571-
if (ret && (ret != -ENOTSUPP))
4572-
dev_err(hsotg->dev, "exit partial_power_down failed\n");
4576+
if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {
4577+
/*
4578+
* Set HW accessible bit before powering on the controller
4579+
* since an interrupt may rise.
4580+
*/
4581+
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
4582+
4583+
4584+
/* Exit partial_power_down */
4585+
ret = dwc2_exit_partial_power_down(hsotg, true);
4586+
if (ret && (ret != -ENOTSUPP))
4587+
dev_err(hsotg->dev, "exit partial_power_down failed\n");
4588+
} else {
4589+
pcgctl = readl(hsotg->regs + PCGCTL);
4590+
pcgctl &= ~PCGCTL_STOPPCLK;
4591+
writel(pcgctl, hsotg->regs + PCGCTL);
4592+
}
45734593

45744594
hsotg->lx_state = DWC2_L0;
45754595

@@ -4581,10 +4601,12 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
45814601
spin_unlock_irqrestore(&hsotg->lock, flags);
45824602
dwc2_port_resume(hsotg);
45834603
} else {
4584-
dwc2_vbus_supply_init(hsotg);
4604+
if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {
4605+
dwc2_vbus_supply_init(hsotg);
45854606

4586-
/* Wait for controller to correctly update D+/D- level */
4587-
usleep_range(3000, 5000);
4607+
/* Wait for controller to correctly update D+/D- level */
4608+
usleep_range(3000, 5000);
4609+
}
45884610

45894611
/*
45904612
* Clear Port Enable and Port Status changes.

0 commit comments

Comments
 (0)