Patchwork [03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.

login
register
mail settings
Submitter Artur Petrosyan
Date April 12, 2019, 1:38 p.m.
Message ID <8f99e3ceb45ede4526363bd9b44d417a6b6ff5cd.1555075928.git.arturp@synopsys.com>
Download mbox | patch
Permalink /patch/771831/
State New
Headers show

Comments

Artur Petrosyan - April 12, 2019, 1:38 p.m.
In host mode port power must be turned on when wakeup
detected or session request interrupt is detected.
Because, otherwise core wouldn't exit form partial
power down.

- Turned on the port power by setting HPRT0_PWR bit.

- Called dwc2_hcd_connect() function after enabling
  the power of the port.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>

---
 drivers/usb/dwc2/core_intr.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

-- 
2.11.0
Jules Maselbas - April 12, 2019, 2:20 p.m.
Hi Artur,

On Fri, Apr 12, 2019 at 01:38:56PM +0000, Artur Petrosyan wrote:
> In host mode port power must be turned on when wakeup
> detected or session request interrupt is detected.
> Because, otherwise core wouldn't exit form partial
> power down.
> 
> - Turned on the port power by setting HPRT0_PWR bit.
> 
> - Called dwc2_hcd_connect() function after enabling
>   the power of the port.
> 
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/core_intr.c | 24 +++++++++++++++++++++---
>  1 file changed, 21 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
> index 19ae2595f1c3..ce523fd2b1b4 100644
> --- a/drivers/usb/dwc2/core_intr.c
> +++ b/drivers/usb/dwc2/core_intr.c
> @@ -312,6 +312,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
>  static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
>  {
>  	int ret;
> +	u32 hprt0;
>  
>  	/* Clear interrupt */
>  	dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
> @@ -320,7 +321,8 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
>  		hsotg->lx_state);
>  
>  	if (dwc2_is_device_mode(hsotg)) {
> -		if (hsotg->lx_state == DWC2_L2) {
> +		if (hsotg->lx_state == DWC2_L2 &&
> +		    hsotg->params.power_down == 1) {
I think you can replace 1 with DWC2_POWER_DOWN_PARAM_PARTIAL.

[snip]

---
Best,
Jules
Artur Petrosyan - April 15, 2019, 7:58 a.m.
Hi Jules,

On 4/12/2019 18:21, Jules Maselbas wrote:
> Hi Artur,
> 
> On Fri, Apr 12, 2019 at 01:38:56PM +0000, Artur Petrosyan wrote:
>> In host mode port power must be turned on when wakeup
>> detected or session request interrupt is detected.
>> Because, otherwise core wouldn't exit form partial
>> power down.
>>
>> - Turned on the port power by setting HPRT0_PWR bit.
>>
>> - Called dwc2_hcd_connect() function after enabling
>>    the power of the port.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> ---
>>   drivers/usb/dwc2/core_intr.c | 24 +++++++++++++++++++++---
>>   1 file changed, 21 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
>> index 19ae2595f1c3..ce523fd2b1b4 100644
>> --- a/drivers/usb/dwc2/core_intr.c
>> +++ b/drivers/usb/dwc2/core_intr.c
>> @@ -312,6 +312,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
>>   static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
>>   {
>>   	int ret;
>> +	u32 hprt0;
>>   
>>   	/* Clear interrupt */
>>   	dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
>> @@ -320,7 +321,8 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
>>   		hsotg->lx_state);
>>   
>>   	if (dwc2_is_device_mode(hsotg)) {
>> -		if (hsotg->lx_state == DWC2_L2) {
>> +		if (hsotg->lx_state == DWC2_L2 &&
>> +		    hsotg->params.power_down == 1) {
> I think you can replace 1 with DWC2_POWER_DOWN_PARAM_PARTIAL.

Thank you for the review. Yeah, you are right it should be updated.

> 
> [snip]
> 
> ---
> Best,
> Jules
> 
>

Patch

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c

index 19ae2595f1c3..ce523fd2b1b4 100644

--- a/drivers/usb/dwc2/core_intr.c

+++ b/drivers/usb/dwc2/core_intr.c

@@ -312,6 +312,7 @@  static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)

 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
 	int ret;
+	u32 hprt0;

 
 	/* Clear interrupt */
 	dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
@@ -320,7 +321,8 @@  static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)

 		hsotg->lx_state);
 
 	if (dwc2_is_device_mode(hsotg)) {
-		if (hsotg->lx_state == DWC2_L2) {

+		if (hsotg->lx_state == DWC2_L2 &&

+		    hsotg->params.power_down == 1) {

 			ret = dwc2_exit_partial_power_down(hsotg, true);
 			if (ret && (ret != -ENOTSUPP))
 				dev_err(hsotg->dev,
@@ -332,6 +334,14 @@  static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)

 		 * established
 		 */
 		dwc2_hsotg_disconnect(hsotg);
+	} else {

+		/* Turn on the port power bit. */

+		hprt0 = dwc2_read_hprt0(hsotg);

+		hprt0 |= HPRT0_PWR;

+		dwc2_writel(hsotg, hprt0, HPRT0);

+

+		/* Connect hcd after port power is set. */

+		dwc2_hcd_connect(hsotg);

 	}
 }
 
@@ -396,6 +406,7 @@  static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)

 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 {
 	int ret;
+	u32 hprt0;

 
 	/* Clear interrupt */
 	dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
@@ -426,8 +437,6 @@  static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)

 		/* Change to L0 state */
 		hsotg->lx_state = DWC2_L0;
 	} else {
-		if (hsotg->params.power_down)

-			return;

 
 		if (hsotg->lx_state != DWC2_L1) {
 			u32 pcgcctl = dwc2_readl(hsotg, PCGCTL);
@@ -435,6 +444,15 @@  static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)

 			/* Restart the Phy Clock */
 			pcgcctl &= ~PCGCTL_STOPPCLK;
 			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+

+			/* Turn on the port power bit. */

+			hprt0 = dwc2_read_hprt0(hsotg);

+			hprt0 |= HPRT0_PWR;

+			dwc2_writel(hsotg, hprt0, HPRT0);

+

+			/* Connect hcd. */

+			dwc2_hcd_connect(hsotg);

+

 			mod_timer(&hsotg->wkp_timer,
 				  jiffies + msecs_to_jiffies(71));
 		} else {