mbox series

[00/14] usb: dwc2: Fix Partial Power down issues.

Message ID cover.1617782102.git.Arthur.Petrosyan@synopsys.com
Headers show
Series usb: dwc2: Fix Partial Power down issues. | expand

Message

Artur Petrosyan April 7, 2021, 10 a.m. UTC
This patch set fixes and improves the Partial Power Down mode for
dwc2 core.
It adds support for the following cases
    1. Entering and exiting partial power down when a port is
       suspended, resumed, port reset is asserted.
    2. Exiting the partial power down mode before removing driver.
    3. Exiting partial power down in wakeup detected interrupt handler.
    4. Exiting from partial power down mode when connector ID.
       status changes to "connId B

It updates and fixes the implementation of dwc2 entering and
exiting partial power down mode when the system (PC) is suspended.

The patch set also improves the implementation of function handlers
for entering and exiting host or device partial power down.

NOTE: This is the second patch set in the power saving mode fixes
series.
This patch set is part of multiple series and is continuation
of the "usb: dwc2: Fix and improve power saving modes" patch set.
(Patch set link: https://marc.info/?l=linux-usb&m=160379622403975&w=2).
The patches that were included in the "usb: dwc2:
Fix and improve power saving modes" which was submitted
earlier was too large and needed to be split up into
smaller patch sets. 


Artur Petrosyan (14):
  usb: dwc2: Add device partial power down functions
  usb: dwc2: Add host partial power down functions
  usb: dwc2: Update enter and exit partial power down functions
  usb: dwc2: Add partial power down exit flow in wakeup intr.
  usb: dwc2: Update port suspend/resume function definitions.
  usb: dwc2: Add enter partial power down when port is suspended
  usb: dwc2: Add exit partial power down when port is resumed
  usb: dwc2: Add exit partial power down when port reset is asserted
  usb: dwc2: Add part. power down exit from
    dwc2_conn_id_status_change().
  usb: dwc2: Allow exit partial power down in urb enqueue
  usb: dwc2: Fix session request interrupt handler
  usb: dwc2: Update partial power down entering by system suspend
  usb: dwc2: Fix partial power down exiting by system resume
  usb: dwc2: Add exit partial power down before removing driver

 drivers/usb/dwc2/core.c      | 113 ++-------
 drivers/usb/dwc2/core.h      |  27 ++-
 drivers/usb/dwc2/core_intr.c |  46 ++--
 drivers/usb/dwc2/gadget.c    | 148 ++++++++++-
 drivers/usb/dwc2/hcd.c       | 458 +++++++++++++++++++++++++----------
 drivers/usb/dwc2/hw.h        |   1 +
 drivers/usb/dwc2/platform.c  |  11 +-
 7 files changed, 558 insertions(+), 246 deletions(-)


base-commit: e9fcb07704fcef6fa6d0333fd2b3a62442eaf45b

Comments

Artur Petrosyan April 8, 2021, 5:57 a.m. UTC | #1
Hi Greg,

On 4/7/2021 14:00, Artur Petrosyan wrote:
> This patch set fixes and improves the Partial Power Down mode for

> dwc2 core.

> It adds support for the following cases

>      1. Entering and exiting partial power down when a port is

>         suspended, resumed, port reset is asserted.

>      2. Exiting the partial power down mode before removing driver.

>      3. Exiting partial power down in wakeup detected interrupt handler.

>      4. Exiting from partial power down mode when connector ID.

>         status changes to "connId B

> 

> It updates and fixes the implementation of dwc2 entering and

> exiting partial power down mode when the system (PC) is suspended.

> 

> The patch set also improves the implementation of function handlers

> for entering and exiting host or device partial power down.

> 

> NOTE: This is the second patch set in the power saving mode fixes

> series.

> This patch set is part of multiple series and is continuation

> of the "usb: dwc2: Fix and improve power saving modes" patch set.

> (Patch set link: https://marc.info/?l=linux-usb&m=160379622403975&w=2).

> The patches that were included in the "usb: dwc2:

> Fix and improve power saving modes" which was submitted

> earlier was too large and needed to be split up into

> smaller patch sets.

> 

> 

> Artur Petrosyan (14):

>    usb: dwc2: Add device partial power down functions

>    usb: dwc2: Add host partial power down functions

>    usb: dwc2: Update enter and exit partial power down functions

>    usb: dwc2: Add partial power down exit flow in wakeup intr.

>    usb: dwc2: Update port suspend/resume function definitions.

>    usb: dwc2: Add enter partial power down when port is suspended

>    usb: dwc2: Add exit partial power down when port is resumed

>    usb: dwc2: Add exit partial power down when port reset is asserted

>    usb: dwc2: Add part. power down exit from

>      dwc2_conn_id_status_change().

>    usb: dwc2: Allow exit partial power down in urb enqueue

>    usb: dwc2: Fix session request interrupt handler

>    usb: dwc2: Update partial power down entering by system suspend

>    usb: dwc2: Fix partial power down exiting by system resume

>    usb: dwc2: Add exit partial power down before removing driver

> 

>   drivers/usb/dwc2/core.c      | 113 ++-------

>   drivers/usb/dwc2/core.h      |  27 ++-

>   drivers/usb/dwc2/core_intr.c |  46 ++--

>   drivers/usb/dwc2/gadget.c    | 148 ++++++++++-

>   drivers/usb/dwc2/hcd.c       | 458 +++++++++++++++++++++++++----------

>   drivers/usb/dwc2/hw.h        |   1 +

>   drivers/usb/dwc2/platform.c  |  11 +-

>   7 files changed, 558 insertions(+), 246 deletions(-)

> 

> 

> base-commit: e9fcb07704fcef6fa6d0333fd2b3a62442eaf45b

> 

I have submitted this patch set yesterday. It contains 14 patches. But 
only 2 of those patches were received by LKML only the cover letter and 
the 13th patch. 
(https://lore.kernel.org/linux-usb/cover.1617782102.git.Arthur.Petrosyan@synopsys.com/T/#t)

I checked here at Synopsys, Minas did receive all the patches as his 
email is in To list. Could this be an issue of vger.kernel.org mailing 
server?

Because I checked every local possibility that could result to such 
behavior. The patch 13 which was received by LKML has the similar 
content as the other patches.

The mailing tool that was used is ssmtp, checked all the configurations 
everything is fine.

Could you please suggest what should I do in this situation?

Regards,
Artur
Artur Petrosyan April 8, 2021, 9:17 a.m. UTC | #2
Hi Greg,

On 4/8/2021 11:28, Artur Petrosyan wrote:
> This patch set fixes and improves the Partial Power Down mode for

> dwc2 core.

> It adds support for the following cases

>      1. Entering and exiting partial power down when a port is

>         suspended, resumed, port reset is asserted.

>      2. Exiting the partial power down mode before removing driver.

>      3. Exiting partial power down in wakeup detected interrupt handler.

>      4. Exiting from partial power down mode when connector ID.

>         status changes to "connId B

> 

> It updates and fixes the implementation of dwc2 entering and

> exiting partial power down mode when the system (PC) is suspended.

> 

> The patch set also improves the implementation of function handlers

> for entering and exiting host or device partial power down.

> 

> NOTE: This is the second patch set in the power saving mode fixes

> series.

> This patch set is part of multiple series and is continuation

> of the "usb: dwc2: Fix and improve power saving modes" patch set.

> (Patch set link: https://marc.info/?l=linux-usb&m=160379622403975&w=2).

> The patches that were included in the "usb: dwc2:

> Fix and improve power saving modes" which was submitted

> earlier was too large and needed to be split up into

> smaller patch sets.

> 

> Changes since V1:

> No changes in the patches or the source code.

> Sending the second version of the patch set because the first version

> was not received by vger.kernel.org.

> 

> 

> 

> Artur Petrosyan (14):

>    usb: dwc2: Add device partial power down functions

>    usb: dwc2: Add host partial power down functions

>    usb: dwc2: Update enter and exit partial power down functions

>    usb: dwc2: Add partial power down exit flow in wakeup intr.

>    usb: dwc2: Update port suspend/resume function definitions.

>    usb: dwc2: Add enter partial power down when port is suspended

>    usb: dwc2: Add exit partial power down when port is resumed

>    usb: dwc2: Add exit partial power down when port reset is asserted

>    usb: dwc2: Add part. power down exit from

>      dwc2_conn_id_status_change().

>    usb: dwc2: Allow exit partial power down in urb enqueue

>    usb: dwc2: Fix session request interrupt handler

>    usb: dwc2: Update partial power down entering by system suspend

>    usb: dwc2: Fix partial power down exiting by system resume

>    usb: dwc2: Add exit partial power down before removing driver

> 

>   drivers/usb/dwc2/core.c      | 113 ++-------

>   drivers/usb/dwc2/core.h      |  27 ++-

>   drivers/usb/dwc2/core_intr.c |  46 ++--

>   drivers/usb/dwc2/gadget.c    | 148 ++++++++++-

>   drivers/usb/dwc2/hcd.c       | 458 +++++++++++++++++++++++++----------

>   drivers/usb/dwc2/hw.h        |   1 +

>   drivers/usb/dwc2/platform.c  |  11 +-

>   7 files changed, 558 insertions(+), 246 deletions(-)

> 

> 

> base-commit: e9fcb07704fcef6fa6d0333fd2b3a62442eaf45b

> 


Re sending as a "v2" did not work :(.
The patches are not in lore again.

Could the issue be with a comma in the end of To: or Cc: list?
Let me remove the comma in the end of those lists and try sending as "v3".

Regards,
Artur
Artur Petrosyan April 8, 2021, 9:44 a.m. UTC | #3
This patch set fixes and improves the Partial Power Down mode for
dwc2 core.
It adds support for the following cases
    1. Entering and exiting partial power down when a port is
       suspended, resumed, port reset is asserted.
    2. Exiting the partial power down mode before removing driver.
    3. Exiting partial power down in wakeup detected interrupt handler.
    4. Exiting from partial power down mode when connector ID.
       status changes to "connId B

It updates and fixes the implementation of dwc2 entering and
exiting partial power down mode when the system (PC) is suspended.

The patch set also improves the implementation of function handlers
for entering and exiting host or device partial power down.

NOTE: This is the second patch set in the power saving mode fixes
series.
This patch set is part of multiple series and is continuation
of the "usb: dwc2: Fix and improve power saving modes" patch set.
(Patch set link: https://marc.info/?l=linux-usb&m=160379622403975&w=2).
The patches that were included in the "usb: dwc2:
Fix and improve power saving modes" which was submitted
earlier was too large and needed to be split up into
smaller patch sets.

Changes since V2:
No changes in the patches or the source code.
Assuming that the issue due to which the patches are not reaching to
vger.kernel.org is a comma in the end of To: or Cc: lists removed
commas in the end of those lists in each email of patches.


Artur Petrosyan (14):
  usb: dwc2: Add device partial power down functions
  usb: dwc2: Add host partial power down functions
  usb: dwc2: Update enter and exit partial power down functions
  usb: dwc2: Add partial power down exit flow in wakeup intr.
  usb: dwc2: Update port suspend/resume function definitions.
  usb: dwc2: Add enter partial power down when port is suspended
  usb: dwc2: Add exit partial power down when port is resumed
  usb: dwc2: Add exit partial power down when port reset is asserted
  usb: dwc2: Add part. power down exit from
    dwc2_conn_id_status_change().
  usb: dwc2: Allow exit partial power down in urb enqueue
  usb: dwc2: Fix session request interrupt handler
  usb: dwc2: Update partial power down entering by system suspend
  usb: dwc2: Fix partial power down exiting by system resume
  usb: dwc2: Add exit partial power down before removing driver

 drivers/usb/dwc2/core.c      | 113 ++-------
 drivers/usb/dwc2/core.h      |  27 ++-
 drivers/usb/dwc2/core_intr.c |  46 ++--
 drivers/usb/dwc2/gadget.c    | 148 ++++++++++-
 drivers/usb/dwc2/hcd.c       | 458 +++++++++++++++++++++++++----------
 drivers/usb/dwc2/hw.h        |   1 +
 drivers/usb/dwc2/platform.c  |  11 +-
 7 files changed, 558 insertions(+), 246 deletions(-)


base-commit: e9fcb07704fcef6fa6d0333fd2b3a62442eaf45b
Artur Petrosyan April 8, 2021, 10:09 a.m. UTC | #4
Hi Greg,

On 4/8/2021 13:17, Artur Petrosyan wrote:
> Hi Greg,

> 

> On 4/8/2021 11:28, Artur Petrosyan wrote:

>> This patch set fixes and improves the Partial Power Down mode for

>> dwc2 core.

>> It adds support for the following cases

>>       1. Entering and exiting partial power down when a port is

>>          suspended, resumed, port reset is asserted.

>>       2. Exiting the partial power down mode before removing driver.

>>       3. Exiting partial power down in wakeup detected interrupt handler.

>>       4. Exiting from partial power down mode when connector ID.

>>          status changes to "connId B

>>

>> It updates and fixes the implementation of dwc2 entering and

>> exiting partial power down mode when the system (PC) is suspended.

>>

>> The patch set also improves the implementation of function handlers

>> for entering and exiting host or device partial power down.

>>

>> NOTE: This is the second patch set in the power saving mode fixes

>> series.

>> This patch set is part of multiple series and is continuation

>> of the "usb: dwc2: Fix and improve power saving modes" patch set.

>> (Patch set link: https://urldefense.com/v3/__https://marc.info/?l=linux-usb&m=160379622403975&w=2__;!!A4F2R9G_pg!IJ-Xl1ZwQU2kmqHB3ITyWyno9BgpWUsC647AqK7GIlgzJu9BzT6VN7jt--__fGdMtgWF69M$ ).

>> The patches that were included in the "usb: dwc2:

>> Fix and improve power saving modes" which was submitted

>> earlier was too large and needed to be split up into

>> smaller patch sets.

>>

>> Changes since V1:

>> No changes in the patches or the source code.

>> Sending the second version of the patch set because the first version

>> was not received by vger.kernel.org.

>>

>>

>>

>> Artur Petrosyan (14):

>>     usb: dwc2: Add device partial power down functions

>>     usb: dwc2: Add host partial power down functions

>>     usb: dwc2: Update enter and exit partial power down functions

>>     usb: dwc2: Add partial power down exit flow in wakeup intr.

>>     usb: dwc2: Update port suspend/resume function definitions.

>>     usb: dwc2: Add enter partial power down when port is suspended

>>     usb: dwc2: Add exit partial power down when port is resumed

>>     usb: dwc2: Add exit partial power down when port reset is asserted

>>     usb: dwc2: Add part. power down exit from

>>       dwc2_conn_id_status_change().

>>     usb: dwc2: Allow exit partial power down in urb enqueue

>>     usb: dwc2: Fix session request interrupt handler

>>     usb: dwc2: Update partial power down entering by system suspend

>>     usb: dwc2: Fix partial power down exiting by system resume

>>     usb: dwc2: Add exit partial power down before removing driver

>>

>>    drivers/usb/dwc2/core.c      | 113 ++-------

>>    drivers/usb/dwc2/core.h      |  27 ++-

>>    drivers/usb/dwc2/core_intr.c |  46 ++--

>>    drivers/usb/dwc2/gadget.c    | 148 ++++++++++-

>>    drivers/usb/dwc2/hcd.c       | 458 +++++++++++++++++++++++++----------

>>    drivers/usb/dwc2/hw.h        |   1 +

>>    drivers/usb/dwc2/platform.c  |  11 +-

>>    7 files changed, 558 insertions(+), 246 deletions(-)

>>

>>

>> base-commit: e9fcb07704fcef6fa6d0333fd2b3a62442eaf45b

>>

> 

> Re sending as a "v2" did not work :(.

> The patches are not in lore again.

> 

> Could the issue be with a comma in the end of To: or Cc: list?

> Let me remove the comma in the end of those lists and try sending as "v3".

> 

> Regards,

> Artur

> 


I just removed the comma in the end of those lists and resent the patch 
set as a "v3" and they are already seen in lore.
There is one strange thing though on lore. Some patch titles are not 
fully visible.

For sure the issue was comma in the end of To: or Cc: lists.
Not working example.
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, 
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,

Working example.
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, 
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org

If the comma is at least in the end of one of those lists (To: or Cc:) 
vger.kernel.org mailing server will not accept them.

Regards,
Artur
Greg Kroah-Hartman April 8, 2021, 11 a.m. UTC | #5
On Thu, Apr 08, 2021 at 10:09:20AM +0000, Artur Petrosyan wrote:
> Hi Greg,

> 

> On 4/8/2021 13:17, Artur Petrosyan wrote:

> > Hi Greg,

> > 

> > On 4/8/2021 11:28, Artur Petrosyan wrote:

> >> This patch set fixes and improves the Partial Power Down mode for

> >> dwc2 core.

> >> It adds support for the following cases

> >>       1. Entering and exiting partial power down when a port is

> >>          suspended, resumed, port reset is asserted.

> >>       2. Exiting the partial power down mode before removing driver.

> >>       3. Exiting partial power down in wakeup detected interrupt handler.

> >>       4. Exiting from partial power down mode when connector ID.

> >>          status changes to "connId B

> >>

> >> It updates and fixes the implementation of dwc2 entering and

> >> exiting partial power down mode when the system (PC) is suspended.

> >>

> >> The patch set also improves the implementation of function handlers

> >> for entering and exiting host or device partial power down.

> >>

> >> NOTE: This is the second patch set in the power saving mode fixes

> >> series.

> >> This patch set is part of multiple series and is continuation

> >> of the "usb: dwc2: Fix and improve power saving modes" patch set.

> >> (Patch set link: https://urldefense.com/v3/__https://marc.info/?l=linux-usb&m=160379622403975&w=2__;!!A4F2R9G_pg!IJ-Xl1ZwQU2kmqHB3ITyWyno9BgpWUsC647AqK7GIlgzJu9BzT6VN7jt--__fGdMtgWF69M$ ).

> >> The patches that were included in the "usb: dwc2:

> >> Fix and improve power saving modes" which was submitted

> >> earlier was too large and needed to be split up into

> >> smaller patch sets.

> >>

> >> Changes since V1:

> >> No changes in the patches or the source code.

> >> Sending the second version of the patch set because the first version

> >> was not received by vger.kernel.org.

> >>

> >>

> >>

> >> Artur Petrosyan (14):

> >>     usb: dwc2: Add device partial power down functions

> >>     usb: dwc2: Add host partial power down functions

> >>     usb: dwc2: Update enter and exit partial power down functions

> >>     usb: dwc2: Add partial power down exit flow in wakeup intr.

> >>     usb: dwc2: Update port suspend/resume function definitions.

> >>     usb: dwc2: Add enter partial power down when port is suspended

> >>     usb: dwc2: Add exit partial power down when port is resumed

> >>     usb: dwc2: Add exit partial power down when port reset is asserted

> >>     usb: dwc2: Add part. power down exit from

> >>       dwc2_conn_id_status_change().

> >>     usb: dwc2: Allow exit partial power down in urb enqueue

> >>     usb: dwc2: Fix session request interrupt handler

> >>     usb: dwc2: Update partial power down entering by system suspend

> >>     usb: dwc2: Fix partial power down exiting by system resume

> >>     usb: dwc2: Add exit partial power down before removing driver

> >>

> >>    drivers/usb/dwc2/core.c      | 113 ++-------

> >>    drivers/usb/dwc2/core.h      |  27 ++-

> >>    drivers/usb/dwc2/core_intr.c |  46 ++--

> >>    drivers/usb/dwc2/gadget.c    | 148 ++++++++++-

> >>    drivers/usb/dwc2/hcd.c       | 458 +++++++++++++++++++++++++----------

> >>    drivers/usb/dwc2/hw.h        |   1 +

> >>    drivers/usb/dwc2/platform.c  |  11 +-

> >>    7 files changed, 558 insertions(+), 246 deletions(-)

> >>

> >>

> >> base-commit: e9fcb07704fcef6fa6d0333fd2b3a62442eaf45b

> >>

> > 

> > Re sending as a "v2" did not work :(.

> > The patches are not in lore again.

> > 

> > Could the issue be with a comma in the end of To: or Cc: list?

> > Let me remove the comma in the end of those lists and try sending as "v3".

> > 

> > Regards,

> > Artur

> > 

> 

> I just removed the comma in the end of those lists and resent the patch 

> set as a "v3" and they are already seen in lore.

> There is one strange thing though on lore. Some patch titles are not 

> fully visible.

> 

> For sure the issue was comma in the end of To: or Cc: lists.

> Not working example.

> To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, 

> linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,


That's an invalid To: line for email.

> Working example.

> To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, 

> linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org


That's a correct line.

> If the comma is at least in the end of one of those lists (To: or Cc:) 

> vger.kernel.org mailing server will not accept them.


I recommend using 'git send-email' with the --to="foo@bar.com" type
options so that you don't have to hand-edit the lines to try to get
stuff like this correct, as it is easy to get wrong.

thanks,

greg k-h
Minas Harutyunyan April 8, 2021, 1:39 p.m. UTC | #6
On 4/8/2021 1:45 PM, Artur Petrosyan wrote:
> Earlier "dwc2_port_suspend()" and "dwc2_port_resume()" functions

> were implemented without proper description and host or device mode

> difference.

> 

> - Added "dwc2_port_suspend" and "dwc2_port_resume" functions to

>    "core.h" header file.

> 

> - Updated function description in documentation.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/core.h |  4 ++++

>   drivers/usb/dwc2/hcd.c  | 25 +++++++++++++++++++------

>   2 files changed, 23 insertions(+), 6 deletions(-)

> 

> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h

> index 39037709a2ad..b7d99cf9e84c 100644

> --- a/drivers/usb/dwc2/core.h

> +++ b/drivers/usb/dwc2/core.h

> @@ -1470,6 +1470,8 @@ void dwc2_hcd_connect(struct dwc2_hsotg *hsotg);

>   void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);

>   void dwc2_hcd_start(struct dwc2_hsotg *hsotg);

>   int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup);

> +void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex);

> +void dwc2_port_resume(struct dwc2_hsotg *hsotg);

>   int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);

>   int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);

>   int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);

> @@ -1493,6 +1495,8 @@ static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}

>   static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}

>   static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)

>   { return 0; }

> +static inline void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) {}

