summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Draszik <andre.draszik@linaro.org>2025-10-09 10:31:25 +0100
committerKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>2025-10-18 19:16:44 +0200
commit1fce7e4d6c42c8164e6e36d8600e16663066c1b2 (patch)
tree555e59e62072a3fddce2d5122dc2bc7ce0230981
parent3abd9b087a4cd7430cec2080c67e7a94fd7a44b4 (diff)
soc: samsung: exynos-pmu: allow specifying read & write access tables for secure regmap
Accessing non-existent PMU registers causes an SError, halting the system. regmap can help us with that by allowing to pass the list of valid registers as part of the config during creation. When this driver creates a new regmap itself rather than relying on syscon_node_to_regmap(), it's therefore easily possible to hook in custom access tables for valid read and write registers. Specifying access tables avoids SErrors for invalid registers and instead the regmap core can just return an error. Outside drivers, this is also helpful when using debugfs to access the regmap. Make it possible for drivers to specify read and write tables to be used on creation of the secure regmap by adding respective fields to struct exynos_pmu_data. Also add kerneldoc to same struct while updating it. Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org> Signed-off-by: André Draszik <andre.draszik@linaro.org> Link: https://patch.msgid.link/20251009-gs101-pmu-regmap-tables-v2-1-2d64f5261952@linaro.org Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-rw-r--r--drivers/soc/samsung/exynos-pmu.c3
-rw-r--r--drivers/soc/samsung/exynos-pmu.h30
2 files changed, 33 insertions, 0 deletions
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 105293970d48..565eb75b003a 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -637,6 +637,9 @@ static int exynos_pmu_probe(struct platform_device *pdev)
pmu_regmcfg = regmap_smccfg;
pmu_regmcfg.max_register = resource_size(res) -
pmu_regmcfg.reg_stride;
+ pmu_regmcfg.wr_table = pmu_context->pmu_data->wr_table;
+ pmu_regmcfg.rd_table = pmu_context->pmu_data->rd_table;
+
/* Need physical address for SMC call */
regmap = devm_regmap_init(dev, NULL,
(void *)(uintptr_t)res->start,
diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h
index 0938bb4fe15f..1658a55fe61c 100644
--- a/drivers/soc/samsung/exynos-pmu.h
+++ b/drivers/soc/samsung/exynos-pmu.h
@@ -13,11 +13,38 @@
#define PMU_TABLE_END (-1U)
+struct regmap_access_table;
+
struct exynos_pmu_conf {
unsigned int offset;
u8 val[NUM_SYS_POWERDOWN];
};
+/**
+ * struct exynos_pmu_data - of_device_id (match) data
+ *
+ * @pmu_config: Optional table detailing register writes for target system
+ * states: SYS_AFTR, SYS_LPA, SYS_SLEEP.
+ * @pmu_config_extra: Optional secondary table detailing additional register
+ * writes for target system states: SYS_AFTR, SYS_LPA,
+ * SYS_SLEEP.
+ * @pmu_secure: Whether or not PMU register writes need to be done via SMC call.
+ * @pmu_cpuhp: Whether or not extra handling is required for CPU hotplug and
+ * CPUidle outside of standard PSCI calls, due to non-compliant
+ * firmware.
+ * @pmu_init: Optional init function.
+ * @powerdown_conf: Optional callback before entering target system states:
+ * SYS_AFTR, SYS_LPA, SYS_SLEEP. This will be invoked before
+ * the registers from @pmu_config are written.
+ * @powerdown_conf_extra: Optional secondary callback before entering
+ * target system states: SYS_AFTR, SYS_LPA, SYS_SLEEP.
+ * This will be invoked after @pmu_config registers have
+ * been written.
+ * @rd_table: A table of readable register ranges in case a custom regmap is
+ * used (i.e. when @pmu_secure is @true).
+ * @wr_table: A table of writable register ranges in case a custom regmap is
+ * used (i.e. when @pmu_secure is @true).
+ */
struct exynos_pmu_data {
const struct exynos_pmu_conf *pmu_config;
const struct exynos_pmu_conf *pmu_config_extra;
@@ -27,6 +54,9 @@ struct exynos_pmu_data {
void (*pmu_init)(void);
void (*powerdown_conf)(enum sys_powerdown);
void (*powerdown_conf_extra)(enum sys_powerdown);
+
+ const struct regmap_access_table *rd_table;
+ const struct regmap_access_table *wr_table;
};
extern void __iomem *pmu_base_addr;