mirror of https://github.com/OpenIPC/firmware.git
150 lines
4.4 KiB
Diff
150 lines
4.4 KiB
Diff
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 <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/smp.h>
|
|
+#include <linux/sunxi-sid.h>
|
|
|
|
-#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 <asm/cacheflush.h>
|
|
|
|
-#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);
|