|
@@ -65,8 +65,12 @@
|
|
|
#define PRCM_PWR_SWITCH_REG(c, cpu) (0x140 + 0x10 * (c) + 0x4 * (cpu))
|
|
|
#define PRCM_CPU_SOFT_ENTRY_REG 0x164
|
|
|
|
|
|
+#define CPU0_SUPPORT_HOTPLUG_MAGIC0 0xFA50392F
|
|
|
+#define CPU0_SUPPORT_HOTPLUG_MAGIC1 0x790DCA3A
|
|
|
+
|
|
|
static void __iomem *cpucfg_base;
|
|
|
static void __iomem *prcm_base;
|
|
|
+static void __iomem *sram_b_smp_base;
|
|
|
|
|
|
static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster)
|
|
|
{
|
|
@@ -125,6 +129,17 @@ static int sunxi_cpu_power_switch_set(unsigned int cpu, unsigned int cluster,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void sunxi_cpu0_hotplug_support_set(bool enable)
|
|
|
+{
|
|
|
+ if (enable) {
|
|
|
+ writel(CPU0_SUPPORT_HOTPLUG_MAGIC0, sram_b_smp_base);
|
|
|
+ writel(CPU0_SUPPORT_HOTPLUG_MAGIC1, sram_b_smp_base + 0x4);
|
|
|
+ } else {
|
|
|
+ writel(0x0, sram_b_smp_base);
|
|
|
+ writel(0x0, sram_b_smp_base + 0x4);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster)
|
|
|
{
|
|
|
u32 reg;
|
|
@@ -133,6 +148,10 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster)
|
|
|
if (cpu >= SUNXI_CPUS_PER_CLUSTER || cluster >= SUNXI_NR_CLUSTERS)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ /* Set hotplug support magic flags for cpu0 */
|
|
|
+ if (cluster == 0 && cpu == 0)
|
|
|
+ sunxi_cpu0_hotplug_support_set(true);
|
|
|
+
|
|
|
/* assert processor power-on reset */
|
|
|
reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
|
|
|
reg &= ~PRCM_CPU_PO_RST_CTRL_CORE(cpu);
|
|
@@ -362,6 +381,13 @@ static bool sunxi_mc_smp_cluster_is_down(unsigned int cluster)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static void sunxi_mc_smp_secondary_init(unsigned int cpu)
|
|
|
+{
|
|
|
+ /* Clear hotplug support magic flags for cpu0 */
|
|
|
+ if (cpu == 0)
|
|
|
+ sunxi_cpu0_hotplug_support_set(false);
|
|
|
+}
|
|
|
+
|
|
|
static int sunxi_mc_smp_boot_secondary(unsigned int l_cpu, struct task_struct *idle)
|
|
|
{
|
|
|
unsigned int mpidr, cpu, cluster;
|
|
@@ -572,13 +598,19 @@ out:
|
|
|
return !ret;
|
|
|
}
|
|
|
|
|
|
+static bool sunxi_mc_smp_cpu_can_disable(unsigned int __unused)
|
|
|
+{
|
|
|
+ return true;
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
static const struct smp_operations sunxi_mc_smp_smp_ops __initconst = {
|
|
|
+ .smp_secondary_init = sunxi_mc_smp_secondary_init,
|
|
|
.smp_boot_secondary = sunxi_mc_smp_boot_secondary,
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
.cpu_die = sunxi_mc_smp_cpu_die,
|
|
|
.cpu_kill = sunxi_mc_smp_cpu_kill,
|
|
|
+ .cpu_can_disable = sunxi_mc_smp_cpu_can_disable,
|
|
|
#endif
|
|
|
};
|
|
|
|
|
@@ -654,7 +686,7 @@ static int __init sunxi_mc_smp_lookback(void)
|
|
|
|
|
|
static int __init sunxi_mc_smp_init(void)
|
|
|
{
|
|
|
- struct device_node *cpucfg_node, *node;
|
|
|
+ struct device_node *cpucfg_node, *sram_node, *node;
|
|
|
struct resource res;
|
|
|
int ret;
|
|
|
|
|
@@ -702,16 +734,31 @@ static int __init sunxi_mc_smp_init(void)
|
|
|
goto err_put_cpucfg_node;
|
|
|
}
|
|
|
|
|
|
+ sram_node = of_find_compatible_node(NULL, NULL,
|
|
|
+ "allwinner,sun9i-a80-smp-sram");
|
|
|
+ if (!sram_node) {
|
|
|
+ ret = -ENODEV;
|
|
|
+ goto err_unmap_release_cpucfg;
|
|
|
+ }
|
|
|
+
|
|
|
+ sram_b_smp_base = of_io_request_and_map(sram_node, 0, "sunxi-mc-smp");
|
|
|
+ if (IS_ERR(sram_b_smp_base)) {
|
|
|
+ ret = PTR_ERR(sram_b_smp_base);
|
|
|
+ pr_err("%s: failed to map secure SRAM\n", __func__);
|
|
|
+ goto err_put_sram_node;
|
|
|
+ }
|
|
|
+
|
|
|
/* Configure CCI-400 for boot cluster */
|
|
|
ret = sunxi_mc_smp_lookback();
|
|
|
if (ret) {
|
|
|
pr_err("%s: failed to configure boot cluster: %d\n",
|
|
|
__func__, ret);
|
|
|
- goto err_unmap_release_cpucfg;
|
|
|
+ goto err_unmap_release_secure_sram;
|
|
|
}
|
|
|
|
|
|
- /* We don't need the CPUCFG device node anymore */
|
|
|
+ /* We don't need the CPUCFG and SRAM device nodes anymore */
|
|
|
of_node_put(cpucfg_node);
|
|
|
+ of_node_put(sram_node);
|
|
|
|
|
|
/* Set the hardware entry point address */
|
|
|
writel(__pa_symbol(sunxi_mc_smp_secondary_startup),
|
|
@@ -724,6 +771,12 @@ static int __init sunxi_mc_smp_init(void)
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
+err_unmap_release_secure_sram:
|
|
|
+ iounmap(sram_b_smp_base);
|
|
|
+ of_address_to_resource(sram_node, 0, &res);
|
|
|
+ release_mem_region(res.start, resource_size(&res));
|
|
|
+err_put_sram_node:
|
|
|
+ of_node_put(sram_node);
|
|
|
err_unmap_release_cpucfg:
|
|
|
iounmap(cpucfg_base);
|
|
|
of_address_to_resource(cpucfg_node, 0, &res);
|