> +static inline void dwc2_port_resume(struct dwc2_hsotg *hsotg) {}

>   static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)

>   { return 0; }

>   static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index dd0362e07444..f4247a66c2b2 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -56,8 +56,6 @@

>   #include "core.h"

>   #include "hcd.h"

>   

> -static void dwc2_port_resume(struct dwc2_hsotg *hsotg);

> -

>   /*

>    * =========================================================================

>    *  Host Core Layer Functions

> @@ -3277,8 +3275,16 @@ static int dwc2_host_is_b_hnp_enabled(struct dwc2_hsotg *hsotg)

>   	return hcd->self.b_hnp_enable;

>   }

>   

> -/* Must NOT be called with interrupt disabled or spinlock held */

> -static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

> +/**

> + * dwc2_port_suspend() - Put controller in suspend mode for host.

> + *

> + * @hsotg: Programming view of the DWC_otg controller

> + * @windex: The control request wIndex field

> + *

> + * This function is for entering Host mode suspend.

> + * Must NOT be called with interrupt disabled or spinlock held.

> + */

> +void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>   {

>   	unsigned long flags;

>   	u32 hprt0;

> @@ -3328,8 +3334,15 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>   	}

>   }

>   

> -/* Must NOT be called with interrupt disabled or spinlock held */

