From 2c3c1048746a4622d8c89a29670120dc8fab93c4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:49:45 +0200 Subject: Adding upstream version 6.1.76. Signed-off-by: Daniel Baumann --- arch/arm/mach-shmobile/platsmp-scu.c | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 arch/arm/mach-shmobile/platsmp-scu.c (limited to 'arch/arm/mach-shmobile/platsmp-scu.c') diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c new file mode 100644 index 000000000..3849f71e6 --- /dev/null +++ b/arch/arm/mach-shmobile/platsmp-scu.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SMP support for SoCs with SCU covered by mach-shmobile + * + * Copyright (C) 2013 Magnus Damm + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + + +static phys_addr_t shmobile_scu_base_phys; +static void __iomem *shmobile_scu_base; + +static int shmobile_scu_cpu_prepare(unsigned int cpu) +{ + /* For this particular CPU register SCU SMP boot vector */ + shmobile_smp_hook(cpu, __pa_symbol(shmobile_boot_scu), + shmobile_scu_base_phys); + return 0; +} + +void __init shmobile_smp_scu_prepare_cpus(phys_addr_t scu_base_phys, + unsigned int max_cpus) +{ + /* install boot code shared by all CPUs */ + shmobile_boot_fn = __pa_symbol(shmobile_smp_boot); + + /* enable SCU and cache coherency on booting CPU */ + shmobile_scu_base_phys = scu_base_phys; + shmobile_scu_base = ioremap(scu_base_phys, PAGE_SIZE); + scu_enable(shmobile_scu_base); + scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL); + + /* Use CPU notifier for reset vector control */ + cpuhp_setup_state_nocalls(CPUHP_ARM_SHMOBILE_SCU_PREPARE, + "arm/shmobile-scu:prepare", + shmobile_scu_cpu_prepare, NULL); +} + +#ifdef CONFIG_HOTPLUG_CPU +void shmobile_smp_scu_cpu_die(unsigned int cpu) +{ + /* For this particular CPU deregister boot vector */ + shmobile_smp_hook(cpu, 0, 0); + + dsb(); + flush_cache_all(); + + /* disable cache coherency */ + scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); + + /* jump to shared mach-shmobile sleep / reset code */ + shmobile_smp_sleep(); +} + +static int shmobile_smp_scu_psr_core_disabled(int cpu) +{ + unsigned long mask = SCU_PM_POWEROFF << (cpu * 8); + + if ((readl(shmobile_scu_base + 8) & mask) == mask) + return 1; + + return 0; +} + +int shmobile_smp_scu_cpu_kill(unsigned int cpu) +{ + int k; + + /* this function is running on another CPU than the offline target, + * here we need wait for shutdown code in platform_cpu_die() to + * finish before asking SoC-specific code to power off the CPU core. + */ + for (k = 0; k < 1000; k++) { + if (shmobile_smp_scu_psr_core_disabled(cpu)) + return 1; + + mdelay(1); + } + + return 0; +} +#endif -- cgit v1.2.3