Samsung SoC drivers for v7.4

1. First driver patches for Exynos5515.
 2. Fix error paths and possible probe-ordering issue of Exynos PMU
    (Power Management) driver.
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAmrDeJ4QHGtyemtAa2Vy
 bmVsLm9yZwAKCRDBN2bmhouD17cCD/9WADWX1lHP8/rgLZLFQNtYR2XFrZAA71Yx
 25nlpwBMmcPw6+/dT60gqeCEIIdv3KU+40UtRTbdPa7ZKYlaK1Jktg2zlDOzato+
 /QgjRJ9/fEstNvbbd7B0N6T9WwKa47OreXp4V9nnR3EZPpjgCxPSJ/m0/f2SwWEj
 1WVzlwhdrchoUxVDO/lYGuNI4/jC+xTocMWvROyZbvuIB+lh2LwBUonX2X5YwszF
 q7EYkNCaz6RBmqmRS7P8vUsYcmmGF0INBxBAyQ3Yxsd+0ii7OAi0BY2Gr7q7nQC8
 6DXTIPazXybbkFhVxUfAlrlMcNMhDePHij3fC870WrS/N8RJDzl7B/MhKcu8+HID
 LUvvY7VCZoaVVkG7POwRV/UjhSKcnT0oGlOxojHoeXsNwk//QJiTRIfOWqHsbhrn
 FGl7vL1+o/TZueUJdoLdYXHBqSELj6k0jNeBWzn2iKF+2veoEn23cynI0yOZxj3D
 SpWw5496hd6jTB4O0+jPB5qUrj1JDhNa0eHZSBbIkZTJum140khwSu3/7YFZyJmM
 EdlpBYIiVPWZpZz6cQk2cPBGgasFpB+8Jy/NV0DHSGnrnnp/HI/Hv0KC9aKftfDA
 y/fEMjUqvbK1CiSnHT/S8tmiflhmaaYMrv4mMdinMEz4P9V2j4cnCrx7s1KUnVsG
 luLlZz6j+A==
 =Ydwa
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmrOQGAACgkQmmx57+YA
 GNlDZQ//UJmkYMt8NCXd5AjOFMJDdc3jnNNSFrnmmfgmTTh1k8Blt2b22bemSkCy
 fknsoDctX59hncTOrAhNg9T0IMvY2pJAOAoSpEyld95kAqGieID1ZuRF1o7YJr4b
 HsbdWoe/2KpzTx6XCQ1SdEVB+8Sd9K0lzXygSzHw6bWScWx1TzVYh1CHVBDwLCgd
 ggqt+Xnb0K7tXcGUaDRRu3Y+Iu1q4fNM9vUC6fOSeav3d0/mz67chqhW5RrOqBym
 UK9k2d2tUAuN25jmwjiyL3KvRMtC/J5kGDFbA6BzMSXKnTAEWEghzfUI4sVtL5Jq
 Aa5MsvtJLckWiM1LzBddDxrsvxZOUPRwRpqP2c5PD3CnsnwTw6guoxYFo1AjMtVF
 dD+ynaSkHCuaHmHPvVkXk/cyRVdK5nNwU5MPyXvd06MEy5zERbmSdNUBtJO8PXzG
 WBJHDDSuLg4aJXiVY7UuG4+vApwSsK4yRwNLK4h4r3XBd2uePEuFyYB5GvOkZSIv
 3fGOPmDhU7iAZyJtVG3lUYLwXXYcoSkuZ9gjJGKYTmARF2CbP1wt82RzIPoJxQVD
 9kkW+oZLL2Wv8biQaHFnDr6ZHnheRKpD5XOvFlk0iuxjDqQu6S6hzky+B5ghXq8z
 Z/pM43PsUGJnfyfkF6Jvsm8NXA9LFetaQTAeVCq61dnmaUi9smo=
 =dANe
 -----END PGP SIGNATURE-----

Merge tag 'samsung-drivers-7.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/drivers

Samsung SoC drivers for v7.4

1. First driver patches for Exynos5515.
2. Fix error paths and possible probe-ordering issue of Exynos PMU
   (Power Management) driver.

* tag 'samsung-drivers-7.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
  soc: samsung: exynos-pmu: order pmu_base_addr before the pmu_context gate
  soc: samsung: exynos-pmu: fix error paths in cpuhotplug/idle states setup
  dt-bindings: sram: Document samsung,exynos850-acpm-sram
  soc: samsung: exynos-chipid: Add Exynos5515 SoC support
  dt-bindings: hwinfo: samsung,exynos-chipid: Add Exynos5515 compatible

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2026-10-13 16:29:46 +02:00
commit ff5091590e
4 changed files with 74 additions and 14 deletions

View File

@ -25,6 +25,7 @@ properties:
- items:
- enum:
- samsung,exynos2200-chipid
- samsung,exynos5515-chipid
- samsung,exynos7885-chipid
- samsung,exynos8895-chipid
- samsung,exynos9610-chipid

View File

@ -44,6 +44,7 @@ properties:
- qcom,rpm-msg-ram
- qcom,shikra-imem
- rockchip,rk3288-pmu-sram
- samsung,exynos850-acpm-sram
reg:
maxItems: 1
@ -160,6 +161,7 @@ if:
enum:
- qcom,rpm-msg-ram
- rockchip,rk3288-pmu-sram
- samsung,exynos850-acpm-sram
then:
required:
- "#address-cells"

View File

@ -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 },

View File

@ -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;
@ -59,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);
@ -461,22 +466,62 @@ 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)
{
struct device *dev = &pdev->dev;
struct regmap_config pmu_regmcfg;
struct exynos_pmu_context *ctx;
struct regmap *regmap;
struct resource *res;
int ret;
@ -485,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;
@ -544,8 +596,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");