Re: [PATCH v7 07/10] pmdomain: samsung: add support for google,gs101-pd
From: Peter Griffin
Date: Fri Mar 06 2026 - 10:25:50 EST
On Fri, 6 Mar 2026 at 10:29, André Draszik <andre.draszik@xxxxxxxxxx> wrote:
>
> 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@xxxxxxxxxxx>
> Signed-off-by: André Draszik <andre.draszik@xxxxxxxxxx>
>
> ---
Reviewed-by: Peter Griffin <peter.griffin@xxxxxxxxxx>
> 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 8df46b41f9bc..2214d9f32d59 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.53.0.473.g4a7958ca14-goog
>