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