From: Stefan Wahren <wahrenst@gmx.net>
To: "Russell King" <linux@armlinux.org.uk>,
"Doug Anderson" <dianders@chromium.org>,
"Florian Fainelli" <florian.fainelli@broadcom.com>,
"Ray Jui" <rjui@broadcom.com>,
"Scott Branden" <sbranden@broadcom.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Jassi Brar" <jassisinghbrar@gmail.com>,
"Maíra Canal" <mcanal@igalia.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Minas Harutyunyan" <hminas@synopsys.com>
Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
Lukas Wunner <lukas@wunner.de>,
Artur Petrosyan <Arthur.Petrosyan@synopsys.com>,
Peter Robinson <pbrobinson@gmail.com>,
dri-devel@lists.freedesktop.org,
bcm-kernel-feedback-list@broadcom.com, linux-pm@vger.kernel.org,
linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
kernel-list@raspberrypi.com, Stefan Wahren <wahrenst@gmx.net>
Subject: [PATCH V3 RFC 8/9] usb: dwc2: Implement recovery after PM domain off
Date: Wed, 21 Aug 2024 23:40:51 +0200 [thread overview]
Message-ID: <20240821214052.6800-9-wahrenst@gmx.net> (raw)
In-Reply-To: <20240821214052.6800-1-wahrenst@gmx.net>
According to the dt-bindings there are some platforms, which have a
dedicated USB power domain for DWC2 IP core supply. If the power domain
is switched off during system suspend then all USB register will lose
their settings.
Use GUSBCFG_TOUTCAL as a canary to detect that the power domain has
been powered off during suspend. Since the GOTGCTL_CURMODE_HOST doesn't
match on all platform with the current mode, additionally backup
GINTSTS. This works reliable to decide which registers should be
restored.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/usb/dwc2/core.c | 1 +
drivers/usb/dwc2/core.h | 2 ++
drivers/usb/dwc2/platform.c | 38 +++++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+)
Hi, would be nice to get some feedback about the approach and
test results on other DWC2 platforms.
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 9919ab725d54..c3d24312db0f 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -43,6 +43,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
/* Backup global regs */
gr = &hsotg->gr_backup;
+ gr->gintsts = dwc2_readl(hsotg, GINTSTS);
gr->gotgctl = dwc2_readl(hsotg, GOTGCTL);
gr->gintmsk = dwc2_readl(hsotg, GINTMSK);
gr->gahbcfg = dwc2_readl(hsotg, GAHBCFG);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 81e8632f29ed..e65a74853bb0 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -667,6 +667,7 @@ struct dwc2_hw_params {
/**
* struct dwc2_gregs_backup - Holds global registers state before
* entering partial power down
+ * @gintsts: Backup of GINTSTS register
* @gotgctl: Backup of GOTGCTL register
* @gintmsk: Backup of GINTMSK register
* @gahbcfg: Backup of GAHBCFG register
@@ -683,6 +684,7 @@ struct dwc2_hw_params {
* @valid: True if registers values backuped.
*/
struct dwc2_gregs_backup {
+ u32 gintsts;
u32 gotgctl;
u32 gintmsk;
u32 gahbcfg;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 7b84416dfc2b..39e9064b6cfe 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -683,6 +683,14 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
regulator_disable(dwc2->usb33d);
}
+ if (is_device_mode)
+ ret = dwc2_gadget_backup_critical_registers(dwc2);
+ else
+ ret = dwc2_host_backup_critical_registers(dwc2);
+
+ if (ret)
+ return ret;
+
if (dwc2->ll_hw_enabled &&
(is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) {
ret = __dwc2_lowlevel_hw_disable(dwc2);
@@ -692,6 +700,24 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
return ret;
}
+static int dwc2_restore_critical_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_gregs_backup *gr;
+
+ gr = &hsotg->gr_backup;
+
+ if (!gr->valid) {
+ dev_err(hsotg->dev, "%s: no registers to restore\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (gr->gintsts & GINTSTS_CURMODE_HOST)
+ return dwc2_host_restore_critical_registers(hsotg);
+
+ return dwc2_gadget_restore_critical_registers(hsotg);
+}
+
static int __maybe_unused dwc2_resume(struct device *dev)
{
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
@@ -704,6 +730,18 @@ static int __maybe_unused dwc2_resume(struct device *dev)
}
dwc2->phy_off_for_suspend = false;
+ /*
+ * During suspend it's possible that the power domain for the
+ * DWC2 controller is disabled and all register values get lost.
+ * In case the GUSBCFG register is not initialized, it's clear the
+ * registers must be restored.
+ */
+ if (!(dwc2_readl(dwc2, GUSBCFG) & GUSBCFG_TOUTCAL_MASK)) {
+ ret = dwc2_restore_critical_registers(dwc2);
+ if (ret)
+ return ret;
+ }
+
if (dwc2->params.activate_stm_id_vb_detection) {
unsigned long flags;
u32 ggpio, gotgctl;
--
2.34.1
next prev parent reply other threads:[~2024-08-21 21:41 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-21 21:40 [PATCH V3 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
2024-08-21 21:40 ` [PATCH V3 1/9] mailbox: bcm2835: Fix timeout during suspend mode Stefan Wahren
2024-08-31 9:19 ` Stefan Wahren
2024-09-01 20:26 ` Jassi Brar
2024-09-01 20:57 ` Stefan Wahren
2024-08-21 21:40 ` [PATCH V3 2/9] drm/vc4: hdmi: Handle error case of pm_runtime_resume_and_get Stefan Wahren
2024-08-22 13:09 ` Maíra Canal
2024-08-21 21:40 ` [PATCH V3 3/9] drm/vc4: Get the rid of DRM_ERROR() Stefan Wahren
2024-08-22 13:10 ` Maíra Canal
2024-08-21 21:40 ` [PATCH V3 4/9] drm/vc4: hdmi: add PM suspend/resume support Stefan Wahren
2024-08-22 12:10 ` kernel test robot
2024-08-21 21:40 ` [PATCH V3 5/9] drm/vc4: v3d: simplify clock retrieval Stefan Wahren
2024-08-22 13:12 ` Maíra Canal
2024-08-21 21:40 ` [PATCH V3 6/9] drm/vc4: v3d: add PM suspend/resume support Stefan Wahren
2024-08-21 21:40 ` [PATCH V3 7/9] usb: dwc2: Refactor backup/restore of registers Stefan Wahren
2024-08-22 9:16 ` kernel test robot
2024-08-22 10:30 ` Stefan Wahren
2024-08-21 21:40 ` Stefan Wahren [this message]
2024-08-29 19:33 ` [PATCH V3 RFC 8/9] usb: dwc2: Implement recovery after PM domain off Doug Anderson
2024-08-21 22:36 ` [PATCH V3 9/9] ARM: bcm2835_defconfig: Enable SUSPEND Stefan Wahren
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=20240821214052.6800-9-wahrenst@gmx.net \
--to=wahrenst@gmx.net \
--cc=Arthur.Petrosyan@synopsys.com \
--cc=airlied@gmail.com \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=daniel@ffwll.ch \
--cc=dave.stevenson@raspberrypi.com \
--cc=dianders@chromium.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=florian.fainelli@broadcom.com \
--cc=gregkh@linuxfoundation.org \
--cc=hminas@synopsys.com \
--cc=jassisinghbrar@gmail.com \
--cc=kernel-list@raspberrypi.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=lukas@wunner.de \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mcanal@igalia.com \
--cc=mripard@kernel.org \
--cc=pbrobinson@gmail.com \
--cc=rjui@broadcom.com \
--cc=sbranden@broadcom.com \
--cc=tzimmermann@suse.de \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox