Thread (20 messages) 20 messages, 3 authors, 2026-03-23

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, &reg);
+
+       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, &reg);
+       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, &reg);
+       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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help