Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 11/11] ARM: dts: ux500: Remove DB8500 EPOD regulators
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

Delete the obsolete DB8500 EPOD regulator nodes.

Keep the VAPE and VSMPS2 compatibility regulators.

Assisted-by: Codex:gpt-5-5
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 arch/arm/boot/dts/st/ste-dbx5x0.dtsi | 92 ------------------------------------
 1 file changed, 92 deletions(-)

diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
index fd6a075e4c93..18727953a863 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
@@ -663,97 +663,17 @@ 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";
 
-				// DB8500_REGULATOR_VAPE
 				db8500_vape_reg: db8500_vape {
 					regulator-always-on;
 					power-domains = <&pm_domains DOMAIN_VAPE>;
 				};
 
-				// 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 {
 					power-domains = <&pm_domains DOMAIN_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 {
-				};
 			};
 		};
 
@@ -1111,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 */
@@ -1130,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 */
@@ -1150,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 */
@@ -1170,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 */
@@ -1215,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 {
@@ -1224,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.54.0



^ permalink raw reply related

* [PATCH 10/11] regulator: db8500: Add power domain regulators
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

Add a DB8500 regulator driver for the VAPE and VSMPS2 compatibility nodes.

Back the regulator enable state with the corresponding power domains.

This is done for off-chip consumers: the corresponding voltage rails are
routed out so they are used for powering different peripherals using
these voltages as supplies.

Assisted-by: Codex:gpt-5-5
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 arch/arm/boot/dts/st/ste-dbx5x0.dtsi |   2 +
 drivers/regulator/Kconfig            |  11 ++
 drivers/regulator/Makefile           |   1 +
 drivers/regulator/db8500-regulator.c | 221 +++++++++++++++++++++++++++++++++++
 4 files changed, 235 insertions(+)

diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
index a6fef302c994..fd6a075e4c93 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
@@ -673,6 +673,7 @@ db8500-prcmu-regulators {
 				// DB8500_REGULATOR_VAPE
 				db8500_vape_reg: db8500_vape {
 					regulator-always-on;
+					power-domains = <&pm_domains DOMAIN_VAPE>;
 				};
 
 				// DB8500_REGULATOR_VARM
@@ -693,6 +694,7 @@ db8500_vsmps1_reg: db8500_vsmps1 {
 
 				// DB8500_REGULATOR_VSMPS2
 				db8500_vsmps2_reg: db8500_vsmps2 {
+					power-domains = <&pm_domains DOMAIN_VSMPS2>;
 				};
 
 				// DB8500_REGULATOR_VSMPS3
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index acc698c17bd2..8db63d8d3fa4 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -397,6 +397,17 @@ config REGULATOR_DA9210
 	  converter 12A DC-DC Buck controlled through an I2C
 	  interface.
 
+config REGULATOR_DB8500
+	bool "ST-Ericsson DB8500 power domain regulators"
+	depends on MFD_DB8500_PRCMU && UX500_PM_DOMAIN && OF
+	default ARCH_U8500
+	help
+	  This driver supports the DB8500 VAPE and VSMPS2 regulators.
+	  These supplies are represented by generic power domains in hardware,
+	  but the same voltage rails are routed out of the chip and used to
+	  supply external peripherals.
+	  Enable this driver to bridge those regulator consumers to genpd.
+
 config REGULATOR_DA9211
 	tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9223/DA9214/DA9224/DA9215/DA9225 regulator"
 	depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 96a02063b843..f4109549525a 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,6 +48,7 @@ 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_DB8500) += db8500-regulator.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-regulator.c b/drivers/regulator/db8500-regulator.c
new file mode 100644
index 000000000000..c5a9a1baaf8e
--- /dev/null
+++ b/drivers/regulator/db8500-regulator.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Linus Walleij <linusw@kernel.org>
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+
+struct db8500_regulator_info {
+	struct regulator_desc desc;
+	struct regulator_init_data init_data;
+	struct device pd_dev;
+	bool enabled;
+};
+
+struct db8500_regulator_match {
+	const char *name;
+	const char *supply_name;
+	const char *constraint_name;
+	int fixed_uV;
+	bool always_on;
+};
+
+static const struct db8500_regulator_match db8500_regulator_matches[] = {
+	{
+		.name = "db8500_vape",
+		.supply_name = "db8500-vape",
+		.constraint_name = "db8500-vape",
+		.always_on = true,
+	}, {
+		.name = "db8500_vsmps2",
+		.supply_name = "db8500-vsmps2",
+		.constraint_name = "db8500-vsmps2",
+		.fixed_uV = 1800000,
+	},
+};
+
+static int db8500_regulator_enable(struct regulator_dev *rdev)
+{
+	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = pm_runtime_resume_and_get(&info->pd_dev);
+	if (ret)
+		return ret;
+
+	info->enabled = true;
+	return 0;
+}
+
+static int db8500_regulator_disable(struct regulator_dev *rdev)
+{
+	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = pm_runtime_put_sync_suspend(&info->pd_dev);
+	if (ret)
+		return ret;
+
+	info->enabled = false;
+	return 0;
+}
+
+static int db8500_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return info->enabled;
+}
+
+static int db8500_regulator_get_voltage(struct regulator_dev *rdev)
+{
+	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+	if (!info->desc.fixed_uV)
+		return -EINVAL;
+
+	return info->desc.fixed_uV;
+}
+
+static const struct regulator_ops db8500_regulator_ops = {
+	.enable = db8500_regulator_enable,
+	.disable = db8500_regulator_disable,
+	.is_enabled = db8500_regulator_is_enabled,
+	.get_voltage = db8500_regulator_get_voltage,
+};
+
+static void db8500_regulator_release(struct device *dev)
+{
+}
+
+static void db8500_regulator_cleanup(void *data)
+{
+	struct db8500_regulator_info *info = data;
+
+	pm_runtime_disable(&info->pd_dev);
+	dev_pm_domain_detach(&info->pd_dev, true);
+	put_device(&info->pd_dev);
+}
+
+static const struct db8500_regulator_match *
+db8500_regulator_match(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(db8500_regulator_matches); i++) {
+		if (of_node_name_eq(np, db8500_regulator_matches[i].name))
+			return &db8500_regulator_matches[i];
+	}
+
+	return NULL;
+}
+
+static int db8500_regulator_register(struct platform_device *pdev,
+				     struct device_node *np)
+{
+	const struct db8500_regulator_match *match;
+	struct regulator_config config = { };
+	struct db8500_regulator_info *info;
+	struct of_phandle_args pd_args;
+	struct regulator_dev *rdev;
+	const char *cells = "#power-domain-cells";
+	int ret;
+
+	match = db8500_regulator_match(np);
+	if (!match)
+		return 0;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	device_initialize(&info->pd_dev);
+	info->pd_dev.parent = &pdev->dev;
+	info->pd_dev.of_node = np;
+	info->pd_dev.release = db8500_regulator_release;
+	ret = dev_set_name(&info->pd_dev, "%s-pd", match->name);
+	if (ret)
+		goto put_device;
+
+	ret = of_parse_phandle_with_args(np, "power-domains", cells, 0, &pd_args);
+	if (ret)
+		goto put_device;
+
+	ret = of_genpd_add_device(&pd_args, &info->pd_dev);
+	of_node_put(pd_args.np);
+	if (ret)
+		goto put_device;
+
+	pm_runtime_enable(&info->pd_dev);
+	ret = devm_add_action_or_reset(&pdev->dev, db8500_regulator_cleanup, info);
+	if (ret)
+		return ret;
+
+	info->init_data.constraints.name = match->constraint_name;
+	info->init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
+	info->init_data.constraints.always_on = match->always_on;
+
+	info->desc.name = match->supply_name;
+	info->desc.of_match = match->name;
+	info->desc.ops = &db8500_regulator_ops;
+	info->desc.type = REGULATOR_VOLTAGE;
+	info->desc.owner = THIS_MODULE;
+	info->desc.fixed_uV = match->fixed_uV;
+	config.dev = &pdev->dev;
+	config.init_data = &info->init_data;
+	config.driver_data = info;
+	config.of_node = np;
+	rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
+	if (IS_ERR(rdev))
+		return PTR_ERR(rdev);
+
+	return 0;
+
+put_device:
+	put_device(&info->pd_dev);
+	return ret;
+}
+
+static int db8500_regulator_probe(struct platform_device *pdev)
+{
+	struct device_node *np;
+	int ret;
+
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		ret = db8500_regulator_register(pdev, np);
+		if (ret) {
+			of_node_put(np);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id db8500_regulator_match_table[] = {
+	{ .compatible = "stericsson,db8500-prcmu-regulator" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, db8500_regulator_match_table);
+
+static struct platform_driver db8500_regulator_driver = {
+	.driver = {
+		.name = "db8500-prcmu-regulators",
+		.of_match_table = db8500_regulator_match_table,
+	},
+	.probe = db8500_regulator_probe,
+};
+module_platform_driver(db8500_regulator_driver);
+
+MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");
+MODULE_DESCRIPTION("DB8500 power-domain regulator driver");
+MODULE_LICENSE("GPL");

-- 
2.54.0



^ permalink raw reply related

* [PATCH 09/11] regulator: db8500-prcmu: Remove EPOD regulators
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

Remove the obsolete DB8500 PRCMU regulator drivers.

Drop the regulator build hooks now that EPODs are power domains.

Keep the MFD cell around because a later patch reuses it for a
small compatibility regulator driver.

Assisted-by: Codex:gpt-5-5
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, 1 insertion(+), 1001 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 21e68a382b11..f1eeab3e6270 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/dbx500-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,248 +2702,13 @@ 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,
+	MFD_CELL_OF("db8500-prcmu-regulators", NULL, NULL, 0, 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 35d1b191462c..acc698c17bd2 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 35639f3115fd..96a02063b843 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 1ec2e1348891..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/dbx500-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 = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
-			if (ret < 0)
-				return ret;
-		}
-		epod_ramret[epod_id] = true;
-	} else {
-		ret = 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 = 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 = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
-			if (ret < 0)
-				return ret;
-		} else {
-			ret = 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.54.0



^ permalink raw reply related

* [PATCH 08/11] dmaengine: ste_dma40: Use power domain for LCLA SRAM
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

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.

Assisted-by: Codex:gpt-5-5
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 drivers/dma/ste_dma40.c | 97 ++++++++++++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 42 deletions(-)

diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 9b803c0aec25..6ca67ec446dc 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"
@@ -571,7 +571,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_pm_enabled: Whether runtime PM was enabled for LCLA by this driver.
  * @phy_res: Vector containing all physical channels.
  * @lcla_pool: lcla pool settings and data.
  * @lcpa_base: The virtual mapped address of LCPA.
@@ -607,7 +608,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;
+	bool				  lcla_pm_enabled;
 	/* Physical half channels */
 	struct d40_phy_res		 *phy_res;
 	struct d40_lcla_pool		  lcla_pool;
@@ -628,6 +630,22 @@ static struct device *chan2dev(struct d40_chan *d40c)
 	return &d40c->chan.dev->device;
 }
 
+static void d40_transfer_runtime_get(struct d40_base *base)
+{
+	if (base->lcla_dev)
+		pm_runtime_get_sync(base->lcla_dev);
+
+	pm_runtime_get_sync(base->dev);
+}
+
+static void d40_transfer_runtime_put(struct d40_base *base)
+{
+	pm_runtime_put_autosuspend(base->dev);
+
+	if (base->lcla_dev)
+		pm_runtime_put_sync_suspend(base->lcla_dev);
+}
+
 static bool chan_is_physical(struct d40_chan *chan)
 {
 	return chan->log_num == D40_PHY_CHAN;
@@ -1516,7 +1534,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 */
@@ -1579,7 +1597,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);
@@ -2052,7 +2070,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;
@@ -2613,7 +2631,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);
@@ -2916,29 +2934,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
@@ -3492,7 +3492,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;
@@ -3590,23 +3593,32 @@ static int __init d40_probe(struct platform_device *pdev)
 	}
 
 	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;
