linux/arch/mips/kernel/smp-bmips.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2011 by Kevin Cernekee (cernekee@gmail.com)
   7 *
   8 * SMP support for BMIPS
   9 */
  10
  11#include <linux/init.h>
  12#include <linux/sched.h>
  13#include <linux/mm.h>
  14#include <linux/delay.h>
  15#include <linux/smp.h>
  16#include <linux/interrupt.h>
  17#include <linux/spinlock.h>
  18#include <linux/cpu.h>
  19#include <linux/cpumask.h>
  20#include <linux/reboot.h>
  21#include <linux/io.h>
  22#include <linux/compiler.h>
  23#include <linux/linkage.h>
  24#include <linux/bug.h>
  25#include <linux/kernel.h>
  26
  27#include <asm/time.h>
  28#include <asm/pgtable.h>
  29#include <asm/processor.h>
  30#include <asm/bootinfo.h>
  31#include <asm/pmon.h>
  32#include <asm/cacheflush.h>
  33#include <asm/tlbflush.h>
  34#include <asm/mipsregs.h>
  35#include <asm/bmips.h>
  36#include <asm/traps.h>
  37#include <asm/barrier.h>
  38
  39static int __maybe_unused max_cpus = 1;
  40
  41/* these may be configured by the platform code */
  42int bmips_smp_enabled = 1;
  43int bmips_cpu_offset;
  44cpumask_t bmips_booted_mask;
  45
  46#ifdef CONFIG_SMP
  47
  48/* initial $sp, $gp - used by arch/mips/kernel/bmips_vec.S */
  49unsigned long bmips_smp_boot_sp;
  50unsigned long bmips_smp_boot_gp;
  51
  52static void bmips_send_ipi_single(int cpu, unsigned int action);
  53static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
  54
  55/* SW interrupts 0,1 are used for interprocessor signaling */
  56#define IPI0_IRQ                        (MIPS_CPU_IRQ_BASE + 0)
  57#define IPI1_IRQ                        (MIPS_CPU_IRQ_BASE + 1)
  58
  59#define CPUNUM(cpu, shift)              (((cpu) + bmips_cpu_offset) << (shift))
  60#define ACTION_CLR_IPI(cpu, ipi)        (0x2000 | CPUNUM(cpu, 9) | ((ipi) << 8))
  61#define ACTION_SET_IPI(cpu, ipi)        (0x3000 | CPUNUM(cpu, 9) | ((ipi) << 8))
  62#define ACTION_BOOT_THREAD(cpu)         (0x08 | CPUNUM(cpu, 0))
  63
  64static void __init bmips_smp_setup(void)
  65{
  66        int i, cpu = 1, boot_cpu = 0;
  67
  68#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
  69        int cpu_hw_intr;
  70
  71        /* arbitration priority */
  72        clear_c0_brcm_cmt_ctrl(0x30);
  73
  74        /* NBK and weak order flags */
  75        set_c0_brcm_config_0(0x30000);
  76
  77        /* Find out if we are running on TP0 or TP1 */
  78        boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
  79
  80        /*
  81         * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
  82         * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
  83         * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
  84         */
  85        if (boot_cpu == 0)
  86                cpu_hw_intr = 0x02;
  87        else
  88                cpu_hw_intr = 0x1d;
  89
  90        change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15));
  91
  92        /* single core, 2 threads (2 pipelines) */
  93        max_cpus = 2;
  94#elif defined(CONFIG_CPU_BMIPS5000)
  95        /* enable raceless SW interrupts */
  96        set_c0_brcm_config(0x03 << 22);
  97
  98        /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
  99        change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
 100
 101        /* N cores, 2 threads per core */
 102        max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
 103
 104        /* clear any pending SW interrupts */
 105        for (i = 0; i < max_cpus; i++) {
 106                write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
 107                write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
 108        }
 109#endif
 110
 111        if (!bmips_smp_enabled)
 112                max_cpus = 1;
 113
 114        /* this can be overridden by the BSP */
 115        if (!board_ebase_setup)
 116                board_ebase_setup = &bmips_ebase_setup;
 117
 118        __cpu_number_map[boot_cpu] = 0;
 119        __cpu_logical_map[0] = boot_cpu;
 120
 121        for (i = 0; i < max_cpus; i++) {
 122                if (i != boot_cpu) {
 123                        __cpu_number_map[i] = cpu;
 124                        __cpu_logical_map[cpu] = i;
 125                        cpu++;
 126                }
 127                set_cpu_possible(i, 1);
 128                set_cpu_present(i, 1);
 129        }
 130}
 131
 132/*
 133 * IPI IRQ setup - runs on CPU0
 134 */
 135static void bmips_prepare_cpus(unsigned int max_cpus)
 136{
 137        if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
 138                        "smp_ipi0", NULL))
 139                panic("Can't request IPI0 interrupt\n");
 140        if (request_irq(IPI1_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
 141                        "smp_ipi1", NULL))
 142                panic("Can't request IPI1 interrupt\n");
 143}
 144
 145/*
 146 * Tell the hardware to boot CPUx - runs on CPU0
 147 */
 148static void bmips_boot_secondary(int cpu, struct task_struct *idle)
 149{
 150        bmips_smp_boot_sp = __KSTK_TOS(idle);
 151        bmips_smp_boot_gp = (unsigned long)task_thread_info(idle);
 152        mb();
 153
 154        /*
 155         * Initial boot sequence for secondary CPU:
 156         *   bmips_reset_nmi_vec @ a000_0000 ->
 157         *   bmips_smp_entry ->
 158         *   plat_wired_tlb_setup (cached function call; optional) ->
 159         *   start_secondary (cached jump)
 160         *
 161         * Warm restart sequence:
 162         *   play_dead WAIT loop ->
 163         *   bmips_smp_int_vec @ BMIPS_WARM_RESTART_VEC ->
 164         *   eret to play_dead ->
 165         *   bmips_secondary_reentry ->
 166         *   start_secondary
 167         */
 168
 169        pr_info("SMP: Booting CPU%d...\n", cpu);
 170
 171        if (cpumask_test_cpu(cpu, &bmips_booted_mask))
 172                bmips_send_ipi_single(cpu, 0);
 173        else {
 174#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
 175                /* Reset slave TP1 if booting from TP0 */
 176                if (cpu_logical_map(cpu) == 1)
 177                        set_c0_brcm_cmt_ctrl(0x01);
 178#elif defined(CONFIG_CPU_BMIPS5000)
 179                if (cpu & 0x01)
 180                        write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
 181                else {
 182                        /*
 183                         * core N thread 0 was already booted; just
 184                         * pulse the NMI line
 185                         */
 186                        bmips_write_zscm_reg(0x210, 0xc0000000);
 187                        udelay(10);
 188                        bmips_write_zscm_reg(0x210, 0x00);
 189                }
 190#endif
 191                cpumask_set_cpu(cpu, &bmips_booted_mask);
 192        }
 193}
 194
 195/*
 196 * Early setup - runs on secondary CPU after cache probe
 197 */
 198static void bmips_init_secondary(void)
 199{
 200        /* move NMI vector to kseg0, in case XKS01 is enabled */
 201
 202#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
 203        void __iomem *cbr = BMIPS_GET_CBR();
 204        unsigned long old_vec;
 205        unsigned long relo_vector;
 206        int boot_cpu;
 207
 208        boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
 209        relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
 210                          BMIPS_RELO_VECTOR_CONTROL_1;
 211
 212        old_vec = __raw_readl(cbr + relo_vector);
 213        __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
 214
 215        clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
 216#elif defined(CONFIG_CPU_BMIPS5000)
 217        write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
 218                (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
 219
 220        write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
 221#endif
 222}
 223
 224/*
 225 * Late setup - runs on secondary CPU before entering the idle loop
 226 */
 227static void bmips_smp_finish(void)
 228{
 229        pr_info("SMP: CPU%d is running\n", smp_processor_id());
 230
 231        /* make sure there won't be a timer interrupt for a little while */
 232        write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
 233
 234        irq_enable_hazard();
 235        set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE);
 236        irq_enable_hazard();
 237}
 238
 239/*
 240 * Runs on CPU0 after all CPUs have been booted
 241 */
 242static void bmips_cpus_done(void)
 243{
 244}
 245
 246#if defined(CONFIG_CPU_BMIPS5000)
 247
 248/*
 249 * BMIPS5000 raceless IPIs
 250 *
 251 * Each CPU has two inbound SW IRQs which are independent of all other CPUs.
 252 * IPI0 is used for SMP_RESCHEDULE_YOURSELF
 253 * IPI1 is used for SMP_CALL_FUNCTION
 254 */
 255
 256static void bmips_send_ipi_single(int cpu, unsigned int action)
 257{
 258        write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
 259}
 260
 261static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
 262{
 263        int action = irq - IPI0_IRQ;
 264
 265        write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), action));
 266
 267        if (action == 0)
 268                scheduler_ipi();
 269        else
 270                smp_call_function_interrupt();
 271
 272        return IRQ_HANDLED;
 273}
 274
 275#else
 276
 277/*
 278 * BMIPS43xx racey IPIs
 279 *
 280 * We use one inbound SW IRQ for each CPU.
 281 *
 282 * A spinlock must be held in order to keep CPUx from accidentally clearing
 283 * an incoming IPI when it writes CP0 CAUSE to raise an IPI on CPUy.  The
 284 * same spinlock is used to protect the action masks.
 285 */
 286
 287static DEFINE_SPINLOCK(ipi_lock);
 288static DEFINE_PER_CPU(int, ipi_action_mask);
 289
 290static void bmips_send_ipi_single(int cpu, unsigned int action)
 291{
 292        unsigned long flags;
 293
 294        spin_lock_irqsave(&ipi_lock, flags);
 295        set_c0_cause(cpu ? C_SW1 : C_SW0);
 296        per_cpu(ipi_action_mask, cpu) |= action;
 297        irq_enable_hazard();
 298        spin_unlock_irqrestore(&ipi_lock, flags);
 299}
 300
 301static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
 302{
 303        unsigned long flags;
 304        int action, cpu = irq - IPI0_IRQ;
 305
 306        spin_lock_irqsave(&ipi_lock, flags);
 307        action = __get_cpu_var(ipi_action_mask);
 308        per_cpu(ipi_action_mask, cpu) = 0;
 309        clear_c0_cause(cpu ? C_SW1 : C_SW0);
 310        spin_unlock_irqrestore(&ipi_lock, flags);
 311
 312        if (action & SMP_RESCHEDULE_YOURSELF)
 313                scheduler_ipi();
 314        if (action & SMP_CALL_FUNCTION)
 315                smp_call_function_interrupt();
 316
 317        return IRQ_HANDLED;
 318}
 319
 320#endif /* BMIPS type */
 321
 322static void bmips_send_ipi_mask(const struct cpumask *mask,
 323        unsigned int action)
 324{
 325        unsigned int i;
 326
 327        for_each_cpu(i, mask)
 328                bmips_send_ipi_single(i, action);
 329}
 330
 331#ifdef CONFIG_HOTPLUG_CPU
 332
 333static int bmips_cpu_disable(void)
 334{
 335        unsigned int cpu = smp_processor_id();
 336
 337        if (cpu == 0)
 338                return -EBUSY;
 339
 340        pr_info("SMP: CPU%d is offline\n", cpu);
 341
 342        set_cpu_online(cpu, false);
 343        cpu_clear(cpu, cpu_callin_map);
 344
 345        local_flush_tlb_all();
 346        local_flush_icache_range(0, ~0);
 347
 348        return 0;
 349}
 350
 351static void bmips_cpu_die(unsigned int cpu)
 352{
 353}
 354
 355void __ref play_dead(void)
 356{
 357        idle_task_exit();
 358
 359        /* flush data cache */
 360        _dma_cache_wback_inv(0, ~0);
 361
 362        /*
 363         * Wakeup is on SW0 or SW1; disable everything else
 364         * Use BEV !IV (BMIPS_WARM_RESTART_VEC) to avoid the regular Linux
 365         * IRQ handlers; this clears ST0_IE and returns immediately.
 366         */
 367        clear_c0_cause(CAUSEF_IV | C_SW0 | C_SW1);
 368        change_c0_status(IE_IRQ5 | IE_IRQ1 | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV,
 369                IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV);
 370        irq_disable_hazard();
 371
 372        /*
 373         * wait for SW interrupt from bmips_boot_secondary(), then jump
 374         * back to start_secondary()
 375         */
 376        __asm__ __volatile__(
 377        "       wait\n"
 378        "       j       bmips_secondary_reentry\n"
 379        : : : "memory");
 380}
 381
 382#endif /* CONFIG_HOTPLUG_CPU */
 383
 384struct plat_smp_ops bmips_smp_ops = {
 385        .smp_setup              = bmips_smp_setup,
 386        .prepare_cpus           = bmips_prepare_cpus,
 387        .boot_secondary         = bmips_boot_secondary,
 388        .smp_finish             = bmips_smp_finish,
 389        .init_secondary         = bmips_init_secondary,
 390        .cpus_done              = bmips_cpus_done,
 391        .send_ipi_single        = bmips_send_ipi_single,
 392        .send_ipi_mask          = bmips_send_ipi_mask,
 393#ifdef CONFIG_HOTPLUG_CPU
 394        .cpu_disable            = bmips_cpu_disable,
 395        .cpu_die                = bmips_cpu_die,
 396#endif
 397};
 398
 399#endif /* CONFIG_SMP */
 400
 401/***********************************************************************
 402 * BMIPS vector relocation
 403 * This is primarily used for SMP boot, but it is applicable to some
 404 * UP BMIPS systems as well.
 405 ***********************************************************************/
 406
 407static void bmips_wr_vec(unsigned long dst, char *start, char *end)
 408{
 409        memcpy((void *)dst, start, end - start);
 410        dma_cache_wback((unsigned long)start, end - start);
 411        local_flush_icache_range(dst, dst + (end - start));
 412        instruction_hazard();
 413}
 414
 415static inline void bmips_nmi_handler_setup(void)
 416{
 417        bmips_wr_vec(BMIPS_NMI_RESET_VEC, &bmips_reset_nmi_vec,
 418                &bmips_reset_nmi_vec_end);
 419        bmips_wr_vec(BMIPS_WARM_RESTART_VEC, &bmips_smp_int_vec,
 420                &bmips_smp_int_vec_end);
 421}
 422
 423void bmips_ebase_setup(void)
 424{
 425        unsigned long new_ebase = ebase;
 426        void __iomem __maybe_unused *cbr;
 427
 428        BUG_ON(ebase != CKSEG0);
 429
 430#if defined(CONFIG_CPU_BMIPS4350)
 431        /*
 432         * BMIPS4350 cannot relocate the normal vectors, but it
 433         * can relocate the BEV=1 vectors.  So CPU1 starts up at
 434         * the relocated BEV=1, IV=0 general exception vector @
 435         * 0xa000_0380.
 436         *
 437         * set_uncached_handler() is used here because:
 438         *  - CPU1 will run this from uncached space
 439         *  - None of the cacheflush functions are set up yet
 440         */
 441        set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
 442                &bmips_smp_int_vec, 0x80);
 443        __sync();
 444        return;
 445#elif defined(CONFIG_CPU_BMIPS4380)
 446        /*
 447         * 0x8000_0000: reset/NMI (initially in kseg1)
 448         * 0x8000_0400: normal vectors
 449         */
 450        new_ebase = 0x80000400;
 451        cbr = BMIPS_GET_CBR();
 452        __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
 453        __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
 454#elif defined(CONFIG_CPU_BMIPS5000)
 455        /*
 456         * 0x8000_0000: reset/NMI (initially in kseg1)
 457         * 0x8000_1000: normal vectors
 458         */
 459        new_ebase = 0x80001000;
 460        write_c0_brcm_bootvec(0xa0088008);
 461        write_c0_ebase(new_ebase);
 462        if (max_cpus > 2)
 463                bmips_write_zscm_reg(0xa0, 0xa008a008);
 464#else
 465        return;
 466#endif
 467        board_nmi_handler_setup = &bmips_nmi_handler_setup;
 468        ebase = new_ebase;
 469}
 470
 471asmlinkage void __weak plat_wired_tlb_setup(void)
 472{
 473        /*
 474         * Called when starting/restarting a secondary CPU.
 475         * Kernel stacks and other important data might only be accessible
 476         * once the wired entries are present.
 477         */
 478}
 479