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/of_address.h> 15 #include <linux/of.h> 16 #include <linux/smp.h> 17 18 #include <asm/cacheflush.h> 19 #include <asm/page.h> 20 #include <asm/smp_scu.h> 21 #include <asm/mach/map.h> 22 23 #include "common.h" 24 #include "hardware.h" 25 26 u32 g_diag_reg; 27 static void __iomem *scu_base; 28 29 static struct map_desc scu_io_desc __initdata = { 30 /* .virtual and .pfn are run-time assigned */ 31 .length = SZ_4K, 32 .type = MT_DEVICE, 33 }; 34 35 void __init imx_scu_map_io(void) 36 { 37 unsigned long base; 38 39 /* Get SCU base */ 40 asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); 41 42 scu_io_desc.virtual = IMX_IO_P2V(base); 43 scu_io_desc.pfn = __phys_to_pfn(base); 44 iotable_init(&scu_io_desc, 1); 45 46 scu_base = IMX_IO_ADDRESS(base); 47 } 48 49 static int imx_boot_secondary(unsigned int cpu, struct task_struct *idle) 50 { 51 imx_set_cpu_jump(cpu, v7_secondary_startup); 52 imx_enable_cpu(cpu, true); 53 return 0; 54 } 55 56 /* 57 * Initialise the CPU possible map early - this describes the CPUs 58 * which may be present or become present in the system. 59 */ 60 static void __init imx_smp_init_cpus(void) 61 { 62 int i, ncores; 63 64 ncores = scu_get_core_count(scu_base); 65 66 for (i = ncores; i < NR_CPUS; i++) 67 set_cpu_possible(i, false); 68 } 69 70 void imx_smp_prepare(void) 71 { 72 scu_enable(scu_base); 73 } 74 75 static void __init imx_smp_prepare_cpus(unsigned int max_cpus) 76 { 77 imx_smp_prepare(); 78 79 /* 80 * The diagnostic register holds the errata bits. Mostly bootloader 81 * does not bring up secondary cores, so that when errata bits are set 82 * in bootloader, they are set only for boot cpu. But on a SMP 83 * configuration, it should be equally done on every single core. 84 * Read the register from boot cpu here, and will replicate it into 85 * secondary cores when booting them. 86 */ 87 asm("mrc p15, 0, %0, c15, c0, 1" : "=r" (g_diag_reg) : : "cc"); 88 sync_cache_w(&g_diag_reg); 89 } 90 91 struct smp_operations imx_smp_ops __initdata = { 92 .smp_init_cpus = imx_smp_init_cpus, 93 .smp_prepare_cpus = imx_smp_prepare_cpus, 94 .smp_boot_secondary = imx_boot_secondary, 95 #ifdef CONFIG_HOTPLUG_CPU 96 .cpu_die = imx_cpu_die, 97 .cpu_kill = imx_cpu_kill, 98 #endif 99 }; 100 101 #define DCFG_CCSR_SCRATCHRW1 0x200 102 103 static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle) 104 { 105 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 106 107 return 0; 108 } 109 110 static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus) 111 { 112 struct device_node *np; 113 void __iomem *dcfg_base; 114 unsigned long paddr; 115 116 np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg"); 117 dcfg_base = of_iomap(np, 0); 118 BUG_ON(!dcfg_base); 119 120 paddr = virt_to_phys(secondary_startup); 121 writel_relaxed(cpu_to_be32(paddr), dcfg_base + DCFG_CCSR_SCRATCHRW1); 122 123 iounmap(dcfg_base); 124 } 125 126 struct smp_operations ls1021a_smp_ops __initdata = { 127 .smp_prepare_cpus = ls1021a_smp_prepare_cpus, 128 .smp_boot_secondary = ls1021a_boot_secondary, 129 }; 130