Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * Copyright (C) 2014-2015 Broadcom Corporation 4 : : * Copyright 2014 Linaro Limited 5 : : */ 6 : : 7 : : #include <linux/cpumask.h> 8 : : #include <linux/delay.h> 9 : : #include <linux/errno.h> 10 : : #include <linux/init.h> 11 : : #include <linux/io.h> 12 : : #include <linux/irqchip/irq-bcm2836.h> 13 : : #include <linux/jiffies.h> 14 : : #include <linux/of.h> 15 : : #include <linux/of_address.h> 16 : : #include <linux/sched.h> 17 : : #include <linux/sched/clock.h> 18 : : #include <linux/smp.h> 19 : : 20 : : #include <asm/cacheflush.h> 21 : : #include <asm/smp.h> 22 : : #include <asm/smp_plat.h> 23 : : #include <asm/smp_scu.h> 24 : : 25 : : /* Size of mapped Cortex A9 SCU address space */ 26 : : #define CORTEX_A9_SCU_SIZE 0x58 27 : : 28 : : #define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */ 29 : : #define BOOT_ADDR_CPUID_MASK 0x3 30 : : 31 : : /* Name of device node property defining secondary boot register location */ 32 : : #define OF_SECONDARY_BOOT "secondary-boot-reg" 33 : : #define MPIDR_CPUID_BITMASK 0x3 34 : : 35 : : /* 36 : : * Enable the Cortex A9 Snoop Control Unit 37 : : * 38 : : * By the time this is called we already know there are multiple 39 : : * cores present. We assume we're running on a Cortex A9 processor, 40 : : * so any trouble getting the base address register or getting the 41 : : * SCU base is a problem. 42 : : * 43 : : * Return 0 if successful or an error code otherwise. 44 : : */ 45 : 0 : static int __init scu_a9_enable(void) 46 : : { 47 : : unsigned long config_base; 48 : : void __iomem *scu_base; 49 : : 50 : 0 : if (!scu_a9_has_base()) { 51 : 0 : pr_err("no configuration base address register!\n"); 52 : 0 : return -ENXIO; 53 : : } 54 : : 55 : : /* Config base address register value is zero for uniprocessor */ 56 : : config_base = scu_a9_get_base(); 57 : 0 : if (!config_base) { 58 : 0 : pr_err("hardware reports only one core\n"); 59 : 0 : return -ENOENT; 60 : : } 61 : : 62 : 0 : scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); 63 : 0 : if (!scu_base) { 64 : 0 : pr_err("failed to remap config base (%lu/%u) for SCU\n", 65 : : config_base, CORTEX_A9_SCU_SIZE); 66 : 0 : return -ENOMEM; 67 : : } 68 : : 69 : : scu_enable(scu_base); 70 : : 71 : 0 : iounmap(scu_base); /* That's the last we'll need of this */ 72 : : 73 : 0 : return 0; 74 : : } 75 : : 76 : 0 : static u32 secondary_boot_addr_for(unsigned int cpu) 77 : : { 78 : 0 : u32 secondary_boot_addr = 0; 79 : 0 : struct device_node *cpu_node = of_get_cpu_node(cpu, NULL); 80 : : 81 : 0 : if (!cpu_node) { 82 : 0 : pr_err("Failed to find device tree node for CPU%u\n", cpu); 83 : 0 : return 0; 84 : : } 85 : : 86 : 0 : if (of_property_read_u32(cpu_node, 87 : : OF_SECONDARY_BOOT, 88 : : &secondary_boot_addr)) 89 : 0 : pr_err("required secondary boot register not specified for CPU%u\n", 90 : : cpu); 91 : : 92 : 0 : of_node_put(cpu_node); 93 : : 94 : 0 : return secondary_boot_addr; 95 : : } 96 : : 97 : 0 : static int nsp_write_lut(unsigned int cpu) 98 : : { 99 : : void __iomem *sku_rom_lut; 100 : : phys_addr_t secondary_startup_phy; 101 : 0 : const u32 secondary_boot_addr = secondary_boot_addr_for(cpu); 102 : : 103 : 0 : if (!secondary_boot_addr) 104 : : return -EINVAL; 105 : : 106 : 0 : sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, 107 : : sizeof(phys_addr_t)); 108 : 0 : if (!sku_rom_lut) { 109 : 0 : pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu); 110 : 0 : return -ENOMEM; 111 : : } 112 : : 113 : 0 : secondary_startup_phy = __pa_symbol(secondary_startup); 114 : : BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX); 115 : : 116 : : writel_relaxed(secondary_startup_phy, sku_rom_lut); 117 : : 118 : : /* Ensure the write is visible to the secondary core */ 119 : 0 : smp_wmb(); 120 : : 121 : 0 : iounmap(sku_rom_lut); 122 : : 123 : 0 : return 0; 124 : : } 125 : : 126 : 0 : static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) 127 : : { 128 : 0 : const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; 129 : : 130 : : /* Enable the SCU on Cortex A9 based SoCs */ 131 : 0 : if (scu_a9_enable()) { 132 : : /* Update the CPU present map to reflect uniprocessor mode */ 133 : 0 : pr_warn("failed to enable A9 SCU - disabling SMP\n"); 134 : 0 : init_cpu_present(&only_cpu_0); 135 : : } 136 : 0 : } 137 : : 138 : : /* 139 : : * The ROM code has the secondary cores looping, waiting for an event. 140 : : * When an event occurs each core examines the bottom two bits of the 141 : : * secondary boot register. When a core finds those bits contain its 142 : : * own core id, it performs initialization, including computing its boot 143 : : * address by clearing the boot register value's bottom two bits. The 144 : : * core signals that it is beginning its execution by writing its boot 145 : : * address back to the secondary boot register, and finally jumps to 146 : : * that address. 147 : : * 148 : : * So to start a core executing we need to: 149 : : * - Encode the (hardware) CPU id with the bottom bits of the secondary 150 : : * start address. 151 : : * - Write that value into the secondary boot register. 152 : : * - Generate an event to wake up the secondary CPU(s). 153 : : * - Wait for the secondary boot register to be re-written, which 154 : : * indicates the secondary core has started. 155 : : */ 156 : 0 : static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) 157 : : { 158 : : void __iomem *boot_reg; 159 : : phys_addr_t boot_func; 160 : : u64 start_clock; 161 : : u32 cpu_id; 162 : : u32 boot_val; 163 : : bool timeout = false; 164 : 0 : const u32 secondary_boot_addr = secondary_boot_addr_for(cpu); 165 : : 166 : 0 : cpu_id = cpu_logical_map(cpu); 167 : 0 : if (cpu_id & ~BOOT_ADDR_CPUID_MASK) { 168 : 0 : pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK); 169 : 0 : return -EINVAL; 170 : : } 171 : : 172 : 0 : if (!secondary_boot_addr) 173 : : return -EINVAL; 174 : : 175 : 0 : boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr, 176 : : sizeof(phys_addr_t)); 177 : 0 : if (!boot_reg) { 178 : 0 : pr_err("unable to map boot register for cpu %u\n", cpu_id); 179 : 0 : return -ENOMEM; 180 : : } 181 : : 182 : : /* 183 : : * Secondary cores will start in secondary_startup(), 184 : : * defined in "arch/arm/kernel/head.S" 185 : : */ 186 : 0 : boot_func = __pa_symbol(secondary_startup); 187 : 0 : BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK); 188 : : BUG_ON(boot_func > (phys_addr_t)U32_MAX); 189 : : 190 : : /* The core to start is encoded in the low bits */ 191 : 0 : boot_val = (u32)boot_func | cpu_id; 192 : : writel_relaxed(boot_val, boot_reg); 193 : : 194 : 0 : sev(); 195 : : 196 : : /* The low bits will be cleared once the core has started */ 197 : : start_clock = local_clock(); 198 : 0 : while (!timeout && readl_relaxed(boot_reg) == boot_val) 199 : 0 : timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS; 200 : : 201 : 0 : iounmap(boot_reg); 202 : : 203 : 0 : if (!timeout) 204 : : return 0; 205 : : 206 : 0 : pr_err("timeout waiting for cpu %u to start\n", cpu_id); 207 : : 208 : 0 : return -ENXIO; 209 : : } 210 : : 211 : : /* Cluster Dormant Control command to bring CPU into a running state */ 212 : : #define CDC_CMD 6 213 : : #define CDC_CMD_OFFSET 0 214 : : #define CDC_CMD_REG(cpu) (CDC_CMD_OFFSET + 4*(cpu)) 215 : : 216 : : /* 217 : : * BCM23550 has a Cluster Dormant Control block that keeps the core in 218 : : * idle state. A command needs to be sent to the block to bring the CPU 219 : : * into running state. 220 : : */ 221 : 0 : static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle) 222 : : { 223 : : void __iomem *cdc_base; 224 : : struct device_node *dn; 225 : : char *name; 226 : : int ret; 227 : : 228 : : /* Make sure a CDC node exists before booting the 229 : : * secondary core. 230 : : */ 231 : : name = "brcm,bcm23550-cdc"; 232 : 0 : dn = of_find_compatible_node(NULL, NULL, name); 233 : 0 : if (!dn) { 234 : 0 : pr_err("unable to find cdc node\n"); 235 : 0 : return -ENODEV; 236 : : } 237 : : 238 : 0 : cdc_base = of_iomap(dn, 0); 239 : 0 : of_node_put(dn); 240 : : 241 : 0 : if (!cdc_base) { 242 : 0 : pr_err("unable to remap cdc base register\n"); 243 : 0 : return -ENOMEM; 244 : : } 245 : : 246 : : /* Boot the secondary core */ 247 : 0 : ret = kona_boot_secondary(cpu, idle); 248 : 0 : if (ret) 249 : : goto out; 250 : : 251 : : /* Bring this CPU to RUN state so that nIRQ nFIQ 252 : : * signals are unblocked. 253 : : */ 254 : 0 : writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu)); 255 : : 256 : : out: 257 : 0 : iounmap(cdc_base); 258 : : 259 : 0 : return ret; 260 : : } 261 : : 262 : 0 : static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) 263 : : { 264 : : int ret; 265 : : 266 : : /* 267 : : * After wake up, secondary core branches to the startup 268 : : * address programmed at SKU ROM LUT location. 269 : : */ 270 : 0 : ret = nsp_write_lut(cpu); 271 : 0 : if (ret) { 272 : 0 : pr_err("unable to write startup addr to SKU ROM LUT\n"); 273 : 0 : goto out; 274 : : } 275 : : 276 : : /* Send a CPU wakeup interrupt to the secondary core */ 277 : 0 : arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 278 : : 279 : : out: 280 : 0 : return ret; 281 : : } 282 : : 283 : 3 : static int bcm2836_boot_secondary(unsigned int cpu, struct task_struct *idle) 284 : : { 285 : : void __iomem *intc_base; 286 : : struct device_node *dn; 287 : : char *name; 288 : : 289 : : name = "brcm,bcm2836-l1-intc"; 290 : 3 : dn = of_find_compatible_node(NULL, NULL, name); 291 : 3 : if (!dn) { 292 : 0 : pr_err("unable to find intc node\n"); 293 : 0 : return -ENODEV; 294 : : } 295 : : 296 : 3 : intc_base = of_iomap(dn, 0); 297 : 3 : of_node_put(dn); 298 : : 299 : 3 : if (!intc_base) { 300 : 0 : pr_err("unable to remap intc base register\n"); 301 : 0 : return -ENOMEM; 302 : : } 303 : : 304 : 3 : writel(virt_to_phys(secondary_startup), 305 : : intc_base + LOCAL_MAILBOX3_SET0 + 16 * cpu); 306 : : 307 : 3 : dsb(sy); 308 : 3 : sev(); 309 : : 310 : 3 : iounmap(intc_base); 311 : : 312 : 3 : return 0; 313 : : } 314 : : 315 : : static const struct smp_operations kona_smp_ops __initconst = { 316 : : .smp_prepare_cpus = bcm_smp_prepare_cpus, 317 : : .smp_boot_secondary = kona_boot_secondary, 318 : : }; 319 : : CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", 320 : : &kona_smp_ops); 321 : : 322 : : static const struct smp_operations bcm23550_smp_ops __initconst = { 323 : : .smp_boot_secondary = bcm23550_boot_secondary, 324 : : }; 325 : : CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550", 326 : : &bcm23550_smp_ops); 327 : : 328 : : static const struct smp_operations nsp_smp_ops __initconst = { 329 : : .smp_prepare_cpus = bcm_smp_prepare_cpus, 330 : : .smp_boot_secondary = nsp_boot_secondary, 331 : : }; 332 : : CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); 333 : : 334 : : const struct smp_operations bcm2836_smp_ops __initconst = { 335 : : .smp_boot_secondary = bcm2836_boot_secondary, 336 : : }; 337 : : CPU_METHOD_OF_DECLARE(bcm_smp_bcm2836, "brcm,bcm2836-smp", &bcm2836_smp_ops);