* [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains
@ 2026-09-20 22:48 Linus Walleij
2026-09-20 22:48 ` [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema Linus Walleij
` (18 more replies)
0 siblings, 19 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Krzysztof Kozlowski, Krzysztof Kozlowski, Frank Li,
Frank Li
This series pays off technical debt from the beginning of the device
tree for ARM initiative in the early 2010s.
Today the Ux500 SoC specifically DB8500 is using what is called "EPOD
regulators" (EPOD = Electric POwer Domain) to control its power domains.
This was done like this because at the time, power domains did not exist
as a concept in the Linux kernel.
This patch series completes the ambitious work started in commit
cd931dcfda5e ("ARM: ux500: Initial support for PM domains") which added
a dummy domain driver for Ux500 in the following steps:
- Convert the old Ux500 power domain text DT bindings to YAML schema.
- Extend the bindings with all the 16 power domains actually existing in
the hardware.
- Add these domains to the existing ux500 power domain driver (still as
dummy domains).
- Add the power domains to the DB8500 SoC DTSI file.
- Move code over from the EPOD regulators to the actual power domain
driver. Since the two drivers now control the same hardware, make the
drivers mutually exclusive.
- Modify the MCDE display driver to use the power domain instead of the
EPOD regulators.
- Modify the DMA40 DMA controller to use the power domain instead of the
EPOD regulators.
- Delete the old EPOD regulators.
- Delete the references to the unused EPOD regulators from the device
tree.
The series is ordered so binding updates and compatibility glue precede
the DTS and driver changes that depend on them.
MERGE STRATEGY:
1. Device tree bindings need review, before that the series is a
no-go.
2. For simplicity, the series can be merged in separate paths and
subsystems as there are no build-time dependencies, as long as the
result ends up in kernel v7.4.
Once the concept and patches are ACKed by the power domain folks, I
will send the patches that can be split out individually to each
maintainer and it can all be merged in parallel. I will send a
pull request to the SoC tree with bindings and DTS changes.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Changes in v3:
- Complete the EPOD regulator removal: delete the old regulator drivers
and the entire db8500-prcmu-regulators DTS node, including VAPE and
VSMPS2. Deprecate the binding and make the node optional, retaining
its schema only for older device trees.
- Make the whole db8500-prcmu-regulators node optional and deprecated,
replacing the individual VAPE and VSMPS2 deprecations.
- Drop the PMU power-domain binding patch: the PMU shares the CPU domain.
- Assign both CPUs to DOMAIN_VARM as described by arm/cpus.yaml, and
remove the separate PMU power-domain assignment.
- Link to v2: https://lore.kernel.org/r/20260914-ux500-power-domains-v7-1-v2-0-9d0c17e1f816@kernel.org
Changes in v2:
- Went on a detour clean-up job relating to buck regulators.
Rebased on kernel v7.3-rc1 and the regulator re-works in this
mail thread:
https://lore.kernel.org/mfd/20260901-ux500-dts-snowball-regulator-v2-0-fe88b01829bf@kernel.org/
- Drop the PM domain "regulators" entirely, the external components
now use their actual buck regulators.
- Fix the DB8500 pin controller power domain to use VAPE.
- Allow power-domain references in the l2c2x0, arm,pmu,
stericsson,u8500-clks, arm,twd-timer, arm,twd-wdt and ste,mcde
schemas used by the DB8500 DTS additions.
- Treat only negative pm_runtime_put_sync_suspend() returns as errors.
- Fix the MCDE probe error path to disable the main clock after reset.
- Fix Ux500 PM-domain probe error cleanup for domains and provider data.
- Drop the unused Ux500 power-state activity counter.
- Describe Ux500 subdomains in DT and use OF child ID helpers.
- Move DMA40 LCLA power-domain get out of atomic transfer paths.
- Enable runtime PM in the generic SRAM driver so SRAM power domains
are managed by their owner before DMA40 takes LCLA references.
- Add a DMA40 device link so system PM orders the LCLA SRAM supplier.
- Add binding fixes for the DB8500 PRCMU regulator child nodes.
- Add an MCDE binding update for the new power-domain reference.
- Fix up the DB8500 DTS changes for the remaining VAPE and VSMPS2
compatibility regulators.
- Link to v1: https://lore.kernel.org/r/20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org
---
Linus Walleij (18):
dt-bindings: power: Convert Ux500 PM domains to schema
dt-bindings: arm: ux500: Drop NR_DOMAINS
dt-bindings: arm: Add the actual power domains on U8500
dt-bindings: mfd: db8500-prcmu: Deprecate EPOD regulators
dt-bindings: display: ste,mcde: Allow power domains
pmdomain: st: ux500: Implement more power domains
ARM: dts: ux500: Rename power domains node
dt-bindings: clock: stericsson,u8500-clks: Allow power domains
dt-bindings: timer: arm,twd-timer: Allow power domains
dt-bindings: watchdog: arm,twd-wdt: Allow power domains
ARM: dts: ux500: Add power domains
pmdomain: st: ux500: Control DB8500 EPODs
drm/mcde: Use power domain for display power
misc: sram: Enable runtime PM
dmaengine: ste_dma40: Use power domain for LCLA SRAM
mfd/regulator: db8500-prcmu: Remove EPOD regulators
dt-bindings: display: ste,mcde: Deprecate EPOD supply
ARM: dts: ux500: Remove DB8500 EPOD regulators
.../devicetree/bindings/arm/ux500/power_domain.txt | 35 --
.../bindings/clock/stericsson,u8500-clks.yaml | 3 +
.../devicetree/bindings/display/ste,mcde.yaml | 10 +-
.../bindings/mfd/stericsson,db8500-prcmu.yaml | 22 +-
.../power/stericsson,ux500-pm-domains.yaml | 49 ++
.../devicetree/bindings/timer/arm,twd-timer.yaml | 3 +
.../devicetree/bindings/watchdog/arm,twd-wdt.yaml | 3 +
MAINTAINERS | 1 +
arch/arm/boot/dts/st/ste-dbx5x0.dtsi | 156 +++----
arch/arm/mach-ux500/Kconfig | 2 +-
drivers/dma/ste_dma40.c | 130 ++++--
drivers/gpu/drm/mcde/mcde_clk_div.c | 4 +-
drivers/gpu/drm/mcde/mcde_display.c | 11 +-
drivers/gpu/drm/mcde/mcde_drm.h | 2 -
drivers/gpu/drm/mcde/mcde_drv.c | 68 +--
drivers/gpu/drm/mcde/mcde_dsi.c | 1 -
drivers/mfd/db8500-prcmu.c | 239 ----------
drivers/misc/sram.c | 5 +
drivers/pmdomain/st/ste-ux500-pm-domain.c | 330 ++++++++++++--
drivers/regulator/Kconfig | 11 -
drivers/regulator/Makefile | 2 -
drivers/regulator/db8500-prcmu.c | 501 ---------------------
drivers/regulator/dbx500-prcmu.c | 155 -------
drivers/regulator/dbx500-prcmu.h | 55 ---
include/dt-bindings/arm/ux500_pm_domains.h | 17 +-
include/linux/regulator/db8500-prcmu.h | 38 --
26 files changed, 560 insertions(+), 1293 deletions(-)
---
base-commit: 67aa45aae7efe0162f198f26714f668b759468c4
change-id: 20260618-ux500-power-domains-v7-1-3c9d095828c2
Best regards,
--
Linus Walleij <linusw@kernel.org>
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-28 5:37 ` Krzysztof Kozlowski
2026-09-20 22:48 ` [PATCH v3 02/18] dt-bindings: arm: ux500: Drop NR_DOMAINS Linus Walleij
` (17 subsequent siblings)
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Convert the legacy Ux500 power domain text binding to YAML.
Move it under bindings/power.
Reference the generic power-domain schema.
Update MAINTAINERS for the new path.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
.../devicetree/bindings/arm/ux500/power_domain.txt | 35 ----------------
.../power/stericsson,ux500-pm-domains.yaml | 49 ++++++++++++++++++++++
MAINTAINERS | 1 +
3 files changed, 50 insertions(+), 35 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/ux500/power_domain.txt b/Documentation/devicetree/bindings/arm/ux500/power_domain.txt
deleted file mode 100644
index 5679d1742d3e..000000000000
--- a/Documentation/devicetree/bindings/arm/ux500/power_domain.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-* ST-Ericsson UX500 PM Domains
-
-UX500 supports multiple PM domains which are used to gate power to one or
-more peripherals on the SOC.
-
-The implementation of PM domains for UX500 are based upon the generic PM domain
-and use the corresponding DT bindings.
-
-==PM domain providers==
-
-Required properties:
- - compatible: Must be "stericsson,ux500-pm-domains".
- - #power-domain-cells : Number of cells in a power domain specifier, must be 1.
-
-Example:
- pm_domains: pm_domains0 {
- compatible = "stericsson,ux500-pm-domains";
- #power-domain-cells = <1>;
- };
-
-==PM domain consumers==
-
-Required properties:
- - power-domains: A phandle and PM domain specifier. Below are the list of
- valid specifiers:
-
- Index Specifier
- ----- ---------
- 0 DOMAIN_VAPE
-
-Example:
- sdi0_per1@80126000 {
- compatible = "arm,pl18x", "arm,primecell";
- power-domains = <&pm_domains DOMAIN_VAPE>
- };
diff --git a/Documentation/devicetree/bindings/power/stericsson,ux500-pm-domains.yaml b/Documentation/devicetree/bindings/power/stericsson,ux500-pm-domains.yaml
new file mode 100644
index 000000000000..1d5b4787aada
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/stericsson,ux500-pm-domains.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/stericsson,ux500-pm-domains.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ST-Ericsson UX500 power domains
+
+maintainers:
+ - Linus Walleij <linusw@kernel.org>
+ - Ulf Hansson <ulfh@kernel.org>
+
+description:
+ The UX500 power domain controller gates power to one or more peripherals on
+ the SoC. Domain specifiers use one cell containing one of the DOMAIN_*
+ indexes defined in dt-bindings/arm/ux500_pm_domains.h.
+
+allOf:
+ - $ref: power-domain.yaml#
+
+properties:
+ compatible:
+ const: stericsson,ux500-pm-domains
+
+ '#power-domain-cells':
+ const: 1
+
+required:
+ - compatible
+ - '#power-domain-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/arm/ux500_pm_domains.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pm_domains: power-controller {
+ compatible = "stericsson,ux500-pm-domains";
+ #power-domain-cells = <1>;
+ };
+
+ mmc@80126000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ reg = <0x80126000 0x1000>;
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3a19da74d00c..560079711469 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3273,6 +3273,7 @@ F: Documentation/devicetree/bindings/arm/ux500.yaml
F: Documentation/devicetree/bindings/arm/ux500/
F: Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
F: Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
+F: Documentation/devicetree/bindings/power/stericsson,ux500-pm-domains.yaml
F: arch/arm/boot/dts/st/ste-*
F: arch/arm/mach-nomadik/
F: arch/arm/mach-ux500/
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 02/18] dt-bindings: arm: ux500: Drop NR_DOMAINS
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
2026-09-20 22:48 ` [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 03/18] dt-bindings: arm: Add the actual power domains on U8500 Linus Walleij
` (16 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Krzysztof Kozlowski, Krzysztof Kozlowski
Keep the internal Ux500 PM domain count local to the only driver
that uses it.
Do not expose this implementation detail through the DT binding header.
Assisted-by: LLM
Suggested-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/pmdomain/st/ste-ux500-pm-domain.c | 2 ++
include/dt-bindings/arm/ux500_pm_domains.h | 2 --
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
index 6896cb4a7b71..c9129a3b1805 100644
--- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
+++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
@@ -17,6 +17,8 @@
#include <dt-bindings/arm/ux500_pm_domains.h>
+#define NR_DOMAINS (DOMAIN_VAPE + 1)
+
static int pd_power_off(struct generic_pm_domain *domain)
{
/*
diff --git a/include/dt-bindings/arm/ux500_pm_domains.h b/include/dt-bindings/arm/ux500_pm_domains.h
index 9bd764f0c9e6..9d94801d8b89 100644
--- a/include/dt-bindings/arm/ux500_pm_domains.h
+++ b/include/dt-bindings/arm/ux500_pm_domains.h
@@ -9,7 +9,5 @@
#define DOMAIN_VAPE 0
-/* Number of PM domains. */
-#define NR_DOMAINS (DOMAIN_VAPE + 1)
#endif
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 03/18] dt-bindings: arm: Add the actual power domains on U8500
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
2026-09-20 22:48 ` [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema Linus Walleij
2026-09-20 22:48 ` [PATCH v3 02/18] dt-bindings: arm: ux500: Drop NR_DOMAINS Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 04/18] dt-bindings: mfd: db8500-prcmu: Deprecate EPOD regulators Linus Walleij
` (15 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Krzysztof Kozlowski
This file has been left in an unfinished state just defining
the root power domain for the U8500 SoC. Fix it up by adding
the actual existing power domains in this SoC.
The PRCMU code and old regulator driver is mentioning some
*_RET domains, this means "retention" and is a state in the
domain and not a domain of its own.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
include/dt-bindings/arm/ux500_pm_domains.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/include/dt-bindings/arm/ux500_pm_domains.h b/include/dt-bindings/arm/ux500_pm_domains.h
index 9d94801d8b89..f7a9fc101fb2 100644
--- a/include/dt-bindings/arm/ux500_pm_domains.h
+++ b/include/dt-bindings/arm/ux500_pm_domains.h
@@ -8,6 +8,21 @@
#define _DT_BINDINGS_ARM_UX500_PM_DOMAINS_H
#define DOMAIN_VAPE 0
+#define DOMAIN_VARM 1
+#define DOMAIN_VMODEM 2
+#define DOMAIN_VPLL 3
+#define DOMAIN_VSMPS1 4
+#define DOMAIN_VSMPS2 5
+#define DOMAIN_VSMPS3 6
+#define DOMAIN_VRF1 7
+#define DOMAIN_SVA_MMDSP 8
+#define DOMAIN_SVA_PIPE 9
+#define DOMAIN_SIA_MMDSP 10
+#define DOMAIN_SIA_PIPE 11
+#define DOMAIN_SGA 12
+#define DOMAIN_B2R2_MCDE 13
+#define DOMAIN_ESRAM_12 14
+#define DOMAIN_ESRAM_34 15
#endif
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 04/18] dt-bindings: mfd: db8500-prcmu: Deprecate EPOD regulators
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (2 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 03/18] dt-bindings: arm: Add the actual power domains on U8500 Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 05/18] dt-bindings: display: ste,mcde: Allow power domains Linus Walleij
` (14 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Krzysztof Kozlowski
Deprecate the db8500-prcmu-regulators node and make it optional as EPOD
control moves to generic power domains. External consumers of VAPE and
VSMPS2 now use the actual AB8500 or AB8505 buck regulators.
Stop requiring the individual regulator child nodes while retaining
their definitions for existing device trees.
Assisted-by: LLM
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
.../bindings/mfd/stericsson,db8500-prcmu.yaml | 22 +---------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
index 4edd4a3bab88..ce9060340e0c 100644
--- a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
+++ b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
@@ -58,6 +58,7 @@ properties:
const: 2
db8500-prcmu-regulators:
+ deprecated: true
description: Node describing the DB8500 regulators. These are mainly
power rails inside the silicon but some of those are also routed
out to external pins.
@@ -207,26 +208,6 @@ properties:
required:
- compatible
- - db8500_vape
- - db8500_varm
- - db8500_vmodem
- - db8500_vpll
- - db8500_vsmps1
- - db8500_vsmps2
- - db8500_vsmps3
- - db8500_vrf1
- - db8500_sva_mmdsp
- - db8500_sva_mmdsp_ret
- - db8500_sva_pipe
- - db8500_sia_mmdsp
- - db8500_sia_mmdsp_ret
- - db8500_sia_pipe
- - db8500_sga
- - db8500_b2r2_mcde
- - db8500_esram12
- - db8500_esram12_ret
- - db8500_esram34
- - db8500_esram34_ret
additionalProperties: false
@@ -294,6 +275,5 @@ required:
- interrupts
- interrupt-controller
- '#interrupt-cells'
- - db8500-prcmu-regulators
additionalProperties: false
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 05/18] dt-bindings: display: ste,mcde: Allow power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (3 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 04/18] dt-bindings: mfd: db8500-prcmu: Deprecate EPOD regulators Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-10-08 17:41 ` Rob Herring
2026-09-20 22:48 ` [PATCH v3 06/18] pmdomain: st: ux500: Implement more " Linus Walleij
` (13 subsequent siblings)
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Krzysztof Kozlowski
Document the MCDE power domain.
Keep the legacy EPOD regulator binding unchanged for now.
Assisted-by: LLM
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Documentation/devicetree/bindings/display/ste,mcde.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/ste,mcde.yaml b/Documentation/devicetree/bindings/display/ste,mcde.yaml
index 7a12d0b817e6..05e7e4ebc882 100644
--- a/Documentation/devicetree/bindings/display/ste,mcde.yaml
+++ b/Documentation/devicetree/bindings/display/ste,mcde.yaml
@@ -35,6 +35,9 @@ properties:
resets:
maxItems: 1
+ power-domains:
+ maxItems: 1
+
epod-supply:
description: a phandle to the EPOD regulator
@@ -109,6 +112,7 @@ examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/arm/ux500_pm_domains.h>
#include <dt-bindings/mfd/dbx500-prcmu.h>
#include <dt-bindings/gpio/gpio.h>
@@ -116,6 +120,7 @@ examples:
compatible = "ste,mcde";
reg = <0xa0350000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pm_domains DOMAIN_B2R2_MCDE>;
epod-supply = <&db8500_b2r2_mcde_reg>;
vana-supply = <&ab8500_ldo_ana_reg>;
clocks = <&prcmu_clk PRCMU_MCDECLK>,
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 06/18] pmdomain: st: ux500: Implement more power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (4 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 05/18] dt-bindings: display: ste,mcde: Allow power domains Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 07/18] ARM: dts: ux500: Rename power domains node Linus Walleij
` (12 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
This starts to implement the power domains that are just skeleton
implementations right now.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/pmdomain/st/ste-ux500-pm-domain.c | 127 +++++++++++++++++++++++++++++-
1 file changed, 125 insertions(+), 2 deletions(-)
diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
index c9129a3b1805..d90a563cd6f3 100644
--- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
+++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
@@ -17,7 +17,7 @@
#include <dt-bindings/arm/ux500_pm_domains.h>
-#define NR_DOMAINS (DOMAIN_VAPE + 1)
+#define NR_DOMAINS (DOMAIN_ESRAM_34 + 1)
static int pd_power_off(struct generic_pm_domain *domain)
{
@@ -43,14 +43,137 @@ static int pd_power_on(struct generic_pm_domain *domain)
return 0;
}
+/*
+ * Apart from these voltage domains there is also VSAFE which is always
+ * on. Vape_esram0_pwr for eSRAM0 is connected to VSAFE.
+ */
static struct generic_pm_domain ux500_pm_domain_vape = {
- .name = "VAPE",
+ /* Vape_pwr */
+ .name = "VAPE", /* 0.95 .. 1.20 V */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_varm = {
+ .name = "VARM",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_vmodem = {
+ .name = "VMODEM",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_vpll = {
+ .name = "VPLL", /* 1.8 V */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+/*
+ * CHECKME: as these are used directly by peripherals as regulators,
+ * perhaps they should stay in the regulator subsystem?
+ */
+static struct generic_pm_domain ux500_pm_domain_vsmps1 = {
+ .name = "VSMPS1", /* Also called VIO (1.2V) */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_vsmps2 = {
+ .name = "VSMPS2", /* Also called VIO (1.8V) */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_vsmps3 = {
+ .name = "VSMPS3",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_vrf1 = {
+ .name = "VRF1",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+/* The following are technically children of VAPE */
+static struct generic_pm_domain ux500_pm_domain_sva_mmdsp = {
+ /* Vape_SVA_MMDSP_pwr */
+ .name = "SVA_MMDSP",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_sva_pipe = {
+ /* Vape_SVA_pwr */
+ .name = "SVA_PIPE",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_sia_mmdsp = {
+ /* Vape_SIA_MMDSP_pwr */
+ .name = "SIA_MMDSP",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_sia_pipe = {
+ /* Vape_SIA_pwr */
+ .name = "SIA_PIPE",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_sga = {
+ /* Vape_SGA_pwr */
+ .name = "SGA",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_b2r2_mcde = {
+ /* Vape_DSS_pwr DSS (display subsystem) */
+ .name = "B2R2_MCDE",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_esram_12 = {
+ /* Vape_esram1_pwr, Vape_esram2_pwr */
+ .name = "ESRAM_12",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain ux500_pm_domain_esram_34 = {
+ /* Vape_esram3_pwr, Vape_esram4_pwr */
+ .name = "ESRAM_34",
.power_off = pd_power_off,
.power_on = pd_power_on,
};
static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = {
[DOMAIN_VAPE] = &ux500_pm_domain_vape,
+ [DOMAIN_VARM] = &ux500_pm_domain_varm,
+ [DOMAIN_VMODEM] = &ux500_pm_domain_vmodem,
+ [DOMAIN_VPLL] = &ux500_pm_domain_vpll,
+ [DOMAIN_VSMPS1] = &ux500_pm_domain_vsmps1,
+ [DOMAIN_VSMPS2] = &ux500_pm_domain_vsmps2,
+ [DOMAIN_VSMPS3] = &ux500_pm_domain_vsmps3,
+ [DOMAIN_VRF1] = &ux500_pm_domain_vrf1,
+ [DOMAIN_SVA_MMDSP] = &ux500_pm_domain_sva_mmdsp,
+ [DOMAIN_SVA_PIPE] = &ux500_pm_domain_sva_pipe,
+ [DOMAIN_SIA_MMDSP] = &ux500_pm_domain_sia_mmdsp,
+ [DOMAIN_SIA_PIPE] = &ux500_pm_domain_sia_pipe,
+ [DOMAIN_SGA] = &ux500_pm_domain_sga,
+ [DOMAIN_B2R2_MCDE] = &ux500_pm_domain_b2r2_mcde,
+ [DOMAIN_ESRAM_12] = &ux500_pm_domain_esram_12,
+ [DOMAIN_ESRAM_34] = &ux500_pm_domain_esram_34,
};
static const struct of_device_id ux500_pm_domain_matches[] = {
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 07/18] ARM: dts: ux500: Rename power domains node
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (5 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 06/18] pmdomain: st: ux500: Implement more " Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 08/18] dt-bindings: clock: stericsson,u8500-clks: Allow power domains Linus Walleij
` (11 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
This matches the naming used in the binding document
Documentation/devicetree/bindings/power/power-domain.yaml
It's most logical to call it a power controller.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/arm/boot/dts/st/ste-dbx5x0.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
index 25a20fafc6b9..11fcae1904e2 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
@@ -343,7 +343,7 @@ pmu {
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
};
- pm_domains: pm_domains0 {
+ pm_domains: power-controller {
compatible = "stericsson,ux500-pm-domains";
#power-domain-cells = <1>;
};
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 08/18] dt-bindings: clock: stericsson,u8500-clks: Allow power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (6 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 07/18] ARM: dts: ux500: Rename power domains node Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 09/18] dt-bindings: timer: arm,twd-timer: " Linus Walleij
` (10 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Allow the DB8500 clock controller node to reference its power domain.
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml b/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml
index 4ebfa5a8d524..75e5e1107ebb 100644
--- a/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml
+++ b/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml
@@ -34,6 +34,9 @@ properties:
- description: PRCC 5 register area
- description: PRCC 6 register area
+ power-domains:
+ maxItems: 1
+
prcmu-clock:
description: A subnode with one clock cell for PRCMU (power, reset, control
management unit) clocks. The cell indicates which PRCMU clock in the
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 09/18] dt-bindings: timer: arm,twd-timer: Allow power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (7 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 08/18] dt-bindings: clock: stericsson,u8500-clks: Allow power domains Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 10/18] dt-bindings: watchdog: arm,twd-wdt: " Linus Walleij
` (9 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Allow TWD timer nodes to reference their power domain.
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Documentation/devicetree/bindings/timer/arm,twd-timer.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/timer/arm,twd-timer.yaml b/Documentation/devicetree/bindings/timer/arm,twd-timer.yaml
index eb1127352c7b..716d5f2d4eac 100644
--- a/Documentation/devicetree/bindings/timer/arm,twd-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/arm,twd-timer.yaml
@@ -33,6 +33,9 @@ properties:
clocks:
maxItems: 1
+ power-domains:
+ maxItems: 1
+
always-on:
description:
If present, the timer is powered through an always-on power domain,
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 10/18] dt-bindings: watchdog: arm,twd-wdt: Allow power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (8 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 09/18] dt-bindings: timer: arm,twd-timer: " Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 11/18] ARM: dts: ux500: Add " Linus Walleij
` (8 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Allow TWD watchdog nodes to reference their power domain.
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Documentation/devicetree/bindings/watchdog/arm,twd-wdt.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/watchdog/arm,twd-wdt.yaml b/Documentation/devicetree/bindings/watchdog/arm,twd-wdt.yaml
index 9646ac72051e..5f6a9d6b9976 100644
--- a/Documentation/devicetree/bindings/watchdog/arm,twd-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/arm,twd-wdt.yaml
@@ -33,6 +33,9 @@ properties:
clocks:
maxItems: 1
+ power-domains:
+ maxItems: 1
+
required:
- compatible
- reg
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 11/18] ARM: dts: ux500: Add power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (9 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 10/18] dt-bindings: watchdog: arm,twd-wdt: " Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 23:04 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs Linus Walleij
` (7 subsequent siblings)
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Add the actual power domains to the CPUs and SoC peripherals.
Both CPUs share DOMAIN_VARM, which also supplies their PMU.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/arm/boot/dts/st/ste-dbx5x0.dtsi | 71 +++++++++++++++++++++++++++++++-----
1 file changed, 62 insertions(+), 9 deletions(-)
diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
index 11fcae1904e2..0603244dc9e8 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
@@ -54,6 +54,7 @@ CPU0: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0x300>;
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&prcmu_clk PRCMU_ARMSS>;
clock-names = "cpu";
clock-latency = <20000>;
@@ -63,6 +64,7 @@ CPU1: cpu@301 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0x301>;
+ power-domains = <&pm_domains DOMAIN_VARM>;
};
};
@@ -154,6 +156,7 @@ sram@40020000 {
reg = <0x40020000 0x40000>;
#address-cells = <1>;
#size-cells = <1>;
+ power-domains = <&pm_domains DOMAIN_ESRAM_12>;
ranges = <0 0x40020000 0x40000>;
};
sram@40060000 {
@@ -162,6 +165,7 @@ sram@40060000 {
reg = <0x40060000 0x40000>;
#address-cells = <1>;
#size-cells = <1>;
+ power-domains = <&pm_domains DOMAIN_ESRAM_34>;
ranges = <0 0x40060000 0x40000>;
lcla: sram@20000 {
@@ -181,7 +185,7 @@ lcla: sram@20000 {
ptm@801ae000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x801ae000 0x1000>;
-
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "apb_pclk", "atclk";
cpu = <&CPU0>;
@@ -197,7 +201,7 @@ ptm0_out_port: endpoint {
ptm@801af000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x801af000 0x1000>;
-
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "apb_pclk", "atclk";
cpu = <&CPU1>;
@@ -213,7 +217,7 @@ ptm1_out_port: endpoint {
funnel@801a6000 {
compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
reg = <0x801a6000 0x1000>;
-
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "apb_pclk", "atclk";
out-ports {
@@ -249,6 +253,7 @@ replicator {
compatible = "arm,coresight-static-replicator";
clocks = <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "atclk";
+ power-domains = <&pm_domains DOMAIN_VARM>;
out-ports {
#address-cells = <1>;
@@ -280,7 +285,7 @@ replicator_in_port0: endpoint {
tpiu@80190000 {
compatible = "arm,coresight-tpiu", "arm,primecell";
reg = <0x80190000 0x1000>;
-
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "apb_pclk", "atclk";
in-ports {
@@ -295,7 +300,7 @@ tpiu_in_port: endpoint {
etb@801a4000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x801a4000 0x1000>;
-
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>;
clock-names = "apb_pclk", "atclk";
in-ports {
@@ -314,11 +319,13 @@ intc: interrupt-controller@a0411000 {
interrupt-controller;
reg = <0xa0411000 0x1000>,
<0xa0410100 0x100>;
+ power-domains = <&pm_domains DOMAIN_VARM>;
};
scu@a0410000 {
compatible = "arm,cortex-a9-scu";
reg = <0xa0410000 0x100>;
+ power-domains = <&pm_domains DOMAIN_VARM>;
};
/*
@@ -326,6 +333,7 @@ scu@a0410000 {
* and various things like spin tables
*/
backupram@80150000 {
+ /* This memory is in the VSAFE (always on) power domain */
compatible = "ste,dbx500-backupram";
reg = <0x80150000 0x2000>;
};
@@ -334,6 +342,7 @@ L2: cache-controller {
compatible = "arm,pl310-cache";
reg = <0xa0412000 0x1000>;
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pm_domains DOMAIN_VARM>;
cache-unified;
cache-level = <2>;
};
@@ -346,6 +355,18 @@ pmu {
pm_domains: power-controller {
compatible = "stericsson,ux500-pm-domains";
#power-domain-cells = <1>;
+ power-domains = <&pm_domains DOMAIN_VAPE>,
+ <&pm_domains DOMAIN_VAPE>,
+ <&pm_domains DOMAIN_VAPE>,
+ <&pm_domains DOMAIN_VAPE>,
+ <&pm_domains DOMAIN_VAPE>,
+ <&pm_domains DOMAIN_VAPE>;
+ power-domains-child-ids = <DOMAIN_SVA_MMDSP>,
+ <DOMAIN_SVA_PIPE>,
+ <DOMAIN_SIA_MMDSP>,
+ <DOMAIN_SIA_PIPE>,
+ <DOMAIN_SGA>,
+ <DOMAIN_B2R2_MCDE>;
};
clocks {
@@ -357,6 +378,7 @@ clocks {
reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
<0x8000f000 0x1000>, <0xa03ff000 0x1000>,
<0xa03cf000 0x1000>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
prcmu_clk: prcmu-clock {
#clock-cells = <1>;
@@ -393,7 +415,7 @@ mtu@a03c6000 {
compatible = "st,nomadik-mtu";
reg = <0xa03c6000 0x1000>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
-
+ power-domains = <&pm_domains DOMAIN_VAPE>;
clocks = <&prcmu_clk PRCMU_TIMCLK>, <&prcc_pclk 6 6>;
clock-names = "timclk", "apb_pclk";
};
@@ -402,7 +424,7 @@ timer@a0410600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0xa0410600 0x20>;
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
-
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&smp_twd_clk>;
};
@@ -410,14 +432,15 @@ watchdog@a0410620 {
compatible = "arm,cortex-a9-twd-wdt";
reg = <0xa0410620 0x20>;
interrupts = <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
+ power-domains = <&pm_domains DOMAIN_VARM>;
clocks = <&smp_twd_clk>;
};
rtc@80154000 {
+ /* This peripheral is in the VSAFE (always on) power domain */
compatible = "arm,pl031", "arm,primecell";
reg = <0x80154000 0x1000>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
-
clocks = <&rtc_clk>;
clock-names = "apb_pclk";
};
@@ -435,6 +458,7 @@ gpio0: gpio@8012e000 {
gpio-bank = <0>;
gpio-ranges = <&pinctrl 0 0 32>;
clocks = <&prcc_pclk 1 9>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio1: gpio@8012e080 {
@@ -450,6 +474,7 @@ gpio1: gpio@8012e080 {
gpio-bank = <1>;
gpio-ranges = <&pinctrl 0 32 5>;
clocks = <&prcc_pclk 1 9>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio2: gpio@8000e000 {
@@ -465,6 +490,7 @@ gpio2: gpio@8000e000 {
gpio-bank = <2>;
gpio-ranges = <&pinctrl 0 64 32>;
clocks = <&prcc_pclk 3 8>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio3: gpio@8000e080 {
@@ -480,6 +506,7 @@ gpio3: gpio@8000e080 {
gpio-bank = <3>;
gpio-ranges = <&pinctrl 0 96 2>;
clocks = <&prcc_pclk 3 8>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio4: gpio@8000e100 {
@@ -495,6 +522,7 @@ gpio4: gpio@8000e100 {
gpio-bank = <4>;
gpio-ranges = <&pinctrl 0 128 32>;
clocks = <&prcc_pclk 3 8>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio5: gpio@8000e180 {
@@ -510,6 +538,7 @@ gpio5: gpio@8000e180 {
gpio-bank = <5>;
gpio-ranges = <&pinctrl 0 160 12>;
clocks = <&prcc_pclk 3 8>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio6: gpio@8011e000 {
@@ -525,6 +554,7 @@ gpio6: gpio@8011e000 {
gpio-bank = <6>;
gpio-ranges = <&pinctrl 0 192 32>;
clocks = <&prcc_pclk 2 11>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio7: gpio@8011e080 {
@@ -540,6 +570,7 @@ gpio7: gpio@8011e080 {
gpio-bank = <7>;
gpio-ranges = <&pinctrl 0 224 7>;
clocks = <&prcc_pclk 2 11>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
gpio8: gpio@a03fe000 {
@@ -555,6 +586,7 @@ gpio8: gpio@a03fe000 {
gpio-bank = <8>;
gpio-ranges = <&pinctrl 0 256 12>;
clocks = <&prcc_pclk 5 1>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
pinctrl: pinctrl {
@@ -570,6 +602,7 @@ usb_per5@a03e0000 {
reg = <0xa03e0000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "mc";
+ power-domains = <&pm_domains DOMAIN_VAPE>;
dr_mode = "otg";
@@ -613,9 +646,11 @@ dma: dma-controller@801C0000 {
memcpy-channels = <56 57 58 59 60>;
clocks = <&prcmu_clk PRCMU_DMACLK>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
prcmu: prcmu@80157000 {
+ /* This peripheral is in the VSAFE (always on) power domain */
compatible = "stericsson,db8500-prcmu", "syscon";
reg = <0x80157000 0x2000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>;
reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm";
@@ -641,6 +676,10 @@ thermal: thermal@801573c0 {
#thermal-sensor-cells = <0>;
};
+ /*
+ * TODO: Delete these bogus regulators and replace with power
+ * domains.
+ */
db8500-prcmu-regulators {
compatible = "stericsson,db8500-prcmu-regulator";
@@ -932,6 +971,7 @@ serial0: serial@80120000 {
clocks = <&prcc_kclk 1 0>, <&prcc_pclk 1 0>;
clock-names = "uart", "apb_pclk";
+ power-domains = <&pm_domains DOMAIN_VAPE>;
resets = <&prcc_reset DB8500_PRCC_1 DB8500_PRCC_1_RESET_UART0>;
status = "disabled";
@@ -948,6 +988,7 @@ serial1: serial@80121000 {
clocks = <&prcc_kclk 1 1>, <&prcc_pclk 1 1>;
clock-names = "uart", "apb_pclk";
+ power-domains = <&pm_domains DOMAIN_VAPE>;
resets = <&prcc_reset DB8500_PRCC_1 DB8500_PRCC_1_RESET_UART1>;
status = "disabled";
@@ -964,6 +1005,7 @@ serial2: serial@80007000 {
clocks = <&prcc_kclk 3 6>, <&prcc_pclk 3 6>;
clock-names = "uart", "apb_pclk";
+ power-domains = <&pm_domains DOMAIN_VAPE>;
resets = <&prcc_reset DB8500_PRCC_3 DB8500_PRCC_3_RESET_UART2>;
status = "disabled";
@@ -1080,7 +1122,9 @@ msp0: msp@80123000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80123000 0x1000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ /* TODO: delete and replace with power-domain handling */
v-ape-supply = <&db8500_vape_reg>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */
<&dma 31 0 0x10>; /* Logical - MemToDev - HighPrio */
@@ -1097,7 +1141,9 @@ msp1: msp@80124000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80124000 0x1000>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ /* TODO: delete and replace with power-domain handling */
v-ape-supply = <&db8500_vape_reg>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
/* This DMA channel only exist on DB8500 v1 */
dmas = <&dma 30 0 0x10>; /* Logical - MemToDev - HighPrio */
@@ -1115,7 +1161,9 @@ msp2: msp@80117000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80117000 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ /* TODO: delete and replace with power-domain handling */
v-ape-supply = <&db8500_vape_reg>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
dmas = <&dma 14 0 0x12>, /* Logical - DevToMem - HighPrio */
<&dma 14 1 0x19>; /* Physical Chan 1 - MemToDev
@@ -1133,7 +1181,9 @@ msp3: msp@80125000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80125000 0x1000>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ /* TODO: delete and replace with power-domain handling */
v-ape-supply = <&db8500_vape_reg>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
/* This DMA channel only exist on DB8500 v2 */
dmas = <&dma 30 0 0x12>; /* Logical - DevToMem - HighPrio */
@@ -1175,14 +1225,17 @@ gpu@a0300000 {
"combined";
clocks = <&prcmu_clk PRCMU_ACLK>, <&prcmu_clk PRCMU_SGACLK>;
clock-names = "bus", "core";
+ power-domains = <&pm_domains DOMAIN_SGA>;
+ /* TODO: delete and replace with power-domain handling */
mali-supply = <&db8500_sga_reg>;
- power-domains = <&pm_domains DOMAIN_VAPE>;
};
mcde@a0350000 {
compatible = "ste,mcde";
reg = <0xa0350000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pm_domains DOMAIN_B2R2_MCDE>;
+ /* TODO: delete and replace with power-domain handling */
epod-supply = <&db8500_b2r2_mcde_reg>;
clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
<&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (10 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 11/18] ARM: dts: ux500: Add " Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 23:04 ` sashiko-bot
2026-09-24 13:44 ` Ulf Hansson
2026-09-20 22:48 ` [PATCH v3 13/18] drm/mcde: Use power domain for display power Linus Walleij
` (6 subsequent siblings)
18 siblings, 2 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Move the DB8500 EPOD state handling into the Ux500 power-domain driver.
Keep the old regulator driver mutually exclusive with the pmdomain driver.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/arm/mach-ux500/Kconfig | 2 +-
drivers/pmdomain/st/ste-ux500-pm-domain.c | 355 +++++++++++++++++++++---------
drivers/regulator/Kconfig | 1 +
3 files changed, 254 insertions(+), 104 deletions(-)
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index c18def269137..56636c993f49 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -26,7 +26,7 @@ menuconfig ARCH_U8500
select PL310_ERRATA_753970 if CACHE_L2X0
select PM_GENERIC_DOMAINS if PM
select REGULATOR
- select REGULATOR_DB8500_PRCMU
+ select UX500_PM_DOMAIN
select REGULATOR_FIXED_VOLTAGE
select SOC_BUS
select RESET_CONTROLLER
diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
index d90a563cd6f3..b31a36a4acd1 100644
--- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
+++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
@@ -6,174 +6,292 @@
*
* Implements PM domains using the generic PM domain for ux500.
*/
+#include <linux/cleanup.h>
#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/printk.h>
-#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/pm_domain.h>
+#include <linux/slab.h>
#include <dt-bindings/arm/ux500_pm_domains.h>
#define NR_DOMAINS (DOMAIN_ESRAM_34 + 1)
+#define UX500_EPOD_NONE NUM_EPOD_ID
-static int pd_power_off(struct generic_pm_domain *domain)
+/**
+ * struct dbx500_powerdomain_info - dbx500 power domain information
+ * @genpd: generic power domain
+ * @epod_id: id for EPOD (power domain)
+ * @is_ramret: RAM retention switch for EPOD (power domain)
+ */
+struct dbx500_powerdomain_info {
+ struct generic_pm_domain genpd;
+ u16 epod_id;
+ bool is_ramret;
+};
+
+static DEFINE_MUTEX(ux500_pd_lock);
+static bool epod_on[NUM_EPOD_ID];
+static bool epod_ramret[NUM_EPOD_ID];
+
+static int enable_epod(u16 epod_id, bool ramret)
{
- /*
- * Handle the gating of the PM domain regulator here.
- *
- * Drivers/subsystems handling devices in the PM domain needs to perform
- * register context save/restore from their respective runtime PM
- * callbacks, to be able to enable PM domain gating/ungating.
- */
+ int ret;
+
+ if (ramret) {
+ if (!epod_on[epod_id]) {
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ if (ret < 0)
+ return ret;
+ }
+ epod_ramret[epod_id] = true;
+ } else {
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_ON);
+ if (ret < 0)
+ return ret;
+ epod_on[epod_id] = true;
+ }
+
return 0;
}
-static int pd_power_on(struct generic_pm_domain *domain)
+static int disable_epod(u16 epod_id, bool ramret)
{
- /*
- * Handle the ungating of the PM domain regulator here.
- *
- * Drivers/subsystems handling devices in the PM domain needs to perform
- * register context save/restore from their respective runtime PM
- * callbacks, to be able to enable PM domain gating/ungating.
- */
+ int ret;
+
+ if (ramret) {
+ if (!epod_on[epod_id]) {
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ if (ret < 0)
+ return ret;
+ }
+ epod_ramret[epod_id] = false;
+ } else {
+ if (epod_ramret[epod_id]) {
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ if (ret < 0)
+ return ret;
+ }
+ epod_on[epod_id] = false;
+ }
+
return 0;
}
+
+static int pd_power_off(struct generic_pm_domain *domain)
+{
+ struct dbx500_powerdomain_info *info =
+ container_of(domain, struct dbx500_powerdomain_info, genpd);
+ int ret = 0;
+
+ guard(mutex)(&ux500_pd_lock);
+ if (info->epod_id < NUM_EPOD_ID)
+ ret = disable_epod(info->epod_id, info->is_ramret);
+
+ return ret;
+}
+
+static int pd_power_on(struct generic_pm_domain *domain)
+{
+ struct dbx500_powerdomain_info *info =
+ container_of(domain, struct dbx500_powerdomain_info, genpd);
+ int ret = 0;
+
+ guard(mutex)(&ux500_pd_lock);
+ if (info->epod_id < NUM_EPOD_ID)
+ ret = enable_epod(info->epod_id, info->is_ramret);
+
+ return ret;
+}
+
/*
* Apart from these voltage domains there is also VSAFE which is always
* on. Vape_esram0_pwr for eSRAM0 is connected to VSAFE.
*/
-static struct generic_pm_domain ux500_pm_domain_vape = {
+static struct dbx500_powerdomain_info ux500_pm_domain_vape = {
/* Vape_pwr */
- .name = "VAPE", /* 0.95 .. 1.20 V */
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "VAPE", /* 0.95 .. 1.20 V */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
-static struct generic_pm_domain ux500_pm_domain_varm = {
- .name = "VARM",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_varm = {
+ .genpd = {
+ .name = "VARM",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
-static struct generic_pm_domain ux500_pm_domain_vmodem = {
- .name = "VMODEM",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_vmodem = {
+ .genpd = {
+ .name = "VMODEM",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
-static struct generic_pm_domain ux500_pm_domain_vpll = {
- .name = "VPLL", /* 1.8 V */
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_vpll = {
+ .genpd = {
+ .name = "VPLL", /* 1.8 V */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
/*
* CHECKME: as these are used directly by peripherals as regulators,
* perhaps they should stay in the regulator subsystem?
*/
-static struct generic_pm_domain ux500_pm_domain_vsmps1 = {
- .name = "VSMPS1", /* Also called VIO (1.2V) */
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_vsmps1 = {
+ .genpd = {
+ .name = "VSMPS1", /* Also called VIO (1.2V) */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
-static struct generic_pm_domain ux500_pm_domain_vsmps2 = {
- .name = "VSMPS2", /* Also called VIO (1.8V) */
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_vsmps2 = {
+ .genpd = {
+ .name = "VSMPS2", /* Also called VIO (1.8V) */
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
-static struct generic_pm_domain ux500_pm_domain_vsmps3 = {
- .name = "VSMPS3",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_vsmps3 = {
+ .genpd = {
+ .name = "VSMPS3",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
-static struct generic_pm_domain ux500_pm_domain_vrf1 = {
- .name = "VRF1",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+static struct dbx500_powerdomain_info ux500_pm_domain_vrf1 = {
+ .genpd = {
+ .name = "VRF1",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = UX500_EPOD_NONE,
};
/* The following are technically children of VAPE */
-static struct generic_pm_domain ux500_pm_domain_sva_mmdsp = {
+static struct dbx500_powerdomain_info ux500_pm_domain_sva_mmdsp = {
/* Vape_SVA_MMDSP_pwr */
- .name = "SVA_MMDSP",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "SVA_MMDSP",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_SVAMMDSP,
};
-static struct generic_pm_domain ux500_pm_domain_sva_pipe = {
+static struct dbx500_powerdomain_info ux500_pm_domain_sva_pipe = {
/* Vape_SVA_pwr */
- .name = "SVA_PIPE",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "SVA_PIPE",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_SVAPIPE,
};
-static struct generic_pm_domain ux500_pm_domain_sia_mmdsp = {
+static struct dbx500_powerdomain_info ux500_pm_domain_sia_mmdsp = {
/* Vape_SIA_MMDSP_pwr */
- .name = "SIA_MMDSP",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "SIA_MMDSP",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_SIAMMDSP,
};
-static struct generic_pm_domain ux500_pm_domain_sia_pipe = {
+static struct dbx500_powerdomain_info ux500_pm_domain_sia_pipe = {
/* Vape_SIA_pwr */
- .name = "SIA_PIPE",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "SIA_PIPE",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_SIAPIPE,
};
-static struct generic_pm_domain ux500_pm_domain_sga = {
+static struct dbx500_powerdomain_info ux500_pm_domain_sga = {
/* Vape_SGA_pwr */
- .name = "SGA",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "SGA",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_SGA,
};
-static struct generic_pm_domain ux500_pm_domain_b2r2_mcde = {
+static struct dbx500_powerdomain_info ux500_pm_domain_b2r2_mcde = {
/* Vape_DSS_pwr DSS (display subsystem) */
- .name = "B2R2_MCDE",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "B2R2_MCDE",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_B2R2_MCDE,
};
-static struct generic_pm_domain ux500_pm_domain_esram_12 = {
+static struct dbx500_powerdomain_info ux500_pm_domain_esram_12 = {
/* Vape_esram1_pwr, Vape_esram2_pwr */
- .name = "ESRAM_12",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "ESRAM_12",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_ESRAM12,
};
-static struct generic_pm_domain ux500_pm_domain_esram_34 = {
+static struct dbx500_powerdomain_info ux500_pm_domain_esram_34 = {
/* Vape_esram3_pwr, Vape_esram4_pwr */
- .name = "ESRAM_34",
- .power_off = pd_power_off,
- .power_on = pd_power_on,
+ .genpd = {
+ .name = "ESRAM_34",
+ .power_off = pd_power_off,
+ .power_on = pd_power_on,
+ },
+ .epod_id = EPOD_ID_ESRAM34,
};
static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = {
- [DOMAIN_VAPE] = &ux500_pm_domain_vape,
- [DOMAIN_VARM] = &ux500_pm_domain_varm,
- [DOMAIN_VMODEM] = &ux500_pm_domain_vmodem,
- [DOMAIN_VPLL] = &ux500_pm_domain_vpll,
- [DOMAIN_VSMPS1] = &ux500_pm_domain_vsmps1,
- [DOMAIN_VSMPS2] = &ux500_pm_domain_vsmps2,
- [DOMAIN_VSMPS3] = &ux500_pm_domain_vsmps3,
- [DOMAIN_VRF1] = &ux500_pm_domain_vrf1,
- [DOMAIN_SVA_MMDSP] = &ux500_pm_domain_sva_mmdsp,
- [DOMAIN_SVA_PIPE] = &ux500_pm_domain_sva_pipe,
- [DOMAIN_SIA_MMDSP] = &ux500_pm_domain_sia_mmdsp,
- [DOMAIN_SIA_PIPE] = &ux500_pm_domain_sia_pipe,
- [DOMAIN_SGA] = &ux500_pm_domain_sga,
- [DOMAIN_B2R2_MCDE] = &ux500_pm_domain_b2r2_mcde,
- [DOMAIN_ESRAM_12] = &ux500_pm_domain_esram_12,
- [DOMAIN_ESRAM_34] = &ux500_pm_domain_esram_34,
+ [DOMAIN_VAPE] = &ux500_pm_domain_vape.genpd,
+ [DOMAIN_VARM] = &ux500_pm_domain_varm.genpd,
+ [DOMAIN_VMODEM] = &ux500_pm_domain_vmodem.genpd,
+ [DOMAIN_VPLL] = &ux500_pm_domain_vpll.genpd,
+ [DOMAIN_VSMPS1] = &ux500_pm_domain_vsmps1.genpd,
+ [DOMAIN_VSMPS2] = &ux500_pm_domain_vsmps2.genpd,
+ [DOMAIN_VSMPS3] = &ux500_pm_domain_vsmps3.genpd,
+ [DOMAIN_VRF1] = &ux500_pm_domain_vrf1.genpd,
+ [DOMAIN_SVA_MMDSP] = &ux500_pm_domain_sva_mmdsp.genpd,
+ [DOMAIN_SVA_PIPE] = &ux500_pm_domain_sva_pipe.genpd,
+ [DOMAIN_SIA_MMDSP] = &ux500_pm_domain_sia_mmdsp.genpd,
+ [DOMAIN_SIA_PIPE] = &ux500_pm_domain_sia_pipe.genpd,
+ [DOMAIN_SGA] = &ux500_pm_domain_sga.genpd,
+ [DOMAIN_B2R2_MCDE] = &ux500_pm_domain_b2r2_mcde.genpd,
+ [DOMAIN_ESRAM_12] = &ux500_pm_domain_esram_12.genpd,
+ [DOMAIN_ESRAM_34] = &ux500_pm_domain_esram_34.genpd,
};
static const struct of_device_id ux500_pm_domain_matches[] = {
@@ -186,11 +304,12 @@ static int ux500_pm_domains_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct genpd_onecell_data *genpd_data;
int i;
+ int ret;
if (!np)
return -ENODEV;
- genpd_data = kzalloc_obj(*genpd_data);
+ genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
if (!genpd_data)
return -ENOMEM;
@@ -198,14 +317,44 @@ static int ux500_pm_domains_probe(struct platform_device *pdev)
genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains);
for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i)
- pm_genpd_init(ux500_pm_domains[i], NULL, false);
+ pm_genpd_init(ux500_pm_domains[i], NULL, true);
+
+ ret = of_genpd_add_provider_onecell(np, genpd_data);
+ if (ret)
+ goto remove_genpds;
+
+ ret = of_genpd_add_child_ids(np, genpd_data);
+ if (ret < 0)
+ goto del_provider;
+
+ platform_set_drvdata(pdev, genpd_data);
- of_genpd_add_provider_onecell(np, genpd_data);
return 0;
+
+del_provider:
+ of_genpd_del_provider(np);
+remove_genpds:
+ while (i--)
+ pm_genpd_remove(ux500_pm_domains[i]);
+
+ return ret;
+}
+
+static void ux500_pm_domains_remove(struct platform_device *pdev)
+{
+ struct genpd_onecell_data *genpd_data = platform_get_drvdata(pdev);
+ int i;
+
+ of_genpd_remove_child_ids(pdev->dev.of_node, genpd_data);
+ of_genpd_del_provider(pdev->dev.of_node);
+
+ for (i = genpd_data->num_domains - 1; i >= 0; i--)
+ pm_genpd_remove(genpd_data->domains[i]);
}
static struct platform_driver ux500_pm_domains_driver = {
.probe = ux500_pm_domains_probe,
+ .remove = ux500_pm_domains_remove,
.driver = {
.name = "ux500_pm_domains",
.of_match_table = ux500_pm_domain_matches,
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 89789ac7a786..851e1a8fc22f 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -414,6 +414,7 @@ config REGULATOR_DBX500_PRCMU
config REGULATOR_DB8500_PRCMU
bool "ST-Ericsson DB8500 Voltage Domain Regulators"
depends on MFD_DB8500_PRCMU
+ depends on !UX500_PM_DOMAIN
select REGULATOR_DBX500_PRCMU
help
This driver supports the voltage domain regulators controlled by the
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 13/18] drm/mcde: Use power domain for display power
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (11 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:58 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 14/18] misc: sram: Enable runtime PM Linus Walleij
` (5 subsequent siblings)
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Replace explicit EPOD regulator handling with runtime PM.
Use the MCDE power domain and drop the regulator dependency.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/gpu/drm/mcde/mcde_clk_div.c | 4 +--
drivers/gpu/drm/mcde/mcde_display.c | 11 +++---
drivers/gpu/drm/mcde/mcde_drm.h | 2 --
drivers/gpu/drm/mcde/mcde_drv.c | 68 ++++++++++++-------------------------
drivers/gpu/drm/mcde/mcde_dsi.c | 1 -
5 files changed, 29 insertions(+), 57 deletions(-)
diff --git a/drivers/gpu/drm/mcde/mcde_clk_div.c b/drivers/gpu/drm/mcde/mcde_clk_div.c
index 8c5af2677357..1a22e6233946 100644
--- a/drivers/gpu/drm/mcde/mcde_clk_div.c
+++ b/drivers/gpu/drm/mcde/mcde_clk_div.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/io.h>
-#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include "mcde_drm.h"
#include "mcde_display_regs.h"
@@ -95,7 +95,7 @@ static unsigned long mcde_clk_div_recalc_rate(struct clk_hw *hw,
* It will come up with 0 in the divider register bits, which
* means "divide by 2".
*/
- if (!regulator_is_enabled(mcde->epod))
+ if (!pm_runtime_active(mcde->dev))
return DIV_ROUND_UP_ULL(prate, 2);
cr = readl(mcde->regs + cdiv->cr);
diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c
index 257a6e84dd58..52f071bb347c 100644
--- a/drivers/gpu/drm/mcde/mcde_display.c
+++ b/drivers/gpu/drm/mcde/mcde_display.c
@@ -7,7 +7,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-buf.h>
-#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/media-bus-format.h>
#include <drm/drm_device.h>
@@ -1168,16 +1168,15 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe,
int ret;
/* This powers up the entire MCDE block and the DSI hardware */
- ret = regulator_enable(mcde->epod);
+ ret = pm_runtime_resume_and_get(mcde->dev);
if (ret) {
- dev_err(drm->dev, "can't re-enable EPOD regulator\n");
+ dev_err(drm->dev, "can't enable MCDE power domain\n");
return;
}
dev_info(drm->dev, "enable MCDE, %d x %d format %p4cc\n",
mode->hdisplay, mode->vdisplay, &format);
-
/* Clear any pending interrupts */
mcde_display_disable_irqs(mcde);
writel(0, mcde->regs + MCDE_IMSCERR);
@@ -1327,9 +1326,9 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
spin_unlock_irq(&crtc->dev->event_lock);
}
- ret = regulator_disable(mcde->epod);
+ ret = pm_runtime_put_sync_suspend(mcde->dev);
if (ret)
- dev_err(drm->dev, "can't disable EPOD regulator\n");
+ dev_err(drm->dev, "can't disable MCDE power domain\n");
/* Make sure we are powered down (before we may power up again) */
usleep_range(50000, 70000);
diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h
index ecb70b4b737c..d4ff7606d917 100644
--- a/drivers/gpu/drm/mcde/mcde_drm.h
+++ b/drivers/gpu/drm/mcde/mcde_drm.h
@@ -91,8 +91,6 @@ struct mcde {
/* Locks the MCDE FIFO control register A and B */
spinlock_t fifo_crx1_lock;
- struct regulator *epod;
- struct regulator *vana;
};
#define to_mcde(dev) container_of(dev, struct mcde, drm)
diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c
index 53275b575f0c..d5a2cc98c65b 100644
--- a/drivers/gpu/drm/mcde/mcde_drv.c
+++ b/drivers/gpu/drm/mcde/mcde_drv.c
@@ -61,7 +61,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -284,45 +284,25 @@ static int mcde_probe(struct platform_device *pdev)
mcde->dev = dev;
platform_set_drvdata(pdev, drm);
- /* First obtain and turn on the main power */
- mcde->epod = devm_regulator_get(dev, "epod");
- if (IS_ERR(mcde->epod)) {
- ret = PTR_ERR(mcde->epod);
- dev_err(dev, "can't get EPOD regulator\n");
- return ret;
- }
- ret = regulator_enable(mcde->epod);
+ pm_runtime_enable(dev);
+ ret = pm_runtime_resume_and_get(dev);
if (ret) {
- dev_err(dev, "can't enable EPOD regulator\n");
+ dev_err(dev, "can't enable MCDE power domain\n");
+ pm_runtime_disable(dev);
return ret;
}
- mcde->vana = devm_regulator_get(dev, "vana");
- if (IS_ERR(mcde->vana)) {
- ret = PTR_ERR(mcde->vana);
- dev_err(dev, "can't get VANA regulator\n");
- goto regulator_epod_off;
- }
- ret = regulator_enable(mcde->vana);
- if (ret) {
- dev_err(dev, "can't enable VANA regulator\n");
- goto regulator_epod_off;
- }
- /*
- * The vendor code uses ESRAM (onchip RAM) and need to activate
- * the v-esram34 regulator, but we don't use that yet
- */
/* Clock the silicon so we can access the registers */
mcde->mcde_clk = devm_clk_get(dev, "mcde");
if (IS_ERR(mcde->mcde_clk)) {
dev_err(dev, "unable to get MCDE main clock\n");
ret = PTR_ERR(mcde->mcde_clk);
- goto regulator_off;
+ goto pm_runtime_put;
}
ret = clk_prepare_enable(mcde->mcde_clk);
if (ret) {
dev_err(dev, "failed to enable MCDE main clock\n");
- goto regulator_off;
+ goto pm_runtime_put;
}
dev_info(dev, "MCDE clk rate %lu Hz\n", clk_get_rate(mcde->mcde_clk));
@@ -413,14 +393,15 @@ static int mcde_probe(struct platform_device *pdev)
/*
* Perform an invasive reset of the MCDE and all blocks by
- * cutting the power to the subsystem, then bring it back up
+ * powering down the subsystem, then bring it back up
* later when we enable the display as a result of
* component_master_add_with_match().
*/
- ret = regulator_disable(mcde->epod);
- if (ret) {
- dev_err(dev, "can't disable EPOD regulator\n");
- return ret;
+ ret = pm_runtime_put_sync_suspend(dev);
+ if (ret < 0) {
+ dev_err(dev, "can't disable MCDE power domain\n");
+ pm_runtime_get_noresume(dev);
+ goto clk_disable;
}
/* Wait 50 ms so we are sure we cut the power */
usleep_range(50000, 70000);
@@ -429,25 +410,21 @@ static int mcde_probe(struct platform_device *pdev)
match);
if (ret) {
dev_err(dev, "failed to add component master\n");
- /*
- * The EPOD regulator is already disabled at this point so some
- * special errorpath code is needed
- */
- clk_disable_unprepare(mcde->mcde_clk);
- regulator_disable(mcde->vana);
- return ret;
+ goto clk_disable_pm_disabled;
}
return 0;
clk_disable:
clk_disable_unprepare(mcde->mcde_clk);
-regulator_off:
- regulator_disable(mcde->vana);
-regulator_epod_off:
- regulator_disable(mcde->epod);
+pm_runtime_put:
+ pm_runtime_put_sync_suspend(dev);
+ goto pm_runtime_disable;
+clk_disable_pm_disabled:
+ clk_disable_unprepare(mcde->mcde_clk);
+pm_runtime_disable:
+ pm_runtime_disable(dev);
return ret;
-
}
static void mcde_remove(struct platform_device *pdev)
@@ -457,8 +434,7 @@ static void mcde_remove(struct platform_device *pdev)
component_master_del(&pdev->dev, &mcde_drm_comp_ops);
clk_disable_unprepare(mcde->mcde_clk);
- regulator_disable(mcde->vana);
- regulator_disable(mcde->epod);
+ pm_runtime_disable(&pdev->dev);
}
static void mcde_shutdown(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
index 694372581840..ab8afb5cb0c5 100644
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -8,7 +8,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_atomic_helper.h>
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 14/18] misc: sram: Enable runtime PM
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (12 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 13/18] drm/mcde: Use power domain for display power Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 23:02 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM Linus Walleij
` (4 subsequent siblings)
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Frank Li
Enable runtime PM for generic SRAM devices after probe has initialized
the SRAM mappings and partitions.
This lets SRAM devices with attached power domains be managed through
runtime PM references from their consumers.
Assisted-by: LLM
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/misc/sram.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index c8990e83a65a..7f19dca7b818 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/mfd/syscon.h>
@@ -425,6 +426,10 @@ static int sram_probe(struct platform_device *pdev)
goto err_free_partitions;
}
+ ret = devm_pm_runtime_set_active_enabled(&pdev->dev);
+ if (ret)
+ goto err_free_partitions;
+
if (sram->pool)
dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
gen_pool_size(sram->pool) / 1024, sram->virt_base);
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (13 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 14/18] misc: sram: Enable runtime PM Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 23:03 ` sashiko-bot
` (2 more replies)
2026-09-20 22:48 ` [PATCH v3 16/18] mfd/regulator: db8500-prcmu: Remove EPOD regulators Linus Walleij
` (3 subsequent siblings)
18 siblings, 3 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij, Frank Li
Replace the LCLA ESRAM regulator with runtime PM.
Use the SRAM device that owns the ESRAM34 power domain.
Hold that domain while DMA transfers are active. The DMA controller is
runtime PM IRQ-safe, so keep taking explicit LCLA runtime PM references
from the descriptor preparation path instead of relying on a runtime PM
device link from the atomic transfer path.
Add a stateless device link so system PM keeps the DMA controller ordered
after the LCLA SRAM supplier.
Suggested-by: Frank Li <Frank.li@oss.nxp.com>
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/dma/ste_dma40.c | 130 ++++++++++++++++++++++++++++++++----------------
1 file changed, 88 insertions(+), 42 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index eda3f91741ed..2841af5b160b 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -21,8 +21,8 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_dma.h>
+#include <linux/of_platform.h>
#include <linux/amba/bus.h>
-#include <linux/regulator/consumer.h>
#include "dmaengine.h"
#include "ste_dma40.h"
@@ -383,6 +383,7 @@ struct d40_lli_pool {
* @node: List entry.
* @is_in_client_list: true if the client owns this descriptor.
* @cyclic: true if this is a cyclic job
+ * @lcla_pm_active: LCLA SRAM power domain is held for this descriptor.
*
* This descriptor is used for both logical and physical transfers.
*/
@@ -402,6 +403,7 @@ struct d40_desc {
bool is_in_client_list;
bool cyclic;
+ bool lcla_pm_active;
};
/**
@@ -571,7 +573,8 @@ struct d40_gen_dmac {
* to phy_chans entries.
* @plat_data: Pointer to provided platform_data which is the driver
* configuration.
- * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
+ * @lcla_dev: SRAM device for the ESRAM bank used by LCLA.
+ * @lcla_link: Device link to keep system PM ordered against LCLA.
* @phy_res: Vector containing all physical channels.
* @lcla_pool: lcla pool settings and data.
* @lcpa_base: The virtual mapped address of LCPA.
@@ -606,7 +609,8 @@ struct d40_base {
struct d40_chan **lookup_log_chans;
struct d40_chan **lookup_phy_chans;
struct stedma40_platform_data *plat_data;
- struct regulator *lcpa_regulator;
+ struct device *lcla_dev;
+ struct device_link *lcla_link;
/* Physical half channels */
struct d40_phy_res *phy_res;
struct d40_lcla_pool lcla_pool;
@@ -628,6 +632,36 @@ static struct device *chan2dev(struct d40_chan *d40c)
return &d40c->chan.dev->device;
}
+static void d40_transfer_runtime_get(struct d40_base *base)
+{
+ pm_runtime_get_sync(base->dev);
+}
+
+static int d40_lcla_runtime_get(struct d40_base *base)
+{
+ if (!base->lcla_dev)
+ return 0;
+
+ return pm_runtime_resume_and_get(base->lcla_dev);
+}
+
+static void d40_desc_lcla_runtime_put(struct d40_chan *d40c,
+ struct d40_desc *d40d)
+{
+ struct d40_base *base = d40c->base;
+
+ if (!d40d->lcla_pm_active)
+ return;
+
+ d40d->lcla_pm_active = false;
+ pm_runtime_put(base->lcla_dev);
+}
+
+static void d40_transfer_runtime_put(struct d40_base *base)
+{
+ pm_runtime_put_autosuspend(base->dev);
+}
+
static bool chan_is_physical(struct d40_chan *chan)
{
return chan->log_num == D40_PHY_CHAN;
@@ -818,6 +852,7 @@ static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d)
d40_pool_lli_free(d40c, d40d);
d40_lcla_free_all(d40c, d40d);
+ d40_desc_lcla_runtime_put(d40c, d40d);
kmem_cache_free(d40c->base->desc_slab, d40d);
}
@@ -1516,7 +1551,7 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
if (d40d != NULL) {
if (!d40c->busy) {
d40c->busy = true;
- pm_runtime_get_sync(d40c->base->dev);
+ d40_transfer_runtime_get(d40c->base);
}
/* Remove from queue */
@@ -1535,6 +1570,7 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
d40_desc_remove(d40d);
d40_desc_free(d40c, d40d);
d40c->busy = false;
+ d40_transfer_runtime_put(d40c->base);
return ERR_PTR(err);
}
}
@@ -1583,7 +1619,7 @@ static void dma_tc_handle(struct d40_chan *d40c)
if (d40_queue_start(d40c) == NULL) {
d40c->busy = false;
- pm_runtime_put_autosuspend(d40c->base->dev);
+ d40_transfer_runtime_put(d40c->base);
}
d40_desc_remove(d40d);
@@ -1637,6 +1673,7 @@ static void dma_tasklet(struct tasklet_struct *t)
} else if (!d40d->is_in_client_list) {
d40_desc_remove(d40d);
d40_lcla_free_all(d40c, d40d);
+ d40_desc_lcla_runtime_put(d40c, d40d);
list_add_tail(&d40d->node, &d40c->client);
d40d->is_in_client_list = true;
}
@@ -2067,7 +2104,7 @@ static int d40_free_dma(struct d40_chan *d40c)
d40c->base->lookup_phy_chans[phy->num] = NULL;
if (d40c->busy)
- pm_runtime_put_autosuspend(d40c->base->dev);
+ d40_transfer_runtime_put(d40c->base);
d40c->busy = false;
d40c->phy_chan = NULL;
@@ -2246,6 +2283,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
dma_addr_t dst_dev_addr;
struct d40_desc *desc;
unsigned long flags;
+ bool got_lcla_pm = false;
int ret;
if (!chan->phy_chan) {
@@ -2255,11 +2293,20 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
d40_set_runtime_config_write(dchan, &chan->slave_config, direction);
+ ret = d40_lcla_runtime_get(chan->base);
+ if (ret) {
+ chan_err(chan, "Failed to enable LCLA power domain\n");
+ return NULL;
+ }
+ got_lcla_pm = !!chan->base->lcla_dev;
+
spin_lock_irqsave(&chan->lock, flags);
desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
if (desc == NULL)
goto unlock;
+ desc->lcla_pm_active = got_lcla_pm;
+ got_lcla_pm = false;
if (sg_next(&sg_src[sg_len - 1]) == sg_src)
desc->cyclic = true;
@@ -2297,6 +2344,8 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
d40_desc_free(chan, desc);
unlock:
spin_unlock_irqrestore(&chan->lock, flags);
+ if (got_lcla_pm)
+ pm_runtime_put(chan->base->lcla_dev);
return NULL;
}
@@ -2628,7 +2677,7 @@ static int d40_terminate_all(struct dma_chan *chan)
d40_term_all(d40c);
pm_runtime_put_autosuspend(d40c->base->dev);
if (d40c->busy)
- pm_runtime_put_autosuspend(d40c->base->dev);
+ d40_transfer_runtime_put(d40c->base);
d40c->busy = false;
spin_unlock_irqrestore(&d40c->lock, flags);
@@ -2931,29 +2980,11 @@ static int __init d40_dmaengine_init(struct d40_base *base,
#ifdef CONFIG_PM_SLEEP
static int dma40_suspend(struct device *dev)
{
- struct d40_base *base = dev_get_drvdata(dev);
- int ret;
-
- ret = pm_runtime_force_suspend(dev);
- if (ret)
- return ret;
-
- if (base->lcpa_regulator)
- ret = regulator_disable(base->lcpa_regulator);
- return ret;
+ return pm_runtime_force_suspend(dev);
}
static int dma40_resume(struct device *dev)
{
- struct d40_base *base = dev_get_drvdata(dev);
- int ret = 0;
-
- if (base->lcpa_regulator) {
- ret = regulator_enable(base->lcpa_regulator);
- if (ret)
- return ret;
- }
-
return pm_runtime_force_resume(dev);
}
#endif
@@ -3509,7 +3540,10 @@ static int __init d40_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct device_node *np_lcpa;
+ struct device_node *np_lcla;
+ struct device_node *np_lcla_parent;
struct d40_base *base;
+ struct platform_device *lcla_pdev;
struct resource *res;
struct resource res_lcpa;
int num_reserved_chans;
@@ -3610,21 +3644,32 @@ static int __init d40_probe(struct platform_device *pdev)
irq_requested = true;
if (base->plat_data->use_esram_lcla) {
+ np_lcla = of_parse_phandle(np, "sram", 1);
+ if (!np_lcla) {
+ dev_err(dev, "no LCLA SRAM node\n");
+ ret = -EINVAL;
+ goto destroy_cache;
+ }
- base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
- if (IS_ERR(base->lcpa_regulator)) {
- d40_err(dev, "Failed to get lcpa_regulator\n");
- ret = PTR_ERR(base->lcpa_regulator);
- base->lcpa_regulator = NULL;
+ np_lcla_parent = of_get_parent(np_lcla);
+ of_node_put(np_lcla);
+ if (!np_lcla_parent) {
+ dev_err(dev, "no LCLA SRAM parent node\n");
+ ret = -EINVAL;
goto destroy_cache;
}
- ret = regulator_enable(base->lcpa_regulator);
- if (ret) {
- d40_err(dev,
- "Failed to enable lcpa_regulator\n");
- regulator_put(base->lcpa_regulator);
- base->lcpa_regulator = NULL;
+ lcla_pdev = of_find_device_by_node(np_lcla_parent);
+ of_node_put(np_lcla_parent);
+ if (!lcla_pdev) {
+ ret = -EPROBE_DEFER;
+ goto destroy_cache;
+ }
+ base->lcla_dev = &lcla_pdev->dev;
+ base->lcla_link = device_link_add(dev, base->lcla_dev,
+ DL_FLAG_STATELESS);
+ if (!base->lcla_link) {
+ ret = -ENODEV;
goto destroy_cache;
}
}
@@ -3663,16 +3708,17 @@ static int __init d40_probe(struct platform_device *pdev)
SZ_1K * base->num_phy_chans,
DMA_TO_DEVICE);
- if (!base->lcla_pool.base_unaligned && base->lcla_pool.base)
+ if (!base->lcla_pool.base_unaligned && base->lcla_pool.base &&
+ base->lcla_pool.pages)
free_pages((unsigned long)base->lcla_pool.base,
base->lcla_pool.pages);
kfree(base->lcla_pool.base_unaligned);
- if (base->lcpa_regulator) {
- regulator_disable(base->lcpa_regulator);
- regulator_put(base->lcpa_regulator);
- }
+ if (base->lcla_link)
+ device_link_del(base->lcla_link);
+ if (base->lcla_dev)
+ put_device(base->lcla_dev);
if (irq_requested)
free_irq(base->irq, base);
if (runtime_pm_enabled)
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 16/18] mfd/regulator: db8500-prcmu: Remove EPOD regulators
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (14 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 22:48 ` [PATCH v3 17/18] dt-bindings: display: ste,mcde: Deprecate EPOD supply Linus Walleij
` (2 subsequent siblings)
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Remove the obsolete DB8500 PRCMU regulator drivers.
Drop the regulator build hooks and the db8500-prcmu-regulators MFD
cell now that EPODs are power domains.
Assisted-by: LLM
Acked-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/mfd/db8500-prcmu.c | 239 ----------------
drivers/regulator/Kconfig | 12 -
drivers/regulator/Makefile | 2 -
drivers/regulator/db8500-prcmu.c | 501 ---------------------------------
drivers/regulator/dbx500-prcmu.c | 155 ----------
drivers/regulator/dbx500-prcmu.h | 55 ----
include/linux/regulator/db8500-prcmu.h | 38 ---
7 files changed, 1002 deletions(-)
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 6672c55f2ebc..687bbf79559e 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -34,8 +34,6 @@
#include <linux/mfd/core.h>
#include <linux/mfd/db8500-prcmu.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/regulator/db8500-prcmu.h>
-#include <linux/regulator/machine.h>
#include "db8500-prcmu-regs.h"
/* Index of different voltages to be used when accessing AVSData */
@@ -2704,249 +2702,12 @@ static void init_prcm_registers(void)
writel(val, (PRCM_A9PL_FORCE_CLKEN));
}
-/*
- * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC
- */
-static struct regulator_consumer_supply db8500_vape_consumers[] = {
- REGULATOR_SUPPLY("v-ape", NULL),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.4"),
- /* "v-mmc" changed to "vcore" in the mainline kernel */
- REGULATOR_SUPPLY("vcore", "sdi0"),
- REGULATOR_SUPPLY("vcore", "sdi1"),
- REGULATOR_SUPPLY("vcore", "sdi2"),
- REGULATOR_SUPPLY("vcore", "sdi3"),
- REGULATOR_SUPPLY("vcore", "sdi4"),
- REGULATOR_SUPPLY("v-dma", "dma40.0"),
- REGULATOR_SUPPLY("v-ape", "ab8500-usb.0"),
- /* "v-uart" changed to "vcore" in the mainline kernel */
- REGULATOR_SUPPLY("vcore", "uart0"),
- REGULATOR_SUPPLY("vcore", "uart1"),
- REGULATOR_SUPPLY("vcore", "uart2"),
- REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"),
- REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"),
- REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
-};
-
-static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
- REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"),
- /* AV8100 regulator */
- REGULATOR_SUPPLY("hdmi_1v8", "0-0070"),
-};
-
-static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
- REGULATOR_SUPPLY("vsupply", "b2r2_bus"),
- REGULATOR_SUPPLY("vsupply", "mcde"),
-};
-
-/* SVA MMDSP regulator switch */
-static struct regulator_consumer_supply db8500_svammdsp_consumers[] = {
- REGULATOR_SUPPLY("sva-mmdsp", "cm_control"),
-};
-
-/* SVA pipe regulator switch */
-static struct regulator_consumer_supply db8500_svapipe_consumers[] = {
- REGULATOR_SUPPLY("sva-pipe", "cm_control"),
-};
-
-/* SIA MMDSP regulator switch */
-static struct regulator_consumer_supply db8500_siammdsp_consumers[] = {
- REGULATOR_SUPPLY("sia-mmdsp", "cm_control"),
-};
-
-/* SIA pipe regulator switch */
-static struct regulator_consumer_supply db8500_siapipe_consumers[] = {
- REGULATOR_SUPPLY("sia-pipe", "cm_control"),
-};
-
-static struct regulator_consumer_supply db8500_sga_consumers[] = {
- REGULATOR_SUPPLY("v-mali", NULL),
-};
-
-/* ESRAM1 and 2 regulator switch */
-static struct regulator_consumer_supply db8500_esram12_consumers[] = {
- REGULATOR_SUPPLY("esram12", "cm_control"),
-};
-
-/* ESRAM3 and 4 regulator switch */
-static struct regulator_consumer_supply db8500_esram34_consumers[] = {
- REGULATOR_SUPPLY("v-esram34", "mcde"),
- REGULATOR_SUPPLY("esram34", "cm_control"),
- REGULATOR_SUPPLY("lcla_esram", "dma40.0"),
-};
-
-static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
- [DB8500_REGULATOR_VAPE] = {
- .constraints = {
- .name = "db8500-vape",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- .always_on = true,
- },
- .consumer_supplies = db8500_vape_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
- },
- [DB8500_REGULATOR_VARM] = {
- .constraints = {
- .name = "db8500-varm",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_VMODEM] = {
- .constraints = {
- .name = "db8500-vmodem",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_VPLL] = {
- .constraints = {
- .name = "db8500-vpll",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_VSMPS1] = {
- .constraints = {
- .name = "db8500-vsmps1",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_VSMPS2] = {
- .constraints = {
- .name = "db8500-vsmps2",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_vsmps2_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_vsmps2_consumers),
- },
- [DB8500_REGULATOR_VSMPS3] = {
- .constraints = {
- .name = "db8500-vsmps3",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_VRF1] = {
- .constraints = {
- .name = "db8500-vrf1",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
- /* dependency to u8500-vape is handled outside regulator framework */
- .constraints = {
- .name = "db8500-sva-mmdsp",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_svammdsp_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers),
- },
- [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
- .constraints = {
- /* "ret" means "retention" */
- .name = "db8500-sva-mmdsp-ret",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
- /* dependency to u8500-vape is handled outside regulator framework */
- .constraints = {
- .name = "db8500-sva-pipe",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_svapipe_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
- },
- [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
- /* dependency to u8500-vape is handled outside regulator framework */
- .constraints = {
- .name = "db8500-sia-mmdsp",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_siammdsp_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers),
- },
- [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
- .constraints = {
- .name = "db8500-sia-mmdsp-ret",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
- /* dependency to u8500-vape is handled outside regulator framework */
- .constraints = {
- .name = "db8500-sia-pipe",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_siapipe_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers),
- },
- [DB8500_REGULATOR_SWITCH_SGA] = {
- .supply_regulator = "db8500-vape",
- .constraints = {
- .name = "db8500-sga",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_sga_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers),
-
- },
- [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
- .supply_regulator = "db8500-vape",
- .constraints = {
- .name = "db8500-b2r2-mcde",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_b2r2_mcde_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers),
- },
- [DB8500_REGULATOR_SWITCH_ESRAM12] = {
- /*
- * esram12 is set in retention and supplied by Vsafe when Vape is off,
- * no need to hold Vape
- */
- .constraints = {
- .name = "db8500-esram12",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_esram12_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers),
- },
- [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
- .constraints = {
- .name = "db8500-esram12-ret",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
- [DB8500_REGULATOR_SWITCH_ESRAM34] = {
- /*
- * esram34 is set in retention and supplied by Vsafe when Vape is off,
- * no need to hold Vape
- */
- .constraints = {
- .name = "db8500-esram34",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = db8500_esram34_consumers,
- .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers),
- },
- [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
- .constraints = {
- .name = "db8500-esram34-ret",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- },
-};
-
static const struct mfd_cell common_prcmu_devs[] = {
MFD_CELL_NAME("db8500_wdt"),
MFD_CELL_NAME("db8500-cpuidle"),
};
static const struct mfd_cell db8500_prcmu_devs[] = {
- MFD_CELL_OF("db8500-prcmu-regulators", NULL,
- &db8500_regulators, sizeof(db8500_regulators), 0,
- "stericsson,db8500-prcmu-regulator"),
MFD_CELL_OF("db8500-thermal",
NULL, NULL, 0, 0, "stericsson,db8500-thermal"),
};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 851e1a8fc22f..c2d6a895245e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -408,18 +408,6 @@ config REGULATOR_DA9211
step down converter 12A or 16A DC-DC Buck controlled through an I2C
interface.
-config REGULATOR_DBX500_PRCMU
- bool
-
-config REGULATOR_DB8500_PRCMU
- bool "ST-Ericsson DB8500 Voltage Domain Regulators"
- depends on MFD_DB8500_PRCMU
- depends on !UX500_PM_DOMAIN
- select REGULATOR_DBX500_PRCMU
- help
- This driver supports the voltage domain regulators controlled by the
- DB8500 PRCMU
-
config REGULATOR_FAN53555
tristate "Fairchild FAN53555 Regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 5a764cec8df8..efe78600fda9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,8 +48,6 @@ obj-$(CONFIG_REGULATOR_DA9063) += da9063-regulator.o
obj-$(CONFIG_REGULATOR_DA9121) += da9121-regulator.o
obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
-obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
-obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_REGULATOR_FAN53880) += fan53880.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
deleted file mode 100644
index 751fe36580fa..000000000000
--- a/drivers/regulator/db8500-prcmu.c
+++ /dev/null
@@ -1,501 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
- * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
- *
- * Power domain regulators on DB8500
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/db8500-prcmu.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/db8500-prcmu.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/of.h>
-#include <linux/module.h>
-#include "dbx500-prcmu.h"
-
-static int db8500_regulator_enable(struct regulator_dev *rdev)
-{
- struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
-
- if (info == NULL)
- return -EINVAL;
-
- dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n",
- info->desc.name);
-
- if (!info->is_enabled) {
- info->is_enabled = true;
- if (!info->exclude_from_power_state)
- power_state_active_enable();
- }
-
- return 0;
-}
-
-static int db8500_regulator_disable(struct regulator_dev *rdev)
-{
- struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
- int ret = 0;
-
- if (info == NULL)
- return -EINVAL;
-
- dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n",
- info->desc.name);
-
- if (info->is_enabled) {
- info->is_enabled = false;
- if (!info->exclude_from_power_state)
- ret = power_state_active_disable();
- }
-
- return ret;
-}
-
-static int db8500_regulator_is_enabled(struct regulator_dev *rdev)
-{
- struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
-
- if (info == NULL)
- return -EINVAL;
-
- dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):"
- " %i\n", info->desc.name, info->is_enabled);
-
- return info->is_enabled;
-}
-
-/* db8500 regulator operations */
-static const struct regulator_ops db8500_regulator_ops = {
- .enable = db8500_regulator_enable,
- .disable = db8500_regulator_disable,
- .is_enabled = db8500_regulator_is_enabled,
-};
-
-/*
- * EPOD control
- */
-static bool epod_on[NUM_EPOD_ID];
-static bool epod_ramret[NUM_EPOD_ID];
-
-static int enable_epod(u16 epod_id, bool ramret)
-{
- int ret;
-
- if (ramret) {
- if (!epod_on[epod_id]) {
- ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
- if (ret < 0)
- return ret;
- }
- epod_ramret[epod_id] = true;
- } else {
- ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_ON);
- if (ret < 0)
- return ret;
- epod_on[epod_id] = true;
- }
-
- return 0;
-}
-
-static int disable_epod(u16 epod_id, bool ramret)
-{
- int ret;
-
- if (ramret) {
- if (!epod_on[epod_id]) {
- ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
- if (ret < 0)
- return ret;
- }
- epod_ramret[epod_id] = false;
- } else {
- if (epod_ramret[epod_id]) {
- ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
- if (ret < 0)
- return ret;
- } else {
- ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
- if (ret < 0)
- return ret;
- }
- epod_on[epod_id] = false;
- }
-
- return 0;
-}
-
-/*
- * Regulator switch
- */
-static int db8500_regulator_switch_enable(struct regulator_dev *rdev)
-{
- struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
- int ret;
-
- if (info == NULL)
- return -EINVAL;
-
- dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n",
- info->desc.name);
-
- ret = enable_epod(info->epod_id, info->is_ramret);
- if (ret < 0) {
- dev_err(rdev_get_dev(rdev),
- "regulator-switch-%s-enable: prcmu call failed\n",
- info->desc.name);
- goto out;
- }
-
- info->is_enabled = true;
-out:
- return ret;
-}
-
-static int db8500_regulator_switch_disable(struct regulator_dev *rdev)
-{
- struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
- int ret;
-
- if (info == NULL)
- return -EINVAL;
-
- dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n",
- info->desc.name);
-
- ret = disable_epod(info->epod_id, info->is_ramret);
- if (ret < 0) {
- dev_err(rdev_get_dev(rdev),
- "regulator_switch-%s-disable: prcmu call failed\n",
- info->desc.name);
- goto out;
- }
-
- info->is_enabled = false;
-out:
- return ret;
-}
-
-static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev)
-{
- struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
-
- if (info == NULL)
- return -EINVAL;
-
- dev_vdbg(rdev_get_dev(rdev),
- "regulator-switch-%s-is_enabled (is_enabled): %i\n",
- info->desc.name, info->is_enabled);
-
- return info->is_enabled;
-}
-
-static const struct regulator_ops db8500_regulator_switch_ops = {
- .enable = db8500_regulator_switch_enable,
- .disable = db8500_regulator_switch_disable,
- .is_enabled = db8500_regulator_switch_is_enabled,
-};
-
-/*
- * Regulator information
- */
-static struct dbx500_regulator_info
-dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
- [DB8500_REGULATOR_VAPE] = {
- .desc = {
- .name = "db8500-vape",
- .of_match = of_match_ptr("db8500_vape"),
- .id = DB8500_REGULATOR_VAPE,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_VARM] = {
- .desc = {
- .name = "db8500-varm",
- .of_match = of_match_ptr("db8500_varm"),
- .id = DB8500_REGULATOR_VARM,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_VMODEM] = {
- .desc = {
- .name = "db8500-vmodem",
- .of_match = of_match_ptr("db8500_vmodem"),
- .id = DB8500_REGULATOR_VMODEM,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_VPLL] = {
- .desc = {
- .name = "db8500-vpll",
- .of_match = of_match_ptr("db8500_vpll"),
- .id = DB8500_REGULATOR_VPLL,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_VSMPS1] = {
- .desc = {
- .name = "db8500-vsmps1",
- .of_match = of_match_ptr("db8500_vsmps1"),
- .id = DB8500_REGULATOR_VSMPS1,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_VSMPS2] = {
- .desc = {
- .name = "db8500-vsmps2",
- .of_match = of_match_ptr("db8500_vsmps2"),
- .id = DB8500_REGULATOR_VSMPS2,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- .fixed_uV = 1800000,
- .n_voltages = 1,
- },
- .exclude_from_power_state = true,
- },
- [DB8500_REGULATOR_VSMPS3] = {
- .desc = {
- .name = "db8500-vsmps3",
- .of_match = of_match_ptr("db8500_vsmps3"),
- .id = DB8500_REGULATOR_VSMPS3,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_VRF1] = {
- .desc = {
- .name = "db8500-vrf1",
- .of_match = of_match_ptr("db8500_vrf1"),
- .id = DB8500_REGULATOR_VRF1,
- .ops = &db8500_regulator_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- },
- [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
- .desc = {
- .name = "db8500-sva-mmdsp",
- .of_match = of_match_ptr("db8500_sva_mmdsp"),
- .id = DB8500_REGULATOR_SWITCH_SVAMMDSP,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SVAMMDSP,
- },
- [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
- .desc = {
- .name = "db8500-sva-mmdsp-ret",
- .of_match = of_match_ptr("db8500_sva_mmdsp_ret"),
- .id = DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SVAMMDSP,
- .is_ramret = true,
- },
- [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
- .desc = {
- .name = "db8500-sva-pipe",
- .of_match = of_match_ptr("db8500_sva_pipe"),
- .id = DB8500_REGULATOR_SWITCH_SVAPIPE,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SVAPIPE,
- },
- [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
- .desc = {
- .name = "db8500-sia-mmdsp",
- .of_match = of_match_ptr("db8500_sia_mmdsp"),
- .id = DB8500_REGULATOR_SWITCH_SIAMMDSP,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SIAMMDSP,
- },
- [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
- .desc = {
- .name = "db8500-sia-mmdsp-ret",
- .of_match = of_match_ptr("db8500_sia_mmdsp_ret"),
- .id = DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SIAMMDSP,
- .is_ramret = true,
- },
- [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
- .desc = {
- .name = "db8500-sia-pipe",
- .of_match = of_match_ptr("db8500_sia_pipe"),
- .id = DB8500_REGULATOR_SWITCH_SIAPIPE,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SIAPIPE,
- },
- [DB8500_REGULATOR_SWITCH_SGA] = {
- .desc = {
- .name = "db8500-sga",
- .of_match = of_match_ptr("db8500_sga"),
- .id = DB8500_REGULATOR_SWITCH_SGA,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_SGA,
- },
- [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
- .desc = {
- .name = "db8500-b2r2-mcde",
- .of_match = of_match_ptr("db8500_b2r2_mcde"),
- .id = DB8500_REGULATOR_SWITCH_B2R2_MCDE,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_B2R2_MCDE,
- },
- [DB8500_REGULATOR_SWITCH_ESRAM12] = {
- .desc = {
- .name = "db8500-esram12",
- .of_match = of_match_ptr("db8500_esram12"),
- .id = DB8500_REGULATOR_SWITCH_ESRAM12,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_ESRAM12,
- .is_enabled = true,
- },
- [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
- .desc = {
- .name = "db8500-esram12-ret",
- .of_match = of_match_ptr("db8500_esram12_ret"),
- .id = DB8500_REGULATOR_SWITCH_ESRAM12RET,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_ESRAM12,
- .is_ramret = true,
- },
- [DB8500_REGULATOR_SWITCH_ESRAM34] = {
- .desc = {
- .name = "db8500-esram34",
- .of_match = of_match_ptr("db8500_esram34"),
- .id = DB8500_REGULATOR_SWITCH_ESRAM34,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_ESRAM34,
- .is_enabled = true,
- },
- [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
- .desc = {
- .name = "db8500-esram34-ret",
- .of_match = of_match_ptr("db8500_esram34_ret"),
- .id = DB8500_REGULATOR_SWITCH_ESRAM34RET,
- .ops = &db8500_regulator_switch_ops,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- },
- .epod_id = EPOD_ID_ESRAM34,
- .is_ramret = true,
- },
-};
-
-static int db8500_regulator_probe(struct platform_device *pdev)
-{
- struct regulator_init_data *db8500_init_data;
- struct dbx500_regulator_info *info;
- struct regulator_config config = { };
- struct regulator_dev *rdev;
- int err, i;
-
- db8500_init_data = dev_get_platdata(&pdev->dev);
-
- for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
- /* assign per-regulator data */
- info = &dbx500_regulator_info[i];
-
- config.driver_data = info;
- config.dev = &pdev->dev;
- if (db8500_init_data)
- config.init_data = &db8500_init_data[i];
-
- rdev = devm_regulator_register(&pdev->dev, &info->desc,
- &config);
- if (IS_ERR(rdev)) {
- err = PTR_ERR(rdev);
- dev_err(&pdev->dev, "failed to register %s: err %i\n",
- info->desc.name, err);
- return err;
- }
- dev_dbg(&pdev->dev, "regulator-%s-probed\n", info->desc.name);
- }
-
- ux500_regulator_debug_init(pdev, dbx500_regulator_info,
- ARRAY_SIZE(dbx500_regulator_info));
- return 0;
-}
-
-static void db8500_regulator_remove(struct platform_device *pdev)
-{
- ux500_regulator_debug_exit();
-}
-
-static struct platform_driver db8500_regulator_driver = {
- .driver = {
- .name = "db8500-prcmu-regulators",
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- .probe = db8500_regulator_probe,
- .remove = db8500_regulator_remove,
-};
-
-static int __init db8500_regulator_init(void)
-{
- return platform_driver_register(&db8500_regulator_driver);
-}
-
-static void __exit db8500_regulator_exit(void)
-{
- platform_driver_unregister(&db8500_regulator_driver);
-}
-
-arch_initcall(db8500_regulator_init);
-module_exit(db8500_regulator_exit);
-
-MODULE_AUTHOR("STMicroelectronics/ST-Ericsson");
-MODULE_DESCRIPTION("DB8500 regulator driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
deleted file mode 100644
index a45c1e1ac7ef..000000000000
--- a/drivers/regulator/dbx500-prcmu.c
+++ /dev/null
@@ -1,155 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
- * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
- *
- * UX500 common part of Power domain regulators
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/regulator/driver.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include "dbx500-prcmu.h"
-
-/*
- * power state reference count
- */
-static int power_state_active_cnt; /* will initialize to zero */
-static DEFINE_SPINLOCK(power_state_active_lock);
-
-void power_state_active_enable(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&power_state_active_lock, flags);
- power_state_active_cnt++;
- spin_unlock_irqrestore(&power_state_active_lock, flags);
-}
-
-int power_state_active_disable(void)
-{
- int ret = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&power_state_active_lock, flags);
- if (power_state_active_cnt <= 0) {
- pr_err("power state: unbalanced enable/disable calls\n");
- ret = -EINVAL;
- goto out;
- }
-
- power_state_active_cnt--;
-out:
- spin_unlock_irqrestore(&power_state_active_lock, flags);
- return ret;
-}
-
-#ifdef CONFIG_REGULATOR_DEBUG
-
-static int power_state_active_get(void)
-{
- unsigned long flags;
- int cnt;
-
- spin_lock_irqsave(&power_state_active_lock, flags);
- cnt = power_state_active_cnt;
- spin_unlock_irqrestore(&power_state_active_lock, flags);
-
- return cnt;
-}
-
-static struct ux500_regulator_debug {
- struct dentry *dir;
- struct dbx500_regulator_info *regulator_array;
- int num_regulators;
- u8 *state_before_suspend;
- u8 *state_after_suspend;
-} rdebug;
-
-static int ux500_regulator_power_state_cnt_show(struct seq_file *s, void *p)
-{
- /* print power state count */
- seq_printf(s, "ux500-regulator power state count: %i\n",
- power_state_active_get());
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(ux500_regulator_power_state_cnt);
-
-static int ux500_regulator_status_show(struct seq_file *s, void *p)
-{
- int i;
-
- /* print dump header */
- seq_puts(s, "ux500-regulator status:\n");
- seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
-
- for (i = 0; i < rdebug.num_regulators; i++) {
- struct dbx500_regulator_info *info;
- /* Access per-regulator data */
- info = &rdebug.regulator_array[i];
-
- /* print status */
- seq_printf(s, "%20s : %8s : %8s : %8s\n",
- info->desc.name,
- info->is_enabled ? "enabled" : "disabled",
- rdebug.state_before_suspend[i] ? "enabled" : "disabled",
- rdebug.state_after_suspend[i] ? "enabled" : "disabled");
- }
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
-
-int
-ux500_regulator_debug_init(struct platform_device *pdev,
- struct dbx500_regulator_info *regulator_info,
- int num_regulators)
-{
- /* create directory */
- rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
-
- /* create "status" file */
- debugfs_create_file("status", 0444, rdebug.dir, &pdev->dev,
- &ux500_regulator_status_fops);
-
- /* create "power-state-count" file */
- debugfs_create_file("power-state-count", 0444, rdebug.dir,
- &pdev->dev, &ux500_regulator_power_state_cnt_fops);
-
- rdebug.regulator_array = regulator_info;
- rdebug.num_regulators = num_regulators;
-
- rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
- if (!rdebug.state_before_suspend)
- goto exit_destroy_power_state;
-
- rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
- if (!rdebug.state_after_suspend)
- goto exit_free;
-
- return 0;
-
-exit_free:
- kfree(rdebug.state_before_suspend);
-exit_destroy_power_state:
- debugfs_remove_recursive(rdebug.dir);
- return -ENOMEM;
-}
-
-int ux500_regulator_debug_exit(void)
-{
- debugfs_remove_recursive(rdebug.dir);
- kfree(rdebug.state_after_suspend);
- kfree(rdebug.state_before_suspend);
-
- return 0;
-}
-#endif
diff --git a/drivers/regulator/dbx500-prcmu.h b/drivers/regulator/dbx500-prcmu.h
deleted file mode 100644
index 2fb3aaef9dbb..000000000000
--- a/drivers/regulator/dbx500-prcmu.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Bengt Jonsson <bengt.jonsson@stericsson.com> for ST-Ericsson,
- * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
- */
-
-#ifndef DBX500_REGULATOR_H
-#define DBX500_REGULATOR_H
-
-#include <linux/platform_device.h>
-
-/**
- * struct dbx500_regulator_info - dbx500 regulator information
- * @desc: regulator description
- * @is_enabled: status of the regulator
- * @epod_id: id for EPOD (power domain)
- * @is_ramret: RAM retention switch for EPOD (power domain)
- *
- */
-struct dbx500_regulator_info {
- struct regulator_desc desc;
- bool is_enabled;
- u16 epod_id;
- bool is_ramret;
- bool exclude_from_power_state;
-};
-
-void power_state_active_enable(void);
-int power_state_active_disable(void);
-
-
-#ifdef CONFIG_REGULATOR_DEBUG
-int ux500_regulator_debug_init(struct platform_device *pdev,
- struct dbx500_regulator_info *regulator_info,
- int num_regulators);
-
-int ux500_regulator_debug_exit(void);
-#else
-
-static inline int ux500_regulator_debug_init(struct platform_device *pdev,
- struct dbx500_regulator_info *regulator_info,
- int num_regulators)
-{
- return 0;
-}
-
-static inline int ux500_regulator_debug_exit(void)
-{
- return 0;
-}
-
-#endif
-#endif
diff --git a/include/linux/regulator/db8500-prcmu.h b/include/linux/regulator/db8500-prcmu.h
deleted file mode 100644
index d58ff273157e..000000000000
--- a/include/linux/regulator/db8500-prcmu.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
- *
- * Interface to power domain regulators on DB8500
- */
-
-#ifndef __REGULATOR_H__
-#define __REGULATOR_H__
-
-/* Number of DB8500 regulators and regulator enumeration */
-enum db8500_regulator_id {
- DB8500_REGULATOR_VAPE,
- DB8500_REGULATOR_VARM,
- DB8500_REGULATOR_VMODEM,
- DB8500_REGULATOR_VPLL,
- DB8500_REGULATOR_VSMPS1,
- DB8500_REGULATOR_VSMPS2,
- DB8500_REGULATOR_VSMPS3,
- DB8500_REGULATOR_VRF1,
- DB8500_REGULATOR_SWITCH_SVAMMDSP,
- DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
- DB8500_REGULATOR_SWITCH_SVAPIPE,
- DB8500_REGULATOR_SWITCH_SIAMMDSP,
- DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
- DB8500_REGULATOR_SWITCH_SIAPIPE,
- DB8500_REGULATOR_SWITCH_SGA,
- DB8500_REGULATOR_SWITCH_B2R2_MCDE,
- DB8500_REGULATOR_SWITCH_ESRAM12,
- DB8500_REGULATOR_SWITCH_ESRAM12RET,
- DB8500_REGULATOR_SWITCH_ESRAM34,
- DB8500_REGULATOR_SWITCH_ESRAM34RET,
- DB8500_NUM_REGULATORS
-};
-
-#endif
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 17/18] dt-bindings: display: ste,mcde: Deprecate EPOD supply
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (15 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 16/18] mfd/regulator: db8500-prcmu: Remove EPOD regulators Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 23:00 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators Linus Walleij
2026-10-06 10:30 ` [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Make epod-supply optional and mark it deprecated.
The MCDE should use its power domain instead.
Assisted-by: LLM
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Documentation/devicetree/bindings/display/ste,mcde.yaml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/ste,mcde.yaml b/Documentation/devicetree/bindings/display/ste,mcde.yaml
index 05e7e4ebc882..ee34b65dd13b 100644
--- a/Documentation/devicetree/bindings/display/ste,mcde.yaml
+++ b/Documentation/devicetree/bindings/display/ste,mcde.yaml
@@ -39,7 +39,8 @@ properties:
maxItems: 1
epod-supply:
- description: a phandle to the EPOD regulator
+ description: a phandle to the legacy EPOD regulator
+ deprecated: true
vana-supply:
description: a phandle to the analog voltage regulator
@@ -103,7 +104,6 @@ required:
- interrupts
- clocks
- clock-names
- - epod-supply
- vana-supply
additionalProperties: false
@@ -121,7 +121,6 @@ examples:
reg = <0xa0350000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&pm_domains DOMAIN_B2R2_MCDE>;
- epod-supply = <&db8500_b2r2_mcde_reg>;
vana-supply = <&ab8500_ldo_ana_reg>;
clocks = <&prcmu_clk PRCMU_MCDECLK>,
<&prcmu_clk PRCMU_LCDCLK>,
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (16 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 17/18] dt-bindings: display: ste,mcde: Deprecate EPOD supply Linus Walleij
@ 2026-09-20 22:48 ` Linus Walleij
2026-09-20 23:05 ` sashiko-bot
2026-10-06 10:30 ` [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
18 siblings, 1 reply; 35+ messages in thread
From: Linus Walleij @ 2026-09-20 22:48 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Linus Walleij
Delete the deprecated db8500-prcmu-regulators node and all its EPOD
regulators, including VAPE and VSMPS2. Their external consumers now use
the AB8500 or AB8505 buck regulators, so no compatibility regulators
are needed.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/arm/boot/dts/st/ste-dbx5x0.dtsi | 103 -----------------------------------
1 file changed, 103 deletions(-)
diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
index 0603244dc9e8..efc84e018c44 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
@@ -675,97 +675,6 @@ thermal: thermal@801573c0 {
interrupt-names = "IRQ_HOTMON_LOW", "IRQ_HOTMON_HIGH";
#thermal-sensor-cells = <0>;
};
-
- /*
- * TODO: Delete these bogus regulators and replace with power
- * domains.
- */
- db8500-prcmu-regulators {
- compatible = "stericsson,db8500-prcmu-regulator";
-
- // DB8500_REGULATOR_VAPE
- db8500_vape_reg: db8500_vape {
- regulator-always-on;
- };
-
- // DB8500_REGULATOR_VARM
- db8500_varm_reg: db8500_varm {
- };
-
- // DB8500_REGULATOR_VMODEM
- db8500_vmodem_reg: db8500_vmodem {
- };
-
- // DB8500_REGULATOR_VPLL
- db8500_vpll_reg: db8500_vpll {
- };
-
- // DB8500_REGULATOR_VSMPS1
- db8500_vsmps1_reg: db8500_vsmps1 {
- };
-
- // DB8500_REGULATOR_VSMPS2
- db8500_vsmps2_reg: db8500_vsmps2 {
- };
-
- // DB8500_REGULATOR_VSMPS3
- db8500_vsmps3_reg: db8500_vsmps3 {
- };
-
- // DB8500_REGULATOR_VRF1
- db8500_vrf1_reg: db8500_vrf1 {
- };
-
- // DB8500_REGULATOR_SWITCH_SVAMMDSP
- db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
- };
-
- // DB8500_REGULATOR_SWITCH_SVAMMDSPRET
- db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
- };
-
- // DB8500_REGULATOR_SWITCH_SVAPIPE
- db8500_sva_pipe_reg: db8500_sva_pipe {
- };
-
- // DB8500_REGULATOR_SWITCH_SIAMMDSP
- db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
- };
-
- // DB8500_REGULATOR_SWITCH_SIAMMDSPRET
- db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
- };
-
- // DB8500_REGULATOR_SWITCH_SIAPIPE
- db8500_sia_pipe_reg: db8500_sia_pipe {
- };
-
- // DB8500_REGULATOR_SWITCH_SGA
- db8500_sga_reg: db8500_sga {
- vin-supply = <&db8500_vape_reg>;
- };
-
- // DB8500_REGULATOR_SWITCH_B2R2_MCDE
- db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
- vin-supply = <&db8500_vape_reg>;
- };
-
- // DB8500_REGULATOR_SWITCH_ESRAM12
- db8500_esram12_reg: db8500_esram12 {
- };
-
- // DB8500_REGULATOR_SWITCH_ESRAM12RET
- db8500_esram12_ret_reg: db8500_esram12_ret {
- };
-
- // DB8500_REGULATOR_SWITCH_ESRAM34
- db8500_esram34_reg: db8500_esram34 {
- };
-
- // DB8500_REGULATOR_SWITCH_ESRAM34RET
- db8500_esram34_ret_reg: db8500_esram34_ret {
- };
- };
};
i2c0: i2c@80004000 {
@@ -1122,8 +1031,6 @@ msp0: msp@80123000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80123000 0x1000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
- /* TODO: delete and replace with power-domain handling */
- v-ape-supply = <&db8500_vape_reg>;
power-domains = <&pm_domains DOMAIN_VAPE>;
dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */
@@ -1141,8 +1048,6 @@ msp1: msp@80124000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80124000 0x1000>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- /* TODO: delete and replace with power-domain handling */
- v-ape-supply = <&db8500_vape_reg>;
power-domains = <&pm_domains DOMAIN_VAPE>;
/* This DMA channel only exist on DB8500 v1 */
@@ -1161,8 +1066,6 @@ msp2: msp@80117000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80117000 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
- /* TODO: delete and replace with power-domain handling */
- v-ape-supply = <&db8500_vape_reg>;
power-domains = <&pm_domains DOMAIN_VAPE>;
dmas = <&dma 14 0 0x12>, /* Logical - DevToMem - HighPrio */
@@ -1181,8 +1084,6 @@ msp3: msp@80125000 {
compatible = "stericsson,ux500-msp-i2s";
reg = <0x80125000 0x1000>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- /* TODO: delete and replace with power-domain handling */
- v-ape-supply = <&db8500_vape_reg>;
power-domains = <&pm_domains DOMAIN_VAPE>;
/* This DMA channel only exist on DB8500 v2 */
@@ -1226,8 +1127,6 @@ gpu@a0300000 {
clocks = <&prcmu_clk PRCMU_ACLK>, <&prcmu_clk PRCMU_SGACLK>;
clock-names = "bus", "core";
power-domains = <&pm_domains DOMAIN_SGA>;
- /* TODO: delete and replace with power-domain handling */
- mali-supply = <&db8500_sga_reg>;
};
mcde@a0350000 {
@@ -1235,8 +1134,6 @@ mcde@a0350000 {
reg = <0xa0350000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&pm_domains DOMAIN_B2R2_MCDE>;
- /* TODO: delete and replace with power-domain handling */
- epod-supply = <&db8500_b2r2_mcde_reg>;
clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
<&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
<&prcmu_clk PRCMU_PLLDSI>; /* HDMI clock */
--
2.55.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v3 13/18] drm/mcde: Use power domain for display power
2026-09-20 22:48 ` [PATCH v3 13/18] drm/mcde: Use power domain for display power Linus Walleij
@ 2026-09-20 22:58 ` sashiko-bot
0 siblings, 0 replies; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 22:58 UTC (permalink / raw)
To: Linus Walleij
Cc: devicetree, Frank.Li, dmaengine, conor+dt, dri-devel, robh, vkoul
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] pm: incorrect success check for pm_runtime_put_sync_suspend()
--
commit 1421b098d2f7f0ffecc255355537663b64ad9955
Author: Linus Walleij <linusw@kernel.org>
drm/mcde: Use power domain for display power
This commit replaces explicit EPOD regulator handling with runtime PM.
It uses the MCDE power domain and drops the regulator dependency.
> diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c
> index 257a6e84dd583..52f071bb347c4 100644
> --- a/drivers/gpu/drm/mcde/mcde_display.c
> +++ b/drivers/gpu/drm/mcde/mcde_display.c
[ ... ]
> @@ -1327,9 +1326,9 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
> spin_unlock_irq(&crtc->dev->event_lock);
> }
>
> - ret = regulator_disable(mcde->epod);
> + ret = pm_runtime_put_sync_suspend(mcde->dev);
> if (ret)
> - dev_err(drm->dev, "can't disable EPOD regulator\n");
> + dev_err(drm->dev, "can't disable MCDE power domain\n");
[Severity: Low]
Does this incorrectly treat a successful return value as an error?
When mcde_display_disable() calls pm_runtime_put_sync_suspend(), the PM core
returns 1 if the device is already suspended. Because this code checks
if (ret) rather than if (ret < 0), the success value of 1 will trigger the
error path.
This will cause a spurious "can't disable MCDE power domain" message to be
printed to the kernel log even when the operation succeeds.
> /* Make sure we are powered down (before we may power up again) */
> usleep_range(50000, 70000);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=13
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 17/18] dt-bindings: display: ste,mcde: Deprecate EPOD supply
2026-09-20 22:48 ` [PATCH v3 17/18] dt-bindings: display: ste,mcde: Deprecate EPOD supply Linus Walleij
@ 2026-09-20 23:00 ` sashiko-bot
0 siblings, 0 replies; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 23:00 UTC (permalink / raw)
To: Linus Walleij
Cc: devicetree, vkoul, robh, dmaengine, conor+dt, Frank.Li, dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] drm/mcde: DT ABI breakage drops legacy power support
- [Medium] dt-bindings: ste,mcde: missing power source requirement
--
commit 789856cac8c2df0e09f5a48ab8bacf3e0a2e001e
Author: Linus Walleij <linusw@kernel.org>
dt-bindings: display: ste,mcde: Deprecate EPOD supply
This commit makes epod-supply optional and marks it as deprecated. It
instructs the MCDE to use its power domain instead.
> diff --git a/Documentation/devicetree/bindings/display/ste,mcde.yaml b/Documentation/devicetree/bindings/display/ste,mcde.yaml
> index 05e7e4ebc8820..ee34b65dd13bf 100644
> --- a/Documentation/devicetree/bindings/display/ste,mcde.yaml
> +++ b/Documentation/devicetree/bindings/display/ste,mcde.yaml
> @@ -39,7 +39,8 @@ properties:
> maxItems: 1
>
> epod-supply:
> - description: a phandle to the EPOD regulator
> + description: a phandle to the legacy EPOD regulator
> + deprecated: true
[Severity: Critical]
The dt-binding deprecates epod-supply in favor of generic power-domains. If
companion driver changes in this series completely drop parsing of
epod-supply and rely solely on pm_runtime to power the hardware, could this
break existing device trees?
Older Device Tree Blobs (DTBs) lack the power-domains property. Because
epod-supply is no longer parsed, the core will not attach the device to the
power domain, and the driver will fail to turn on the hardware.
Could accessing unpowered display registers cause a synchronous external
abort or silent display failure?
Would it be possible to maintain legacy fallback logic in the driver or
dynamically map the regulator to the power domain in the core, rather than
breaking existing DTBs?
[ ... ]
> @@ -103,7 +104,6 @@ required:
> - interrupts
> - clocks
> - clock-names
> - - epod-supply
> - vana-supply
>
> additionalProperties: false
[Severity: Medium]
Since epod-supply is being removed from the required list to transition to
power-domains, should power-domains be added to the required list, or
perhaps an anyOf block used to enforce that at least one power source is
provided?
The MCDE hardware requires a power source to function. Without either
epod-supply or power-domains in the required properties, it seems a device
tree omitting both would silently pass schema validation, allowing
incomplete hardware descriptions to be accepted.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=17
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 14/18] misc: sram: Enable runtime PM
2026-09-20 22:48 ` [PATCH v3 14/18] misc: sram: Enable runtime PM Linus Walleij
@ 2026-09-20 23:02 ` sashiko-bot
0 siblings, 0 replies; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 23:02 UTC (permalink / raw)
To: Linus Walleij
Cc: dmaengine, robh, devicetree, dri-devel, Frank.Li, vkoul, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] misc: sram: Missing pm_runtime_get_sync() in sysfs read/write paths
- [Medium] misc: sram: Hardware initialization is not restored after runtime resume
--
commit b2dc9fd44cd639efd34dbecb064c4f1f3097e1eb
Author: Linus Walleij <linusw@kernel.org>
misc: sram: Enable runtime PM
Enable runtime PM for generic SRAM devices after probe has initialized
the SRAM mappings and partitions.
This lets SRAM devices with attached power domains be managed through
runtime PM references from their consumers.
> diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
> index c8990e83a65a2..7f19dca7b818e 100644
> --- a/drivers/misc/sram.c
> +++ b/drivers/misc/sram.c
[ ... ]
> @@ -425,6 +426,10 @@ static int sram_probe(struct platform_device *pdev)
> goto err_free_partitions;
> }
>
> + ret = devm_pm_runtime_set_active_enabled(&pdev->dev);
[Severity: High]
Does this code allow sysfs read/write paths to access unpowered MMIO hardware?
Since runtime PM is now enabled, the SRAM device can be suspended by its
attached power domain. If userspace accesses the exported sysfs bin
attributes, sram_read() and sram_write() perform MMIO accesses without
waking the device:
drivers/misc/sram.c:sram_read() {
...
mutex_lock(&part->lock);
memcpy_fromio(buf, part->base + pos, count);
mutex_unlock(&part->lock);
...
}
Will this cause an asynchronous external abort and crash the system if the
hardware is accessed while suspended?
[Severity: Medium]
Will hardware state be lost and not restored on resume?
Earlier in sram_probe(), hardware initialization is performed:
drivers/misc/sram.c:sram_probe() {
...
if (config && config->init) {
ret = config->init();
...
}
If the device is attached to a PM domain that powers it down, waking it up
will turn on the power but will not re-apply the config->init() callback
(such as atmel_securam_wait) because the driver lacks a runtime_resume
callback.
Can this lead to hardware faults or data corruption if the RAM is accessed
before it is ready?
> + if (ret)
> + goto err_free_partitions;
> +
> if (sram->pool)
> dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
> gen_pool_size(sram->pool) / 1024, sram->virt_base);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=14
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM
2026-09-20 22:48 ` [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM Linus Walleij
@ 2026-09-20 23:03 ` sashiko-bot
2026-09-21 16:36 ` Frank Li
2026-09-24 13:26 ` Ulf Hansson
2 siblings, 0 replies; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 23:03 UTC (permalink / raw)
To: Linus Walleij
Cc: Frank.Li, dri-devel, devicetree, conor+dt, dmaengine, robh, vkoul
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dmaengine: ste_dma40: pm_runtime_resume_and_get() sleeps in atomic context
- [Medium] dmaengine: ste_dma40: unnecessary LCLA SRAM power domain wakeup for physical channels
--
commit 711af1477e65e64325b0b0970b88c4b5d746ee74
Author: Linus Walleij <linusw@kernel.org>
dmaengine: ste_dma40: Use power domain for LCLA SRAM
This patch replaces the LCLA ESRAM regulator with runtime PM handling.
It adds a reference to the SRAM device that owns the ESRAM34 power domain
and holds that domain during descriptor preparation while transfers are
active.
> diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
> index eda3f91741ed5..2841af5b160b8 100644
> --- a/drivers/dma/ste_dma40.c
> +++ b/drivers/dma/ste_dma40.c
[ ... ]
> @@ -628,6 +632,36 @@ static struct device *chan2dev(struct d40_chan *d40c)
> return &d40c->chan.dev->device;
> }
>
> +static void d40_transfer_runtime_get(struct d40_base *base)
> +{
> + pm_runtime_get_sync(base->dev);
> +}
> +
> +static int d40_lcla_runtime_get(struct d40_base *base)
> +{
> + if (!base->lcla_dev)
> + return 0;
> +
> + return pm_runtime_resume_and_get(base->lcla_dev);
[Severity: High]
Does this sleep in atomic context?
When d40_prep_sg() in drivers/dma/ste_dma40.c prepares a transfer, it calls
d40_lcla_runtime_get(), which invokes pm_runtime_resume_and_get() here.
DMA clients can call dmaengine_prep_slave_sg() or dmaengine_prep_dma_cyclic()
while holding a spinlock or from an interrupt handler. Since lcla_dev is an
external platform device and is not marked pm_runtime_irq_safe(), the PM
core's rpm_resume() will attempt to sleep waiting for the power domain.
Could this cause a scheduling while atomic panic when clients prepare DMA
from an atomic context?
> +}
> +
> +static void d40_desc_lcla_runtime_put(struct d40_chan *d40c,
[ ... ]
> @@ -2246,6 +2283,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
> dma_addr_t dst_dev_addr;
> struct d40_desc *desc;
> unsigned long flags;
> + bool got_lcla_pm = false;
> int ret;
>
> if (!chan->phy_chan) {
> @@ -2255,11 +2293,20 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
>
> d40_set_runtime_config_write(dchan, &chan->slave_config, direction);
>
> + ret = d40_lcla_runtime_get(chan->base);
[Severity: Medium]
Could this unnecessarily activate the LCLA SRAM power domain for physical
channels?
In drivers/dma/ste_dma40.c, d40_prep_sg() unconditionally resumes the
domain here before checking if the channel is logical or physical. Since
physical channels map directly to hardware registers and do not use the
LCLA SRAM, does this unnecessarily keep the power domain active and
introduce wakeup latency for physical channels?
> + if (ret) {
> + chan_err(chan, "Failed to enable LCLA power domain\n");
> + return NULL;
> + }
> + got_lcla_pm = !!chan->base->lcla_dev;
> +
> spin_lock_irqsave(&chan->lock, flags);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=15
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 11/18] ARM: dts: ux500: Add power domains
2026-09-20 22:48 ` [PATCH v3 11/18] ARM: dts: ux500: Add " Linus Walleij
@ 2026-09-20 23:04 ` sashiko-bot
0 siblings, 0 replies; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 23:04 UTC (permalink / raw)
To: Linus Walleij
Cc: vkoul, devicetree, conor+dt, robh, dri-devel, Frank.Li, dmaengine
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] dt-bindings: undocumented power-domains property causes schema validation failure
--
commit 043bcab3d2585239bd006e899482166025b03c26
Author: Linus Walleij <linusw@kernel.org>
ARM: dts: ux500: Add power domains
This commit adds power domain properties to CPUs and various SoC peripherals
in the DBX500 device tree. Both CPUs are updated to share DOMAIN_VARM, which
also supplies their PMU.
> diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
> index 11fcae1904e20..0603244dc9e83 100644
> --- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
> +++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
[ ... ]
> @@ -154,6 +156,7 @@ sram@40020000 {
> reg = <0x40020000 0x40000>;
> #address-cells = <1>;
> #size-cells = <1>;
> + power-domains = <&pm_domains DOMAIN_ESRAM_12>;
[Severity: Low]
Does this cause strict schema validation to fail during dtbs_check? The
mmio-sram binding strictly prohibits undocumented properties and does not list
power-domains.
[ ... ]
> @@ -314,11 +319,13 @@ intc: interrupt-controller@a0411000 {
> interrupt-controller;
> reg = <0xa0411000 0x1000>,
> <0xa0410100 0x100>;
> + power-domains = <&pm_domains DOMAIN_VARM>;
> };
>
> scu@a0410000 {
> compatible = "arm,cortex-a9-scu";
> reg = <0xa0410000 0x100>;
> + power-domains = <&pm_domains DOMAIN_VARM>;
[Severity: Low]
Similarly, does the addition of power-domains here trigger a warning? The
arm,scu.yaml binding prohibits undocumented properties and does not define
power-domains for arm,cortex-a9-scu.
[ ... ]
> @@ -393,7 +415,7 @@ mtu@a03c6000 {
> compatible = "st,nomadik-mtu";
> reg = <0xa03c6000 0x1000>;
> interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
> -
> + power-domains = <&pm_domains DOMAIN_VAPE>;
[Severity: Low]
Will this fail dtbs_check validation? The st,nomadik-mtu binding does not
list power-domains and typically prohibits undocumented properties.
[ ... ]
> @@ -435,6 +458,7 @@ gpio0: gpio@8012e000 {
> gpio-bank = <0>;
> gpio-ranges = <&pinctrl 0 0 32>;
> clocks = <&prcc_pclk 1 9>;
> + power-domains = <&pm_domains DOMAIN_VAPE>;
[Severity: Low]
Does this property need to be added to the st,nomadik-gpio.yaml schema first?
The schema has unevaluatedProperties: false and currently does not define
power-domains.
[ ... ]
> @@ -613,9 +646,11 @@ dma: dma-controller@801C0000 {
> memcpy-channels = <56 57 58 59 60>;
>
> clocks = <&prcmu_clk PRCMU_DMACLK>;
> + power-domains = <&pm_domains DOMAIN_VAPE>;
[Severity: Low]
Could this undocumented property in stericsson,dma40.yaml cause dtbs_check
to fail? That schema uses additionalProperties: false without listing
power-domains.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=11
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs
2026-09-20 22:48 ` [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs Linus Walleij
@ 2026-09-20 23:04 ` sashiko-bot
2026-09-24 13:44 ` Ulf Hansson
1 sibling, 0 replies; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 23:04 UTC (permalink / raw)
To: Linus Walleij
Cc: conor+dt, Frank.Li, dmaengine, dri-devel, robh, vkoul, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] pmdomain: ux500: missing RAM retention flags in power domains
- [Medium] pmdomain: ux500: power leak from initializing domains as OFF
--
commit 9e8ecf92bb791471023c621b0664e285a95b3ad6
Author: Linus Walleij <linusw@kernel.org>
pmdomain: st: ux500: Control DB8500 EPODs
This commit moves the DB8500 EPOD state handling into the Ux500 power-domain
driver. It also keeps the old regulator driver mutually exclusive with the
pmdomain driver.
> diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
> index d90a563cd6f37..b31a36a4acd17 100644
> --- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
> +++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
[ ... ]
> +static int enable_epod(u16 epod_id, bool ramret)
> +{
> + int ret;
> +
> + if (ramret) {
> + if (!epod_on[epod_id]) {
> + ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
[Severity: High]
Are the RAM retention branches in enable_epod() and disable_epod() dead code?
The dbx500_powerdomain_info struct defines an is_ramret boolean, and these
functions check it to use EPOD_STATE_RAMRET. However, none of the 16 domains
initialized in ux500_pm_domains set .is_ramret = true.
[ ... ]
> -static struct generic_pm_domain ux500_pm_domain_sva_mmdsp = {
> +static struct dbx500_powerdomain_info ux500_pm_domain_sva_mmdsp = {
> /* Vape_SVA_MMDSP_pwr */
> - .name = "SVA_MMDSP",
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> + .genpd = {
> + .name = "SVA_MMDSP",
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = EPOD_ID_SVAMMDSP,
> };
[Severity: High]
Will the omission of .is_ramret = true here cause SRAM data loss or prevent
the domain from entering retention during suspend?
In the old regulator driver, domains such as SVAMMDSP, SIAMMDSP, ESRAM12,
and ESRAM34 explicitly had this flag set. Because the flag is never set in
the new PM domain driver, it defaults to false. This means normal runtime PM
transitions will fully power off the domains (EPOD_STATE_OFF) instead of
retaining their state.
[ ... ]
> @@ -186,11 +304,12 @@ static int ux500_pm_domains_probe(struct platform_device *pdev)
[ ... ]
> genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains);
>
> for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i)
> - pm_genpd_init(ux500_pm_domains[i], NULL, false);
> + pm_genpd_init(ux500_pm_domains[i], NULL, true);
[Severity: Medium]
Could initializing these domains as software-OFF (is_off = true) lead to a
power leak if the bootloader leaves them enabled?
When initialized as OFF (true), the genpd framework does not set stay_on
and considers the domain to be already powered off in software. Because of
this, genpd_power_off_unused() sees them as already OFF and skips calling
pd_power_off().
Consequently, any domain left ON by the bootloader without an active kernel
consumer is never powered off, failing to replicate the late init cleanup
behavior of the old regulator driver.
> +
> + ret = of_genpd_add_provider_onecell(np, genpd_data);
> + if (ret)
> + goto remove_genpds;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=12
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators
2026-09-20 22:48 ` [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators Linus Walleij
@ 2026-09-20 23:05 ` sashiko-bot
2026-09-21 7:06 ` Linus Walleij
0 siblings, 1 reply; 35+ messages in thread
From: sashiko-bot @ 2026-09-20 23:05 UTC (permalink / raw)
To: Linus Walleij
Cc: vkoul, dri-devel, devicetree, conor+dt, Frank.Li, dmaengine, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] soc: ux500: missing v-ape-supply causes dummy regulator warning or probe failure
--
commit 3a86fcf38f93ed2dd8837f7b5a7e6f474011a07f
Author: Linus Walleij <linusw@kernel.org>
ARM: dts: ux500: Remove DB8500 EPOD regulators
Delete the deprecated db8500-prcmu-regulators node and all its EPOD
regulators, including VAPE and VSMPS2. Their external consumers now use
the AB8500 or AB8505 buck regulators, so no compatibility regulators
are needed.
> diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
> index 0603244dc9e83..efc84e018c44a 100644
> --- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
> +++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
[ ... ]
> @@ -1122,8 +1031,6 @@ msp0: msp@80123000 {
> compatible = "stericsson,ux500-msp-i2s";
> reg = <0x80123000 0x1000>;
> interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
> - /* TODO: delete and replace with power-domain handling */
> - v-ape-supply = <&db8500_vape_reg>;
> power-domains = <&pm_domains DOMAIN_VAPE>;
>
> dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */
[Severity: Medium]
Will removing the v-ape-supply property cause regressions in the
ux500-msp-i2s driver?
Looking at sound/soc/ux500/ux500_msp_dai.c:ux500_msp_drv_probe(), it
unconditionally requests this regulator:
drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
if (IS_ERR(drvdata->reg_vape)) {
Will this missing supply cause the regulator framework to fall back to a
dummy regulator (emitting a warning) or return an error and break the
driver probe entirely?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260921-ux500-power-domains-v7-1-v3-0-9352be6b86b1@kernel.org?part=18
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators
2026-09-20 23:05 ` sashiko-bot
@ 2026-09-21 7:06 ` Linus Walleij
0 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-09-21 7:06 UTC (permalink / raw)
To: sashiko-reviews
Cc: vkoul, dri-devel, devicetree, conor+dt, Frank.Li, dmaengine, robh
On Mon, Sep 21, 2026 at 1:05 AM <sashiko-bot@kernel.org> wrote:
> Will removing the v-ape-supply property cause regressions in the
> ux500-msp-i2s driver?
>
> Looking at sound/soc/ux500/ux500_msp_dai.c:ux500_msp_drv_probe(), it
> unconditionally requests this regulator:
>
> drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
> if (IS_ERR(drvdata->reg_vape)) {
>
> Will this missing supply cause the regulator framework to fall back to a
> dummy regulator (emitting a warning) or return an error and break the
> driver probe entirely?
Ooops I'll add a patch removing that so the driver just uses the power
domain.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM
2026-09-20 22:48 ` [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM Linus Walleij
2026-09-20 23:03 ` sashiko-bot
@ 2026-09-21 16:36 ` Frank Li
2026-09-24 13:26 ` Ulf Hansson
2 siblings, 0 replies; 35+ messages in thread
From: Frank Li @ 2026-09-21 16:36 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones,
linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine
On Mon, Sep 21, 2026 at 12:48:21AM +0200, Linus Walleij wrote:
> Replace the LCLA ESRAM regulator with runtime PM.
>
> Use the SRAM device that owns the ESRAM34 power domain.
>
> Hold that domain while DMA transfers are active. The DMA controller is
> runtime PM IRQ-safe, so keep taking explicit LCLA runtime PM references
> from the descriptor preparation path instead of relying on a runtime PM
> device link from the atomic transfer path.
>
> Add a stateless device link so system PM keeps the DMA controller ordered
> after the LCLA SRAM supplier.
>
> Suggested-by: Frank Li <Frank.li@oss.nxp.com>
> Assisted-by: LLM
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> drivers/dma/ste_dma40.c | 130 ++++++++++++++++++++++++++++++++----------------
> 1 file changed, 88 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
> index eda3f91741ed..2841af5b160b 100644
> --- a/drivers/dma/ste_dma40.c
> +++ b/drivers/dma/ste_dma40.c
> @@ -21,8 +21,8 @@
> #include <linux/of.h>
> #include <linux/of_address.h>
> #include <linux/of_dma.h>
> +#include <linux/of_platform.h>
> #include <linux/amba/bus.h>
> -#include <linux/regulator/consumer.h>
>
> #include "dmaengine.h"
> #include "ste_dma40.h"
> @@ -383,6 +383,7 @@ struct d40_lli_pool {
> * @node: List entry.
> * @is_in_client_list: true if the client owns this descriptor.
> * @cyclic: true if this is a cyclic job
> + * @lcla_pm_active: LCLA SRAM power domain is held for this descriptor.
> *
> * This descriptor is used for both logical and physical transfers.
> */
> @@ -402,6 +403,7 @@ struct d40_desc {
>
> bool is_in_client_list;
> bool cyclic;
> + bool lcla_pm_active;
> };
>
> /**
> @@ -571,7 +573,8 @@ struct d40_gen_dmac {
> * to phy_chans entries.
> * @plat_data: Pointer to provided platform_data which is the driver
> * configuration.
> - * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
> + * @lcla_dev: SRAM device for the ESRAM bank used by LCLA.
> + * @lcla_link: Device link to keep system PM ordered against LCLA.
> * @phy_res: Vector containing all physical channels.
> * @lcla_pool: lcla pool settings and data.
> * @lcpa_base: The virtual mapped address of LCPA.
> @@ -606,7 +609,8 @@ struct d40_base {
> struct d40_chan **lookup_log_chans;
> struct d40_chan **lookup_phy_chans;
> struct stedma40_platform_data *plat_data;
> - struct regulator *lcpa_regulator;
> + struct device *lcla_dev;
> + struct device_link *lcla_link;
> /* Physical half channels */
> struct d40_phy_res *phy_res;
> struct d40_lcla_pool lcla_pool;
> @@ -628,6 +632,36 @@ static struct device *chan2dev(struct d40_chan *d40c)
> return &d40c->chan.dev->device;
> }
>
> +static void d40_transfer_runtime_get(struct d40_base *base)
> +{
> + pm_runtime_get_sync(base->dev);
should use pm_runtime_resume_and_get() also? avoid need call
pm_runtime_put_noidle() to maintance ref count.
pm_runtime_get_sync() many return failure, why needn't check return value
here.
Frank
> +}
> +
> +static int d40_lcla_runtime_get(struct d40_base *base)
> +{
> + if (!base->lcla_dev)
> + return 0;
> +
> + return pm_runtime_resume_and_get(base->lcla_dev);
> +}
> +
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM
2026-09-20 22:48 ` [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM Linus Walleij
2026-09-20 23:03 ` sashiko-bot
2026-09-21 16:36 ` Frank Li
@ 2026-09-24 13:26 ` Ulf Hansson
2026-09-30 20:15 ` Frank Li
2026-10-06 13:21 ` Vinod Koul
2 siblings, 2 replies; 35+ messages in thread
From: Ulf Hansson @ 2026-09-24 13:26 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones,
linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Frank Li
On Mon, Sep 21, 2026 at 12:49 AM Linus Walleij <linusw@kernel.org> wrote:
>
> Replace the LCLA ESRAM regulator with runtime PM.
>
> Use the SRAM device that owns the ESRAM34 power domain.
>
> Hold that domain while DMA transfers are active. The DMA controller is
> runtime PM IRQ-safe, so keep taking explicit LCLA runtime PM references
> from the descriptor preparation path instead of relying on a runtime PM
> device link from the atomic transfer path.
A bit of an orthogonal problem, but related to the above. The irqsafe
thing have been discussed in the past for DMA controller drivers.
Would it possible to get rid of the irqsafe configuration for the dma
controller device, altogether?
I don't recall exactly, but not the entire consumer DMA API is allowed
to be called in atomic context, but perhaps that is not sufficient to
allow us to drop the irqsafe configuration for the DMA controller
device?
If not, I wonder if the consumer of the DMA (like an mmc controller)
should be assigned as a consumer device (using device links and
DL_FLAG_PM_RUNTIME) of the DMA controller device. In this way, the
consumer (mmc) would be able to control the supplier (DMA) through the
device link directly using runtime PM. This could potentially avoid
the requirement of having to use irqsafe for the DMA controller
device. Maybe someone already tried this?
If the irqsafe configuration can be dropped, in some way or the other,
this patch could become less intrusive, as all that would be needed is
to create a device link to sram device using DL_FLAG_PM_RUNTIME.
Kind regards
Uffe
>
> Add a stateless device link so system PM keeps the DMA controller ordered
> after the LCLA SRAM supplier.
>
> Suggested-by: Frank Li <Frank.li@oss.nxp.com>
> Assisted-by: LLM
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> drivers/dma/ste_dma40.c | 130 ++++++++++++++++++++++++++++++++----------------
> 1 file changed, 88 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
> index eda3f91741ed..2841af5b160b 100644
> --- a/drivers/dma/ste_dma40.c
> +++ b/drivers/dma/ste_dma40.c
> @@ -21,8 +21,8 @@
> #include <linux/of.h>
> #include <linux/of_address.h>
> #include <linux/of_dma.h>
> +#include <linux/of_platform.h>
> #include <linux/amba/bus.h>
> -#include <linux/regulator/consumer.h>
>
> #include "dmaengine.h"
> #include "ste_dma40.h"
> @@ -383,6 +383,7 @@ struct d40_lli_pool {
> * @node: List entry.
> * @is_in_client_list: true if the client owns this descriptor.
> * @cyclic: true if this is a cyclic job
> + * @lcla_pm_active: LCLA SRAM power domain is held for this descriptor.
> *
> * This descriptor is used for both logical and physical transfers.
> */
> @@ -402,6 +403,7 @@ struct d40_desc {
>
> bool is_in_client_list;
> bool cyclic;
> + bool lcla_pm_active;
> };
>
> /**
> @@ -571,7 +573,8 @@ struct d40_gen_dmac {
> * to phy_chans entries.
> * @plat_data: Pointer to provided platform_data which is the driver
> * configuration.
> - * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
> + * @lcla_dev: SRAM device for the ESRAM bank used by LCLA.
> + * @lcla_link: Device link to keep system PM ordered against LCLA.
> * @phy_res: Vector containing all physical channels.
> * @lcla_pool: lcla pool settings and data.
> * @lcpa_base: The virtual mapped address of LCPA.
> @@ -606,7 +609,8 @@ struct d40_base {
> struct d40_chan **lookup_log_chans;
> struct d40_chan **lookup_phy_chans;
> struct stedma40_platform_data *plat_data;
> - struct regulator *lcpa_regulator;
> + struct device *lcla_dev;
> + struct device_link *lcla_link;
> /* Physical half channels */
> struct d40_phy_res *phy_res;
> struct d40_lcla_pool lcla_pool;
> @@ -628,6 +632,36 @@ static struct device *chan2dev(struct d40_chan *d40c)
> return &d40c->chan.dev->device;
> }
>
> +static void d40_transfer_runtime_get(struct d40_base *base)
> +{
> + pm_runtime_get_sync(base->dev);
> +}
> +
> +static int d40_lcla_runtime_get(struct d40_base *base)
> +{
> + if (!base->lcla_dev)
> + return 0;
> +
> + return pm_runtime_resume_and_get(base->lcla_dev);
> +}
> +
> +static void d40_desc_lcla_runtime_put(struct d40_chan *d40c,
> + struct d40_desc *d40d)
> +{
> + struct d40_base *base = d40c->base;
> +
> + if (!d40d->lcla_pm_active)
> + return;
> +
> + d40d->lcla_pm_active = false;
> + pm_runtime_put(base->lcla_dev);
> +}
> +
> +static void d40_transfer_runtime_put(struct d40_base *base)
> +{
> + pm_runtime_put_autosuspend(base->dev);
> +}
> +
> static bool chan_is_physical(struct d40_chan *chan)
> {
> return chan->log_num == D40_PHY_CHAN;
> @@ -818,6 +852,7 @@ static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d)
>
> d40_pool_lli_free(d40c, d40d);
> d40_lcla_free_all(d40c, d40d);
> + d40_desc_lcla_runtime_put(d40c, d40d);
> kmem_cache_free(d40c->base->desc_slab, d40d);
> }
>
> @@ -1516,7 +1551,7 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
> if (d40d != NULL) {
> if (!d40c->busy) {
> d40c->busy = true;
> - pm_runtime_get_sync(d40c->base->dev);
> + d40_transfer_runtime_get(d40c->base);
> }
>
> /* Remove from queue */
> @@ -1535,6 +1570,7 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
> d40_desc_remove(d40d);
> d40_desc_free(d40c, d40d);
> d40c->busy = false;
> + d40_transfer_runtime_put(d40c->base);
> return ERR_PTR(err);
> }
> }
> @@ -1583,7 +1619,7 @@ static void dma_tc_handle(struct d40_chan *d40c)
> if (d40_queue_start(d40c) == NULL) {
> d40c->busy = false;
>
> - pm_runtime_put_autosuspend(d40c->base->dev);
> + d40_transfer_runtime_put(d40c->base);
> }
>
> d40_desc_remove(d40d);
> @@ -1637,6 +1673,7 @@ static void dma_tasklet(struct tasklet_struct *t)
> } else if (!d40d->is_in_client_list) {
> d40_desc_remove(d40d);
> d40_lcla_free_all(d40c, d40d);
> + d40_desc_lcla_runtime_put(d40c, d40d);
> list_add_tail(&d40d->node, &d40c->client);
> d40d->is_in_client_list = true;
> }
> @@ -2067,7 +2104,7 @@ static int d40_free_dma(struct d40_chan *d40c)
> d40c->base->lookup_phy_chans[phy->num] = NULL;
>
> if (d40c->busy)
> - pm_runtime_put_autosuspend(d40c->base->dev);
> + d40_transfer_runtime_put(d40c->base);
>
> d40c->busy = false;
> d40c->phy_chan = NULL;
> @@ -2246,6 +2283,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
> dma_addr_t dst_dev_addr;
> struct d40_desc *desc;
> unsigned long flags;
> + bool got_lcla_pm = false;
> int ret;
>
> if (!chan->phy_chan) {
> @@ -2255,11 +2293,20 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
>
> d40_set_runtime_config_write(dchan, &chan->slave_config, direction);
>
> + ret = d40_lcla_runtime_get(chan->base);
> + if (ret) {
> + chan_err(chan, "Failed to enable LCLA power domain\n");
> + return NULL;
> + }
> + got_lcla_pm = !!chan->base->lcla_dev;
> +
> spin_lock_irqsave(&chan->lock, flags);
>
> desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
> if (desc == NULL)
> goto unlock;
> + desc->lcla_pm_active = got_lcla_pm;
> + got_lcla_pm = false;
>
> if (sg_next(&sg_src[sg_len - 1]) == sg_src)
> desc->cyclic = true;
> @@ -2297,6 +2344,8 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
> d40_desc_free(chan, desc);
> unlock:
> spin_unlock_irqrestore(&chan->lock, flags);
> + if (got_lcla_pm)
> + pm_runtime_put(chan->base->lcla_dev);
> return NULL;
> }
>
> @@ -2628,7 +2677,7 @@ static int d40_terminate_all(struct dma_chan *chan)
> d40_term_all(d40c);
> pm_runtime_put_autosuspend(d40c->base->dev);
> if (d40c->busy)
> - pm_runtime_put_autosuspend(d40c->base->dev);
> + d40_transfer_runtime_put(d40c->base);
> d40c->busy = false;
>
> spin_unlock_irqrestore(&d40c->lock, flags);
> @@ -2931,29 +2980,11 @@ static int __init d40_dmaengine_init(struct d40_base *base,
> #ifdef CONFIG_PM_SLEEP
> static int dma40_suspend(struct device *dev)
> {
> - struct d40_base *base = dev_get_drvdata(dev);
> - int ret;
> -
> - ret = pm_runtime_force_suspend(dev);
> - if (ret)
> - return ret;
> -
> - if (base->lcpa_regulator)
> - ret = regulator_disable(base->lcpa_regulator);
> - return ret;
> + return pm_runtime_force_suspend(dev);
> }
>
> static int dma40_resume(struct device *dev)
> {
> - struct d40_base *base = dev_get_drvdata(dev);
> - int ret = 0;
> -
> - if (base->lcpa_regulator) {
> - ret = regulator_enable(base->lcpa_regulator);
> - if (ret)
> - return ret;
> - }
> -
> return pm_runtime_force_resume(dev);
> }
> #endif
> @@ -3509,7 +3540,10 @@ static int __init d40_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct device_node *np = pdev->dev.of_node;
> struct device_node *np_lcpa;
> + struct device_node *np_lcla;
> + struct device_node *np_lcla_parent;
> struct d40_base *base;
> + struct platform_device *lcla_pdev;
> struct resource *res;
> struct resource res_lcpa;
> int num_reserved_chans;
> @@ -3610,21 +3644,32 @@ static int __init d40_probe(struct platform_device *pdev)
> irq_requested = true;
>
> if (base->plat_data->use_esram_lcla) {
> + np_lcla = of_parse_phandle(np, "sram", 1);
> + if (!np_lcla) {
> + dev_err(dev, "no LCLA SRAM node\n");
> + ret = -EINVAL;
> + goto destroy_cache;
> + }
>
> - base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
> - if (IS_ERR(base->lcpa_regulator)) {
> - d40_err(dev, "Failed to get lcpa_regulator\n");
> - ret = PTR_ERR(base->lcpa_regulator);
> - base->lcpa_regulator = NULL;
> + np_lcla_parent = of_get_parent(np_lcla);
> + of_node_put(np_lcla);
> + if (!np_lcla_parent) {
> + dev_err(dev, "no LCLA SRAM parent node\n");
> + ret = -EINVAL;
> goto destroy_cache;
> }
>
> - ret = regulator_enable(base->lcpa_regulator);
> - if (ret) {
> - d40_err(dev,
> - "Failed to enable lcpa_regulator\n");
> - regulator_put(base->lcpa_regulator);
> - base->lcpa_regulator = NULL;
> + lcla_pdev = of_find_device_by_node(np_lcla_parent);
> + of_node_put(np_lcla_parent);
> + if (!lcla_pdev) {
> + ret = -EPROBE_DEFER;
> + goto destroy_cache;
> + }
> + base->lcla_dev = &lcla_pdev->dev;
> + base->lcla_link = device_link_add(dev, base->lcla_dev,
> + DL_FLAG_STATELESS);
> + if (!base->lcla_link) {
> + ret = -ENODEV;
> goto destroy_cache;
> }
> }
> @@ -3663,16 +3708,17 @@ static int __init d40_probe(struct platform_device *pdev)
> SZ_1K * base->num_phy_chans,
> DMA_TO_DEVICE);
>
> - if (!base->lcla_pool.base_unaligned && base->lcla_pool.base)
> + if (!base->lcla_pool.base_unaligned && base->lcla_pool.base &&
> + base->lcla_pool.pages)
> free_pages((unsigned long)base->lcla_pool.base,
> base->lcla_pool.pages);
>
> kfree(base->lcla_pool.base_unaligned);
>
> - if (base->lcpa_regulator) {
> - regulator_disable(base->lcpa_regulator);
> - regulator_put(base->lcpa_regulator);
> - }
> + if (base->lcla_link)
> + device_link_del(base->lcla_link);
> + if (base->lcla_dev)
> + put_device(base->lcla_dev);
> if (irq_requested)
> free_irq(base->irq, base);
> if (runtime_pm_enabled)
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs
2026-09-20 22:48 ` [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs Linus Walleij
2026-09-20 23:04 ` sashiko-bot
@ 2026-09-24 13:44 ` Ulf Hansson
1 sibling, 0 replies; 35+ messages in thread
From: Ulf Hansson @ 2026-09-24 13:44 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones,
linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine
On Mon, Sep 21, 2026 at 12:49 AM Linus Walleij <linusw@kernel.org> wrote:
>
> Move the DB8500 EPOD state handling into the Ux500 power-domain driver.
>
> Keep the old regulator driver mutually exclusive with the pmdomain driver.
>
> Assisted-by: LLM
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> arch/arm/mach-ux500/Kconfig | 2 +-
> drivers/pmdomain/st/ste-ux500-pm-domain.c | 355 +++++++++++++++++++++---------
> drivers/regulator/Kconfig | 1 +
> 3 files changed, 254 insertions(+), 104 deletions(-)
>
> diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
> index c18def269137..56636c993f49 100644
> --- a/arch/arm/mach-ux500/Kconfig
> +++ b/arch/arm/mach-ux500/Kconfig
> @@ -26,7 +26,7 @@ menuconfig ARCH_U8500
> select PL310_ERRATA_753970 if CACHE_L2X0
> select PM_GENERIC_DOMAINS if PM
> select REGULATOR
> - select REGULATOR_DB8500_PRCMU
> + select UX500_PM_DOMAIN
> select REGULATOR_FIXED_VOLTAGE
> select SOC_BUS
> select RESET_CONTROLLER
> diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
> index d90a563cd6f3..b31a36a4acd1 100644
> --- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
> +++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
> @@ -6,174 +6,292 @@
> *
> * Implements PM domains using the generic PM domain for ux500.
> */
> +#include <linux/cleanup.h>
> #include <linux/device.h>
> -#include <linux/kernel.h>
> -#include <linux/platform_device.h>
> -#include <linux/printk.h>
> -#include <linux/slab.h>
> #include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/db8500-prcmu.h>
> +#include <linux/mutex.h>
> #include <linux/of.h>
> +#include <linux/platform_device.h>
> #include <linux/pm_domain.h>
> +#include <linux/slab.h>
>
> #include <dt-bindings/arm/ux500_pm_domains.h>
>
> #define NR_DOMAINS (DOMAIN_ESRAM_34 + 1)
> +#define UX500_EPOD_NONE NUM_EPOD_ID
>
> -static int pd_power_off(struct generic_pm_domain *domain)
> +/**
> + * struct dbx500_powerdomain_info - dbx500 power domain information
> + * @genpd: generic power domain
> + * @epod_id: id for EPOD (power domain)
> + * @is_ramret: RAM retention switch for EPOD (power domain)
> + */
> +struct dbx500_powerdomain_info {
> + struct generic_pm_domain genpd;
> + u16 epod_id;
> + bool is_ramret;
This one is unused for the defined power domains. Is the plan to add
support for this on top, later on?
> +};
> +
> +static DEFINE_MUTEX(ux500_pd_lock);
> +static bool epod_on[NUM_EPOD_ID];
> +static bool epod_ramret[NUM_EPOD_ID];
> +
> +static int enable_epod(u16 epod_id, bool ramret)
> {
> - /*
> - * Handle the gating of the PM domain regulator here.
> - *
> - * Drivers/subsystems handling devices in the PM domain needs to perform
> - * register context save/restore from their respective runtime PM
> - * callbacks, to be able to enable PM domain gating/ungating.
> - */
> + int ret;
> +
> + if (ramret) {
> + if (!epod_on[epod_id]) {
> + ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
> + if (ret < 0)
> + return ret;
> + }
> + epod_ramret[epod_id] = true;
> + } else {
> + ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_ON);
> + if (ret < 0)
> + return ret;
> + epod_on[epod_id] = true;
> + }
> +
> return 0;
> }
>
> -static int pd_power_on(struct generic_pm_domain *domain)
> +static int disable_epod(u16 epod_id, bool ramret)
> {
> - /*
> - * Handle the ungating of the PM domain regulator here.
> - *
> - * Drivers/subsystems handling devices in the PM domain needs to perform
> - * register context save/restore from their respective runtime PM
> - * callbacks, to be able to enable PM domain gating/ungating.
> - */
> + int ret;
> +
> + if (ramret) {
> + if (!epod_on[epod_id]) {
> + ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
> + if (ret < 0)
> + return ret;
> + }
> + epod_ramret[epod_id] = false;
> + } else {
> + if (epod_ramret[epod_id]) {
> + ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
> + if (ret < 0)
> + return ret;
> + } else {
> + ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
> + if (ret < 0)
> + return ret;
> + }
> + epod_on[epod_id] = false;
> + }
> +
> return 0;
> }
>
> +
> +static int pd_power_off(struct generic_pm_domain *domain)
> +{
> + struct dbx500_powerdomain_info *info =
> + container_of(domain, struct dbx500_powerdomain_info, genpd);
> + int ret = 0;
> +
> + guard(mutex)(&ux500_pd_lock);
> + if (info->epod_id < NUM_EPOD_ID)
> + ret = disable_epod(info->epod_id, info->is_ramret);
> +
> + return ret;
> +}
> +
> +static int pd_power_on(struct generic_pm_domain *domain)
> +{
> + struct dbx500_powerdomain_info *info =
> + container_of(domain, struct dbx500_powerdomain_info, genpd);
> + int ret = 0;
> +
> + guard(mutex)(&ux500_pd_lock);
> + if (info->epod_id < NUM_EPOD_ID)
> + ret = enable_epod(info->epod_id, info->is_ramret);
> +
> + return ret;
> +}
> +
> /*
> * Apart from these voltage domains there is also VSAFE which is always
> * on. Vape_esram0_pwr for eSRAM0 is connected to VSAFE.
> */
> -static struct generic_pm_domain ux500_pm_domain_vape = {
> +static struct dbx500_powerdomain_info ux500_pm_domain_vape = {
> /* Vape_pwr */
> - .name = "VAPE", /* 0.95 .. 1.20 V */
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> + .genpd = {
> + .name = "VAPE", /* 0.95 .. 1.20 V */
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
Several power domains below share this epod_id. What does that really
mean? Or is this only temporary?
> };
>
> -static struct generic_pm_domain ux500_pm_domain_varm = {
> - .name = "VARM",
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_varm = {
> + .genpd = {
> + .name = "VARM",
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
>
> -static struct generic_pm_domain ux500_pm_domain_vmodem = {
> - .name = "VMODEM",
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_vmodem = {
> + .genpd = {
> + .name = "VMODEM",
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
>
> -static struct generic_pm_domain ux500_pm_domain_vpll = {
> - .name = "VPLL", /* 1.8 V */
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_vpll = {
> + .genpd = {
> + .name = "VPLL", /* 1.8 V */
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
>
> /*
> * CHECKME: as these are used directly by peripherals as regulators,
> * perhaps they should stay in the regulator subsystem?
> */
> -static struct generic_pm_domain ux500_pm_domain_vsmps1 = {
> - .name = "VSMPS1", /* Also called VIO (1.2V) */
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_vsmps1 = {
> + .genpd = {
> + .name = "VSMPS1", /* Also called VIO (1.2V) */
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
>
> -static struct generic_pm_domain ux500_pm_domain_vsmps2 = {
> - .name = "VSMPS2", /* Also called VIO (1.8V) */
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_vsmps2 = {
> + .genpd = {
> + .name = "VSMPS2", /* Also called VIO (1.8V) */
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
>
> -static struct generic_pm_domain ux500_pm_domain_vsmps3 = {
> - .name = "VSMPS3",
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_vsmps3 = {
> + .genpd = {
> + .name = "VSMPS3",
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
>
> -static struct generic_pm_domain ux500_pm_domain_vrf1 = {
> - .name = "VRF1",
> - .power_off = pd_power_off,
> - .power_on = pd_power_on,
> +static struct dbx500_powerdomain_info ux500_pm_domain_vrf1 = {
> + .genpd = {
> + .name = "VRF1",
> + .power_off = pd_power_off,
> + .power_on = pd_power_on,
> + },
> + .epod_id = UX500_EPOD_NONE,
> };
[...]
Kind regards
Uffe
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema
2026-09-20 22:48 ` [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema Linus Walleij
@ 2026-09-28 5:37 ` Krzysztof Kozlowski
0 siblings, 0 replies; 35+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-28 5:37 UTC (permalink / raw)
To: Linus Walleij
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Mark Brown, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, Vinod Koul, Frank Li, Lee Jones,
linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine
On Mon, Sep 21, 2026 at 12:48:07AM +0200, Linus Walleij wrote:
> +description:
> + The UX500 power domain controller gates power to one or more peripherals on
> + the SoC. Domain specifiers use one cell containing one of the DOMAIN_*
> + indexes defined in dt-bindings/arm/ux500_pm_domains.h.
Use rather full path, so include/dt-bindings/arm/ux500_pm_domains.h
> +
> +allOf:
> + - $ref: power-domain.yaml#
> +
> +properties:
> + compatible:
> + const: stericsson,ux500-pm-domains
> +
> + '#power-domain-cells':
> + const: 1
> +
> +required:
> + - compatible
> + - '#power-domain-cells'
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/arm/ux500_pm_domains.h>
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> + pm_domains: power-controller {
> + compatible = "stericsson,ux500-pm-domains";
> + #power-domain-cells = <1>;
> + };
> +
> + mmc@80126000 {
> + compatible = "arm,pl18x", "arm,primecell";
> + reg = <0x80126000 0x1000>;
> + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
> + power-domains = <&pm_domains DOMAIN_VAPE>;
> + };
Please drop the consumer from the example (thus also arm-gic header).
With these:
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM
2026-09-24 13:26 ` Ulf Hansson
@ 2026-09-30 20:15 ` Frank Li
2026-10-06 13:21 ` Vinod Koul
1 sibling, 0 replies; 35+ messages in thread
From: Frank Li @ 2026-09-30 20:15 UTC (permalink / raw)
To: Ulf Hansson
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Ulf Hansson, Mark Brown, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Vinod Koul,
Frank Li, Lee Jones, linux-arm-kernel, devicetree, linux-pm,
dri-devel, dmaengine
On Thu, Sep 24, 2026 at 03:26:47PM +0200, Ulf Hansson wrote:
> On Mon, Sep 21, 2026 at 12:49 AM Linus Walleij <linusw@kernel.org> wrote:
> >
> > Replace the LCLA ESRAM regulator with runtime PM.
> >
> > Use the SRAM device that owns the ESRAM34 power domain.
> >
> > Hold that domain while DMA transfers are active. The DMA controller is
> > runtime PM IRQ-safe, so keep taking explicit LCLA runtime PM references
> > from the descriptor preparation path instead of relying on a runtime PM
> > device link from the atomic transfer path.
>
> A bit of an orthogonal problem, but related to the above. The irqsafe
> thing have been discussed in the past for DMA controller drivers.
>
> Would it possible to get rid of the irqsafe configuration for the dma
> controller device, altogether?
>
> I don't recall exactly, but not the entire consumer DMA API is allowed
> to be called in atomic context, but perhaps that is not sufficient to
> allow us to drop the irqsafe configuration for the DMA controller
> device?
>
> If not, I wonder if the consumer of the DMA (like an mmc controller)
> should be assigned as a consumer device (using device links and
> DL_FLAG_PM_RUNTIME) of the DMA controller device. In this way, the
> consumer (mmc) would be able to control the supplier (DMA) through the
> device link directly using runtime PM.
Yes, I support this method.
there are someworks. welcome to join discussion to make it move forward.
https://lore.kernel.org/dmaengine/aNVufDmHjLRauKYo@lizhi-Precision-Tower-5810/
https://lore.kernel.org/dmaengine/20250903-v6-16-topic-sdma-v1-9-ac7bab629e8b@pengutronix.de/
Frank
> This could potentially avoid
> the requirement of having to use irqsafe for the DMA controller
> device. Maybe someone already tried this?
>
> If the irqsafe configuration can be dropped, in some way or the other,
> this patch could become less intrusive, as all that would be needed is
> to create a device link to sram device using DL_FLAG_PM_RUNTIME.
>
> Kind regards
> Uffe
>
> >
> > Add a stateless device link so system PM keeps the DMA controller ordered
> > after the LCLA SRAM supplier.
> >
> > Suggested-by: Frank Li <Frank.li@oss.nxp.com>
> > Assisted-by: LLM
> > Signed-off-by: Linus Walleij <linusw@kernel.org>
> > ---
> > drivers/dma/ste_dma40.c | 130 ++++++++++++++++++++++++++++++++----------------
> > 1 file changed, 88 insertions(+), 42 deletions(-)
> >
> > diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
> > index eda3f91741ed..2841af5b160b 100644
> > --- a/drivers/dma/ste_dma40.c
> > +++ b/drivers/dma/ste_dma40.c
> > @@ -21,8 +21,8 @@
> > #include <linux/of.h>
> > #include <linux/of_address.h>
> > #include <linux/of_dma.h>
> > +#include <linux/of_platform.h>
> > #include <linux/amba/bus.h>
> > -#include <linux/regulator/consumer.h>
> >
> > #include "dmaengine.h"
> > #include "ste_dma40.h"
> > @@ -383,6 +383,7 @@ struct d40_lli_pool {
> > * @node: List entry.
> > * @is_in_client_list: true if the client owns this descriptor.
> > * @cyclic: true if this is a cyclic job
> > + * @lcla_pm_active: LCLA SRAM power domain is held for this descriptor.
> > *
> > * This descriptor is used for both logical and physical transfers.
> > */
> > @@ -402,6 +403,7 @@ struct d40_desc {
> >
> > bool is_in_client_list;
> > bool cyclic;
> > + bool lcla_pm_active;
> > };
> >
> > /**
> > @@ -571,7 +573,8 @@ struct d40_gen_dmac {
> > * to phy_chans entries.
> > * @plat_data: Pointer to provided platform_data which is the driver
> > * configuration.
> > - * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
> > + * @lcla_dev: SRAM device for the ESRAM bank used by LCLA.
> > + * @lcla_link: Device link to keep system PM ordered against LCLA.
> > * @phy_res: Vector containing all physical channels.
> > * @lcla_pool: lcla pool settings and data.
> > * @lcpa_base: The virtual mapped address of LCPA.
> > @@ -606,7 +609,8 @@ struct d40_base {
> > struct d40_chan **lookup_log_chans;
> > struct d40_chan **lookup_phy_chans;
> > struct stedma40_platform_data *plat_data;
> > - struct regulator *lcpa_regulator;
> > + struct device *lcla_dev;
> > + struct device_link *lcla_link;
> > /* Physical half channels */
> > struct d40_phy_res *phy_res;
> > struct d40_lcla_pool lcla_pool;
> > @@ -628,6 +632,36 @@ static struct device *chan2dev(struct d40_chan *d40c)
> > return &d40c->chan.dev->device;
> > }
> >
> > +static void d40_transfer_runtime_get(struct d40_base *base)
> > +{
> > + pm_runtime_get_sync(base->dev);
> > +}
> > +
> > +static int d40_lcla_runtime_get(struct d40_base *base)
> > +{
> > + if (!base->lcla_dev)
> > + return 0;
> > +
> > + return pm_runtime_resume_and_get(base->lcla_dev);
> > +}
> > +
> > +static void d40_desc_lcla_runtime_put(struct d40_chan *d40c,
> > + struct d40_desc *d40d)
> > +{
> > + struct d40_base *base = d40c->base;
> > +
> > + if (!d40d->lcla_pm_active)
> > + return;
> > +
> > + d40d->lcla_pm_active = false;
> > + pm_runtime_put(base->lcla_dev);
> > +}
> > +
> > +static void d40_transfer_runtime_put(struct d40_base *base)
> > +{
> > + pm_runtime_put_autosuspend(base->dev);
> > +}
> > +
> > static bool chan_is_physical(struct d40_chan *chan)
> > {
> > return chan->log_num == D40_PHY_CHAN;
> > @@ -818,6 +852,7 @@ static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d)
> >
> > d40_pool_lli_free(d40c, d40d);
> > d40_lcla_free_all(d40c, d40d);
> > + d40_desc_lcla_runtime_put(d40c, d40d);
> > kmem_cache_free(d40c->base->desc_slab, d40d);
> > }
> >
> > @@ -1516,7 +1551,7 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
> > if (d40d != NULL) {
> > if (!d40c->busy) {
> > d40c->busy = true;
> > - pm_runtime_get_sync(d40c->base->dev);
> > + d40_transfer_runtime_get(d40c->base);
> > }
> >
> > /* Remove from queue */
> > @@ -1535,6 +1570,7 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
> > d40_desc_remove(d40d);
> > d40_desc_free(d40c, d40d);
> > d40c->busy = false;
> > + d40_transfer_runtime_put(d40c->base);
> > return ERR_PTR(err);
> > }
> > }
> > @@ -1583,7 +1619,7 @@ static void dma_tc_handle(struct d40_chan *d40c)
> > if (d40_queue_start(d40c) == NULL) {
> > d40c->busy = false;
> >
> > - pm_runtime_put_autosuspend(d40c->base->dev);
> > + d40_transfer_runtime_put(d40c->base);
> > }
> >
> > d40_desc_remove(d40d);
> > @@ -1637,6 +1673,7 @@ static void dma_tasklet(struct tasklet_struct *t)
> > } else if (!d40d->is_in_client_list) {
> > d40_desc_remove(d40d);
> > d40_lcla_free_all(d40c, d40d);
> > + d40_desc_lcla_runtime_put(d40c, d40d);
> > list_add_tail(&d40d->node, &d40c->client);
> > d40d->is_in_client_list = true;
> > }
> > @@ -2067,7 +2104,7 @@ static int d40_free_dma(struct d40_chan *d40c)
> > d40c->base->lookup_phy_chans[phy->num] = NULL;
> >
> > if (d40c->busy)
> > - pm_runtime_put_autosuspend(d40c->base->dev);
> > + d40_transfer_runtime_put(d40c->base);
> >
> > d40c->busy = false;
> > d40c->phy_chan = NULL;
> > @@ -2246,6 +2283,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
> > dma_addr_t dst_dev_addr;
> > struct d40_desc *desc;
> > unsigned long flags;
> > + bool got_lcla_pm = false;
> > int ret;
> >
> > if (!chan->phy_chan) {
> > @@ -2255,11 +2293,20 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
> >
> > d40_set_runtime_config_write(dchan, &chan->slave_config, direction);
> >
> > + ret = d40_lcla_runtime_get(chan->base);
> > + if (ret) {
> > + chan_err(chan, "Failed to enable LCLA power domain\n");
> > + return NULL;
> > + }
> > + got_lcla_pm = !!chan->base->lcla_dev;
> > +
> > spin_lock_irqsave(&chan->lock, flags);
> >
> > desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
> > if (desc == NULL)
> > goto unlock;
> > + desc->lcla_pm_active = got_lcla_pm;
> > + got_lcla_pm = false;
> >
> > if (sg_next(&sg_src[sg_len - 1]) == sg_src)
> > desc->cyclic = true;
> > @@ -2297,6 +2344,8 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
> > d40_desc_free(chan, desc);
> > unlock:
> > spin_unlock_irqrestore(&chan->lock, flags);
> > + if (got_lcla_pm)
> > + pm_runtime_put(chan->base->lcla_dev);
> > return NULL;
> > }
> >
> > @@ -2628,7 +2677,7 @@ static int d40_terminate_all(struct dma_chan *chan)
> > d40_term_all(d40c);
> > pm_runtime_put_autosuspend(d40c->base->dev);
> > if (d40c->busy)
> > - pm_runtime_put_autosuspend(d40c->base->dev);
> > + d40_transfer_runtime_put(d40c->base);
> > d40c->busy = false;
> >
> > spin_unlock_irqrestore(&d40c->lock, flags);
> > @@ -2931,29 +2980,11 @@ static int __init d40_dmaengine_init(struct d40_base *base,
> > #ifdef CONFIG_PM_SLEEP
> > static int dma40_suspend(struct device *dev)
> > {
> > - struct d40_base *base = dev_get_drvdata(dev);
> > - int ret;
> > -
> > - ret = pm_runtime_force_suspend(dev);
> > - if (ret)
> > - return ret;
> > -
> > - if (base->lcpa_regulator)
> > - ret = regulator_disable(base->lcpa_regulator);
> > - return ret;
> > + return pm_runtime_force_suspend(dev);
> > }
> >
> > static int dma40_resume(struct device *dev)
> > {
> > - struct d40_base *base = dev_get_drvdata(dev);
> > - int ret = 0;
> > -
> > - if (base->lcpa_regulator) {
> > - ret = regulator_enable(base->lcpa_regulator);
> > - if (ret)
> > - return ret;
> > - }
> > -
> > return pm_runtime_force_resume(dev);
> > }
> > #endif
> > @@ -3509,7 +3540,10 @@ static int __init d40_probe(struct platform_device *pdev)
> > struct device *dev = &pdev->dev;
> > struct device_node *np = pdev->dev.of_node;
> > struct device_node *np_lcpa;
> > + struct device_node *np_lcla;
> > + struct device_node *np_lcla_parent;
> > struct d40_base *base;
> > + struct platform_device *lcla_pdev;
> > struct resource *res;
> > struct resource res_lcpa;
> > int num_reserved_chans;
> > @@ -3610,21 +3644,32 @@ static int __init d40_probe(struct platform_device *pdev)
> > irq_requested = true;
> >
> > if (base->plat_data->use_esram_lcla) {
> > + np_lcla = of_parse_phandle(np, "sram", 1);
> > + if (!np_lcla) {
> > + dev_err(dev, "no LCLA SRAM node\n");
> > + ret = -EINVAL;
> > + goto destroy_cache;
> > + }
> >
> > - base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
> > - if (IS_ERR(base->lcpa_regulator)) {
> > - d40_err(dev, "Failed to get lcpa_regulator\n");
> > - ret = PTR_ERR(base->lcpa_regulator);
> > - base->lcpa_regulator = NULL;
> > + np_lcla_parent = of_get_parent(np_lcla);
> > + of_node_put(np_lcla);
> > + if (!np_lcla_parent) {
> > + dev_err(dev, "no LCLA SRAM parent node\n");
> > + ret = -EINVAL;
> > goto destroy_cache;
> > }
> >
> > - ret = regulator_enable(base->lcpa_regulator);
> > - if (ret) {
> > - d40_err(dev,
> > - "Failed to enable lcpa_regulator\n");
> > - regulator_put(base->lcpa_regulator);
> > - base->lcpa_regulator = NULL;
> > + lcla_pdev = of_find_device_by_node(np_lcla_parent);
> > + of_node_put(np_lcla_parent);
> > + if (!lcla_pdev) {
> > + ret = -EPROBE_DEFER;
> > + goto destroy_cache;
> > + }
> > + base->lcla_dev = &lcla_pdev->dev;
> > + base->lcla_link = device_link_add(dev, base->lcla_dev,
> > + DL_FLAG_STATELESS);
> > + if (!base->lcla_link) {
> > + ret = -ENODEV;
> > goto destroy_cache;
> > }
> > }
> > @@ -3663,16 +3708,17 @@ static int __init d40_probe(struct platform_device *pdev)
> > SZ_1K * base->num_phy_chans,
> > DMA_TO_DEVICE);
> >
> > - if (!base->lcla_pool.base_unaligned && base->lcla_pool.base)
> > + if (!base->lcla_pool.base_unaligned && base->lcla_pool.base &&
> > + base->lcla_pool.pages)
> > free_pages((unsigned long)base->lcla_pool.base,
> > base->lcla_pool.pages);
> >
> > kfree(base->lcla_pool.base_unaligned);
> >
> > - if (base->lcpa_regulator) {
> > - regulator_disable(base->lcpa_regulator);
> > - regulator_put(base->lcpa_regulator);
> > - }
> > + if (base->lcla_link)
> > + device_link_del(base->lcla_link);
> > + if (base->lcla_dev)
> > + put_device(base->lcla_dev);
> > if (irq_requested)
> > free_irq(base->irq, base);
> > if (runtime_pm_enabled)
> >
> > --
> > 2.55.0
> >
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
` (17 preceding siblings ...)
2026-09-20 22:48 ` [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators Linus Walleij
@ 2026-10-06 10:30 ` Linus Walleij
18 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2026-10-06 10:30 UTC (permalink / raw)
To: Ulf Hansson
Cc: linux-arm-kernel, devicetree, linux-pm, dri-devel, dmaengine,
Krzysztof Kozlowski, Krzysztof Kozlowski, Frank Li, Frank Li,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Mark Brown,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Frank Li,
Lee Jones
Hi Ulf,
On Mon, Sep 21, 2026 at 12:48 AM Linus Walleij <linusw@kernel.org> wrote:
> This series pays off technical debt from the beginning of the device
> tree for ARM initiative in the early 2010s.
I have so many fixes series that need to land for v7.4 that this is
mostly targeted at v7.4 at this point.
However:
> Linus Walleij (18):
> dt-bindings: power: Convert Ux500 PM domains to schema
> dt-bindings: arm: ux500: Drop NR_DOMAINS
> dt-bindings: arm: Add the actual power domains on U8500
What do you think about applying these three patches to the
PM domain tree as a starter for v7.4 if it's not too late?
They are reviewed by binding maintainers and should be
uncontroversial and will make it possible to avoid trouble when
merging more stuff later.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM
2026-09-24 13:26 ` Ulf Hansson
2026-09-30 20:15 ` Frank Li
@ 2026-10-06 13:21 ` Vinod Koul
1 sibling, 0 replies; 35+ messages in thread
From: Vinod Koul @ 2026-10-06 13:21 UTC (permalink / raw)
To: Ulf Hansson
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Ulf Hansson, Mark Brown, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Frank Li,
Lee Jones, linux-arm-kernel, devicetree, linux-pm, dri-devel,
dmaengine, Frank Li
On 24-09-26, 15:26, Ulf Hansson wrote:
> On Mon, Sep 21, 2026 at 12:49 AM Linus Walleij <linusw@kernel.org> wrote:
> >
> > Replace the LCLA ESRAM regulator with runtime PM.
> >
> > Use the SRAM device that owns the ESRAM34 power domain.
> >
> > Hold that domain while DMA transfers are active. The DMA controller is
> > runtime PM IRQ-safe, so keep taking explicit LCLA runtime PM references
> > from the descriptor preparation path instead of relying on a runtime PM
> > device link from the atomic transfer path.
>
> A bit of an orthogonal problem, but related to the above. The irqsafe
> thing have been discussed in the past for DMA controller drivers.
>
> Would it possible to get rid of the irqsafe configuration for the dma
> controller device, altogether?
>
> I don't recall exactly, but not the entire consumer DMA API is allowed
> to be called in atomic context, but perhaps that is not sufficient to
> allow us to drop the irqsafe configuration for the DMA controller
> device?
>
> If not, I wonder if the consumer of the DMA (like an mmc controller)
> should be assigned as a consumer device (using device links and
> DL_FLAG_PM_RUNTIME) of the DMA controller device. In this way, the
> consumer (mmc) would be able to control the supplier (DMA) through the
> device link directly using runtime PM. This could potentially avoid
> the requirement of having to use irqsafe for the DMA controller
> device. Maybe someone already tried this?
>
> If the irqsafe configuration can be dropped, in some way or the other,
> this patch could become less intrusive, as all that would be needed is
> to create a device link to sram device using DL_FLAG_PM_RUNTIME.
That is a consequence of dmaengine work running in tasklet and thus
softirq mode. The dmaengine tasks need to run with a higher priority to
enable higher dmaengine throughput. We have plans to move to WQ_BH [1], but
I think that runs in softirq mode as well...
[1]: cover.1786384168.git.allen.lkml@gmail.com
--
~Vinod
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 05/18] dt-bindings: display: ste,mcde: Allow power domains
2026-09-20 22:48 ` [PATCH v3 05/18] dt-bindings: display: ste,mcde: Allow power domains Linus Walleij
@ 2026-10-08 17:41 ` Rob Herring
0 siblings, 0 replies; 35+ messages in thread
From: Rob Herring @ 2026-10-08 17:41 UTC (permalink / raw)
To: Linus Walleij
Cc: Krzysztof Kozlowski, Conor Dooley, Ulf Hansson, Mark Brown,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Vinod Koul, Frank Li, Lee Jones, linux-arm-kernel,
devicetree, linux-pm, dri-devel, dmaengine, Krzysztof Kozlowski
On Sun, Sep 20, 2026 at 5:48 PM Linus Walleij <linusw@kernel.org> wrote:
>
> Document the MCDE power domain.
>
> Keep the legacy EPOD regulator binding unchanged for now.
>
> Assisted-by: LLM
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> Documentation/devicetree/bindings/display/ste,mcde.yaml | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/ste,mcde.yaml b/Documentation/devicetree/bindings/display/ste,mcde.yaml
> index 7a12d0b817e6..05e7e4ebc882 100644
> --- a/Documentation/devicetree/bindings/display/ste,mcde.yaml
> +++ b/Documentation/devicetree/bindings/display/ste,mcde.yaml
> @@ -35,6 +35,9 @@ properties:
> resets:
> maxItems: 1
>
> + power-domains:
> + maxItems: 1
> +
> epod-supply:
> description: a phandle to the EPOD regulator
>
> @@ -109,6 +112,7 @@ examples:
> - |
> #include <dt-bindings/interrupt-controller/irq.h>
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/arm/ux500_pm_domains.h>
> #include <dt-bindings/mfd/dbx500-prcmu.h>
> #include <dt-bindings/gpio/gpio.h>
>
> @@ -116,6 +120,7 @@ examples:
> compatible = "ste,mcde";
> reg = <0xa0350000 0x1000>;
> interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
> + power-domains = <&pm_domains DOMAIN_B2R2_MCDE>;
This patch is in next, but the define is not breaking dt_binding_check.
Rob
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2026-10-08 17:41 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-20 22:48 [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
2026-09-20 22:48 ` [PATCH v3 01/18] dt-bindings: power: Convert Ux500 PM domains to schema Linus Walleij
2026-09-28 5:37 ` Krzysztof Kozlowski
2026-09-20 22:48 ` [PATCH v3 02/18] dt-bindings: arm: ux500: Drop NR_DOMAINS Linus Walleij
2026-09-20 22:48 ` [PATCH v3 03/18] dt-bindings: arm: Add the actual power domains on U8500 Linus Walleij
2026-09-20 22:48 ` [PATCH v3 04/18] dt-bindings: mfd: db8500-prcmu: Deprecate EPOD regulators Linus Walleij
2026-09-20 22:48 ` [PATCH v3 05/18] dt-bindings: display: ste,mcde: Allow power domains Linus Walleij
2026-10-08 17:41 ` Rob Herring
2026-09-20 22:48 ` [PATCH v3 06/18] pmdomain: st: ux500: Implement more " Linus Walleij
2026-09-20 22:48 ` [PATCH v3 07/18] ARM: dts: ux500: Rename power domains node Linus Walleij
2026-09-20 22:48 ` [PATCH v3 08/18] dt-bindings: clock: stericsson,u8500-clks: Allow power domains Linus Walleij
2026-09-20 22:48 ` [PATCH v3 09/18] dt-bindings: timer: arm,twd-timer: " Linus Walleij
2026-09-20 22:48 ` [PATCH v3 10/18] dt-bindings: watchdog: arm,twd-wdt: " Linus Walleij
2026-09-20 22:48 ` [PATCH v3 11/18] ARM: dts: ux500: Add " Linus Walleij
2026-09-20 23:04 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 12/18] pmdomain: st: ux500: Control DB8500 EPODs Linus Walleij
2026-09-20 23:04 ` sashiko-bot
2026-09-24 13:44 ` Ulf Hansson
2026-09-20 22:48 ` [PATCH v3 13/18] drm/mcde: Use power domain for display power Linus Walleij
2026-09-20 22:58 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 14/18] misc: sram: Enable runtime PM Linus Walleij
2026-09-20 23:02 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 15/18] dmaengine: ste_dma40: Use power domain for LCLA SRAM Linus Walleij
2026-09-20 23:03 ` sashiko-bot
2026-09-21 16:36 ` Frank Li
2026-09-24 13:26 ` Ulf Hansson
2026-09-30 20:15 ` Frank Li
2026-10-06 13:21 ` Vinod Koul
2026-09-20 22:48 ` [PATCH v3 16/18] mfd/regulator: db8500-prcmu: Remove EPOD regulators Linus Walleij
2026-09-20 22:48 ` [PATCH v3 17/18] dt-bindings: display: ste,mcde: Deprecate EPOD supply Linus Walleij
2026-09-20 23:00 ` sashiko-bot
2026-09-20 22:48 ` [PATCH v3 18/18] ARM: dts: ux500: Remove DB8500 EPOD regulators Linus Walleij
2026-09-20 23:05 ` sashiko-bot
2026-09-21 7:06 ` Linus Walleij
2026-10-06 10:30 ` [PATCH v3 00/18] pmdomain: st: ux500: Implement ux500 power domains Linus Walleij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox