Linux-USB Archive on lore.kernel.org
 help / color / Atom feed
From: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
To: Felipe Balbi <balbi@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: John Youn <John.Youn@synopsys.com>,
	Artur Petrosyan <Arthur.Petrosyan@synopsys.com>,
	Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Subject: [PATCH v3 01/14] usb: dwc2: Add device partial power down functions
Date: Thu, 08 Apr 2021 13:44:29 +0400
Message-ID: <20210408094430.383B9A0094@mailhost.synopsys.com> (raw)
In-Reply-To: <cover.1617782102.git.Arthur.Petrosyan@synopsys.com>

For device mode Partial Power Down entering and exiting
separate functions are needed to implement the logic.
Earlier the logic was implemented in one function. Which was
confusing the readability. Also both host and device implementations
were in the same function.

- Added device partial power down functions which must be called
by dwc2_enter_partial_power_down()/dwc2_exit_partial_power_down()
functions.

- Added "in_ppd" flag in "dwc2_hsotg" struct to indicate the
core state after entering into partial power down mode.

Added function names:
dwc2_gadget_enter_partial_power_down()
dwc2_gadget_exit_partial_power_down()

NOTE: There is a checkpatch "CHECK" warning on "udelay(100)".
The delay is needed to properly exit gadget Partial Power Down
A delay less than 100 doesn't work.

Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
---
 drivers/usb/dwc2/core.h   |  10 +++
 drivers/usb/dwc2/gadget.c | 128 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index d0ebe721fb98..ed54d834138d 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -865,6 +865,7 @@ struct dwc2_hregs_backup {
  * @gadget_enabled:	Peripheral mode sub-driver initialization indicator.
  * @ll_hw_enabled:	Status of low-level hardware resources.
  * @hibernated:		True if core is hibernated
+ * @in_ppd:		True if core is partial power down mode.
  * @reset_phy_on_wake:	Quirk saying that we should assert PHY reset on a
  *			remote wakeup.
  * @phy_off_for_suspend: Status of whether we turned the PHY off at suspend.
@@ -1060,6 +1061,7 @@ struct dwc2_hsotg {
 	unsigned int gadget_enabled:1;
 	unsigned int ll_hw_enabled:1;
 	unsigned int hibernated:1;
+	unsigned int in_ppd:1;
 	unsigned int reset_phy_on_wake:1;
 	unsigned int need_phy_for_wake:1;
 	unsigned int phy_off_for_suspend:1;
@@ -1409,6 +1411,9 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
 int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg);
 int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 				 int rem_wakeup, int reset);
+int dwc2_gadget_enter_partial_power_down(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
+					bool restore);
 int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
@@ -1442,6 +1447,11 @@ static inline int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
 static inline int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 					       int rem_wakeup, int reset)
 { return 0; }
+static inline int dwc2_gadget_enter_partial_power_down(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
+						      bool restore)
+{ return 0; }
 static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index ad4c94366dad..98a2a63c67ae 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5351,3 +5351,131 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 
 	return ret;
 }
