Re: [PATCH RFC 7/8] soc: samsung: exynos-pmu: add Exynos850 CPU hotplug support
From: Peter Griffin <peter.griffin@linaro.org>
Date: 2026-03-06 14:15:47
Also in:
linux-devicetree, linux-samsung-soc, lkml
Hi Alexey, Thanks for your patch. On Thu, 26 Feb 2026 at 15:47, Alexey Klimov [off-list ref] wrote:
quoted hunk ↗ jump to hunk
Some Exynos-based SoCs require specific set of writes/updates to PMU and PMU intr gen blocks in order to put a CPU or a group of CPUs into a different sleep states or prepare these entities for a CPU_OFF. The same is valid for a reverse procedures like wake-ups or CPU(s) online. Without these writes/updates the CPU(s) wake-up or online fails. Add support for Exynos850-based SoCs for PMU and PMU intr gen write/update sequences. While at this, also add description of Exynos850 PMU registers. Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org> --- drivers/soc/samsung/exynos-pmu.c | 86 +++++++++++++++++++++++++++-- include/linux/soc/samsung/exynos-regs-pmu.h | 5 ++ 2 files changed, 87 insertions(+), 4 deletions(-)diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index 0967fa56708a..7b9b8e22d91b 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c@@ -118,6 +118,10 @@ static const struct regmap_config regmap_pmu_intr = { .use_raw_spinlock = true, }; +const struct exynos_pmu_data exynos850_pmu_data = { + .pmu_cpuhp = true, +}; +
You may want to consider having an e850-pmu.c file to contain the e850 specific data and hooks. Andre recently moved some of the gs101-specific parts into gs101-pmu.c (although not the actual gs101 online/offline hooks). Now that more SoCs are being added it could be a good time for exynos-pmu to contain only the generic code and the <soc>-pmu.c file having the peculiarities/hooks for the specific SoC.
quoted hunk ↗ jump to hunk
/* * PMU platform driver and devicetree bindings. */@@ -151,6 +155,7 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = { .compatible = "samsung,exynos7-pmu", }, { .compatible = "samsung,exynos850-pmu", + .data = &exynos850_pmu_data, }, { /*sentinel*/ }, };@@ -229,6 +234,65 @@ EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle); #define CPU_INFORM_CLEAR 0 #define CPU_INFORM_C2 1 +static int __exynos850_cpu_pmu_online(unsigned int cpu) + __must_hold(&pmu_context->cpupm_lock) +{ + u32 this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 2); + u32 cluster_cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1); + unsigned int cpuhint = smp_processor_id(); + u32 reg, mask; + + /* clear cpu inform hint */ + regmap_write(pmu_context->pmureg, EXYNOS850_CPU_INFORM(cpuhint), + CPU_INFORM_CLEAR); + + mask = BIT(cpu); + + regmap_update_bits(pmu_context->pmuintrgen, EXYNOS_GRP2_INTR_BID_ENABLE, + mask, (0 << cpu)); + + regmap_read(pmu_context->pmuintrgen, EXYNOS_GRP2_INTR_BID_UPEND, ®); + + regmap_write(pmu_context->pmuintrgen, EXYNOS_GRP2_INTR_BID_CLEAR, + reg & mask); + + regmap_update_bits(pmu_context->pmureg, + EXYNOS850_CLUSTER_CPU_INT_EN(this_cluster, cluster_cpu), + 1 << 3, 0 << 3); + return 0; +} + +static int __exynos850_cpu_pmu_offline(unsigned int cpu) + __must_hold(&pmu_context->cpupm_lock) +{ + u32 this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 2); + u32 cluster_cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1); + unsigned int cpuhint = smp_processor_id(); + u32 reg, mask; + + /* set cpu inform hint */ + regmap_write(pmu_context->pmureg, EXYNOS850_CPU_INFORM(cpuhint), + CPU_INFORM_C2); + + mask = BIT(cpu); + regmap_update_bits(pmu_context->pmuintrgen, EXYNOS_GRP2_INTR_BID_ENABLE, + mask, BIT(cpu)); + + regmap_read(pmu_context->pmuintrgen, EXYNOS_GRP1_INTR_BID_UPEND, ®); + regmap_write(pmu_context->pmuintrgen, EXYNOS_GRP1_INTR_BID_CLEAR, + reg & mask); + + mask = (BIT(cpu + 8)); + regmap_read(pmu_context->pmuintrgen, EXYNOS_GRP1_INTR_BID_UPEND, ®); + regmap_write(pmu_context->pmuintrgen, EXYNOS_GRP1_INTR_BID_CLEAR, + reg & mask); + + regmap_update_bits(pmu_context->pmureg, + EXYNOS850_CLUSTER_CPU_INT_EN(this_cluster, cluster_cpu), + 1 << 3, 1 << 3); + return 0; +} + /* * __gs101_cpu_pmu_ prefix functions are common code shared by CPU PM notifiers * (CPUIdle) and CPU hotplug callbacks. Functions should be called with IRQs@@ -416,8 +480,12 @@ static int setup_cpuhp_and_cpuidle(struct device *dev) void __iomem *virt_addr; int ret, cpu; - intr_gen_node = of_parse_phandle(dev->of_node, - "google,pmu-intr-gen-syscon", 0); + intr_gen_node = of_parse_phandle(dev->of_node, "samsung,pmu-intr-gen-syscon", 0); + + /* Fall back to the google pmu intr gen property for older DTBs */ + if (!intr_gen_node) + intr_gen_node = of_parse_phandle(dev->of_node, "google,pmu-intr-gen-syscon", 0); + if (!intr_gen_node) { /* * To maintain support for older DTs that didn't specify syscon@@ -427,9 +495,19 @@ static int setup_cpuhp_and_cpuidle(struct device *dev) return 0; } - pmu_context->cpu_pmu_online = __gs101_cpu_pmu_online; - pmu_context->cpu_pmu_offline = __gs101_cpu_pmu_offline; + if (of_machine_is_compatible("google,gs101")) { + pmu_context->cpu_pmu_online = __gs101_cpu_pmu_online; + pmu_context->cpu_pmu_offline = __gs101_cpu_pmu_offline; + } + + if (of_machine_is_compatible("samsung,exynos850")) { + pmu_context->cpu_pmu_online = __exynos850_cpu_pmu_online; + pmu_context->cpu_pmu_offline = __exynos850_cpu_pmu_offline;
There should be no compatibles inside probe (that rule applies to all drivers & subsystems). Instead use the driver match data (exynos_pmu_data). regards, Peter