2 * RK30 SMP source file. It contains platform specific fucntions
3 * needed for the linux smp kernel.
5 * Copyright (C) 2012 ROCKCHIP, Inc.
9 #include <linux/init.h>
10 #include <linux/smp.h>
12 #include <linux/version.h>
14 #include <asm/cacheflush.h>
15 #include <asm/fiq_glue.h>
16 #include <asm/hardware/gic.h>
17 #include <asm/smp_scu.h>
22 #define SCU_STANDBY_EN (1 << 5)
25 static void gic_raise_softirq_non_secure(const struct cpumask *mask, unsigned int irq)
27 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
28 unsigned long map = *cpus_addr(*mask);
31 unsigned long map = 0;
33 /* Convert our logical CPU mask into a physical one. */
34 for_each_cpu(cpu, mask)
35 map |= 1 << cpu_logical_map(cpu);
39 * Ensure that stores to Normal memory are visible to the
40 * other CPUs before issuing the IPI.
44 /* this always happens on GIC0 */
45 writel_relaxed(map << 16 | irq | 0x8000, RK30_GICD_BASE + GIC_DIST_SOFTINT);
48 static void gic_secondary_init_non_secure(void)
50 #define GIC_DIST_SECURITY 0x080
51 writel_relaxed(0xffffffff, RK30_GICD_BASE + GIC_DIST_SECURITY);
52 writel_relaxed(0xf, RK30_GICC_BASE + GIC_CPU_CTRL);
57 void __cpuinit platform_secondary_init(unsigned int cpu)
60 * if any interrupts are already enabled for the primary
61 * core (e.g. timer irq), then they will not have been enabled
64 gic_secondary_init(0);
67 gic_secondary_init_non_secure();
72 extern void rk30_sram_secondary_startup(void);
74 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
76 static bool first = true;
79 unsigned long sz = 0x10;
80 unsigned int i, ncores = scu_get_core_count(RK30_SCU_BASE);
82 for (i = 1; i < ncores; i++)
83 pmu_set_power_domain(PD_A9_0 + i, false);
85 memcpy(RK30_IMEM_BASE, rk30_sram_secondary_startup, sz);
86 flush_icache_range((unsigned long)RK30_IMEM_BASE, (unsigned long)RK30_IMEM_BASE + sz);
87 outer_clean_range(0, sz);
93 pmu_set_power_domain(PD_A9_0 + cpu, true);
99 * Initialise the CPU possible map early - this describes the CPUs
100 * which may be present or become present in the system.
102 void __init smp_init_cpus(void)
104 unsigned int i, ncores = scu_get_core_count(RK30_SCU_BASE);
106 if (ncores > nr_cpu_ids) {
107 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
112 for (i = 0; i < ncores; i++)
113 set_cpu_possible(i, true);
116 set_smp_cross_call(gic_raise_softirq_non_secure);
118 set_smp_cross_call(gic_raise_softirq);
122 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
124 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
128 * Initialise the present map, which describes the set of CPUs
129 * actually populated at the present time.
131 for (i = 0; i < max_cpus; i++)
132 set_cpu_present(i, true);
135 writel_relaxed(readl_relaxed(RK30_SCU_BASE + SCU_CTRL) | SCU_STANDBY_EN, RK30_SCU_BASE + SCU_CTRL);
137 scu_enable(RK30_SCU_BASE);