+		if (!pm_runtime_enabled(base->lcla_dev)) {
+			pm_runtime_enable(base->lcla_dev);
+			base->lcla_pm_enabled = true;
+		}
 	}
 
 	writel_relaxed(D40_DREG_GCC_ENABLE_ALL, base->virtbase + D40_DREG_GCC);
@@ -3642,16 +3654,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_pm_enabled)
+		pm_runtime_disable(base->lcla_dev);
+	if (base->lcla_dev)
+		put_device(base->lcla_dev);
 	pm_runtime_disable(base->dev);
 
  report_failure:

-- 
2.54.0



^ permalink raw reply related

* [PATCH 07/11] drm/mcde: Use power domain for display power
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

Replace explicit EPOD regulator handling with runtime PM.

Use the MCDE power domain and drop the regulator dependency.

Assisted-by: Codex:gpt-5-5
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     | 63 +++++++++++--------------------------
 drivers/gpu/drm/mcde/mcde_dsi.c     |  1 -
 5 files changed, 25 insertions(+), 56 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 5f2c462bad7e..3f966cccda5a 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>
 
@@ -283,45 +283,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));
 
@@ -412,14 +392,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);
+	ret = pm_runtime_put_sync_suspend(dev);
 	if (ret) {
-		dev_err(dev, "can't disable EPOD regulator\n");
-		return ret;
+		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);
@@ -428,25 +409,18 @@ 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);
+clk_disable_pm_disabled:
+	pm_runtime_disable(dev);
 	return ret;
-
 }
 
 static void mcde_remove(struct platform_device *pdev)
@@ -456,8 +430,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 47d45897ed06..e09b2d4aca0c 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.54.0



^ permalink raw reply related

* [PATCH 06/11] pmdomain: st: ux500: Control DB8500 EPODs
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

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: Codex:gpt-5-5
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 arch/arm/mach-ux500/Kconfig               |   2 +-
 drivers/pmdomain/st/ste-ux500-pm-domain.c | 380 ++++++++++++++++++++++--------
 drivers/regulator/Kconfig                 |   1 +
 3 files changed, 282 insertions(+), 101 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 723001004690..1cd5b4985db0 100644
--- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
+++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
@@ -6,172 +6,315 @@
  *
  * Implements PM domains using the generic PM domain for ux500.
  */
+#include <linux/cleanup.h>
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/kernel.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/printk.h>
 #include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/pm_domain.h>
 
 #include <dt-bindings/arm/ux500_pm_domains.h>
 
-static int pd_power_off(struct generic_pm_domain *domain)
+#define UX500_EPOD_NONE		NUM_EPOD_ID
+
+/**
+ * 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)
+ * @exclude_from_power_state: exclude domain from power state count
+ */
+struct dbx500_powerdomain_info {
+	struct generic_pm_domain genpd;
+	u16 epod_id;
+	bool is_ramret;
+	bool exclude_from_power_state;
+};
+
+static DEFINE_MUTEX(ux500_pd_lock);
+static int power_state_active_cnt;
+static bool epod_on[NUM_EPOD_ID];
+static bool epod_ramret[NUM_EPOD_ID];
+
+static void power_state_active_enable(void)
+{
+	power_state_active_cnt++;
+}
+
+static int power_state_active_disable(void)
 {
-	/*
-	 * 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.
-	 */
+	if (power_state_active_cnt <= 0) {
+		pr_err("power state: unbalanced enable/disable calls\n");
+		return -EINVAL;
+	}
+
+	power_state_active_cnt--;
 	return 0;
 }
 