> -static void dwc2_port_resume(struct dwc2_hsotg *hsotg)

> +/**

> + * dwc2_port_resume() - Exit controller from suspend mode for host.

> + *

> + * @hsotg: Programming view of the DWC_otg controller

> + *

> + * This function is for exiting Host mode suspend.

> + * Must NOT be called with interrupt disabled or spinlock held.

> + */

> +void dwc2_port_resume(struct dwc2_hsotg *hsotg)

>   {

>   	unsigned long flags;

>   	u32 hprt0;

>
Minas Harutyunyan April 8, 2021, 1:39 p.m. UTC | #7
On 4/8/2021 1:45 PM, Artur Petrosyan wrote:
> Adds flow of entering Partial Power Down in

> "dwc2_port_suspend()" function when core receives suspend.

> 

> NOTE: Switch case statement is used for hibernation partial

> power down and clock gating mode determination. In this patch

> only Partial Power Down is implemented the Hibernation and

> clock gating implementations are planned to be added.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/core.h |  5 +++--

>   drivers/usb/dwc2/hcd.c  | 48 ++++++++++++++++++++++++++---------------

>   2 files changed, 34 insertions(+), 19 deletions(-)

> 

> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h

> index b7d99cf9e84c..76807abd753b 100644

> --- a/drivers/usb/dwc2/core.h

> +++ b/drivers/usb/dwc2/core.h

> @@ -1470,7 +1470,7 @@ void dwc2_hcd_connect(struct dwc2_hsotg *hsotg);

>   void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);

