--- zzzz-none-000/linux-3.10.107/arch/arm/mach-socfpga/platsmp.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/arm/mach-socfpga/platsmp.c 2021-02-04 17:41:59.000000000 +0000 @@ -29,53 +29,68 @@ #include "core.h" -static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) { int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; - if (cpu1start_addr) { + if (socfpga_cpu1start_addr) { + /* This will put CPU #1 into reset. */ + writel(RSTMGR_MPUMODRST_CPU1, + rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST); + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); - __raw_writel(virt_to_phys(socfpga_secondary_startup), - (sys_manager_base_addr + (cpu1start_addr & 0x000000ff))); + writel(virt_to_phys(secondary_startup), + sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff)); flush_cache_all(); smp_wmb(); outer_clean_range(0, trampoline_size); - /* This will release CPU #1 out of reset.*/ - __raw_writel(0, rst_manager_base_addr + 0x10); + /* This will release CPU #1 out of reset. */ + writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST); } return 0; } -/* - * Initialise the CPU possible map early - this describes the CPUs - * which may be present or become present in the system. - */ -static void __init socfpga_smp_init_cpus(void) +static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle) { - unsigned int i, ncores; + int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; + + if (socfpga_cpu1start_addr) { + writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr + + SOCFPGA_A10_RSTMGR_MODMPURST); + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); - ncores = scu_get_core_count(socfpga_scu_base_addr); + writel(virt_to_phys(secondary_startup), + sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff)); - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + flush_cache_all(); + smp_wmb(); + outer_clean_range(0, trampoline_size); - /* sanity check */ - if (ncores > num_possible_cpus()) { - pr_warn("socfpga: no. of cores (%d) greater than configured" - "maximum of %d - clipping\n", ncores, num_possible_cpus()); - ncores = num_possible_cpus(); + /* This will release CPU #1 out of reset. */ + writel(0, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_MODMPURST); } - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + return 0; } static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) { + struct device_node *np; + void __iomem *socfpga_scu_base_addr; + + np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (!np) { + pr_err("%s: missing scu\n", __func__); + return; + } + + socfpga_scu_base_addr = of_iomap(np, 0); + if (!socfpga_scu_base_addr) + return; scu_enable(socfpga_scu_base_addr); } @@ -86,17 +101,39 @@ */ static void socfpga_cpu_die(unsigned int cpu) { - cpu_do_idle(); + /* Do WFI. If we wake up early, go back into WFI */ + while (1) + cpu_do_idle(); +} - /* We should have never returned from idle */ - panic("cpu %d unexpectedly exit from shutdown\n", cpu); +/* + * We need a dummy function so that platform_can_cpu_hotplug() knows + * we support CPU hotplug. However, the function does not need to do + * anything, because CPUs going offline just do WFI. We could reset + * the CPUs but it would increase power consumption. + */ +static int socfpga_cpu_kill(unsigned int cpu) +{ + return 1; } -struct smp_operations socfpga_smp_ops __initdata = { - .smp_init_cpus = socfpga_smp_init_cpus, +static struct smp_operations socfpga_smp_ops __initdata = { .smp_prepare_cpus = socfpga_smp_prepare_cpus, .smp_boot_secondary = socfpga_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = socfpga_cpu_die, + .cpu_kill = socfpga_cpu_kill, +#endif +}; + +static struct smp_operations socfpga_a10_smp_ops __initdata = { + .smp_prepare_cpus = socfpga_smp_prepare_cpus, + .smp_boot_secondary = socfpga_a10_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = socfpga_cpu_die, + .cpu_kill = socfpga_cpu_kill, #endif }; + +CPU_METHOD_OF_DECLARE(socfpga_smp, "altr,socfpga-smp", &socfpga_smp_ops); +CPU_METHOD_OF_DECLARE(socfpga_a10_smp, "altr,socfpga-a10-smp", &socfpga_a10_smp_ops);