+
+/**
+ * dwc2_gadget_enter_partial_power_down() - Put controller in partial
+ * power down.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ *
+ * Return: non-zero if failed to enter device partial power down.
+ *
+ * This function is for entering device mode partial power down.
+ */
+int dwc2_gadget_enter_partial_power_down(struct dwc2_hsotg *hsotg)
+{
+	u32 pcgcctl;
+	int ret = 0;
+
+	dev_dbg(hsotg->dev, "Entering device partial power down started.\n");
+
+	/* Backup all registers */
+	ret = dwc2_backup_global_registers(hsotg);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to backup global registers\n",
+			__func__);
+		return ret;
+	}
+
+	ret = dwc2_backup_device_registers(hsotg);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to backup device registers\n",
+			__func__);
+		return ret;
+	}
+
+	/*
+	 * Clear any pending interrupts since dwc2 will not be able to
+	 * clear them after entering partial_power_down.
+	 */
+	dwc2_writel(hsotg, 0xffffffff, GINTSTS);
+
+	/* Put the controller in low power state */
+	pcgcctl = dwc2_readl(hsotg, PCGCTL);
+
+	pcgcctl |= PCGCTL_PWRCLMP;
+	dwc2_writel(hsotg, pcgcctl, PCGCTL);
+	udelay(5);
+
+	pcgcctl |= PCGCTL_RSTPDWNMODULE;
+	dwc2_writel(hsotg, pcgcctl, PCGCTL);
+	udelay(5);
+
+	pcgcctl |= PCGCTL_STOPPCLK;
+	dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+	/* Set in_ppd flag to 1 as here core enters suspend. */
+	hsotg->in_ppd = 1;
+	hsotg->lx_state = DWC2_L2;
+
+	dev_dbg(hsotg->dev, "Entering device partial power down completed.\n");
+
+	return ret;
+}
+
+/*
+ * dwc2_gadget_exit_partial_power_down() - Exit controller from device partial
+ * power down.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @restore: indicates whether need to restore the registers or not.
+ *
+ * Return: non-zero if failed to exit device partial power down.
+ *
+ * This function is for exiting from device mode partial power down.
+ */
+int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
+					bool restore)
+{
+	u32 pcgcctl;
+	u32 dctl;
+	struct dwc2_dregs_backup *dr;
+	int ret = 0;
+
+	dr = &hsotg->dr_backup;
+
+	dev_dbg(hsotg->dev, "Exiting device partial Power Down started.\n");
+
+	pcgcctl = dwc2_readl(hsotg, PCGCTL);
+	pcgcctl &= ~PCGCTL_STOPPCLK;
+	dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+	pcgcctl = dwc2_readl(hsotg, PCGCTL);
+	pcgcctl &= ~PCGCTL_PWRCLMP;
+	dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+	pcgcctl = dwc2_readl(hsotg, PCGCTL);
+	pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
+	dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+	udelay(100);
+	if (restore) {
+		ret = dwc2_restore_global_registers(hsotg);
+		if (ret) {
+			dev_err(hsotg->dev, "%s: failed to restore registers\n",
+				__func__);
+			return ret;
+		}
+		/* Restore DCFG */
+		dwc2_writel(hsotg, dr->dcfg, DCFG);
+
+		ret = dwc2_restore_device_registers(hsotg, 0);
+		if (ret) {
+			dev_err(hsotg->dev, "%s: failed to restore device registers\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	/* Set the Power-On Programming done bit */
+	dctl = dwc2_readl(hsotg, DCTL);
+	dctl |= DCTL_PWRONPRGDONE;
+	dwc2_writel(hsotg, dctl, DCTL);
+
+	/* Set in_ppd flag to 0 as here core exits from suspend. */
+	hsotg->in_ppd = 0;
+	hsotg->lx_state = DWC2_L0;
+
+	dev_dbg(hsotg->dev, "Exiting device partial Power Down completed.\n");
+	return ret;
+}
-- 
2.25.1


  parent reply index

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-07 10:00 [PATCH 00/14] usb: dwc2: Fix Partial Power down issues Artur Petrosyan
2021-04-07 10:08 ` [PATCH 13/14] usb: dwc2: Fix partial power down exiting by system resume Artur Petrosyan
2021-04-08  5:57 ` [PATCH 00/14] usb: dwc2: Fix Partial Power down issues Artur Petrosyan
2021-04-08  6:09   ` Greg Kroah-Hartman
2021-04-08  7:28 ` [PATCH v2 " Artur Petrosyan
2021-04-08  9:17   ` Artur Petrosyan
2021-04-08 10:09     ` Artur Petrosyan
2021-04-08 11:00       ` Greg Kroah-Hartman
2021-04-08  7:30 ` [PATCH v2 13/14] usb: dwc2: Fix partial power down exiting by system resume Artur Petrosyan
2021-04-08  9:44 ` [PATCH v3 00/14] usb: dwc2: Fix Partial Power down issues Artur Petrosyan
2021-04-08  9:44 ` Artur Petrosyan [this message]
2021-04-08  9:44 ` [PATCH v3 02/14] usb: dwc2: Add host partial power down functions Artur Petrosyan
2021-04-08  9:44 ` [PATCH v3 03/14] usb: dwc2: Update enter and exit " Artur Petrosyan
2021-04-08  9:44 ` [PATCH v3 04/14] usb: dwc2: Add partial power down exit flow in wakeup intr Artur Petrosyan
2021-04-08  9:45 ` [PATCH v3 05/14] usb: dwc2: Update port suspend/resume function definitions Artur Petrosyan
2021-04-08 13:39   ` Minas Harutyunyan
2021-04-08  9:45 ` [PATCH v3 06/14] usb: dwc2: Add enter partial power down when port is suspended Artur Petrosyan
2021-04-08 13:39   ` Minas Harutyunyan
2021-04-08  9:45 ` [PATCH v3 07/14] usb: dwc2: Add exit partial power down when port is resumed Artur Petrosyan
2021-04-08 13:39   ` Minas Harutyunyan
2021-04-08  9:45 ` [PATCH v3 08/14] usb: dwc2: Add exit partial power down when port reset is asserted Artur Petrosyan
2021-04-08 13:39   ` Minas Harutyunyan
2021-04-08  9:45 ` [PATCH v3 09/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change() Artur Petrosyan
2021-04-08  9:45 ` [PATCH v3 10/14] usb: dwc2: Allow exit partial power down in urb enqueue Artur Petrosyan
2021-04-08 13:40   ` Minas Harutyunyan
2021-04-08  9:45 ` [PATCH v3 11/14] usb: dwc2: Fix session request interrupt handler Artur Petrosyan
2021-04-08  9:45 ` [PATCH v3 12/14] usb: dwc2: Update partial power down entering by system suspend Artur Petrosyan
2021-04-08 13:40   ` Minas Harutyunyan
2021-04-08  9:46 ` [PATCH v3 13/14] usb: dwc2: Fix partial power down exiting by system resume Artur Petrosyan
2021-04-08 13:40   ` Minas Harutyunyan
2021-04-08  9:46 ` [PATCH v3 14/14] usb: dwc2: Add exit partial power down before removing driver Artur Petrosyan
2021-04-08 13:41   ` Minas Harutyunyan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210408094430.383B9A0094@mailhost.synopsys.com \
    --to=arthur.petrosyan@synopsys.com \
    --cc=John.Youn@synopsys.com \
    --cc=Minas.Harutyunyan@synopsys.com \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-USB Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-usb/0 linux-usb/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-usb linux-usb/ https://lore.kernel.org/linux-usb \
		linux-usb@vger.kernel.org
	public-inbox-index linux-usb

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-usb


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git