>   void dwc2_hcd_start(struct dwc2_hsotg *hsotg);

>   int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup);

> -void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex);

> +int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex);

>   void dwc2_port_resume(struct dwc2_hsotg *hsotg);

>   int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);

>   int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);

> @@ -1495,7 +1495,8 @@ static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}

>   static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}

>   static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)

>   { return 0; }

> -static inline void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) {}

> +static inline int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

> +{ return 0; }

>   static inline void dwc2_port_resume(struct dwc2_hsotg *hsotg) {}

>   static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)

>   { return 0; }

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index f4247a66c2b2..e7fb0d5940bc 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -3281,15 +3281,18 @@ static int dwc2_host_is_b_hnp_enabled(struct dwc2_hsotg *hsotg)

>    * @hsotg: Programming view of the DWC_otg controller

>    * @windex: The control request wIndex field

>    *

> + * Return: non-zero if failed to enter suspend mode for host.

> + *

>    * This function is for entering Host mode suspend.

>    * Must NOT be called with interrupt disabled or spinlock held.

>    */

> -void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

> +int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>   {

>   	unsigned long flags;

>   	u32 hprt0;

>   	u32 pcgctl;

>   	u32 gotgctl;

> +	int ret = 0;

>   

>   	dev_dbg(hsotg->dev, "%s()\n", __func__);

>   

> @@ -3302,22 +3305,31 @@ void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>   		hsotg->op_state = OTG_STATE_A_SUSPEND;

>   	}

