linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi
@ 2024-10-25 10:36 Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
                   ` (8 more replies)
  0 siblings, 9 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

This series implement the initial S2Idle support for
the Raspberry Pi, which was a long time on my TODO list [1]. The
changes allow to suspend and resume the Raspberry Pi via debug UART.
The focus is on the BCM2835 SoC, because it's less complex than its
successors and have enough documentation.

Now the VC4 part has been split from the series [4], because of some issues
in that part.

Cherry-picking of patches should be fine.

Test steps:
- configure debug console (pl011 or mini UART) as wakeup source
- send system to idle state

  echo freeze > /sys/power/state

- wakeup system by console traffic

The clock gating must be restored, because otherwise we have a
regression on Raspberry Pi 3 B+ . Luckily the disabling of clock gating
isn't necessary anymore. Thanks to the rest of the DWC2 patches which
based on an idea of Doug Anderson. The USB domain is now powered down
and the USB devices are still usable after resume. There might be room
for improvements, but at least the system won't freeze forever as before.

Here are some figures for the Raspberry Pi 1 (without any
devices connected except of a debug UART):

running but CPU idle = 1.67 W
S2Idle               = 1.33 W

In comparison with HDMI & USB keyboard connected (but neither active
nor wakeup source):

running but CPU idle = 1.82 W
S2Idle               = 1.33 W

The series has been successfully tested on the following platforms:
Raspberry Pi 1 B
Raspberry Pi 3 B+

Changes in V5:
- add missing version

Changes in V4:
- added Reviewed-by from Doug
- dropped applied VC4 improvement patches
- fix DWC2 register backup
- add revert because of Raspberry Pi 3B+ regression
- add suspend/resume support for DMA & eMMC to be on the safe side

Changes in V3:
- added Reviewed-by & Acked-by from Florian & Maíra
- dropped applied pmdomain & bcm2835aux patches
- address comments by Maíra (patch 3 & 5)
- replace old USB recovery patch with canary approach [3], which should
  work with other platforms

Changes in V2:
- rebased against todays mainline
- added Reviewed-by from Florian
- added Acked-by from Minas
- dropped "irqchip/bcm2835: Enable SKIP_SET_WAKE and MASK_ON_SUSPEND"
  because it has been applied by Thomas Gleixner
- dropped "pmdomain: raspberrypi-power: Avoid powering down USB"
  because this workaround has been replaced by patch 14
- use drm_err_once instead of DRM_ERROR and return connector_status_unknown
  in patch 6
- add new patch in order to clean-up all DRM_ERROR
- add new patch to improve raspberrypi-power logging
- add new patch to simplify V3D clock retrieval
- add new patch 5 to avoid power down of wakeup devices
- add new patch 12 to avoid confusion about ACPI ID of BCM283x USB
- add new patch 8 & 10 which address the problem that HDMI
  is not functional after s2idle
- add more links and fix typo in patch 13
- add new WIP patch 14 which recover DWC2 register after power down
- take care of UART clock in patch 15 as commented by Florian
- use SYSTEM_SLEEP_PM_OPS in patch 15

[1] - https://github.com/lategoodbye/rpi-zero/issues/9
[2] - https://bugzilla.redhat.com/show_bug.cgi?id=2283978
[3] - https://lore.kernel.org/linux-usb/CAD=FV=W7sdi1+SHfhY6RrjK32r8iAGe4w+O_u5Sp982vgBU6EQ@mail.gmail.com/
[4] - https://lore.kernel.org/dri-devel/20241003124107.39153-1-wahrenst@gmx.net/

Stefan Wahren (9):
  Revert "usb: dwc2: Skip clock gating on Broadcom SoCs"
  dmaengine: bcm2835-dma: add suspend/resume pm support
  mmc: bcm2835: Fix type of current clock speed
  mmc: bcm2835: Introduce proper clock handling
  mmc: bcm2835: add suspend/resume pm support
  usb: dwc2: gadget: Introduce register restore flags
  usb: dwc2: Refactor backup/restore of registers
  usb: dwc2: Implement recovery after PM domain off
  ARM: bcm2835_defconfig: Enable SUSPEND

 arch/arm/configs/bcm2835_defconfig |   2 -
 drivers/dma/bcm2835-dma.c          |  30 ++++++++
 drivers/mmc/host/bcm2835.c         |  56 +++++++++++---
 drivers/usb/dwc2/core.c            |   1 +
 drivers/usb/dwc2/core.h            |  23 +++++-
 drivers/usb/dwc2/gadget.c          | 116 +++++++++++++++--------------
 drivers/usb/dwc2/hcd.c             |  99 ++++++++++++------------
 drivers/usb/dwc2/params.c          |   1 -
 drivers/usb/dwc2/platform.c        |  38 ++++++++++
 9 files changed, 245 insertions(+), 121 deletions(-)

--
2.34.1



^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs"
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-29  9:44   ` Ivan T . Ivanov
  2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

The commit d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
introduced a regression on Raspberry Pi 3 B Plus, which prevents
enumeration of the onboard Microchip LAN7800 in case no external USB device
is connected during boot.

