Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

André Draszik and committed by
Krzysztof Kozlowski
1fce7e4d 3abd9b08

+33
+3
drivers/soc/samsung/exynos-pmu.c
··· 637 637 pmu_regmcfg = regmap_smccfg; 638 638 pmu_regmcfg.max_register = resource_size(res) - 639 639 pmu_regmcfg.reg_stride; 640 + pmu_regmcfg.wr_table = pmu_context->pmu_data->wr_table; 641 + pmu_regmcfg.rd_table = pmu_context->pmu_data->rd_table; 642 + 640 643 /* Need physical address for SMC call */ 641 644 regmap = devm_regmap_init(dev, NULL, 642 645 (void *)(uintptr_t)res->start,
+30
drivers/soc/samsung/exynos-pmu.h
··· 13 13 14 14 #define PMU_TABLE_END (-1U) 15 15 16 + struct regmap_access_table; 17 + 16 18 struct exynos_pmu_conf { 17 19 unsigned int offset; 18 20 u8 val[NUM_SYS_POWERDOWN]; 19 21 }; 20 22 23 + /** 24 + * struct exynos_pmu_data - of_device_id (match) data 25 + * 26 + * @pmu_config: Optional table detailing register writes for target system 27 + * states: SYS_AFTR, SYS_LPA, SYS_SLEEP. 28 + * @pmu_config_extra: Optional secondary table detailing additional register 29 + * writes for target system states: SYS_AFTR, SYS_LPA, 30 + * SYS_SLEEP. 31 + * @pmu_secure: Whether or not PMU register writes need to be done via SMC call. 32 + * @pmu_cpuhp: Whether or not extra handling is required for CPU hotplug and 33 + * CPUidle outside of standard PSCI calls, due to non-compliant 34 + * firmware. 35 + * @pmu_init: Optional init function. 36 + * @powerdown_conf: Optional callback before entering target system states: 37 + * SYS_AFTR, SYS_LPA, SYS_SLEEP. This will be invoked before 38 + * the registers from @pmu_config are written. 39 + * @powerdown_conf_extra: Optional secondary callback before entering 40 + * target system states: SYS_AFTR, SYS_LPA, SYS_SLEEP. 41 + * This will be invoked after @pmu_config registers have 42 + * been written. 43 + * @rd_table: A table of readable register ranges in case a custom regmap is 44 + * used (i.e. when @pmu_secure is @true). 45 + * @wr_table: A table of writable register ranges in case a custom regmap is 46 + * used (i.e. when @pmu_secure is @true). 47 + */ 21 48 struct exynos_pmu_data { 22 49 const struct exynos_pmu_conf *pmu_config; 23 50 const struct exynos_pmu_conf *pmu_config_extra; ··· 54 27 void (*pmu_init)(void); 55 28 void (*powerdown_conf)(enum sys_powerdown); 56 29 void (*powerdown_conf_extra)(enum sys_powerdown); 30 + 31 + const struct regmap_access_table *rd_table; 32 + const struct regmap_access_table *wr_table; 57 33 }; 58 34 59 35 extern void __iomem *pmu_base_addr;