>   

> -	hprt0 = dwc2_read_hprt0(hsotg);

> -	hprt0 |= HPRT0_SUSP;

> -	dwc2_writel(hsotg, hprt0, HPRT0);

> -

> -	hsotg->bus_suspended = true;

> -

> -	/*

> -	 * If power_down is supported, Phy clock will be suspended

> -	 * after registers are backuped.

> -	 */

> -	if (!hsotg->params.power_down) {

> -		/* Suspend the Phy Clock */

> -		pcgctl = dwc2_readl(hsotg, PCGCTL);

> -		pcgctl |= PCGCTL_STOPPCLK;

> -		dwc2_writel(hsotg, pcgctl, PCGCTL);

> -		udelay(10);

> +	switch (hsotg->params.power_down) {

> +	case DWC2_POWER_DOWN_PARAM_PARTIAL:

> +		ret = dwc2_enter_partial_power_down(hsotg);

> +		if (ret)

> +			dev_err(hsotg->dev,

> +				"enter partial_power_down failed.\n");

> +		break;

> +	case DWC2_POWER_DOWN_PARAM_HIBERNATION:

> +	case DWC2_POWER_DOWN_PARAM_NONE:

> +	default:

> +		hprt0 = dwc2_read_hprt0(hsotg);

> +		hprt0 |= HPRT0_SUSP;

> +		dwc2_writel(hsotg, hprt0, HPRT0);

> +		hsotg->bus_suspended = true;

> +		/*

> +		 * If power_down is supported, Phy clock will be suspended

> +		 * after registers are backuped.

> +		 */

> +		if (!hsotg->params.power_down) {

> +			/* Suspend the Phy Clock */

> +			pcgctl = dwc2_readl(hsotg, PCGCTL);

> +			pcgctl |= PCGCTL_STOPPCLK;

> +			dwc2_writel(hsotg, pcgctl, PCGCTL);

> +			udelay(10);

> +		}

>   	}

>   

>   	/* For HNP the bus must be suspended for at least 200ms */

> @@ -3332,6 +3344,8 @@ void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>   	} else {

>   		spin_unlock_irqrestore(&hsotg->lock, flags);

>   	}

> +

> +	return ret;

>   }

>   