-static int pd_power_on(struct generic_pm_domain *domain)
+static int enable_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 = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+			if (ret < 0)
+				return ret;
+		}
+		epod_ramret[epod_id] = true;
+	} else {
+		ret = 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 = 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 = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+			if (ret < 0)
+				return ret;
+		} else {
+			ret = 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);
+	else if (!info->exclude_from_power_state)
+		ret = power_state_active_disable();
+
+	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);
+	else if (!info->exclude_from_power_state)
+		power_state_active_enable();
+
+	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,
+	.exclude_from_power_state = true,
 };
 
-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_esram0_pwr, Vape_esram1_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[] = {
@@ -179,11 +322,44 @@ static const struct of_device_id ux500_pm_domain_matches[] = {
 	{ },
 };
 
+static int ux500_pm_domain_add_subdomain(struct generic_pm_domain *domain)
+{
+	return pm_genpd_add_subdomain(&ux500_pm_domain_vape.genpd, domain);
+}
+
+static int ux500_pm_domains_add_subdomains(void)
+{
+	int ret;
+
+	ret = ux500_pm_domain_add_subdomain(&ux500_pm_domain_sva_mmdsp.genpd);
+	if (ret)
+		return ret;
+
+	ret = ux500_pm_domain_add_subdomain(&ux500_pm_domain_sva_pipe.genpd);
+	if (ret)
+		return ret;
+
+	ret = ux500_pm_domain_add_subdomain(&ux500_pm_domain_sia_mmdsp.genpd);
+	if (ret)
+		return ret;
+
+	ret = ux500_pm_domain_add_subdomain(&ux500_pm_domain_sia_pipe.genpd);
+	if (ret)
+		return ret;
+
+	ret = ux500_pm_domain_add_subdomain(&ux500_pm_domain_sga.genpd);
+	if (ret)
+		return ret;
+
+	return ux500_pm_domain_add_subdomain(&ux500_pm_domain_b2r2_mcde.genpd);
+}
+
 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;
@@ -196,7 +372,11 @@ 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 = ux500_pm_domains_add_subdomains();
+	if (ret)
+		return ret;
 
 	of_genpd_add_provider_onecell(np, genpd_data);
 	return 0;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 87554ab92801..35d1b191462c 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.54.0



^ permalink raw reply related

* [PATCH 05/11] ARM: dts: ux500: Add power domains
From: Linus Walleij @ 2026-06-18  5:00 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, Linus Walleij
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

Add the actual power domains to all the SoC peripherals.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/boot/dts/st/ste-dbx5x0.dtsi | 58 ++++++++++++++++++++++++++++++------
 1 file changed, 49 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
index d76a65da7011..a6fef302c994 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi
@@ -154,6 +154,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 +163,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 +183,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 +199,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 +215,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 +251,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 +283,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 +298,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 +317,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 +331,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 +340,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>;
 		};