Fixes: d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/usb/dwc2/params.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 68226defdc60..4d73fae80b12 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -23,7 +23,6 @@ static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg)
 	p->max_transfer_size = 65535;
 	p->max_packet_count = 511;
 	p->ahbcfg = 0x10;
-	p->no_clock_gating = true;
 }

 static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)
--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-11-09 17:37   ` Stefan Wahren
  2024-12-02 16:52   ` Vinod Koul
  2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

bcm2835-dma provides the service to others, so it should
suspend late and resume early.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index e1b92b4d7b05..647dda9f3376 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
 	return chan;
 }

+static int bcm2835_dma_suspend_late(struct device *dev)
+{
+	struct bcm2835_dmadev *od = dev_get_drvdata(dev);
+	struct bcm2835_chan *c, *next;
+
+	list_for_each_entry_safe(c, next, &od->ddev.channels,
+				 vc.chan.device_node) {
+		void __iomem *chan_base = c->chan_base;
+
+		if (readl(chan_base + BCM2835_DMA_ADDR)) {
+			dev_warn(dev, "Suspend is prevented by chan %d\n",
+				 c->ch);
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+}
+
+static int bcm2835_dma_resume_early(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops bcm2835_dma_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late,
+				     bcm2835_dma_resume_early)
+};
+
 static int bcm2835_dma_probe(struct platform_device *pdev)
 {
 	struct bcm2835_dmadev *od;
@@ -1033,6 +1062,7 @@ static struct platform_driver bcm2835_dma_driver = {
 	.driver = {
 		.name = "bcm2835-dma",
 		.of_match_table = of_match_ptr(bcm2835_dma_of_match),
+		.pm = pm_ptr(&bcm2835_dma_pm_ops),
 	},
 };

--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-28 11:43   ` Ulf Hansson
  2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

The type of mmc_ios.clock is unsigned int, so the cached value
should be of the same type.

Fixes: 660fc733bd74 ("mmc: bcm2835: Add new driver for the sdhost controller.")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/mmc/host/bcm2835.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 35d8fdea668b..3d3eda5a337c 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -150,7 +150,7 @@ struct bcm2835_host {

 	struct platform_device	*pdev;

-	int			clock;		/* Current clock speed */
+	unsigned int		clock;		/* Current clock speed */
 	unsigned int		max_clk;	/* Max possible freq */
 	struct work_struct	dma_work;
 	struct delayed_work	timeout_work;	/* Timer for timeouts */
--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
                   ` (2 preceding siblings ...)
  2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-28 11:43   ` Ulf Hansson
  2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

The custom sdhost controller on BCM2835 is feed by the critical VPU clock.
In preparation for PM suspend/resume support, add a proper clock handling
to the driver like in the other clock consumers (e.g. I2C).

Move the clock handling behind mmc_of_parse(), because it could return
with -EPROBE_DEFER and we want to minimize potential clock operation during
boot phase.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/mmc/host/bcm2835.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 3d3eda5a337c..107666b7c1c8 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -148,6 +148,7 @@ struct bcm2835_host {
 	void __iomem		*ioaddr;
 	u32			phys_addr;

+	struct clk		*clk;
 	struct platform_device	*pdev;

 	unsigned int		clock;		/* Current clock speed */
@@ -1345,7 +1346,6 @@ static int bcm2835_add_host(struct bcm2835_host *host)
 static int bcm2835_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct clk *clk;
 	struct bcm2835_host *host;
 	struct mmc_host *mmc;
 	const __be32 *regaddr_p;
@@ -1393,15 +1393,6 @@ static int bcm2835_probe(struct platform_device *pdev)
 		/* Ignore errors to fall back to PIO mode */
 	}

-
-	clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(clk)) {
-		ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n");
-		goto err;
-	}
-
-	host->max_clk = clk_get_rate(clk);
-
 	host->irq = platform_get_irq(pdev, 0);
 	if (host->irq < 0) {
 		ret = host->irq;
@@ -1412,16 +1403,30 @@ static int bcm2835_probe(struct platform_device *pdev)
 	if (ret)
 		goto err;

-	ret = bcm2835_add_host(host);
+	host->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = dev_err_probe(dev, PTR_ERR(host->clk), "could not get clk\n");
+		goto err;
+	}
+
+	ret = clk_prepare_enable(host->clk);
 	if (ret)
 		goto err;

+	host->max_clk = clk_get_rate(host->clk);
+
+	ret = bcm2835_add_host(host);
+	if (ret)
+		goto err_clk;
+
 	platform_set_drvdata(pdev, host);

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

 	return 0;

+err_clk:
+	clk_disable_unprepare(host->clk);
 err:
 	dev_dbg(dev, "%s -> err %d\n", __func__, ret);
 	if (host->dma_chan_rxtx)
@@ -1445,6 +1450,8 @@ static void bcm2835_remove(struct platform_device *pdev)
 	cancel_work_sync(&host->dma_work);
 	cancel_delayed_work_sync(&host->timeout_work);

+	clk_disable_unprepare(host->clk);
+
 	if (host->dma_chan_rxtx)
 		dma_release_channel(host->dma_chan_rxtx);

--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
                   ` (3 preceding siblings ...)
  2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-28 10:56   ` Ulf Hansson
  2024-10-25 10:36 ` [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags Stefan Wahren
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

Add a minimalistic suspend/resume PM support.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/mmc/host/bcm2835.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 107666b7c1c8..17c327b7b5cc 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -1343,6 +1343,30 @@ static int bcm2835_add_host(struct bcm2835_host *host)
 	return 0;
 }

+static int bcm2835_suspend(struct device *dev)
+{
+	struct bcm2835_host *host = dev_get_drvdata(dev);
+
+	if (!host->data_complete) {
+		dev_warn(dev, "Suspend is prevented\n");
+		return -EBUSY;
+	}
+
+	clk_disable_unprepare(host->clk);
+
+	return 0;
+}
+
+static int bcm2835_resume(struct device *dev)
+{
+	struct bcm2835_host *host = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(host->clk);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835_pm_ops, bcm2835_suspend,
+				bcm2835_resume);
+
 static int bcm2835_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1471,6 +1495,7 @@ static struct platform_driver bcm2835_driver = {
 		.name		= "sdhost-bcm2835",
 		.probe_type	= PROBE_PREFER_ASYNCHRONOUS,
 		.of_match_table	= bcm2835_match,
+		.pm = pm_ptr(&bcm2835_pm_ops),
 	},
 };
 module_platform_driver(bcm2835_driver);
--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
                   ` (4 preceding siblings ...)
  2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers Stefan Wahren
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

dwc2_restore_device_registers() use a single boolean
to decide about the register restoring behavior.
So replace this with a flags parameter, which can
be extended later.

No functional change intended.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/usb/dwc2/core.h   |  6 ++++--
 drivers/usb/dwc2/gadget.c | 12 +++++++-----
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 2bd74f3033ed..48f4b639ca2f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1127,6 +1127,8 @@ struct dwc2_hsotg {
 #define DWC2_FS_IOT_ID		0x55310000
 #define DWC2_HS_IOT_ID		0x55320000

+#define DWC2_RESTORE_DCTL BIT(0)
+
 #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
 	union dwc2_hcd_internal_flags {
 		u32 d32;
@@ -1420,7 +1422,7 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 #define dwc2_is_device_enabled(hsotg) (hsotg->enabled)
 int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags);
 int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg);
 int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 				 int rem_wakeup, int reset);
@@ -1459,7 +1461,7 @@ static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
 static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg,
-						int remote_wakeup)
+						unsigned int flags)
 { return 0; }
 static inline int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
 { return 0; }
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index e7bf9cc635be..96d703f4c509 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5203,11 +5203,11 @@ int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
  * if controller power were disabled.
  *
  * @hsotg: Programming view of the DWC_otg controller
- * @remote_wakeup: Indicates whether resume is initiated by Device or Host.
+ * @flags: Defines which registers should be restored.
  *
  * Return: 0 if successful, negative error code otherwise
  */
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags)
 {
 	struct dwc2_dregs_backup *dr;
 	int i;
@@ -5223,7 +5223,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 	}
 	dr->valid = false;

-	if (!remote_wakeup)
+	if (flags & DWC2_RESTORE_DCTL)
 		dwc2_writel(hsotg, dr->dctl, DCTL);

 	dwc2_writel(hsotg, dr->daintmsk, DAINTMSK);
@@ -5414,6 +5414,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 	u32 gpwrdn;
 	u32 dctl;
 	int ret = 0;
+	unsigned int flags = 0;
 	struct dwc2_gregs_backup *gr;
 	struct dwc2_dregs_backup *dr;

@@ -5476,6 +5477,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 		dctl = dwc2_readl(hsotg, DCTL);
 		dctl |= DCTL_PWRONPRGDONE;
 		dwc2_writel(hsotg, dctl, DCTL);
+		flags |= DWC2_RESTORE_DCTL;
 	}
 	/* Wait for interrupts which must be cleared */
 	mdelay(2);
@@ -5491,7 +5493,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 	}

 	/* Restore device registers */
-	ret = dwc2_restore_device_registers(hsotg, rem_wakeup);
+	ret = dwc2_restore_device_registers(hsotg, flags);
 	if (ret) {
 		dev_err(hsotg->dev, "%s: failed to restore device registers\n",
 			__func__);
@@ -5619,7 +5621,7 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
 		/* Restore DCFG */
 		dwc2_writel(hsotg, dr->dcfg, DCFG);

-		ret = dwc2_restore_device_registers(hsotg, 0);
+		ret = dwc2_restore_device_registers(hsotg, DWC2_RESTORE_DCTL);
 		if (ret) {
 			dev_err(hsotg->dev, "%s: failed to restore device registers\n",
 				__func__);
--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
                   ` (5 preceding siblings ...)
  2024-10-25 10:36 ` [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND Stefan Wahren
  8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

The DWC2 runtime PM code reuses similar patterns to backup and
restore the registers. So consolidate them in USB mode specific
variants. This also has the advantage it is reusable for further
PM improvements.

Special care is taken for DCFG register during device mode restore.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/usb/dwc2/core.h   |  15 ++++++
 drivers/usb/dwc2/gadget.c | 108 +++++++++++++++++++-------------------
 drivers/usb/dwc2/hcd.c    |  99 +++++++++++++++++-----------------
 3 files changed, 121 insertions(+), 101 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 48f4b639ca2f..265791fbe87f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1128,6 +1128,7 @@ struct dwc2_hsotg {
 #define DWC2_HS_IOT_ID		0x55320000

 #define DWC2_RESTORE_DCTL BIT(0)
+#define DWC2_RESTORE_DCFG BIT(1)

 #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
 	union dwc2_hcd_internal_flags {
@@ -1437,6 +1438,9 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
 void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
 void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg,
+					   unsigned int flags);
 static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg)
 { hsotg->fifo_map = 0; }
 #else
@@ -1484,6 +1488,11 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
 static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
+static inline int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg,
+							 unsigned int flags)
+{ return 0; }
 static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg) {}
 #endif

@@ -1507,6 +1516,8 @@ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg,
 void dwc2_host_enter_clock_gating(struct dwc2_hsotg *hsotg);
 void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup);
 bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2);
+int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg);
+int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg);
 static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg)
 { schedule_work(&hsotg->phy_reset_work); }
 #else
@@ -1546,6 +1557,10 @@ static inline void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg,
 					       int rem_wakeup) {}
 static inline bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2)
 { return false; }
+static inline int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
 static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) {}

 #endif
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 96d703f4c509..2e071a0342f8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5223,6 +5223,9 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags)
 	}
 	dr->valid = false;

+	if (flags & DWC2_RESTORE_DCFG)
+		dwc2_writel(hsotg, dr->dcfg, DCFG);
+
 	if (flags & DWC2_RESTORE_DCTL)
 		dwc2_writel(hsotg, dr->dctl, DCTL);

@@ -5309,6 +5312,49 @@ void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg)
 	dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK));
 }

+int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{
+	int ret;
+
+	/* 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;
+	}
+
+	return 0;
+}
+
+int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg,
+					   unsigned int flags)
+{
+	int ret;
+
+	ret = dwc2_restore_global_registers(hsotg);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to restore registers\n",
+			__func__);
+		return ret;
+	}
+	ret = dwc2_restore_device_registers(hsotg, flags);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to restore device registers\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
 /**
  * dwc2_gadget_enter_hibernation() - Put controller in Hibernation.
  *
@@ -5326,18 +5372,9 @@ int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
 	/* Change to L2(suspend) state */
 	hsotg->lx_state = DWC2_L2;
 	dev_dbg(hsotg->dev, "Start of hibernation completed\n");
-	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__);
+	ret = dwc2_gadget_backup_critical_registers(hsotg);
+	if (ret)
 		return ret;
-	}

 	gpwrdn = GPWRDN_PWRDNRSTN;
 	udelay(10);
@@ -5485,20 +5522,9 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 	dwc2_writel(hsotg, 0xffffffff, GINTSTS);

 	/* Restore global registers */
-	ret = dwc2_restore_global_registers(hsotg);
-	if (ret) {
-		dev_err(hsotg->dev, "%s: failed to restore registers\n",
-			__func__);
-		return ret;
-	}
-
-	/* Restore device registers */
-	ret = dwc2_restore_device_registers(hsotg, flags);
-	if (ret) {
-		dev_err(hsotg->dev, "%s: failed to restore device registers\n",
-			__func__);
+	ret = dwc2_gadget_restore_critical_registers(hsotg, flags);
+	if (ret)
 		return ret;
-	}

 	if (rem_wakeup) {
 		mdelay(10);
@@ -5532,19 +5558,9 @@ int dwc2_gadget_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 	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__);
+	ret = dwc2_gadget_backup_critical_registers(hsotg);
+	if (ret)
 		return ret;
-	}

 	/*
 	 * Clear any pending interrupts since dwc2 will not be able to
@@ -5591,11 +5607,8 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
 {
 	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);
@@ -5612,21 +5625,10 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,

 	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, DWC2_RESTORE_DCTL);
-		if (ret) {
-			dev_err(hsotg->dev, "%s: failed to restore device registers\n",
-				__func__);
+		ret = dwc2_gadget_restore_critical_registers(hsotg, DWC2_RESTORE_DCTL |
+							     DWC2_RESTORE_DCFG);
+		if (ret)
 			return ret;
-		}
 	}

 	/* Set the Power-On Programming done bit */
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index cb54390e7de4..32fa606e5d59 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5477,6 +5477,49 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
 	return 0;
 }

+int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{
+	int ret;
+
+	/* 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_host_registers(hsotg);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to backup host registers\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg)
+{
+	int ret;
+
+	ret = dwc2_restore_global_registers(hsotg);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to restore registers\n",
+			__func__);
+		return ret;
+	}
+
+	ret = dwc2_restore_host_registers(hsotg);
+	if (ret) {
+		dev_err(hsotg->dev, "%s: failed to restore host registers\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
 /**
  * dwc2_host_enter_hibernation() - Put controller in Hibernation.
  *
@@ -5492,18 +5535,9 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
 	u32 gpwrdn;

 	dev_dbg(hsotg->dev, "Preparing host for hibernation\n");
-	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_host_registers(hsotg);
-	if (ret) {
-		dev_err(hsotg->dev, "%s: failed to backup host registers\n",
-			__func__);
+	ret = dwc2_host_backup_critical_registers(hsotg);
+	if (ret)
 		return ret;
-	}

 	/* Enter USB Suspend Mode */
 	hprt0 = dwc2_readl(hsotg, HPRT0);
@@ -5697,20 +5731,9 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
 	dwc2_writel(hsotg, 0xffffffff, GINTSTS);

 	/* Restore global registers */
-	ret = dwc2_restore_global_registers(hsotg);
-	if (ret) {
-		dev_err(hsotg->dev, "%s: failed to restore registers\n",
-			__func__);
+	ret = dwc2_host_restore_critical_registers(hsotg);
+	if (ret)
 		return ret;
-	}
-
-	/* Restore host registers */
-	ret = dwc2_restore_host_registers(hsotg);
-	if (ret) {
-		dev_err(hsotg->dev, "%s: failed to restore host registers\n",
-			__func__);
-		return ret;
-	}

 	if (rem_wakeup) {
 		dwc2_hcd_rem_wakeup(hsotg);
@@ -5777,19 +5800,9 @@ int dwc2_host_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 		dev_warn(hsotg->dev, "Suspend wasn't generated\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_host_registers(hsotg);
-	if (ret) {
-		dev_err(hsotg->dev, "%s: failed to backup host registers\n",
-			__func__);
+	ret = dwc2_host_backup_critical_registers(hsotg);
+	if (ret)
 		return ret;
-	}

 	/*
 	 * Clear any pending interrupts since dwc2 will not be able to
@@ -5858,19 +5871,9 @@ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg,

 	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;
-		}
-
-		ret = dwc2_restore_host_registers(hsotg);
-		if (ret) {
-			dev_err(hsotg->dev, "%s: failed to restore host registers\n",
-				__func__);
+		ret = dwc2_host_restore_critical_registers(hsotg);
+		if (ret)
 			return ret;
-		}
 	}

 	/* Drive resume signaling and exit suspend mode on the port. */
--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
                   ` (6 preceding siblings ...)
  2024-10-25 10:36 ` [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  2024-10-25 10:36 ` [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND Stefan Wahren
  8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren, Douglas Anderson

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>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/usb/dwc2/core.c     |  1 +
 drivers/usb/dwc2/core.h     |  2 ++
 drivers/usb/dwc2/platform.c | 38 +++++++++++++++++++++++++++++++++++++
 3 files changed, 41 insertions(+)

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 265791fbe87f..34127b890b2a 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 c1b7209b9483..4a3c81cd45d6 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -685,6 +685,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);
@@ -694,6 +702,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, "No valid register backup, failed to restore\n");
+		return -EINVAL;
+	}
+
+	if (gr->gintsts & GINTSTS_CURMODE_HOST)
+		return dwc2_host_restore_critical_registers(hsotg);
+
+	return dwc2_gadget_restore_critical_registers(hsotg, DWC2_RESTORE_DCTL |
+						      DWC2_RESTORE_DCFG);
+}
+
 static int __maybe_unused dwc2_resume(struct device *dev)
 {
 	struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
@@ -706,6 +732,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



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND
  2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
                   ` (7 preceding siblings ...)
  2024-10-25 10:36 ` [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
  8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
  To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
  Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
	kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
	linux-usb, Stefan Wahren

Since the Raspberry Pi supports Suspend-To-Idle now, this option
should be enabled. This should make power management testing easier.

Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
---
 arch/arm/configs/bcm2835_defconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index b5f0bd8dd536..97632dee1ab3 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -38,8 +38,6 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_CPUFREQ_DT=y
 CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
 CONFIG_VFP=y
-# CONFIG_SUSPEND is not set
-CONFIG_PM=y
 CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
--
2.34.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support
  2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
@ 2024-10-28 10:56   ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2024-10-28 10:56 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
	Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

On Fri, 25 Oct 2024 at 12:36, Stefan Wahren <wahrenst@gmx.net> wrote:
>
> Add a minimalistic suspend/resume PM support.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
>  drivers/mmc/host/bcm2835.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index 107666b7c1c8..17c327b7b5cc 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -1343,6 +1343,30 @@ static int bcm2835_add_host(struct bcm2835_host *host)
>         return 0;
>  }
>
> +static int bcm2835_suspend(struct device *dev)
> +{
> +       struct bcm2835_host *host = dev_get_drvdata(dev);
> +
> +       if (!host->data_complete) {
> +               dev_warn(dev, "Suspend is prevented\n");
> +               return -EBUSY;
> +       }

This should not be needed.

The mmc core makes sure all outstanding requests have been flushed,
before the host controller becomes suspended.

> +
> +       clk_disable_unprepare(host->clk);
> +
> +       return 0;
> +}
> +
> +static int bcm2835_resume(struct device *dev)
> +{
> +       struct bcm2835_host *host = dev_get_drvdata(dev);
> +
> +       return clk_prepare_enable(host->clk);
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835_pm_ops, bcm2835_suspend,
> +                               bcm2835_resume);
> +
>  static int bcm2835_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> @@ -1471,6 +1495,7 @@ static struct platform_driver bcm2835_driver = {
>                 .name           = "sdhost-bcm2835",
>                 .probe_type     = PROBE_PREFER_ASYNCHRONOUS,
>                 .of_match_table = bcm2835_match,
> +               .pm = pm_ptr(&bcm2835_pm_ops),
>         },
>  };
>  module_platform_driver(bcm2835_driver);

Kind regards
Uffe


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed
  2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
@ 2024-10-28 11:43   ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2024-10-28 11:43 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
	Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

On Fri, 25 Oct 2024 at 12:36, Stefan Wahren <wahrenst@gmx.net> wrote:
>
> The type of mmc_ios.clock is unsigned int, so the cached value
> should be of the same type.
>
> Fixes: 660fc733bd74 ("mmc: bcm2835: Add new driver for the sdhost controller.")
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/bcm2835.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index 35d8fdea668b..3d3eda5a337c 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -150,7 +150,7 @@ struct bcm2835_host {
>
>         struct platform_device  *pdev;
>
> -       int                     clock;          /* Current clock speed */
> +       unsigned int            clock;          /* Current clock speed */
>         unsigned int            max_clk;        /* Max possible freq */
>         struct work_struct      dma_work;
>         struct delayed_work     timeout_work;   /* Timer for timeouts */
> --
> 2.34.1
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling
  2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
@ 2024-10-28 11:43   ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2024-10-28 11:43 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
	Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

On Fri, 25 Oct 2024 at 12:36, Stefan Wahren <wahrenst@gmx.net> wrote:
>
> The custom sdhost controller on BCM2835 is feed by the critical VPU clock.
> In preparation for PM suspend/resume support, add a proper clock handling
> to the driver like in the other clock consumers (e.g. I2C).
>
> Move the clock handling behind mmc_of_parse(), because it could return
> with -EPROBE_DEFER and we want to minimize potential clock operation during
> boot phase.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/bcm2835.c | 29 ++++++++++++++++++-----------
>  1 file changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index 3d3eda5a337c..107666b7c1c8 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -148,6 +148,7 @@ struct bcm2835_host {
>         void __iomem            *ioaddr;
>         u32                     phys_addr;
>
> +       struct clk              *clk;
>         struct platform_device  *pdev;
>
>         unsigned int            clock;          /* Current clock speed */
> @@ -1345,7 +1346,6 @@ static int bcm2835_add_host(struct bcm2835_host *host)
>  static int bcm2835_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> -       struct clk *clk;
>         struct bcm2835_host *host;
>         struct mmc_host *mmc;
>         const __be32 *regaddr_p;
> @@ -1393,15 +1393,6 @@ static int bcm2835_probe(struct platform_device *pdev)
>                 /* Ignore errors to fall back to PIO mode */
>         }
>
> -
> -       clk = devm_clk_get(dev, NULL);
> -       if (IS_ERR(clk)) {
> -               ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n");
> -               goto err;
> -       }
> -
> -       host->max_clk = clk_get_rate(clk);
> -
>         host->irq = platform_get_irq(pdev, 0);
>         if (host->irq < 0) {
>                 ret = host->irq;
> @@ -1412,16 +1403,30 @@ static int bcm2835_probe(struct platform_device *pdev)
>         if (ret)
>                 goto err;
>
> -       ret = bcm2835_add_host(host);
> +       host->clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(host->clk)) {
> +               ret = dev_err_probe(dev, PTR_ERR(host->clk), "could not get clk\n");
> +               goto err;
> +       }
> +
> +       ret = clk_prepare_enable(host->clk);
>         if (ret)
>                 goto err;
>
> +       host->max_clk = clk_get_rate(host->clk);
> +
> +       ret = bcm2835_add_host(host);
> +       if (ret)
> +               goto err_clk;
> +
>         platform_set_drvdata(pdev, host);
>
>         dev_dbg(dev, "%s -> OK\n", __func__);
>
>         return 0;
>
> +err_clk:
> +       clk_disable_unprepare(host->clk);
>  err:
>         dev_dbg(dev, "%s -> err %d\n", __func__, ret);
>         if (host->dma_chan_rxtx)
> @@ -1445,6 +1450,8 @@ static void bcm2835_remove(struct platform_device *pdev)
>         cancel_work_sync(&host->dma_work);
>         cancel_delayed_work_sync(&host->timeout_work);
>
> +       clk_disable_unprepare(host->clk);
> +
>         if (host->dma_chan_rxtx)
>                 dma_release_channel(host->dma_chan_rxtx);
>
> --
> 2.34.1
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs"
  2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
@ 2024-10-29  9:44   ` Ivan T . Ivanov
  0 siblings, 0 replies; 18+ messages in thread
From: Ivan T . Ivanov @ 2024-10-29  9:44 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman,
	Lukas Wunner, Peter Robinson, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

Hi Stefan,

On 10-25 12:36, Stefan Wahren wrote:
> 
> The commit d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
> introduced a regression on Raspberry Pi 3 B Plus, which prevents
> enumeration of the onboard Microchip LAN7800 in case no external USB device
> is connected during boot.
> 
> Fixes: d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
>  drivers/usb/dwc2/params.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
> index 68226defdc60..4d73fae80b12 100644
> --- a/drivers/usb/dwc2/params.c
> +++ b/drivers/usb/dwc2/params.c
> @@ -23,7 +23,6 @@ static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg)
>  	p->max_transfer_size = 65535;
>  	p->max_packet_count = 511;
>  	p->ahbcfg = 0x10;
> -	p->no_clock_gating = true;
>  }
> 

Thanks, this makes RPi3 Ethernet operational again.

Tested-by: Ivan T. Ivanov <iivanov@suse.de>

Regards.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
  2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
@ 2024-11-09 17:37   ` Stefan Wahren
  2024-12-02 16:52   ` Vinod Koul
  1 sibling, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-11-09 17:37 UTC (permalink / raw)
  To: Russell King, Lukas Wunner, Florian Fainelli, Ray Jui,
	Scott Branden, Vinod Koul
  Cc: Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, Ulf Hansson,
	kernel-list, Greg Kroah-Hartman, Minas Harutyunyan,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

Am 25.10.24 um 12:36 schrieb Stefan Wahren:
> bcm2835-dma provides the service to others, so it should
> suspend late and resume early.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>

Since there wasn't any feedback for this patch, i want to send a gentle
ping ...

Regards

> ---
>   drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
>   1 file changed, 30 insertions(+)
>
> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> index e1b92b4d7b05..647dda9f3376 100644
> --- a/drivers/dma/bcm2835-dma.c
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
>   	return chan;
>   }
>
> +static int bcm2835_dma_suspend_late(struct device *dev)
> +{
> +	struct bcm2835_dmadev *od = dev_get_drvdata(dev);
> +	struct bcm2835_chan *c, *next;
> +
> +	list_for_each_entry_safe(c, next, &od->ddev.channels,
> +				 vc.chan.device_node) {
> +		void __iomem *chan_base = c->chan_base;
> +
> +		if (readl(chan_base + BCM2835_DMA_ADDR)) {
> +			dev_warn(dev, "Suspend is prevented by chan %d\n",
> +				 c->ch);
> +			return -EBUSY;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int bcm2835_dma_resume_early(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops bcm2835_dma_pm_ops = {
> +	SET_LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late,
> +				     bcm2835_dma_resume_early)
> +};
> +
>   static int bcm2835_dma_probe(struct platform_device *pdev)
>   {
>   	struct bcm2835_dmadev *od;
> @@ -1033,6 +1062,7 @@ static struct platform_driver bcm2835_dma_driver = {
>   	.driver = {
>   		.name = "bcm2835-dma",
>   		.of_match_table = of_match_ptr(bcm2835_dma_of_match),
> +		.pm = pm_ptr(&bcm2835_dma_pm_ops),
>   	},
>   };
>
> --
> 2.34.1
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
  2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
  2024-11-09 17:37   ` Stefan Wahren
@ 2024-12-02 16:52   ` Vinod Koul
  2024-12-02 18:51     ` Stefan Wahren
  1 sibling, 1 reply; 18+ messages in thread
From: Vinod Koul @ 2024-12-02 16:52 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
	Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

On 25-10-24, 12:36, Stefan Wahren wrote:
> bcm2835-dma provides the service to others, so it should
> suspend late and resume early.
> 
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
>  drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> index e1b92b4d7b05..647dda9f3376 100644
> --- a/drivers/dma/bcm2835-dma.c
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
>  	return chan;
>  }
> 
> +static int bcm2835_dma_suspend_late(struct device *dev)
> +{
> +	struct bcm2835_dmadev *od = dev_get_drvdata(dev);
> +	struct bcm2835_chan *c, *next;
> +
> +	list_for_each_entry_safe(c, next, &od->ddev.channels,
> +				 vc.chan.device_node) {
> +		void __iomem *chan_base = c->chan_base;
> +
> +		if (readl(chan_base + BCM2835_DMA_ADDR)) {
> +			dev_warn(dev, "Suspend is prevented by chan %d\n",
> +				 c->ch);
> +			return -EBUSY;
> +		}

Can you help understand how this helps by logging... we are not adding
anything except checking this and resume is NOP as well!

> +	}
> +
> +	return 0;
> +}
> +
> +static int bcm2835_dma_resume_early(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops bcm2835_dma_pm_ops = {
> +	SET_LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late,
> +				     bcm2835_dma_resume_early)
> +};
> +
>  static int bcm2835_dma_probe(struct platform_device *pdev)
>  {
>  	struct bcm2835_dmadev *od;
> @@ -1033,6 +1062,7 @@ static struct platform_driver bcm2835_dma_driver = {
>  	.driver = {
>  		.name = "bcm2835-dma",
>  		.of_match_table = of_match_ptr(bcm2835_dma_of_match),
> +		.pm = pm_ptr(&bcm2835_dma_pm_ops),
>  	},
>  };
> 
> --
> 2.34.1

-- 
~Vinod


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
  2024-12-02 16:52   ` Vinod Koul
@ 2024-12-02 18:51     ` Stefan Wahren
  2024-12-04 12:27       ` Vinod Koul
  0 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-12-02 18:51 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
	Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

Hi Vinod,

Am 02.12.24 um 17:52 schrieb Vinod Koul:
> On 25-10-24, 12:36, Stefan Wahren wrote:
>> bcm2835-dma provides the service to others, so it should
>> suspend late and resume early.
>>
>> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
>> ---
>>   drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
>>   1 file changed, 30 insertions(+)
>>
>> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
>> index e1b92b4d7b05..647dda9f3376 100644
>> --- a/drivers/dma/bcm2835-dma.c
>> +++ b/drivers/dma/bcm2835-dma.c
>> @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
>>   	return chan;
>>   }
>>
>> +static int bcm2835_dma_suspend_late(struct device *dev)
>> +{
>> +	struct bcm2835_dmadev *od = dev_get_drvdata(dev);
>> +	struct bcm2835_chan *c, *next;
>> +
>> +	list_for_each_entry_safe(c, next, &od->ddev.channels,
>> +				 vc.chan.device_node) {
>> +		void __iomem *chan_base = c->chan_base;
>> +
>> +		if (readl(chan_base + BCM2835_DMA_ADDR)) {
>> +			dev_warn(dev, "Suspend is prevented by chan %d\n",
>> +				 c->ch);
>> +			return -EBUSY;
>> +		}
> Can you help understand how this helps by logging... we are not adding
> anything except checking this and resume is NOP as well!
My intention of this patch is just to make sure, that no DMA transfer is
in progress during late_suspend. So i followed the implementation of
fsldma.c

Additionally i added this warning mostly to know if this ever occurs.
But i wasn't able to trigger.

Should i drop the warning and make resume callback = NULL?

Best regards




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
  2024-12-02 18:51     ` Stefan Wahren
@ 2024-12-04 12:27       ` Vinod Koul
  0 siblings, 0 replies; 18+ messages in thread
From: Vinod Koul @ 2024-12-04 12:27 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
	Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
	Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
	bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb

On 02-12-24, 19:51, Stefan Wahren wrote:
> Hi Vinod,
> 
> Am 02.12.24 um 17:52 schrieb Vinod Koul:
> > On 25-10-24, 12:36, Stefan Wahren wrote:
> > > bcm2835-dma provides the service to others, so it should
> > > suspend late and resume early.
> > > 
> > > Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> > > ---
> > >   drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
> > >   1 file changed, 30 insertions(+)
> > > 
> > > diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> > > index e1b92b4d7b05..647dda9f3376 100644
> > > --- a/drivers/dma/bcm2835-dma.c
> > > +++ b/drivers/dma/bcm2835-dma.c
> > > @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
> > >   	return chan;
> > >   }
> > > 
> > > +static int bcm2835_dma_suspend_late(struct device *dev)
> > > +{
> > > +	struct bcm2835_dmadev *od = dev_get_drvdata(dev);
> > > +	struct bcm2835_chan *c, *next;
> > > +
> > > +	list_for_each_entry_safe(c, next, &od->ddev.channels,
> > > +				 vc.chan.device_node) {
> > > +		void __iomem *chan_base = c->chan_base;
> > > +
> > > +		if (readl(chan_base + BCM2835_DMA_ADDR)) {
> > > +			dev_warn(dev, "Suspend is prevented by chan %d\n",
> > > +				 c->ch);
> > > +			return -EBUSY;
> > > +		}
> > Can you help understand how this helps by logging... we are not adding
> > anything except checking this and resume is NOP as well!
> My intention of this patch is just to make sure, that no DMA transfer is
> in progress during late_suspend. So i followed the implementation of
> fsldma.c
> 
> Additionally i added this warning mostly to know if this ever occurs.
> But i wasn't able to trigger.

Okay in the case I dont think it is a abd idea. But the patch
description should mention that add a warning while suspending if
channels are active or something like that.
Patch title and description should mention this..

> 
> Should i drop the warning and make resume callback = NULL?

Yes that would be better as well, no point in having dummy code

-- 
~Vinod


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2024-12-04 12:30 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
2024-10-29  9:44   ` Ivan T . Ivanov
2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
2024-11-09 17:37   ` Stefan Wahren
2024-12-02 16:52   ` Vinod Koul
2024-12-02 18:51     ` Stefan Wahren
2024-12-04 12:27       ` Vinod Koul
2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
2024-10-28 11:43   ` Ulf Hansson
2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
2024-10-28 11:43   ` Ulf Hansson
2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
2024-10-28 10:56   ` Ulf Hansson
2024-10-25 10:36 ` [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND Stefan Wahren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).