diff -drupN a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c --- a/arch/arm/mach-sunxi/platsmp.c 2018-08-06 17:23:04.000000000 +0300 +++ b/arch/arm/mach-sunxi/platsmp.c 2022-06-12 05:28:14.000000000 +0300 @@ -20,19 +20,13 @@ #include #include #include +#include -#define CPUCFG_CPU_PWR_CLAMP_STATUS_REG(cpu) ((cpu) * 0x40 + 0x64) -#define CPUCFG_CPU_RST_CTRL_REG(cpu) (((cpu) + 1) * 0x40) -#define CPUCFG_CPU_CTRL_REG(cpu) (((cpu) + 1) * 0x40 + 0x04) -#define CPUCFG_CPU_STATUS_REG(cpu) (((cpu) + 1) * 0x40 + 0x08) -#define CPUCFG_GEN_CTRL_REG 0x184 -#define CPUCFG_PRIVATE0_REG 0x1a4 -#define CPUCFG_PRIVATE1_REG 0x1a8 -#define CPUCFG_DBG_CTL0_REG 0x1e0 -#define CPUCFG_DBG_CTL1_REG 0x1e4 +#include -#define PRCM_CPU_PWROFF_REG 0x100 -#define PRCM_CPU_PWR_CLAMP_REG(cpu) (((cpu) * 4) + 0x140) +#include "platsmp.h" + +void *cpus_boot_entry[NR_CPUS]; static void __iomem *cpucfg_membase; static void __iomem *prcm_membase; @@ -116,7 +110,7 @@ static int sun6i_smp_boot_secondary(unsi return 0; } -static const struct smp_operations sun6i_smp_ops __initconst = { +static struct smp_operations sun6i_smp_ops __initdata = { .smp_prepare_cpus = sun6i_smp_prepare_cpus, .smp_boot_secondary = sun6i_smp_boot_secondary, }; @@ -185,8 +179,110 @@ static int sun8i_smp_boot_secondary(unsi return 0; } -static const struct smp_operations sun8i_smp_ops __initconst = { +struct smp_operations sun8i_smp_ops __initdata = { .smp_prepare_cpus = sun8i_smp_prepare_cpus, .smp_boot_secondary = sun8i_smp_boot_secondary, }; CPU_METHOD_OF_DECLARE(sun8i_a23_smp, "allwinner,sun8i-a23", &sun8i_smp_ops); + +static void sunxi_set_cpus_boot_entry(int cpu, void *entry) +{ + if (cpu < num_possible_cpus()) { + cpus_boot_entry[cpu] = (void *)(virt_to_phys(entry)); + /* barrier */ + smp_wmb(); + __cpuc_flush_dcache_area(cpus_boot_entry, + sizeof(cpus_boot_entry)); + outer_clean_range(__pa(&cpus_boot_entry), + __pa(&cpus_boot_entry + 1)); + } +} + +static void __init sunxi_smp_init_cpus(void) +{ + unsigned int i, ncores = get_nr_cores(); + +#if defined(CONFIG_ARCH_SUN8IW11) || defined(CONFIG_ARCH_SUN8IW7) + unsigned int chip_ver = sunxi_get_soc_ver(); + + switch (chip_ver) { + case SUN8IW11P2_REV_A: + case SUN8IW11P3_REV_A: + case SUN8IW11P4_REV_A: + case SUN8IW7P1_REV_A: + case SUN8IW7P1_REV_B: + ncores = 4; + break; + case SUN8IW11P1_REV_A: + case SUN8IW7P2_REV_A: + case SUN8IW7P2_REV_B: + default: + ncores = 2; + break; + } +#endif + pr_debug("[%s] ncores = %u\n", __func__, ncores); + if (ncores > nr_cpu_ids) { + pr_warn(KERN_ERR "SMP: %u CPUs physically present. Only %d configured.\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); + +#ifdef CONFIG_CPU_IDLE_SUNXI + sunxi_idle_cpux_flag_init(); +#endif + pr_debug("[%s] done\n", __func__); +} + +/* + * Boot a secondary CPU, and assign it the specified idle task. + * This also gives us the initial stack to use for this CPU. + */ +static int sunxi_smp_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + if (!(sunxi_cpucfg_base && sunxi_soft_entry_base)) + return -EFAULT; + + spin_lock(&cpu_lock); + +#ifdef CONFIG_CPU_IDLE_SUNXI + writel(virt_to_phys(sunxi_cpux_entry_judge), + sunxi_soft_entry_base + CPU_SOFT_ENTRY_REG(cpu)); +#else + writel(virt_to_phys(sunxi_secondary_startup), + sunxi_soft_entry_base + CPU_SOFT_ENTRY_REG(cpu)); +#endif + + sunxi_set_cpus_boot_entry(cpu, secondary_startup); + + sunxi_enable_cpu(cpu); + + /* + * Now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&cpu_lock); + pr_debug("[%s] done\n", __func__); + + return 0; +} + +struct smp_operations sunxi_smp_ops = { + .smp_init_cpus = sunxi_smp_init_cpus, + .smp_boot_secondary = sunxi_smp_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = sunxi_cpu_die, + .cpu_kill = sunxi_cpu_kill, + .cpu_disable = sunxi_cpu_disable, +#endif +}; + + +CPU_METHOD_OF_DECLARE(sun8iw11p1_smp, "allwinner,sun8iw11p1", &sunxi_smp_ops); +CPU_METHOD_OF_DECLARE(sun8iw15p1_smp, "allwinner,sun8iw15p1", &sunxi_smp_ops); +CPU_METHOD_OF_DECLARE(sun8iw12p1_smp, "allwinner,sun8iw12p1", &sunxi_smp_ops); +CPU_METHOD_OF_DECLARE(sun8iw17p1_smp, "allwinner,sun8iw17p1", &sunxi_smp_ops); +CPU_METHOD_OF_DECLARE(sun8iw7p1_smp, "allwinner,sun8iw7p1", &sunxi_smp_ops);