>   /**

>
Minas Harutyunyan April 8, 2021, 1:39 p.m. UTC | #8
On 4/8/2021 1:45 PM, Artur Petrosyan wrote:
> Added flow of exiting Partial Power Down in

> "dwc2_port_resume()" function when core receives resume.

> 

> NOTE: Switch case statement is used for hibernation partial

> power down and clock gating mode determination. In this patch

> only Partial Power Down is implemented the Hibernation and

> clock gating implementations are planned to be added.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/core.h |  5 ++--

>   drivers/usb/dwc2/hcd.c  | 61 ++++++++++++++++++++++++++---------------

>   2 files changed, 42 insertions(+), 24 deletions(-)

> 

> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h

> index 76807abd753b..5a7850482e57 100644

> --- a/drivers/usb/dwc2/core.h

> +++ b/drivers/usb/dwc2/core.h

> @@ -1471,7 +1471,7 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);

>   void dwc2_hcd_start(struct dwc2_hsotg *hsotg);

>   int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup);

>   int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex);

> -void dwc2_port_resume(struct dwc2_hsotg *hsotg);

> +int dwc2_port_resume(struct dwc2_hsotg *hsotg);

>   int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);

>   int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);

>   int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);

> @@ -1497,7 +1497,8 @@ static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)

>   { return 0; }

>   static inline int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>   { return 0; }

> -static inline void dwc2_port_resume(struct dwc2_hsotg *hsotg) {}

> +static inline int dwc2_port_resume(struct dwc2_hsotg *hsotg)

> +{ return 0; }

>   static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)

>   { return 0; }

>   static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index e7fb0d5940bc..720354df014b 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -3353,44 +3353,61 @@ int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)

>    *

>    * @hsotg: Programming view of the DWC_otg controller

>    *

> + * Return: non-zero if failed to exit suspend mode for host.

> + *

>    * This function is for exiting Host mode suspend.

>    * Must NOT be called with interrupt disabled or spinlock held.

>    */

> -void dwc2_port_resume(struct dwc2_hsotg *hsotg)

> +int dwc2_port_resume(struct dwc2_hsotg *hsotg)

>   {

>   	unsigned long flags;

>   	u32 hprt0;

>   	u32 pcgctl;

> +	int ret = 0;

>   

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

>   

> -	/*

> -	 * If power_down is supported, Phy clock is already resumed

> -	 * after registers restore.

> -	 */

> -	if (!hsotg->params.power_down) {

> -		pcgctl = dwc2_readl(hsotg, PCGCTL);

> -		pcgctl &= ~PCGCTL_STOPPCLK;

> -		dwc2_writel(hsotg, pcgctl, PCGCTL);

> +	switch (hsotg->params.power_down) {

> +	case DWC2_POWER_DOWN_PARAM_PARTIAL:

> +		ret = dwc2_exit_partial_power_down(hsotg, 0, true);

> +		if (ret)

> +			dev_err(hsotg->dev,

> +				"exit partial_power_down failed.\n");

> +		break;

> +	case DWC2_POWER_DOWN_PARAM_HIBERNATION:

> +	case DWC2_POWER_DOWN_PARAM_NONE:

> +	default:

> +		/*

> +		 * If power_down is supported, Phy clock is already resumed

> +		 * after registers restore.

> +		 */

> +		if (!hsotg->params.power_down) {

> +			pcgctl = dwc2_readl(hsotg, PCGCTL);

> +			pcgctl &= ~PCGCTL_STOPPCLK;

> +			dwc2_writel(hsotg, pcgctl, PCGCTL);

> +			spin_unlock_irqrestore(&hsotg->lock, flags);

> +			msleep(20);

> +			spin_lock_irqsave(&hsotg->lock, flags);

> +		}

> +

> +		hprt0 = dwc2_read_hprt0(hsotg);

> +		hprt0 |= HPRT0_RES;

> +		hprt0 &= ~HPRT0_SUSP;

> +		dwc2_writel(hsotg, hprt0, HPRT0);

>   		spin_unlock_irqrestore(&hsotg->lock, flags);

> -		msleep(20);

> +

> +		msleep(USB_RESUME_TIMEOUT);

> +

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

> +		hprt0 = dwc2_read_hprt0(hsotg);

> +		hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);

> +		dwc2_writel(hsotg, hprt0, HPRT0);

> +		hsotg->bus_suspended = false;

>   	}

>   

> -	hprt0 = dwc2_read_hprt0(hsotg);

> -	hprt0 |= HPRT0_RES;

> -	hprt0 &= ~HPRT0_SUSP;

> -	dwc2_writel(hsotg, hprt0, HPRT0);

>   	spin_unlock_irqrestore(&hsotg->lock, flags);

>   

> -	msleep(USB_RESUME_TIMEOUT);

> -

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

> -	hprt0 = dwc2_read_hprt0(hsotg);

> -	hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);

> -	dwc2_writel(hsotg, hprt0, HPRT0);

> -	hsotg->bus_suspended = false;

> -	spin_unlock_irqrestore(&hsotg->lock, flags);

> +	return ret;

>   }

>   

>   /* Handles hub class-specific requests */

>
Minas Harutyunyan April 8, 2021, 1:39 p.m. UTC | #9
On 4/8/2021 1:45 PM, Artur Petrosyan wrote:
> Adds Partial Power Down exiting flow when set port feature

> reset is received in suspended state.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/hcd.c | 9 +++++++++

>   1 file changed, 9 insertions(+)

> 

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index 720354df014b..7c7496719152 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -3694,6 +3694,15 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,

>   			if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION &&

>   			    hsotg->hibernated)

>   				dwc2_exit_hibernation(hsotg, 0, 1, 1);

> +

> +			if (hsotg->in_ppd) {

> +				retval = dwc2_exit_partial_power_down(hsotg, 1,

> +								      true);

> +				if (retval)

> +					dev_err(hsotg->dev,

> +						"exit partial_power_down failed\n");

> +			}

> +

>   			hprt0 = dwc2_read_hprt0(hsotg);

>   			dev_dbg(hsotg->dev,

>   				"SetPortFeature - USB_PORT_FEAT_RESET\n");

