From 3de7d6f8dd121d5d4b74182765be5ee8f3954d29 Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Tue, 18 Aug 2026 16:05:42 +0100 Subject: [PATCH 1/5] dt-bindings: hwinfo: samsung,exynos-chipid: Add Exynos5515 compatible Add "samsung,exynos5515-chipid" compatible string to binding document, which is fully compatible with "samsung,exynos850-chipid". Signed-off-by: Aiden Isik Link: https://patch.msgid.link/20260818-for-next-lucky7-chipid-v2-1-28ae49f5c349@member.fsf.org Signed-off-by: Krzysztof Kozlowski --- .../devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml b/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml index b9cdfe52b62f..619faf33214b 100644 --- a/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml +++ b/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml @@ -25,6 +25,7 @@ properties: - items: - enum: - samsung,exynos2200-chipid + - samsung,exynos5515-chipid - samsung,exynos7885-chipid - samsung,exynos8895-chipid - samsung,exynos9610-chipid From 2f04ec82e51da9d5af5cb48c9f24c0318655b0f7 Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Tue, 18 Aug 2026 16:05:43 +0100 Subject: [PATCH 2/5] soc: samsung: exynos-chipid: Add Exynos5515 SoC support Add Exynos5515 information to the soc_ids table. The ChipID for Exynos5515 is "0xE5515000". Signed-off-by: Aiden Isik Link: https://patch.msgid.link/20260818-for-next-lucky7-chipid-v2-2-28ae49f5c349@member.fsf.org Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-chipid.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 6ef9751e2509..506a0bcdfe30 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -64,6 +64,7 @@ static const struct exynos_soc_id { { "EXYNOS8890", 0xE8890000 }, /* Compatible with: samsung,exynos850-chipid */ { "EXYNOS2200", 0xE9925000 }, + { "EXYNOS5515", 0xE5515000 }, { "EXYNOS7885", 0xE7885000 }, { "EXYNOS850", 0xE3830000 }, { "EXYNOS8895", 0xE8895000 }, From ca4fb89e677527e32d16c5eb779eb34bccd2b967 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Mon, 14 Sep 2026 17:58:44 +0100 Subject: [PATCH 3/5] dt-bindings: sram: Document samsung,exynos850-acpm-sram Document "samsung,exynos850-acpm-sram" which represents an SRAM region used for ACPM communication on Samsung-based SoCs. The SRAM is consumed as a whole, is not split up using child nodes and properties related to this are not required, that is why "mmio-sram" compatible can't be used for ACPM purposes because it requires child nodes to be declared, which are not needed and make no sense in case of ACPM. Reviewed-by: Krzysztof Kozlowski Reviewed-by: Sam Protsenko Signed-off-by: Alexey Klimov Reviewed-by: Peter Griffin Link: https://patch.msgid.link/20260914-exynos850_sram-v4-1-253871de0f61@linaro.org Signed-off-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/sram/sram.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index b83fc6831947..b9c4d4f3199b 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -43,6 +43,7 @@ properties: - qcom,rpm-msg-ram - qcom,shikra-imem - rockchip,rk3288-pmu-sram + - samsung,exynos850-acpm-sram reg: maxItems: 1 @@ -159,6 +160,7 @@ if: enum: - qcom,rpm-msg-ram - rockchip,rk3288-pmu-sram + - samsung,exynos850-acpm-sram then: required: - "#address-cells" From f7b2b6acf658be412b0c4746d07d210a9e18f13b Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 30 Sep 2026 00:50:31 +0100 Subject: [PATCH 4/5] soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup The setup_cpuhp_and_cpuidle() initialisation sequence currently ignores the return values of cpuhp_setup_state(), cpu_pm_register_notifier(), and register_reboot_notifier(). If any of these registrations fail during probe() routine, the driver returns 0, leaving the driver partially configured. Furthermore, if anything after setup_cpuhp_and_cpuidle() fails in probe() routine, for instance devm_mfd_add_devices(), the probe() lacks an error path and leaves notifiers and cpu hotplug states registered. Introduce variables for the cpu hotplug state IDs in exynos_pmu_context struct, that should be initialised to CPUHP_INVALID by default. Check all return codes in setup_cpuhp_and_cpuidle(), and add an error path to remove registered states on failure. Finally, add destroy_cpuhp_and_cpuidle() helper to safely tear down notifiers and cpu hotplug states. Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260513-exynos850-cpuhotplug-v4-0-54fec5f65362@linaro.org?part=3 Fixes: 78b72897a5c8 ("soc: samsung: exynos-pmu: Enable CPU Idle for gs101") Cc: stable@vger.kernel.org Signed-off-by: Alexey Klimov Link: https://patch.msgid.link/20260930-exynos-pmu-cpuhp-idle-fixes-v3-1-4269d8425978@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-pmu.c | 61 +++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index f5fcdde9750e..759b246eccf9 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -38,6 +38,8 @@ struct exynos_pmu_context { unsigned long *in_cpuhp; bool sys_insuspend; bool sys_inreboot; + int cpuhp_prepare_state; + int cpuhp_online_state; }; void __iomem *pmu_base_addr; @@ -461,16 +463,55 @@ static int setup_cpuhp_and_cpuidle(struct device *dev) gs101_cpuhp_pmu_online(cpu); /* register CPU hotplug callbacks */ - cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare", - gs101_cpuhp_pmu_online, NULL); + pmu_context->cpuhp_prepare_state = CPUHP_INVALID; + pmu_context->cpuhp_online_state = CPUHP_INVALID; - cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online", - NULL, gs101_cpuhp_pmu_offline); + ret = cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare", + gs101_cpuhp_pmu_online, NULL); + if (ret < 0) + return ret; + + pmu_context->cpuhp_prepare_state = ret; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online", + NULL, gs101_cpuhp_pmu_offline); + if (ret < 0) + goto clean_cpuhp_state_prepare; + + pmu_context->cpuhp_online_state = ret; /* register CPU PM notifiers for cpuidle */ - cpu_pm_register_notifier(&gs101_cpu_pm_notifier); - register_reboot_notifier(&exynos_cpupm_reboot_nb); - return 0; + ret = cpu_pm_register_notifier(&gs101_cpu_pm_notifier); + if (ret) + goto clean_cpuhp_states; + + ret = register_reboot_notifier(&exynos_cpupm_reboot_nb); + if (!ret) + /* Success */ + return ret; + + cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier); + +clean_cpuhp_states: + cpuhp_remove_state(pmu_context->cpuhp_online_state); + pmu_context->cpuhp_online_state = CPUHP_INVALID; + +clean_cpuhp_state_prepare: + cpuhp_remove_state(pmu_context->cpuhp_prepare_state); + pmu_context->cpuhp_prepare_state = CPUHP_INVALID; + + return ret; +} + +static void destroy_cpuhp_and_cpuidle(void) +{ + cpu_pm_unregister_notifier(&gs101_cpu_pm_notifier); + unregister_reboot_notifier(&exynos_cpupm_reboot_nb); + + if (pmu_context->cpuhp_prepare_state != CPUHP_INVALID) + cpuhp_remove_state(pmu_context->cpuhp_prepare_state); + if (pmu_context->cpuhp_online_state != CPUHP_INVALID) + cpuhp_remove_state(pmu_context->cpuhp_online_state); } static int exynos_pmu_probe(struct platform_device *pdev) @@ -544,8 +585,12 @@ static int exynos_pmu_probe(struct platform_device *pdev) ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, exynos_pmu_devs, ARRAY_SIZE(exynos_pmu_devs), NULL, 0, NULL); - if (ret) + if (ret) { + if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) + destroy_cpuhp_and_cpuidle(); + return ret; + } if (devm_of_platform_populate(dev)) dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n"); From 682df6e2330123019fcdb9f6122f34a395082356 Mon Sep 17 00:00:00 2001 From: Jaidev Shastri Date: Mon, 21 Sep 2026 21:07:23 -0400 Subject: [PATCH 5/5] soc: samsung: exynos-pmu: order pmu_base_addr before the pmu_context gate exynos_sys_powerdown_conf() returns early while pmu_context is NULL and otherwise programs the PMU through pmu_raw_writel(), which uses the separate global pmu_base_addr. exynos_pmu_probe() maps pmu_base_addr and stores pmu_context afterwards, both with plain stores, and the reader loads both plainly. Neither the two stores nor the two loads are ordered. The callers are the Exynos cpuidle AFTR path and the suspend path on 32-bit Exynos, which run on other CPUs, so a caller that sees pmu_context before pmu_base_addr writes the power-down configuration through a NULL base. Publish pmu_context with smp_store_release() and read it with smp_load_acquire(). Found with MBCheck, a static herd7-based memory consistency checker. Signed-off-by: Jaidev Shastri Link: https://patch.msgid.link/20260921-mb-exynos-pmu-v1-1-4babb522ce0d@vt.edu Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-pmu.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index 759b246eccf9..c78fbd16c4ad 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -61,11 +61,14 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) { unsigned int i; const struct exynos_pmu_data *pmu_data; + struct exynos_pmu_context *ctx; - if (!pmu_context || !pmu_context->pmu_data) + /* Pairs with the smp_store_release() in exynos_pmu_probe(). */ + ctx = smp_load_acquire(&pmu_context); + if (!ctx || !ctx->pmu_data) return; - pmu_data = pmu_context->pmu_data; + pmu_data = ctx->pmu_data; if (pmu_data->powerdown_conf) pmu_data->powerdown_conf(mode); @@ -518,6 +521,7 @@ static int exynos_pmu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct regmap_config pmu_regmcfg; + struct exynos_pmu_context *ctx; struct regmap *regmap; struct resource *res; int ret; @@ -526,12 +530,19 @@ static int exynos_pmu_probe(struct platform_device *pdev) if (IS_ERR(pmu_base_addr)) return PTR_ERR(pmu_base_addr); - pmu_context = devm_kzalloc(&pdev->dev, - sizeof(struct exynos_pmu_context), - GFP_KERNEL); - if (!pmu_context) + ctx = devm_kzalloc(&pdev->dev, sizeof(struct exynos_pmu_context), + GFP_KERNEL); + if (!ctx) return -ENOMEM; + /* + * exynos_sys_powerdown_conf() gates on pmu_context and then writes + * through pmu_base_addr, which is a separate global. Publish the + * context with release semantics so that the mapping is visible to + * a CPU that passes the gate. + */ + smp_store_release(&pmu_context, ctx); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV;