[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260128-gs101-pd-v4-7-cbe7bd5a4060@linaro.org>
Date: Wed, 28 Jan 2026 16:10:56 +0000
From: André Draszik <andre.draszik@...aro.org>
To: Krzysztof Kozlowski <krzk@...nel.org>,
Alim Akhtar <alim.akhtar@...sung.com>, Rob Herring <robh@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Ulf Hansson <ulf.hansson@...aro.org>, Liam Girdwood <lgirdwood@...il.com>,
Mark Brown <broonie@...nel.org>
Cc: Peter Griffin <peter.griffin@...aro.org>,
Tudor Ambarus <tudor.ambarus@...aro.org>, Juan Yescas <jyescas@...gle.com>,
Will McVicker <willmcvicker@...gle.com>, kernel-team@...roid.com,
linux-arm-kernel@...ts.infradead.org, linux-samsung-soc@...r.kernel.org,
devicetree@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-pm@...r.kernel.org,
André Draszik <andre.draszik@...aro.org>,
Marek Szyprowski <m.szyprowski@...sung.com>
Subject: [PATCH v4 07/10] pmdomain: samsung: add support for
google,gs101-pd
On Google gs101, direct mmio register access to the PMU registers
doesn't work and access must happen via a regmap created by the PMU
driver instead.
Add a flag to the device match data to denote this case, and obtain
the regmap using the parent node in DT if true, while keeping to use
the traditional direct mmio regmap otherwise.
Additionally, the status is just one bit on gs101.
Tested-by: Marek Szyprowski <m.szyprowski@...sung.com>
Signed-off-by: André Draszik <andre.draszik@...aro.org>
---
v4:
- add 'use_parent_regmap' flag instead of going by 'syscon' compatible
in parent, as it's not a given that the parent provides a syscon-
compatible regmap (it actually doesn't anymore after recent changes
on gs101)
I've still kept Marek's Tested-by from v3, as legacy Exynos code
doesn't change.
---
drivers/pmdomain/samsung/exynos-pm-domains.c | 66 +++++++++++++++++++---------
1 file changed, 46 insertions(+), 20 deletions(-)
diff --git a/drivers/pmdomain/samsung/exynos-pm-domains.c b/drivers/pmdomain/samsung/exynos-pm-domains.c
index 8df46b41f9bc8f0b2a03300169a4b52457faaf4d..2214d9f32d5967b60e84f68f4e99a725d66a39eb 100644
--- a/drivers/pmdomain/samsung/exynos-pm-domains.c
+++ b/drivers/pmdomain/samsung/exynos-pm-domains.c
@@ -12,6 +12,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
#include <linux/pm_domain.h>
#include <linux/delay.h>
#include <linux/of.h>
@@ -21,6 +22,7 @@
struct exynos_pm_domain_config {
/* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
u32 local_pwr_cfg;
+ bool use_parent_regmap;
};
/*
@@ -93,8 +95,16 @@ static const struct exynos_pm_domain_config exynos5433_cfg = {
.local_pwr_cfg = 0xf,
};
+static const struct exynos_pm_domain_config gs101_cfg = {
+ .local_pwr_cfg = BIT(0),
+ .use_parent_regmap = true,
+};
+
static const struct of_device_id exynos_pm_domain_of_match[] = {
{
+ .compatible = "google,gs101-pd",
+ .data = &gs101_cfg,
+ }, {
.compatible = "samsung,exynos4210-pd",
.data = &exynos4210_cfg,
}, {
@@ -122,17 +132,9 @@ static int exynos_pd_probe(struct platform_device *pdev)
struct of_phandle_args child, parent;
struct exynos_pm_domain *pd;
struct resource *res;
- void __iomem *base;
unsigned int val;
int on, ret;
- struct regmap_config reg_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .use_relaxed_mmio = true,
- };
-
pm_domain_cfg = of_device_get_match_data(dev);
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
@@ -143,25 +145,49 @@ static int exynos_pd_probe(struct platform_device *pdev)
return -ENOMEM;
/*
- * The resource typically points into the address space of the PMU.
+ * The resource typically points into the address space of the PMU and
+ * we have to consider two cases:
+ * 1) some implementations require a custom regmap (from PMU parent)
+ * 2) this driver might map the same addresses as the PMU driver
* Therefore, avoid using devm_platform_get_and_ioremap_resource() and
- * instead use platform_get_resource() and devm_ioremap() to avoid
+ * instead use platform_get_resource() here, and below for case 1) use
+ * syscon_node_to_regmap() while for case 2) use devm_ioremap() to avoid
* conflicts due to address space overlap.
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return dev_err_probe(dev, -ENXIO, "missing IO resources");
- base = devm_ioremap(dev, res->start, resource_size(res));
- if (!base)
- return dev_err_probe(dev, -ENOMEM,
- "failed to ioremap PMU registers");
-
- reg_config.max_register = resource_size(res) - reg_config.reg_stride;
- pd->regmap = devm_regmap_init_mmio(dev, base, ®_config);
- if (IS_ERR(pd->regmap))
- return dev_err_probe(dev, PTR_ERR(base),
- "failed to init regmap");
+ if (pm_domain_cfg->use_parent_regmap) {
+ pd->regmap = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(pd->regmap))
+ return dev_err_probe(dev, PTR_ERR(pd->regmap),
+ "failed to acquire PMU regmap");
+
+ pd->configuration_reg = res->start;
+ pd->status_reg = res->start;
+ } else {
+ void __iomem *base;
+
+ const struct regmap_config reg_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .use_relaxed_mmio = true,
+ .max_register = (resource_size(res)
+ - reg_config.reg_stride),
+ };
+
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to ioremap PMU registers");
+
+ pd->regmap = devm_regmap_init_mmio(dev, base, ®_config);
+ if (IS_ERR(pd->regmap))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "failed to init regmap");
+ }
pd->pd.power_off = exynos_pd_power_off;
pd->pd.power_on = exynos_pd_power_on;
--
2.52.0.457.g6b5491de43-goog
Powered by blists - more mailing lists