@@ -341,6 +348,7 @@ L2: cache-controller {
 		pmu {
 			compatible = "arm,cortex-a9-pmu";
 			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			power-domains = <&pm_domains DOMAIN_VARM>;
 		};
 
 		pm_domains: power-controller {
@@ -357,6 +365,7 @@ clocks {
 			reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
 			    <0x8000f000 0x1000>, <0xa03ff000 0x1000>,
 			    <0xa03cf000 0x1000>;
+			power-domains = <&pm_domains DOMAIN_VPLL>; /* CHECKME: correct domain? */
 
 			prcmu_clk: prcmu-clock {
 				#clock-cells = <1>;
@@ -393,7 +402,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 +411,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 +419,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 +445,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 +461,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 +477,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 +493,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 +509,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 +525,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 +541,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 +557,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 +573,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 +589,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 +633,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 +663,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 +958,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 +975,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 +992,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 +1109,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 +1128,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 +1148,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 +1168,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 +1212,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.54.0



^ permalink raw reply related

* [PATCH 04/11] ARM: dts: ux500: Rename power domains node
From: Linus Walleij @ 2026-06-18  5:00 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, Linus Walleij
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

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 <linus.walleij@linaro.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 0f87abeddc33..d76a65da7011 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.54.0



^ permalink raw reply related

* [PATCH 03/11] pmdomain: st: ux500: Implement more power domains
From: Linus Walleij @ 2026-06-18  5:00 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, Linus Walleij
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

This starts to implement the power domains that are just skeleton
implementations right now.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/pmdomain/st/ste-ux500-pm-domain.c | 125 +++++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 1 deletion(-)

diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
index 6896cb4a7b71..723001004690 100644
--- a/drivers/pmdomain/st/ste-ux500-pm-domain.c
+++ b/drivers/pmdomain/st/ste-ux500-pm-domain.c
@@ -41,14 +41,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_esram0_pwr, Vape_esram1_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.54.0



^ permalink raw reply related

* [PATCH 02/11] dt-bindings: Add the actual power domains on U8500
From: Linus Walleij @ 2026-06-18  5:00 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, Linus Walleij
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

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.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 include/dt-bindings/arm/ux500_pm_domains.h | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/include/dt-bindings/arm/ux500_pm_domains.h b/include/dt-bindings/arm/ux500_pm_domains.h
index 9bd764f0c9e6..1c168e59ac90 100644
--- a/include/dt-bindings/arm/ux500_pm_domains.h
+++ b/include/dt-bindings/arm/ux500_pm_domains.h
@@ -8,8 +8,23 @@
 #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
 
 /* Number of PM domains. */
-#define NR_DOMAINS		(DOMAIN_VAPE + 1)
+#define NR_DOMAINS		(DOMAIN_ESRAM_34 + 1)
 
 #endif

-- 
2.54.0



^ permalink raw reply related

* [PATCH 01/11] dt-bindings: power: Convert Ux500 PM domains to schema
From: Linus Walleij @ 2026-06-18  5:00 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
In-Reply-To: <20260618-ux500-power-domains-v7-1-v1-0-eb5e50b1a588@kernel.org>

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: Codex:gpt-5-5
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 .../devicetree/bindings/arm/ux500/power_domain.txt | 35 ----------------
 .../power/stericsson,ux500-pm-domains.yaml         | 46 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 3 files changed, 47 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..72c39c083efb
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/stericsson,ux500-pm-domains.yaml
@@ -0,0 +1,46 @@
+# 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>
+
+    pm_domains: power-controller {
+        compatible = "stericsson,ux500-pm-domains";
+        #power-domain-cells = <1>;
+    };
+
+    sdi0_per1@80126000 {
+        compatible = "arm,pl18x", "arm,primecell";
+        power-domains = <&pm_domains DOMAIN_VAPE>;
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index c8d4b913f26c..a984c4647cc7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3167,6 +3167,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.54.0



^ permalink raw reply related

* [PATCH 00/11] pmdomain: st: ux500: Implement ux500 power domains
From: Linus Walleij @ 2026-06-18  5:00 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, Linus Walleij

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 EPOS regulators.

- Modify the DMA40 DMA controller to use the power domain instead of
  the EPOD regulators.

- Delete the old EPOD regulators.

- Implement regulators activating the VANA and VSMPS2 power domains for the
  power domain voltage rails that are routed off-chip as external supplies,
  re-using the existing EPOD regulator bindings.

- Delete the references to the unused EPOD regulators from the device tree,
  keeping the references to VANA and VSMPS2.

This is a bit of brain transplant on the Ux500, and the series is not very
boot-bisectable.

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.3. 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.

Signed-off-by: Linus Walleij <linusw@kernel.org>
---
Linus Walleij (11):
      dt-bindings: power: Convert Ux500 PM domains to schema
      dt-bindings: Add the actual power domains on U8500
      pmdomain: st: ux500: Implement more power domains
      ARM: dts: ux500: Rename power domains node
      ARM: dts: ux500: Add power domains
      pmdomain: st: ux500: Control DB8500 EPODs
      drm/mcde: Use power domain for display power
      dmaengine: ste_dma40: Use power domain for LCLA SRAM
      regulator: db8500-prcmu: Remove EPOD regulators
      regulator: db8500: Add power domain regulators
      ARM: dts: ux500: Remove DB8500 EPOD regulators

 .../devicetree/bindings/arm/ux500/power_domain.txt |  35 --
 .../power/stericsson,ux500-pm-domains.yaml         |  46 ++
 MAINTAINERS                                        |   1 +
 arch/arm/boot/dts/st/ste-dbx5x0.dtsi               | 134 ++----
 arch/arm/mach-ux500/Kconfig                        |   2 +-
 drivers/dma/ste_dma40.c                            |  97 ++--
 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                    |  63 +--
 drivers/gpu/drm/mcde/mcde_dsi.c                    |   1 -
 drivers/mfd/db8500-prcmu.c                         | 239 +---------
 drivers/pmdomain/st/ste-ux500-pm-domain.c          | 353 ++++++++++++++-
 drivers/regulator/Kconfig                          |  22 +-
 drivers/regulator/Makefile                         |   3 +-
 drivers/regulator/db8500-prcmu.c                   | 501 ---------------------
 drivers/regulator/db8500-regulator.c               | 221 +++++++++
 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 --
 21 files changed, 748 insertions(+), 1252 deletions(-)
---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260618-ux500-power-domains-v7-1-3c9d095828c2

Best regards,
-- 
Linus Walleij <linusw@kernel.org>



^ permalink raw reply

* [PATCH 56/78] ASoC: codecs: tas2783: Use guard() for mutex locks
From: phucduc.bui @ 2026-06-18  4:54 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Cheng-Yi Chiang,
	Tzung-Bi Shih, Guenter Roeck, Benson Leung, David Rhodes,
	Richard Fitzgerald, povik+lin, Charles Keepax, Support Opensource,
	Nick Li, Herve Codina, Srinivas Kandagatla, Matthias Brugger,
	AngeloGioacchino Del Regno, Shenghao Ding, Kevin Lu, Baojun Xu,
	Sen Wang, Oder Chiou, Lars-Peter Clausen, nuno.sa, Steven Eckhoff,
	patches, chrome-platform, asahi, linux-arm-msm, linux-sound,
	linux-kernel, linux-arm-kernel, linux-mediatek, bui duc phuc
In-Reply-To: <20260617103235.449609-1-phucduc.bui@gmail.com>

From: bui duc phuc <phucduc.bui@gmail.com>

Clean up the code using guard() for mutex locks.
Merely code refactoring, and no behavior change.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 sound/soc/codecs/tas2783-sdw.c | 89 ++++++++++++++++------------------
 1 file changed, 43 insertions(+), 46 deletions(-)

diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index 7d70e7e3f24f..763663daf3e1 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -691,12 +691,12 @@ static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev)
 		return 0;
 	}
 
-	mutex_lock(&tas_dev->calib_lock);
-	ret = tas2783_validate_calibdata(tas_dev, tas_dev->cali_data.data,
-					 tas_dev->cali_data.read_sz);
-	if (!ret)
-		tas2783_set_calib_params_to_device(tas_dev, tmp_val);
-	mutex_unlock(&tas_dev->calib_lock);
+	scoped_guard(mutex, &tas_dev->calib_lock) {
+		ret = tas2783_validate_calibdata(tas_dev, tas_dev->cali_data.data,
+						 tas_dev->cali_data.read_sz);
+		if (!ret)
+			tas2783_set_calib_params_to_device(tas_dev, tmp_val);
+	}
 
 	return ret;
 }
@@ -764,27 +764,27 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
 		goto out;
 	}
 
-	mutex_lock(&tas_dev->pde_lock);
-	while (offset < (img_sz - FW_FL_HDR)) {
-		offset += tas_fw_get_next_file(&buf[offset], file);
-		dev_dbg(tas_dev->dev,
-			"v=%d, fid=%d, ver=%d, len=%d, daddr=0x%x, fw=%p",
-			file->vendor_id, file->file_id,
-			file->version, file->length,
-			file->dest_addr, file->fw_data);
-
-		ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
-				       file->dest_addr,
-				       file->length,
-				       file->fw_data);
-		if (ret < 0) {
-			dev_err(tas_dev->dev,
-				"FW download failed: %d", ret);
-			break;
+	scoped_guard(mutex, &tas_dev->pde_lock) {
+		while (offset < (img_sz - FW_FL_HDR)) {
+			offset += tas_fw_get_next_file(&buf[offset], file);
+			dev_dbg(tas_dev->dev,
+				"v=%d, fid=%d, ver=%d, len=%d, daddr=0x%x, fw=%p",
+				file->vendor_id, file->file_id,
+				file->version, file->length,
+				file->dest_addr, file->fw_data);
+
+			ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
+					       file->dest_addr,
+					       file->length,
+					       file->fw_data);
+			if (ret < 0) {
+				dev_err(tas_dev->dev,
+					"FW download failed: %d", ret);
+				break;
+			}
+			cur_file++;
 		}
-		cur_file++;
 	}
-	mutex_unlock(&tas_dev->pde_lock);
 
 	if (cur_file == 0) {
 		dev_err(tas_dev->dev, "fw with no files");
@@ -917,22 +917,22 @@ static s32 tas_sdw_hw_params(struct snd_pcm_substream *substream,
 		dev_err(tas_dev->dev,
 			"clear latch failed, err=%d", ret);
 
-	mutex_lock(&tas_dev->pde_lock);
-	/*
-	 * Sometimes, there is error returned during power on.
-	 * So added retry logic to ensure power on so that
-	 * port prepare succeeds
-	 */
-	do {
-		ret = regmap_write(tas_dev->regmap,
-				   SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23,
-						TAS2783_SDCA_CTL_REQ_POW_STATE, 0),
-						TAS2783_SDCA_POW_STATE_ON);
-		if (!ret)
-			break;
-		usleep_range(2000, 2200);
-	} while (retry--);
-	mutex_unlock(&tas_dev->pde_lock);
+	scoped_guard(mutex, &tas_dev->pde_lock) {
+		/*
+		 * Sometimes, there is error returned during power on.
+		 * So added retry logic to ensure power on so that
+		 * port prepare succeeds
+		 */
+		do {
+			ret = regmap_write(tas_dev->regmap,
+					   SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23,
+							TAS2783_SDCA_CTL_REQ_POW_STATE, 0),
+							TAS2783_SDCA_POW_STATE_ON);
+			if (!ret)
+				break;
+			usleep_range(2000, 2200);
+		} while (retry--);
+	}
 	if (ret)
 		return ret;
 
@@ -965,14 +965,11 @@ static s32 tas_sdw_pcm_hw_free(struct snd_pcm_substream *substream,
 
 	sdw_stream_remove_slave(tas_dev->sdw_peripheral, sdw_stream);
 
-	mutex_lock(&tas_dev->pde_lock);
-	ret = regmap_write(tas_dev->regmap,
+	guard(mutex)(&tas_dev->pde_lock);
+	return regmap_write(tas_dev->regmap,
 			   SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_PDE23,
 					TAS2783_SDCA_CTL_REQ_POW_STATE, 0),
 			   TAS2783_SDCA_POW_STATE_OFF);
-	mutex_unlock(&tas_dev->pde_lock);
-
-	return ret;
 }
 
 static const struct snd_soc_dai_ops tas_dai_ops = {
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH v6 00/20] dma-mapping: Use DMA_ATTR_CC_SHARED through direct, pool and swiotlb paths
From: Alexey Kardashevskiy @ 2026-06-18  4:44 UTC (permalink / raw)
  To: Jason Gunthorpe, Catalin Marinas
  Cc: Aneesh Kumar K.V (Arm), iommu, linux-arm-kernel, linux-kernel,
	linux-coco, Robin Murphy, Marek Szyprowski, Will Deacon,
	Marc Zyngier, Steven Price, Suzuki K Poulose, Jiri Pirko,
	Mostafa Saleh, Petr Tesarik, Dan Williams, Xu Yilun, linuxppc-dev,
	linux-s390, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Sven Schnelle, x86
In-Reply-To: <20260609144746.GL2764304@ziepe.ca>



On 10/6/26 00:47, Jason Gunthorpe wrote:
> On Tue, Jun 09, 2026 at 02:43:08PM +0100, Catalin Marinas wrote:
>> On Thu, Jun 04, 2026 at 02:09:39PM +0530, Aneesh Kumar K.V (Arm) wrote:
>>> This series propagates DMA_ATTR_CC_SHARED through the dma-direct,
>>> dma-pool, and swiotlb paths so that encrypted and decrypted DMA buffers
>>> are handled consistently.
>>>
>>> Today, the direct DMA path mostly relies on force_dma_unencrypted() for
>>> shared/decrypted buffer handling. This series consolidates the
>>> force_dma_unencrypted() checks in the top-level functions and ensures
>>> that the remaining DMA interfaces use DMA attributes to make the correct
>>> decisions.
>>
>> Please check Sashiko's reports, it has some good points:
>>
>> https://sashiko.dev/#/patchset/20260604083959.1265923-1-aneesh.kumar@kernel.org
>>
>> I think the main one is the swiotlb_tbl_map_single() changes which break
>> AMD SME host support. There cc_platform_has(CC_ATTR_MEM_ENCRYPT) is true
>> but force_dma_unencrypted() is false. Normally you'd not end up on this
>> path but you can have swiotlb=force.
> 
> IMHO that's an AMD issue, not with the design of this series..
> 
> The series is right, a device that is !force_dma_decrypted() must be
> considerd to be a trusted device and we must never place any DMA
> mappings for a trusted device into shared memory.


swiotlb=force forces swiotlb, not decryption.

> That AMD has done somethine insane:
> 
> bool force_dma_unencrypted(struct device *dev)
> {
> 	/*
> 	 * For SEV, all DMA must be to unencrypted addresses.
> 	 */
> 	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
> 		return true;
> 
> 	/*
> 	 * For SME, all DMA must be to unencrypted addresses if the
> 	 * device does not support DMA to addresses that include the
> 	 * encryption mask.
> 	 */
> 	if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)) {
> 		u64 dma_enc_mask = DMA_BIT_MASK(__ffs64(sme_me_mask));
> 		u64 dma_dev_mask = min_not_zero(dev->coherent_dma_mask,
> 						dev->bus_dma_limit);
> 
> 		if (dma_dev_mask <= dma_enc_mask)
> 			return true;
> 	}


