1 /* 2 * Copyright 2011 Freescale Semiconductor, Inc. 3 * Copyright 2011 Linaro Ltd. 4 * 5 * The code contained herein is licensed under the GNU General Public 6 * License. You may obtain a copy of the GNU General Public License 7 * Version 2 or later at the following locations: 8 * 9 * http://www.opensource.org/licenses/gpl-license.html 10 * http://www.gnu.org/copyleft/gpl.html 11 */ 12 13 #include <linux/init.h> 14 #include <linux/smp.h> 15 #include <linux/irqchip/arm-gic.h> 16 #include <asm/page.h> 17 #include <asm/smp_scu.h> 18 #include <asm/mach/map.h> 19 20 #include "common.h" 21 #include "hardware.h" 22 23 #define SCU_STANDBY_ENABLE (1 << 5) 24 25 static void __iomem *scu_base; 26 27 static struct map_desc scu_io_desc __initdata = { 28 /* .virtual and .pfn are run-time assigned */ 29 .length = SZ_4K, 30 .type = MT_DEVICE, 31 }; 32 33 void __init imx_scu_map_io(void) 34 { 35 unsigned long base; 36 37 /* Get SCU base */ 38 asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); 39 40 scu_io_desc.virtual = IMX_IO_P2V(base); 41 scu_io_desc.pfn = __phys_to_pfn(base); 42 iotable_init(&scu_io_desc, 1); 43 44 scu_base = IMX_IO_ADDRESS(base); 45 } 46 47 void imx_scu_standby_enable(void) 48 { 49 u32 val = readl_relaxed(scu_base); 50 51 val |= SCU_STANDBY_ENABLE; 52 writel_relaxed(val, scu_base); 53 } 54 55 static void __cpuinit imx_secondary_init(unsigned int cpu) 56 { 57 /* 58 * if any interrupts are already enabled for the primary 59 * core (e.g. timer irq), then they will not have been enabled 60 * for us: do so 61 */ 62 gic_secondary_init(0); 63 } 64 65 static int __cpuinit imx_boot_secondary(unsigned int cpu, struct task_struct *idle) 66 { 67 imx_set_cpu_jump(cpu, v7_secondary_startup); 68 imx_enable_cpu(cpu, true); 69 return 0; 70 } 71 72 /* 73 * Initialise the CPU possible map early - this describes the CPUs 74 * which may be present or become present in the system. 75 */ 76 static void __init imx_smp_init_cpus(void) 77 { 78 int i, ncores; 79 80 ncores = scu_get_core_count(scu_base); 81 82 for (i = 0; i < ncores; i++) 83 set_cpu_possible(i, true); 84 } 85 86 void imx_smp_prepare(void) 87 { 88 scu_enable(scu_base); 89 } 90 91 static void __init imx_smp_prepare_cpus(unsigned int max_cpus) 92 { 93 imx_smp_prepare(); 94 } 95 96 struct smp_operations imx_smp_ops __initdata = { 97 .smp_init_cpus = imx_smp_init_cpus, 98 .smp_prepare_cpus = imx_smp_prepare_cpus, 99 .smp_secondary_init = imx_secondary_init, 100 .smp_boot_secondary = imx_boot_secondary, 101 #ifdef CONFIG_HOTPLUG_CPU 102 .cpu_die = imx_cpu_die, 103 .cpu_kill = imx_cpu_kill, 104 #endif 105 }; 106