usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
When device cable is disconnected core receives suspend interrupt and enters hibernation. After entering into hibernation GPWRDN_RST_DET and GPWRDN_STS_CHGINT interrupts are asserted. Allowed exit from gadget hibernation from GPWRDN_RST_DET by checking only linestate. Changed the return type of "dwc2_handle_gpwrdn_intr()" function from void to int because exit from hibernation functions have a return value. Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com> Link: https://lore.kernel.org/r/20210416124723.B6F17A005C@mailhost.synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									24d209dba5
								
							
						
					
					
						commit
						4111d5f805
					
				| @ -751,10 +751,11 @@ static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg, | ||||
|  * The GPWRDN interrupts are those that occur in both Host and | ||||
|  * Device mode while core is in hibernated state. | ||||
|  */ | ||||
| static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) | ||||
| static int dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) | ||||
| { | ||||
| 	u32 gpwrdn; | ||||
| 	int linestate; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	gpwrdn = dwc2_readl(hsotg, GPWRDN); | ||||
| 	/* clear all interrupt */ | ||||
| @ -778,17 +779,27 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) | ||||
| 		if (hsotg->hw_params.hibernation && | ||||
| 		    hsotg->hibernated) { | ||||
| 			if (gpwrdn & GPWRDN_IDSTS) { | ||||
| 				dwc2_exit_hibernation(hsotg, 0, 0, 0); | ||||
| 				ret = dwc2_exit_hibernation(hsotg, 0, 0, 0); | ||||
| 				if (ret) | ||||
| 					dev_err(hsotg->dev, | ||||
| 						"exit hibernation failed.\n"); | ||||
| 				call_gadget(hsotg, resume); | ||||
| 			} else { | ||||
| 				dwc2_exit_hibernation(hsotg, 1, 0, 1); | ||||
| 				ret = dwc2_exit_hibernation(hsotg, 1, 0, 1); | ||||
| 				if (ret) | ||||
| 					dev_err(hsotg->dev, | ||||
| 						"exit hibernation failed.\n"); | ||||
| 			} | ||||
| 		} | ||||
| 	} else if ((gpwrdn & GPWRDN_RST_DET) && | ||||
| 		   (gpwrdn & GPWRDN_RST_DET_MSK)) { | ||||
| 		dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__); | ||||
| 		if (!linestate && (gpwrdn & GPWRDN_BSESSVLD)) | ||||
| 			dwc2_exit_hibernation(hsotg, 0, 1, 0); | ||||
| 		if (!linestate) { | ||||
| 			ret = dwc2_exit_hibernation(hsotg, 0, 1, 0); | ||||
| 			if (ret) | ||||
| 				dev_err(hsotg->dev, | ||||
| 					"exit hibernation failed.\n"); | ||||
| 		} | ||||
| 	} else if ((gpwrdn & GPWRDN_STS_CHGINT) && | ||||
| 		   (gpwrdn & GPWRDN_STS_CHGINT_MSK)) { | ||||
| 		dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__); | ||||
| @ -800,6 +811,8 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) | ||||
| 		 */ | ||||
| 		dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user