So when I try "mem_encrypt=on iommu=pt swiotlb=force" with this patchset, it fails to boot. But it boots with a hack like this:

===
@@ -39,7 +41,7 @@ bool force_dma_unencrypted(struct device *dev)
                         return true;
         }
  
-       return false;
+       return swiotlb_force_bounce;
  }
===

Or we say "mem_encrypt=on iommu=pt swiotlb=force" combo is just weird and we won't be supporting which bit in this? Thanks,


> 
> Is an AMD issue. We already have an address mask limit system built
> into the DMA API, arch code should not be co-opting the CC mechanism
> to create a special pool for address limited devices.
> 
> The correct thing is to ensure the DMA API is checking any address
> limits on the actual true dma_addr_t, not on an intermediate like a
> phys_addr before it is adjusted with any C bit. Then it is a normal
> low address swiotlb bounce like any other.
> 
> I think we can ignore this Sashiko remark, in real systems the use of
> swiotlb for 64 bit devices is very rare. Though it would be good to
> remove this code from AMD...> 
> Jason

-- 
Alexey



^ permalink raw reply

* Re: [PATCH v5 2/8] media: v4l2-fwnode: Add common helper library for 1-to-1 subdev registration
From: Frank Li @ 2026-06-18  4:13 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Mauro Carvalho Chehab, Michael Riesch, Laurent Pinchart, Frank Li,
	Martin Kepplinger-Novakovic, Rui Miguel Silva, Purism Kernel Team,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-media, linux-kernel,
	imx, devicetree, linux-arm-kernel
In-Reply-To: <ajMhZP5YHuQdhc5M@kekkonen.localdomain>

On Thu, Jun 18, 2026 at 01:36:20AM +0300, Sakari Ailus wrote:
> Hi Frank,
>
> Thanks for the patch.

Thanks for you quick reply.

>
> On Wed, Jun 17, 2026 at 03:50:12PM -0400, Frank.Li@oss.nxp.com wrote:
> > From: Frank Li <Frank.Li@nxp.com>
> >
> > Many V4L2 subdev drivers implement the same registration and media pad
> > setup logic for simple pipelines consisting of a single sink pad and a
> > single source pad. As a result, the same boilerplate code is duplicated
> > across multiple drivers.
> >
> > Introduce a common helper library for 1-to-1 subdevs to encapsulate the
> > registration, media entity initialization, and cleanup paths. Drivers
> > can embed a struct v4l2_subdev_1to1 instance and use the provided helper
> > APIs instead of open-coding the setup sequence.
>
> I appreciate your efforts in trying to reduce the amount of code drivers
> need simply to get things done but I think there are a few issues with the
> approach taken in this patch:
>
> - The new helpers aren't generic enough, but require two pads; one sink,
>   one source.

It can cover many case already, there are many bridge type subdev. after
glace of all code, many CSI2RX is type device. It should one kind important
type/case, like sensors.

And I plan do 1 TO N replicator driver, which duplicate 1 sink pad to N
source pad (with/without register config), plus exist video-mux driver,

It think It can cover more than 80% cases.

> You could provide special helpers for just this case, but
>   right now it looks like that if there's something you need that the
>   helper assumes you don't, you can't use the helper at all. In other
>   words, more modularity would be nice.

We can add it later if need, which easy to replace 1to1 API, like I did
for sensor one.

>
> - The new helper should work with the existing types and not add new types
>   (struct v4l2_subdev_1to1).

May be save vep data into v4l2_subdev to avoid parse it every time. and
enhence media_entity_pads_init() to avoid refer caller data.

>
> - There should be a way to provide default V4L2 fwnode endpoint
>   configuration as well as to validate the obtained configuration.

Do you means remote_bustype_cap_mask information get from a callback?

>
> I don't have a good proposal to address the above but at least one way I
> can think of making error handling easier would be to use devm_() for
> teardown in more places we to today. That certainly does have its own
> issues though.

I tried it before, media and v4l2's clean up is not revised order of init.
Sorry, I can't find original thread. I remember laurnet pinchart said there
are order problem.

1  v4l2_subdev_init()
2. v4l2_async_subdev_nf_init()
3. v4l2_async_nf_register()
4. media_entity_pads_init()
5  v4l2_async_register_subdev()


v4l2_async_unregister_subdev(sd);
v4l2_subdev_cleanup(sd);        // Not sure if it save to move to last step
media_entity_cleanup(&sd->entity);
v4l2_async_nf_unregister(&csi2->notifier);
v4l2_async_nf_cleanup(&csi2->notifier);

Frank
>
> --
> Kind regards,
>
> Sakari Ailus


^ permalink raw reply

* [PATCH v2] nvmem: rockchip-otp: skip zero-byte reads
From: Ruoyu Wang @ 2026-06-18  4:08 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Heiko Stuebner, Jonas Karlman, linux-arm-kernel, linux-rockchip,
	linux-kernel, Ruoyu Wang

nvmem_device_read() does not reject a zero-byte read before calling the
provider reg_read callback. rockchip_otp_read() then enables clocks and
dispatches to the SoC-specific callback.

Return 0 from rockchip_otp_read() before enabling clocks when bytes is
zero. This avoids hardware access for empty reads and prevents zero
counts from reaching the internal reg_read callbacks.

