diff mbox series

[v2,4/8] usb: chipidea: udc: add suspend/resume support for device controller

Message ID 20221013151442.3262951-5-xu.yang_2@nxp.com (mailing list archive)
State Accepted
Commit 235ffc17d0146d806f6ad8c094c24ff4878f2edb
Headers show
Series add power lost support during system suspend/resume | expand

Commit Message

Xu Yang Oct. 13, 2022, 3:14 p.m. UTC
The controller's power may be powered off during system suspend. This
will add suspend/resume support when the controller suffers power lost.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

---
Changes since v1:
- wrap suspend/resume functions with CONFIG_PM_SLEEP.
---
 drivers/usb/chipidea/udc.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

Comments

Peter Chen Oct. 17, 2022, 1:07 a.m. UTC | #1
On 22-10-13 23:14:38, Xu Yang wrote:
> The controller's power may be powered off during system suspend. This
> will add suspend/resume support when the controller suffers power lost.
> 
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> 

Acked-by: Peter Chen <peter.chen@kernel.org>

Peter
> ---
> Changes since v1:
> - wrap suspend/resume functions with CONFIG_PM_SLEEP.
> ---
>  drivers/usb/chipidea/udc.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
> index 8c3e3a635ac2..54c09245ad05 100644
> --- a/drivers/usb/chipidea/udc.c
> +++ b/drivers/usb/chipidea/udc.c
> @@ -2181,6 +2181,34 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci)
>  				     ci->platdata->pins_default);
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
> +static void udc_suspend(struct ci_hdrc *ci)
> +{
> +	/*
> +	 * Set OP_ENDPTLISTADDR to be non-zero for
> +	 * checking if controller resume from power lost
> +	 * in non-host mode.
> +	 */
> +	if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0)
> +		hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0);
> +}
> +
> +static void udc_resume(struct ci_hdrc *ci, bool power_lost)
> +{
> +	if (power_lost) {
> +		if (ci->is_otg)
> +			hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
> +					OTGSC_BSVIS | OTGSC_BSVIE);
> +		if (ci->vbus_active)
> +			usb_gadget_vbus_disconnect(&ci->gadget);
> +	}
> +
> +	/* Restore value 0 if it was set for power lost check */
> +	if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0xFFFFFFFF)
> +		hw_write(ci, OP_ENDPTLISTADDR, ~0, 0);
> +}
> +#endif
> +
>  /**
>   * ci_hdrc_gadget_init - initialize device related bits
>   * @ci: the controller
> @@ -2201,6 +2229,10 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
>  
>  	rdrv->start	= udc_id_switch_for_device;
>  	rdrv->stop	= udc_id_switch_for_host;
> +#ifdef CONFIG_PM_SLEEP
> +	rdrv->suspend	= udc_suspend;
> +	rdrv->resume	= udc_resume;
> +#endif
>  	rdrv->irq	= udc_irq;
>  	rdrv->name	= "gadget";
>  
> -- 
> 2.34.1
>
diff mbox series

Patch

diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 8c3e3a635ac2..54c09245ad05 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -2181,6 +2181,34 @@  static void udc_id_switch_for_host(struct ci_hdrc *ci)
 				     ci->platdata->pins_default);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static void udc_suspend(struct ci_hdrc *ci)
+{
+	/*
+	 * Set OP_ENDPTLISTADDR to be non-zero for
+	 * checking if controller resume from power lost
+	 * in non-host mode.
+	 */
+	if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0)
+		hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0);
+}
+
+static void udc_resume(struct ci_hdrc *ci, bool power_lost)
+{
+	if (power_lost) {
+		if (ci->is_otg)
+			hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
+					OTGSC_BSVIS | OTGSC_BSVIE);
+		if (ci->vbus_active)
+			usb_gadget_vbus_disconnect(&ci->gadget);
+	}
+
+	/* Restore value 0 if it was set for power lost check */
+	if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0xFFFFFFFF)
+		hw_write(ci, OP_ENDPTLISTADDR, ~0, 0);
+}
+#endif
+
 /**
  * ci_hdrc_gadget_init - initialize device related bits
  * @ci: the controller
@@ -2201,6 +2229,10 @@  int ci_hdrc_gadget_init(struct ci_hdrc *ci)
 
 	rdrv->start	= udc_id_switch_for_device;
 	rdrv->stop	= udc_id_switch_for_host;
+#ifdef CONFIG_PM_SLEEP
+	rdrv->suspend	= udc_suspend;
+	rdrv->resume	= udc_resume;
+#endif
 	rdrv->irq	= udc_irq;
 	rdrv->name	= "gadget";