summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc2/core.c
diff options
context:
space:
mode:
authorArtur Petrosyan <Arthur.Petrosyan@synopsys.com>2021-04-08 13:44:45 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-09 15:16:38 +0200
commitc9c394abfa8456808fd3a0083f7fd81c3188bd0c (patch)
tree2c8d71183b05088072b9c3d30d32558ff782f3a7 /drivers/usb/dwc2/core.c
parent9ce9e5ad17d6c7cf943c9d365e8e12d6759e01db (diff)
downloadlwn-c9c394abfa8456808fd3a0083f7fd81c3188bd0c.tar.gz
lwn-c9c394abfa8456808fd3a0083f7fd81c3188bd0c.zip
usb: dwc2: Update enter and exit partial power down functions
These are wrapper functions which are calling device or host enter/exit partial power down functions. This change is done because we need to separate device and host partial power down functions as the programming flow has a lot of difference between host and device. With this update during partial power down exit driver relies on backup value of "GOTGCTL_CURMODE_HOST" to determine the mode of core before entering to PPD. Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com> Link: https://lore.kernel.org/r/20210408094446.6491BA022E@mailhost.synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc2/core.c')
-rw-r--r--drivers/usb/dwc2/core.c113
1 files changed, 19 insertions, 94 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fec17a2d2447..cb65f7f60573 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -131,54 +131,26 @@ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
* dwc2_exit_partial_power_down() - Exit controller from Partial Power Down.
*
* @hsotg: Programming view of the DWC_otg controller
+ * @rem_wakeup: indicates whether resume is initiated by Reset.
* @restore: Controller registers need to be restored
*/
-int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
+int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ bool restore)
{
- u32 pcgcctl;
- int ret = 0;
-
- if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
- return -ENOTSUPP;
-
- 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);
+ struct dwc2_gregs_backup *gr;
- 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;
- }
- if (dwc2_is_host_mode(hsotg)) {
- ret = dwc2_restore_host_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore host registers\n",
- __func__);
- return ret;
- }
- } else {
- ret = dwc2_restore_device_registers(hsotg, 0);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore device registers\n",
- __func__);
- return ret;
- }
- }
- }
+ gr = &hsotg->gr_backup;
- return ret;
+ /*
+ * Restore host or device regisers with the same mode core enterted
+ * to partial power down by checking "GOTGCTL_CURMODE_HOST" backup
+ * value of the "gotgctl" register.
+ */
+ if (gr->gotgctl & GOTGCTL_CURMODE_HOST)
+ return dwc2_host_exit_partial_power_down(hsotg, rem_wakeup,
+ restore);
+ else
+ return dwc2_gadget_exit_partial_power_down(hsotg, restore);
}
/**
@@ -188,57 +160,10 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
*/
int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
{
- u32 pcgcctl;
- int ret = 0;
-
- if (!hsotg->params.power_down)
- return -ENOTSUPP;
-
- /* 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;
- }
-
- if (dwc2_is_host_mode(hsotg)) {
- ret = dwc2_backup_host_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup host registers\n",
- __func__);
- return ret;
- }
- } else {
- 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);
- ndelay(20);
-
- pcgcctl |= PCGCTL_RSTPDWNMODULE;
- dwc2_writel(hsotg, pcgcctl, PCGCTL);
- ndelay(20);
-
- pcgcctl |= PCGCTL_STOPPCLK;
- dwc2_writel(hsotg, pcgcctl, PCGCTL);
-
- return ret;
+ if (dwc2_is_host_mode(hsotg))
+ return dwc2_host_enter_partial_power_down(hsotg);
+ else
+ return dwc2_gadget_enter_partial_power_down(hsotg);
}
/**