Fixes: 8ab099fafbbc ("nvmem: rockchip-otp: Add support for RK3588")
Suggested-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
v2:
- Handle empty reads in rockchip_otp_read() instead of initializing ret in
  rk3588_otp_read().

 drivers/nvmem/rockchip-otp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index 0ec78b5e19e7d..95685a9fcc77b 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -272,6 +272,9 @@ static int rockchip_otp_read(void *context, unsigned int offset,
 	if (!otp->data || !otp->data->reg_read)
 		return -EINVAL;
 
+	if (!bytes)
+		return 0;
+
 	ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
 	if (ret < 0) {
 		dev_err(otp->dev, "failed to prepare/enable clks\n");
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH 11/78] ASoC: codecs: cros_ec_codec: Use guard() for mutex locks
From: Tzung-Bi Shih @ 2026-06-18  4:05 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Cheng-Yi Chiang, Guenter Roeck, Benson Leung, David Rhodes,
	Richard Fitzgerald, povik+lin, Charles Keepax, Support Opensource,
	Nick Li, Herve Codina, Srinivas Kandagatla, Matthias Brugger,
	AngeloGioacchino Del Regno, Shenghao Ding, Kevin Lu, Baojun Xu,
	Sen Wang, Oder Chiou, Lars-Peter Clausen, nuno.sa, Steven Eckhoff,
	patches, chrome-platform, asahi, linux-arm-msm, linux-sound,
	linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260617103235.449609-12-phucduc.bui@gmail.com>

On Wed, Jun 17, 2026 at 05:31:28PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
> 
> Clean up the code using guard() for mutex locks.
> Merely code refactoring, and no behavior change.
> 
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>

Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>


^ permalink raw reply

* Re: [PATCH v4] dmaengine: sun6i-dma: Fix memory leak in sun6i_dma_terminate_all
From: Frank Li @ 2026-06-18  3:22 UTC (permalink / raw)
  To: Hongling Zeng
  Cc: vkoul, Frank.Li, wens, jernej.skrabec, samuel, mripard, arnd,
	dmaengine, linux-arm-kernel, linux-sunxi, linux-kernel,
	zhongling0719
In-Reply-To: <20260618020609.1155962-1-zenghongling@kylinos.cn>

On Thu, Jun 18, 2026 at 10:06:09AM +0800, Hongling Zeng wrote:
> When terminating DMA transfers, active descriptors are not properly
> reclaimed. Only cyclic descriptors were handled, leaving non-cyclic
> descriptors and their LLI chains to be permanently leaked.
>
> Fix by using vchan_terminate_vdesc() which handles both cyclic and
> non-cyclic descriptors by adding them to desc_terminated queue for
> proper cleanup.
>
> Add pchan->desc != pchan->done check to prevent double-adding completed
> descriptors, which would corrupt the list.
>
> Fixes: 555859308723 ("dmaengine: sun6i: Add driver for the Allwinner A31 DMA controller")
> Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
> Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> Suggested-by: Frank Li <Frank.li@oss.nxp.com>

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>
> ---
>  Change in v2;
>  -Add pchan->desc != pchan->done check to prevent race condition
>   where completed descriptors could be double-added to desc_completed
>   list, causing list corruption
> ---
>  Change in v3:
>  -Fix by using vchan_terminate_vdesc() as suggested by Frank Li
> ---
>  Change in v4:
>  -Correct the commit message
> ---
>  drivers/dma/sun6i-dma.c | 13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 7a79f346250a..134ae840f176 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -946,16 +946,13 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)
>
>  	spin_lock_irqsave(&vchan->vc.lock, flags);
>
> -	if (vchan->cyclic) {
> -		vchan->cyclic = false;
> -		if (pchan && pchan->desc) {
> -			struct virt_dma_desc *vd = &pchan->desc->vd;
> -			struct virt_dma_chan *vc = &vchan->vc;
> -
> -			list_add_tail(&vd->node, &vc->desc_completed);
> -		}
> +	if (pchan && pchan->desc && pchan->desc != pchan->done) {
> +		struct virt_dma_desc *vd = &pchan->desc->vd;
> +
> +		vchan_terminate_vdesc(vd);
>  	}
>
> +	vchan->cyclic = false;
>  	vchan_get_all_descriptors(&vchan->vc, &head);
>
>  	if (pchan) {
> --
> 2.25.1
>


^ permalink raw reply

* Re: [PATCH 1/3] PCI: rcar-gen4: Configure AXIINTC if iMSI-RX not used
From: Marek Vasut @ 2026-06-18  3:21 UTC (permalink / raw)
  To: Manivannan Sadhasivam, Marek Vasut
  Cc: linux-pci, Yoshihiro Shimoda, Krzysztof Wilczyński,
	Bjorn Helgaas, Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Lorenzo Pieralisi, Marc Zyngier, Rob Herring,
	devicetree, linux-arm-kernel, linux-doc, linux-kernel,
	linux-renesas-soc
In-Reply-To: <lstafqaogzunb2azyqwvtt3swrk42nu3n5zyct2la5fqxomaqg@wyrz3qolhist>

On 6/17/26 12:33 PM, Manivannan Sadhasivam wrote:

Hello Manivannan,

[...]

>> +/* INTC address */
>> +#define AXIINTCADDR		0x0a00
>> +/* GITS GIC ITS translation register */
>> +#define AXIINTCADDR_VAL		0xf1050000
> 
> As Marc pointed out, this address should be fetched from DT, not hardcoded in
> the driver.

I will reply to Marc when I have this ready for V2.

>> +
>> +/* INTC control & mask */
>> +#define AXIINTCCONT		0x0a04
>> +#define INTC_EN			BIT(31)
>> +#define INTC_MASK		GENMASK(11, 2)
>> +
>>   /* PCIe Power Management Control */
>>   #define PCIEPWRMNGCTRL		0x0070
>>   #define APP_CLK_REQ_N		BIT(11)
>> @@ -305,6 +319,39 @@ static struct rcar_gen4_pcie *rcar_gen4_pcie_alloc(struct platform_device *pdev)
>>   	return rcar;
>>   }
>>   
>> +static void rcar_gen4_pcie_host_msi_init(struct dw_pcie_rp *pp)
>> +{
>> +	struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
>> +	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
>> +	u32 val;
>> +
>> +	/* Make sure MSICAP0 MSIE is configured. */
>> +	val = dw_pcie_readl_dbi(dw, MSICAP0);
>> +	if (pci_msi_enabled())
>> +		val |= MSICAP0_MSIE;
>> +	else
>> +		val &= ~MSICAP0_MSIE;
>> +	dw_pcie_writel_dbi(dw, MSICAP0, val);
>> +
>> +	if (!pci_msi_enabled() || pp->use_imsi_rx) {
> 
> If MSI is not enabled, then what's the point in clearing these registers (also
> above)? I see it as a redundant code. Is there a necessity to clear them?
AXIINTCCONT INTC_EN should not be set if MSI is disabled, this code 
makes sure it is not set, even if it might have been left set e.g. by 
prior stage. So no, this is not redundant code, this makes sure the 
controller is correctly configured.


^ permalink raw reply

* Re: [PATCH v2 0/3] ASoC: rockchip: Use guard() for spin locks
From: Bui Duc Phuc @ 2026-06-18  3:16 UTC (permalink / raw)
  To: Nicolas Frattaroli
  Cc: Heiko Stuebner, Liam Girdwood, Mark Brown, Nicolas Frattaroli,
	Jaroslav Kysela, Takashi Iwai, linux-sound, linux-rockchip,
	linux-arm-kernel, linux-kernel
In-Reply-To: <mPIrpl-QRw6_Q9DZcTQ5xA@collabora.com>

Hi Nicolas,

Thanks for the feedback.

> FWIW, the SAI patch wasn't sent to the proper maintainer e-mail
> for it which is why I didn't notice this series at all until now,
> and the whole thing is pointless churn that wasn't even tested.
>
> From a cursory glance, whatever LLM was pointed at this and decided
> to make the output my problem also didn't do a good job, the scoped
> indentation of rockchip_sai_runtime_suspend seems pointless because
> it could've been replaced by a pm guard followed by a spinlock guard,
> without an additional level of indentation, and `if (ret == 0) {` is
> not kernel style.
>
> It's not worth the revert but it sucks that I have to now set up a
> new lei search for all the drivers I am supposed to receive mail for
> because vibecoders can't be bothered to run get_maintainers as they
> pad their CV with nonsense like this.
>
> >
> > [1/3] ASoC: rockchip: rockchip_i2s: Use guard() for spin locks
> >       https://git.kernel.org/broonie/sound/c/4bda5af16920
> > [2/3] ASoC: rockchip: i2s-tdm: Use guard() for spin locks
> >       https://git.kernel.org/broonie/sound/c/ec22437fc41a
> > [3/3] ASoC: rockchip: rockchip_sai: Use guard() for spin locks
> >       https://git.kernel.org/broonie/sound/c/f7fe9f707360
> >

Regarding the claim that the Rockchip SAI patch was not sent to the proper
maintainer, I believe there may be a misunderstanding.
Before sending the series, I ran get_maintainer.pl on the patch set and
included all recipients reported by the script, including:

Nicolas Frattaroli <frattaroli.nicolas@gmail.com>

along with the relevant mailing lists.

------------------------------------------
phuc@phuc-desktop:~/work/linux$ ls ../patch/sound/rockchip/clean/
0000-cover-letter.patch
v2-0000-cover-letter.patch
0001-ASoC-rockchip-rockchip_i2s-Use-guard-for-spin-locks.patch
v2-0001-ASoC-rockchip-rockchip_i2s-Use-guard-for-spin-loc.patch
0002-ASoC-rockchip-i2s-tdm-Use-guard-for-spin-locks.patch
v2-0002-ASoC-rockchip-i2s-tdm-Use-guard-for-spin-locks.patch
0003-ASoC-rockchip-rockchip_sai-Use-guard-for-spin-locks.patch
v2-0003-ASoC-rockchip-rockchip_sai-Use-guard-for-spin-loc.patch
phuc@phuc-desktop:~/work/linux$
phuc@phuc-desktop:~/work/linux$
phuc@phuc-desktop:~/work/linux$
phuc@phuc-desktop:~/work/linux$ ./scripts/get_maintainer.pl
../patch/sound/rockchip/clean/000*.patch
./scripts/get_maintainer.pl: file
'../patch/sound/rockchip/clean/0000-cover-letter.patch' doesn't appear
to be a patch.  Add -f to options?
Liam Girdwood <lgirdwood@gmail.com> (maintainer:SOUND - SOC LAYER /
DYNAMIC AUDIO POWER MANAGEM...)
Mark Brown <broonie@kernel.org> (maintainer:SOUND - SOC LAYER /
DYNAMIC AUDIO POWER MANAGEM...)
Jaroslav Kysela <perex@perex.cz> (maintainer:SOUND)
Takashi Iwai <tiwai@suse.com> (maintainer:SOUND)
Heiko Stuebner <heiko@sntech.de> (maintainer:ARM/Rockchip SoC support)
Nicolas Frattaroli <frattaroli.nicolas@gmail.com> (maintainer:ROCKCHIP
I2S TDM DRIVER)
linux-sound@vger.kernel.org (open list:SOUND - SOC LAYER / DYNAMIC
AUDIO POWER MANAGEM...)
linux-arm-kernel@lists.infradead.org (moderated list:ARM/Rockchip SoC support)
linux-rockchip@lists.infradead.org (open list:ARM/Rockchip SoC support)
linux-kernel@vger.kernel.org (open list)
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) status: Supported
phuc@phuc-desktop:~/work/linux$
phuc@phuc-desktop:~/work/linux$
---------------------------------------------

If there are additional maintainers or mailing lists that should receive these
patches but are not currently reported by get_maintainer.pl, please let me know
so I can include them in future submissions.
I would also appreciate avoiding assumptions that the series was generated
by an LLM. The patches were prepared manually and submitted as part of
my ongoing effort to convert lock/unlock patterns to guard()/scoped_guard()
helpers where appropriate.
The series was build-tested before submission, so I do not believe it
is accurate
to describe it as "wasn't even tested".
Whether a particular conversion is worthwhile is certainly open to
technical discussion,
but I do not think it is reasonable to conclude that a patch was AI-generated
simply based on disagreements about the implementation details.
I understand maintainers have different preferences regarding how aggressively
such conversions should be applied, and I am happy to adjust the approach
based on review feedback.

Best regards,
Phuc


^ permalink raw reply

* [PATCH v4 2/2] Bluetooth: btmtksdio: call cancel_work_sync() out of host lock scope
From: Sergey Senozhatsky @ 2026-06-18  3:13 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Sean Wang
  Cc: Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
	linux-mediatek, Sergey Senozhatsky, stable
In-Reply-To: <20260618031338.1011410-1-senozhatsky@chromium.org>

cancel_work_sync() should be called outside of host lock scope
in order to avoid circular locking scenario:

CPU0                            CPU1
                                close()/reset()
                                  sdio_claim_host()
txrx_work
  sdio_claim_host() // sleeps
                                  cancel_work_sync() // sleeps

In addition, when txrx_work() runs concurrently with close()/reset()
it better not to re-enable interrupts by testing for BTMTKSDIO_FUNC_ENABLED
and not BTMTKSDIO_HW_RESET_ACTIVE before C_INT_EN_SET write.  However,
btmtksdio_close() clears the BTMTKSDIO_FUNC_ENABLED too late (after
cancel_work_sync() call).  Move BTMTKSDIO_FUNC_ENABLED bit-clear earlier
so that txrx_work can see concurrent close().

Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
Cc: stable@vger.kernel.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
 drivers/bluetooth/btmtksdio.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index d8c8d2857527..207d04cc2282 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -625,7 +625,9 @@ static void btmtksdio_txrx_work(struct work_struct *work)
 	} while (int_status && time_is_after_jiffies(txrx_timeout));
 
 	/* Enable interrupt */