>
Minas Harutyunyan April 8, 2021, 1:40 p.m. UTC | #10
On 4/8/2021 1:45 PM, Artur Petrosyan wrote:
> When core is in partial power down state and an external

> hub is connected, upper layer sends URB enqueue request,

> which results in port reset issue.

> 

> Added exit from partial power down state to avoid port

> reset issue and process upper layer request correctly.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/hcd.c | 7 +++++++

>   1 file changed, 7 insertions(+)

> 

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index 9529e9839961..cb52bc41bfb8 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -4633,6 +4633,13 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,

>   		dwc2_dump_urb_info(hcd, urb, "urb_enqueue");

>   	}

>   

> +	if (hsotg->in_ppd) {

> +		retval = dwc2_exit_partial_power_down(hsotg, 0, true);

> +		if (retval)

> +			dev_err(hsotg->dev,

> +				"exit partial_power_down failed\n");

> +	}

> +

>   	if (!ep)

>   		return -EINVAL;

>   

>
Minas Harutyunyan April 8, 2021, 1:40 p.m. UTC | #11
On 4/8/2021 1:45 PM, Artur Petrosyan wrote:
> With current implementation the port power is being disabled,

> which is not required by the programming guide. Also, if there

> is a system which works only in "DWC2_POWER_DOWN_PARAM_NONE"

> (clock gating) mode the current implementation does not set

> Gate hclk bit in pcgctl register.

> 

> Rearranges and updates the implementation of entering to partial

> power down power saving mode when PC is suspended to get

> rid of many "if" statements and removes disabling of port power.

> 

> NOTE: Switch case statement is used for hibernation partial

> power down and clock gating mode determination. In this patch

> only Partial Power Down is implemented the Hibernation and

> clock gating implementations are planned to be added.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/hcd.c | 53 ++++++++++++++----------------------------

>   1 file changed, 18 insertions(+), 35 deletions(-)

> 

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index cb52bc41bfb8..34030bafdff4 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -4367,8 +4367,6 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)

>   	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);

>   	unsigned long flags;

>   	int ret = 0;

> -	u32 hprt0;

> -	u32 pcgctl;

>   

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

>   

> @@ -4384,47 +4382,32 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)

>   	if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)

>   		goto unlock;

>   

> -	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||

> -	    hsotg->flags.b.port_connect_status == 0)

> +	if (hsotg->bus_suspended)

>   		goto skip_power_saving;

>   

> -	/*

> -	 * Drive USB suspend and disable port Power

> -	 * if usb bus is not suspended.

> -	 */

> -	if (!hsotg->bus_suspended) {

> -		hprt0 = dwc2_read_hprt0(hsotg);

> -		if (hprt0 & HPRT0_CONNSTS) {

> -			hprt0 |= HPRT0_SUSP;

> -			if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL)

> -				hprt0 &= ~HPRT0_PWR;

> -			dwc2_writel(hsotg, hprt0, HPRT0);

> -		}

> -		if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {

> -			spin_unlock_irqrestore(&hsotg->lock, flags);

> -			dwc2_vbus_supply_exit(hsotg);

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

> -		} else {

> -			pcgctl = readl(hsotg->regs + PCGCTL);

> -			pcgctl |= PCGCTL_STOPPCLK;

> -			writel(pcgctl, hsotg->regs + PCGCTL);

> -		}

> -	}

> +	if (hsotg->flags.b.port_connect_status == 0)

> +		goto skip_power_saving;

>   

> -	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {

> +	switch (hsotg->params.power_down) {

> +	case DWC2_POWER_DOWN_PARAM_PARTIAL:

>   		/* Enter partial_power_down */

>   		ret = dwc2_enter_partial_power_down(hsotg);

> -		if (ret) {

> -			if (ret != -ENOTSUPP)

> -				dev_err(hsotg->dev,

> -					"enter partial_power_down failed\n");

> -			goto skip_power_saving;

> -		}

> -

> -		/* After entering partial_power_down, hardware is no more accessible */

> +		if (ret)

> +			dev_err(hsotg->dev,

> +				"enter partial_power_down failed\n");

> +		/* After entering suspend, hardware is not accessible */

>   		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

> +		break;

> +	case DWC2_POWER_DOWN_PARAM_HIBERNATION:

> +	case DWC2_POWER_DOWN_PARAM_NONE:

> +	default:

> +		goto skip_power_saving;

>   	}

>   

> +	spin_unlock_irqrestore(&hsotg->lock, flags);

> +	dwc2_vbus_supply_exit(hsotg);

> +	spin_lock_irqsave(&hsotg->lock, flags);

> +

>   	/* Ask phy to be suspended */

>   	if (!IS_ERR_OR_NULL(hsotg->uphy)) {

>   		spin_unlock_irqrestore(&hsotg->lock, flags);

>
Minas Harutyunyan April 8, 2021, 1:40 p.m. UTC | #12
On 4/8/2021 1:46 PM, Artur Petrosyan wrote:
> Fixes the implementation of exiting from partial power down

> power saving mode when PC is resumed.

> 

> Added port connection status checking which prevents exiting from

> Partial Power Down mode from _dwc2_hcd_resume() if not in Partial

> Power Down mode.

> 

> Rearranged the implementation to get rid of many "if"

> statements.

> 

> NOTE: Switch case statement is used for hibernation partial

> power down and clock gating mode determination. In this patch

> only Partial Power Down is implemented the Hibernation and

> clock gating implementations are planned to be added.

> 

> Cc: <stable@vger.kernel.org>

> Fixes: 6f6d70597c15 ("usb: dwc2: bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE")

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/hcd.c | 90 +++++++++++++++++++++---------------------

>   1 file changed, 46 insertions(+), 44 deletions(-)

> 

> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c

> index 34030bafdff4..f096006df96f 100644

> --- a/drivers/usb/dwc2/hcd.c

> +++ b/drivers/usb/dwc2/hcd.c

> @@ -4427,7 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)

>   {

>   	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);

>   	unsigned long flags;

> -	u32 pcgctl;

> +	u32 hprt0;

>   	int ret = 0;

>   

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

> @@ -4438,11 +4438,40 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)

