@@ -4471,6 +4471,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
4471
4471
unsigned long flags ;
4472
4472
int ret = 0 ;
4473
4473
u32 hprt0 ;
4474
+ u32 pcgctl ;
4474
4475
4475
4476
spin_lock_irqsave (& hsotg -> lock , flags );
4476
4477
@@ -4486,7 +4487,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
4486
4487
if (hsotg -> op_state == OTG_STATE_B_PERIPHERAL )
4487
4488
goto unlock ;
4488
4489
4489
- if (hsotg -> params .power_down != DWC2_POWER_DOWN_PARAM_PARTIAL )
4490
+ if (hsotg -> params .power_down > DWC2_POWER_DOWN_PARAM_PARTIAL )
4490
4491
goto skip_power_saving ;
4491
4492
4492
4493
/*
@@ -4495,21 +4496,35 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
4495
4496
*/
4496
4497
if (!hsotg -> bus_suspended ) {
4497
4498
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
+ }
4504
4514
}
4505
4515
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 );
4513
4528
}
4514
4529
4515
4530
/* Ask phy to be suspended */
@@ -4519,9 +4534,6 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
4519
4534
spin_lock_irqsave (& hsotg -> lock , flags );
4520
4535
}
4521
4536
4522
- /* After entering partial_power_down, hardware is no more accessible */
4523
- clear_bit (HCD_FLAG_HW_ACCESSIBLE , & hcd -> flags );
4524
-
4525
4537
skip_power_saving :
4526
4538
hsotg -> lx_state = DWC2_L2 ;
4527
4539
unlock :
@@ -4534,6 +4546,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
4534
4546
{
4535
4547
struct dwc2_hsotg * hsotg = dwc2_hcd_to_hsotg (hcd );
4536
4548
unsigned long flags ;
4549
+ u32 pcgctl ;
4537
4550
int ret = 0 ;
4538
4551
4539
4552
spin_lock_irqsave (& hsotg -> lock , flags );
@@ -4544,17 +4557,11 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
4544
4557
if (hsotg -> lx_state != DWC2_L2 )
4545
4558
goto unlock ;
4546
4559
4547
- if (hsotg -> params .power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ) {
4560
+ if (hsotg -> params .power_down > DWC2_POWER_DOWN_PARAM_PARTIAL ) {
4548
4561
hsotg -> lx_state = DWC2_L0 ;
4549
4562
goto unlock ;
4550
4563
}
4551
4564
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
-
4558
4565
/*
4559
4566
* Enable power if not already done.
4560
4567
* This must not be spinlocked since duration
@@ -4566,10 +4573,23 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
4566
4573
spin_lock_irqsave (& hsotg -> lock , flags );
4567
4574
}
4568
4575
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
+ }
4573
4593
4574
4594
hsotg -> lx_state = DWC2_L0 ;
4575
4595
@@ -4581,10 +4601,12 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
4581
4601
spin_unlock_irqrestore (& hsotg -> lock , flags );
4582
4602
dwc2_port_resume (hsotg );
4583
4603
} else {
4584
- dwc2_vbus_supply_init (hsotg );
4604
+ if (hsotg -> params .power_down == DWC2_POWER_DOWN_PARAM_PARTIAL ) {
4605
+ dwc2_vbus_supply_init (hsotg );
4585
4606
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
+ }
4588
4610
4589
4611
/*
4590
4612
* Clear Port Enable and Port Status changes.
0 commit comments