-	if (bdev->func->irq_handler)
+	if (bdev->func->irq_handler &&
+	    test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state) &&
+	    !test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
 		sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
 
 	sdio_release_host(bdev->func);
@@ -741,6 +743,8 @@ static int btmtksdio_close(struct hci_dev *hdev)
 	if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
 		return 0;
 
+	clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
+
 	sdio_claim_host(bdev->func);
 
 	/* Disable interrupt */
@@ -748,11 +752,12 @@ static int btmtksdio_close(struct hci_dev *hdev)
 
 	sdio_release_irq(bdev->func);
 
+	sdio_release_host(bdev->func);
 	cancel_work_sync(&bdev->txrx_work);
+	sdio_claim_host(bdev->func);
 
 	btmtksdio_fw_pmctrl(bdev);
 
-	clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
 	sdio_disable_func(bdev->func);
 
 	sdio_release_host(bdev->func);
@@ -1295,7 +1300,10 @@ static void btmtksdio_reset(struct hci_dev *hdev)
 
 	sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
 	skb_queue_purge(&bdev->txq);
+
+	sdio_release_host(bdev->func);
 	cancel_work_sync(&bdev->txrx_work);
+	sdio_claim_host(bdev->func);
 
 	gpiod_set_value_cansleep(bdev->reset, 1);
 	msleep(100);
-- 
2.54.0.1189.g8c84645362-goog



^ permalink raw reply related

* [PATCH v4 0/2] Bluetooth: btmtksdio: teardown fixes
From: Sergey Senozhatsky @ 2026-06-18  3:13 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Sean Wang
  Cc: Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
	linux-mediatek, Sergey Senozhatsky

This fixes several teardown issues:

     INFO: task kworker/u17:0:189 blocked for more than 122 seconds.
     __cancel_work_timer+0x3f4/0x460
     cancel_work_sync+0x1c/0x2c
     btmtksdio_flush+0x2c/0x40
     hci_dev_open_sync+0x10c4/0x2190
     [..]