>   	if (hsotg->lx_state != DWC2_L2)

>   		goto unlock;

>   

> -	if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) {

> +	hprt0 = dwc2_read_hprt0(hsotg);

> +

> +	/*

> +	 * Added port connection status checking which prevents exiting from

> +	 * Partial Power Down mode from _dwc2_hcd_resume() if not in Partial

> +	 * Power Down mode.

> +	 */

> +	if (hprt0 & HPRT0_CONNSTS) {

> +		hsotg->lx_state = DWC2_L0;

> +		goto unlock;

> +	}

> +

> +	switch (hsotg->params.power_down) {

> +	case DWC2_POWER_DOWN_PARAM_PARTIAL:

> +		ret = dwc2_exit_partial_power_down(hsotg, 0, true);

> +		if (ret)

> +			dev_err(hsotg->dev,

> +				"exit partial_power_down failed\n");

> +		/*

> +		 * Set HW accessible bit before powering on the controller

> +		 * since an interrupt may rise.

> +		 */

> +		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

> +		break;

> +	case DWC2_POWER_DOWN_PARAM_HIBERNATION:

> +	case DWC2_POWER_DOWN_PARAM_NONE:

> +	default:

>   		hsotg->lx_state = DWC2_L0;

>   		goto unlock;

>   	}

>   

> +	/* Change Root port status, as port status change occurred after resume.*/

> +	hsotg->flags.b.port_suspend_change = 1;

> +

>   	/*

>   	 * Enable power if not already done.

>   	 * This must not be spinlocked since duration

> @@ -4454,52 +4483,25 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)

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

>   	}

>   

> -	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {

> -		/*

> -		 * Set HW accessible bit before powering on the controller

> -		 * since an interrupt may rise.

> -		 */

> -		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

> -

> -

> -		/* Exit partial_power_down */

> -		ret = dwc2_exit_partial_power_down(hsotg, 0, true);

> -		if (ret && (ret != -ENOTSUPP))

> -			dev_err(hsotg->dev, "exit partial_power_down failed\n");

> -	} else {

> -		pcgctl = readl(hsotg->regs + PCGCTL);

> -		pcgctl &= ~PCGCTL_STOPPCLK;

> -		writel(pcgctl, hsotg->regs + PCGCTL);

> -	}

> -

> -	hsotg->lx_state = DWC2_L0;

> -

> +	/* Enable external vbus supply after resuming the port. */

>   	spin_unlock_irqrestore(&hsotg->lock, flags);

> +	dwc2_vbus_supply_init(hsotg);

>   

> -	if (hsotg->bus_suspended) {

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

> -		hsotg->flags.b.port_suspend_change = 1;

> -		spin_unlock_irqrestore(&hsotg->lock, flags);

> -		dwc2_port_resume(hsotg);

> -	} else {

> -		if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {

> -			dwc2_vbus_supply_init(hsotg);

> -

> -			/* Wait for controller to correctly update D+/D- level */

> -			usleep_range(3000, 5000);

> -		}

> +	/* Wait for controller to correctly update D+/D- level */

> +	usleep_range(3000, 5000);

> +	spin_lock_irqsave(&hsotg->lock, flags);

>   

> -		/*

> -		 * Clear Port Enable and Port Status changes.

> -		 * Enable Port Power.

> -		 */

> -		dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |

> -				HPRT0_ENACHG, HPRT0);

> -		/* Wait for controller to detect Port Connect */

> -		usleep_range(5000, 7000);

> -	}

> +	/*

> +	 * Clear Port Enable and Port Status changes.

> +	 * Enable Port Power.

> +	 */

> +	dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |

> +			HPRT0_ENACHG, HPRT0);

>   

> -	return ret;

> +	/* Wait for controller to detect Port Connect */

> +	spin_unlock_irqrestore(&hsotg->lock, flags);

> +	usleep_range(5000, 7000);

> +	spin_lock_irqsave(&hsotg->lock, flags);

>   unlock:

>   	spin_unlock_irqrestore(&hsotg->lock, flags);

>   

>
Minas Harutyunyan April 8, 2021, 1:41 p.m. UTC | #13
On 4/8/2021 1:46 PM, Artur Petrosyan wrote:
> When dwc2 core is in partial power down mode

> loading driver again causes driver fail. Because in

> that mode registers are not accessible.

> 

> Added a flow of exiting the partial power down mode

> to avoid the driver reload failure.

> 

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


Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>


> ---

>   Changes in v3:

>   - None

>   Changes in v2:

>   - None

> 

>   drivers/usb/dwc2/platform.c | 11 ++++++++++-

>   1 file changed, 10 insertions(+), 1 deletion(-)

> 

> diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c

> index 5f18acac7406..b28b8cd45799 100644

> --- a/drivers/usb/dwc2/platform.c

> +++ b/drivers/usb/dwc2/platform.c

> @@ -316,6 +316,15 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)

>   static int dwc2_driver_remove(struct platform_device *dev)

>   {

>   	struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);

> +	int ret = 0;

> +

> +	/* Exit Partial Power Down when driver is removed. */

> +	if (hsotg->in_ppd) {

> +		ret = dwc2_exit_partial_power_down(hsotg, 0, true);

> +		if (ret)

> +			dev_err(hsotg->dev,

> +				"exit partial_power_down failed\n");

> +	}

>   

>   	dwc2_debugfs_exit(hsotg);

>   	if (hsotg->hcd_enabled)

> @@ -334,7 +343,7 @@ static int dwc2_driver_remove(struct platform_device *dev)

>   	reset_control_assert(hsotg->reset);

>   	reset_control_assert(hsotg->reset_ecc);

>   

> -	return 0;

> +	return ret;

>   }

>   

>   /**

>