close/flush can deadlock when run concurrently with btmtksdio_txrx_work().
In addition btmtksdio_txrx_work() re-enables interrupts regardless of
close/flush being executed on another CPU.

v3 -> v4:
- fix commit message linter warnings/errors (tabs, subject line over 80
  chars).

Sergey Senozhatsky (2):
  Bluetooth: btmtksdio: test for BUS IO errors in btmtksdio_txrx_work()
  Bluetooth: btmtksdio: call cancel_work_sync() out of host lock scope

 drivers/bluetooth/btmtksdio.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

--
2.54.0.1189.g8c84645362-goog



^ permalink raw reply

* [PATCH v4 1/2] Bluetooth: btmtksdio: test for BUS IO errors in btmtksdio_txrx_work()
From: Sergey Senozhatsky @ 2026-06-18  3:13 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Sean Wang
  Cc: Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
	linux-mediatek, Sergey Senozhatsky, stable
In-Reply-To: <20260618031338.1011410-1-senozhatsky@chromium.org>

btmtksdio_txrx_work() loop termination condition checks for
int_status being non-zero, however, this evaluates to true
even when sdio_readl() encounters BUS I/O error (in which
case int_status is 0xffffffff).  Break out of the loop if
sdio_readl() errors out.

Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
Cc: stable@vger.kernel.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
 drivers/bluetooth/btmtksdio.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index c6f80c419e90..d8c8d2857527 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -574,7 +574,9 @@ static void btmtksdio_txrx_work(struct work_struct *work)
 	txrx_timeout = jiffies + 5 * HZ;
 
 	do {
-		int_status = sdio_readl(bdev->func, MTK_REG_CHISR, NULL);
+		int_status = sdio_readl(bdev->func, MTK_REG_CHISR, &err);
+		if (err < 0 || int_status == 0xffffffff)
+			break;
 
 		/* Ack an interrupt as soon as possible before any operation on
 		 * hardware.
-- 
2.54.0.1189.g8c84645362-goog



^ permalink raw reply related

* Re: [PATCH 2/3] irqchip/gic-v3: Add Renesas R-Car Gen4 erratum workaround
From: Marek Vasut @ 2026-06-18  2:38 UTC (permalink / raw)
  To: Geert Uytterhoeven, Marek Vasut
  Cc: linux-pci, Yoshihiro Shimoda, Krzysztof Wilczyński,
	Bjorn Helgaas, Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
	Marc Zyngier, Rob Herring, devicetree, linux-arm-kernel,
	linux-doc, linux-kernel, linux-renesas-soc
In-Reply-To: <CAMuHMdX7XuHQDSsX4P7NZ46_OnCX2o25szuALwSs2z+PHq+JNg@mail.gmail.com>

On 6/17/26 9:09 AM, Geert Uytterhoeven wrote:

Hello Geert,

>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -4901,6 +4901,18 @@ static bool __maybe_unused its_enable_rk3568002(void *data)
>>          return true;
>>   }
>>
>> +static bool __maybe_unused its_enable_renesas_gen4(void *data)
>> +{
>> +       if (!of_machine_is_compatible("renesas,r8a779f0") &&
>> +           !of_machine_is_compatible("renesas,r8a779g0") &&
>> +           !of_machine_is_compatible("renesas,r8a779h0"))
> 
> of_machine_compatible_match() with an array of strings might generate
> smaller code (I didn't check if 3 entries is enough to trip the balance).

Let me handle that as part of suggestion from Marc.


^ permalink raw reply

* Re: [PATCH 2/3] irqchip/gic-v3: Add Renesas R-Car Gen4 erratum workaround
From: Marek Vasut @ 2026-06-18  2:50 UTC (permalink / raw)
  To: Marc Zyngier, Marek Vasut
  Cc: linux-pci, Yoshihiro Shimoda, Krzysztof Wilczyński,
	Bjorn Helgaas, Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
	Rob Herring, devicetree, linux-arm-kernel, linux-doc,
	linux-kernel, linux-renesas-soc
In-Reply-To: <864ij1tyrj.wl-maz@kernel.org>

On 6/17/26 9:24 AM, Marc Zyngier wrote:

Hello Marc,

>> Renesas R-Car S4/V4H/V4M GIC600 integration has address width for AXI
>> or APB interface configured to 32 bit, it can therefore access only
>> the first 4 GiB of physical address space. This information comes from
>> R-Car V4H Interface Specification sheet, there is currently no technical
>> update number assigned to this limitation. Further input from hardware
>> engineer indicates that this limitation also applies to R-Car S4 and V4M.
>> Name the limitation GEN4GICITS1, and add a driver quirk to mitigate this
>> limitation.

My concern is this ^ , I do not have an erratum number, because there 
isn't one. I am in touch with the hardware engineer and I did get a 
glimpse at internal details of the three SoC, which confirm the 
limitations. Is this sufficient ?

>> Note that the 0x0201743b GIC600 ID is not Renesas-specific, it is
>> common for many ARM GICv3 implementations. Therefore, add an extra
> 
> Not quite. It designates GIC600 unambiguously.

What I am trying to communicate is, that the 0x0201743b ID is not ID of 
the Renesas GIC implementation, but it is a generic ARM GIC600 ID. That 
is why we cannot match the quirk on the ID (it is generic ARM GIC600 
ID), and instead we have to match the quirk on the [ ID combined with 
of_machine_is_compatible("renesas,...") ].

> It is just that GIC600
> is integrated in zillions of SoCs, most of which don't have this
> problem (the machine I'm typing this from has a GIC600 *and* 96GB of
> RAM).

Right.

Shall I reword this paragraph somehow to make it clearer ?

>> of_machine_is_compatible() check.
>>
>> The GIC600 implementation in R-Car S4/V4H/V4M is r1p6.
> 
> Is this relevant?

I included it for the sake of completeness and to provide all relevant 
information, based on previous discussions about similar limitations 
that I could find on lore.k.o

[...]

>> +#ifdef CONFIG_RENESAS_ERRATUM_GEN4GICITS1
>> +	{
>> +		.desc   = "ITS: Renesas R-Car Gen4 GIC600 32-bit limit",
>> +		.iidr   = 0x0201743b,
>> +		.mask   = 0xffffffff,
>> +		.init   = its_enable_renesas_gen4,
>> +	},
>>   #endif
>>   	{
>>   	}
> 
> 
> Honestly, that's a bit too much copy-paste for my taste. Just refactor
> the erratum handling to be more generic, something like this:
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 291d7668cc8da..380c4758647d2 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -4894,10 +4894,17 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
>   	return true;
>   }
>   
> -static bool __maybe_unused its_enable_rk3568002(void *data)
> +static const char * const dma_impaired_platforms[] = {
> +#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
> +	"rockchip,rk3566",
> +	"rockchip,rk3568",
> +#endif
> +	NULL,
> +};
> +
> +static bool __maybe_unused its_enable_dma32(void *data)
>   {
> -	if (!of_machine_is_compatible("rockchip,rk3566") &&
> -	    !of_machine_is_compatible("rockchip,rk3568"))
> +	if (!of_machine_compatible_match(dma_impaired_platforms))
>   		return false;
>   
>   	gfp_flags_quirk |= GFP_DMA32;
> @@ -4972,14 +4979,12 @@ static const struct gic_quirk its_quirks[] = {
>   		.property = "dma-noncoherent",
>   		.init   = its_set_non_coherent,
>   	},
> -#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
>   	{
> -		.desc   = "ITS: Rockchip erratum RK3568002",
> +		.desc   = "ITS: Broken GIC600 integration limited to 32bit PA",
>   		.iidr   = 0x0201743b,
>   		.mask   = 0xffffffff,
> -		.init   = its_enable_rk3568002,
> +		.init   = its_enable_dma32,
>   	},
> -#endif
>   	{
>   	}
>   };
> 
> Then add the two lines you need in a separate patch.

Will do in V2.

> In the future, please provide a cover letter when you have more than a
> single patch (git will happily generate one for you).
OK


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox