linux/arch/mips/sibyte/bcm1480/smp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2001,2002,2004 Broadcom Corporation
   4 */
   5
   6#include <linux/init.h>
   7#include <linux/delay.h>
   8#include <linux/smp.h>
   9#include <linux/kernel_stat.h>
  10#include <linux/sched.h>
  11#include <linux/sched/task_stack.h>
  12
  13#include <asm/mmu_context.h>
  14#include <asm/io.h>
  15#include <asm/fw/cfe/cfe_api.h>
  16#include <asm/sibyte/sb1250.h>
  17#include <asm/sibyte/bcm1480_regs.h>
  18#include <asm/sibyte/bcm1480_int.h>
  19
  20/*
  21 * These are routines for dealing with the bcm1480 smp capabilities
  22 * independent of board/firmware
  23 */
  24
  25static void *mailbox_0_set_regs[] = {
  26        IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
  27        IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
  28        IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
  29        IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
  30};
  31
  32static void *mailbox_0_clear_regs[] = {
  33        IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
  34        IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
  35        IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
  36        IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
  37};
  38
  39static void *mailbox_0_regs[] = {
  40        IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
  41        IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
  42        IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
  43        IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
  44};
  45
  46/*
  47 * SMP init and finish on secondary CPUs
  48 */
  49void bcm1480_smp_init(void)
  50{
  51        unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
  52                STATUSF_IP1 | STATUSF_IP0;
  53
  54        /* Set interrupt mask, but don't enable */
  55        change_c0_status(ST0_IM, imask);
  56}
  57
  58/*
  59 * These are routines for dealing with the sb1250 smp capabilities
  60 * independent of board/firmware
  61 */
  62
  63/*
  64 * Simple enough; everything is set up, so just poke the appropriate mailbox
  65 * register, and we should be set
  66 */
  67static void bcm1480_send_ipi_single(int cpu, unsigned int action)
  68{
  69        __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
  70}
  71
  72static void bcm1480_send_ipi_mask(const struct cpumask *mask,
  73                                  unsigned int action)
  74{
  75        unsigned int i;
  76
  77        for_each_cpu(i, mask)
  78                bcm1480_send_ipi_single(i, action);
  79}
  80
  81/*
  82 * Code to run on secondary just after probing the CPU
  83 */
  84static void bcm1480_init_secondary(void)
  85{
  86        extern void bcm1480_smp_init(void);
  87
  88        bcm1480_smp_init();
  89}
  90
  91/*
  92 * Do any tidying up before marking online and running the idle
  93 * loop
  94 */
  95static void bcm1480_smp_finish(void)
  96{
  97        extern void sb1480_clockevent_init(void);
  98
  99        sb1480_clockevent_init();
 100        local_irq_enable();
 101}
 102
 103/*
 104 * Setup the PC, SP, and GP of a secondary processor and start it
 105 * running!
 106 */
 107static int bcm1480_boot_secondary(int cpu, struct task_struct *idle)
 108{
 109        int retval;
 110
 111        retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
 112                               __KSTK_TOS(idle),
 113                               (unsigned long)task_thread_info(idle), 0);
 114        if (retval != 0)
 115                printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
 116        return retval;
 117}
 118
 119/*
 120 * Use CFE to find out how many CPUs are available, setting up
 121 * cpu_possible_mask and the logical/physical mappings.
 122 * XXXKW will the boot CPU ever not be physical 0?
 123 *
 124 * Common setup before any secondaries are started
 125 */
 126static void __init bcm1480_smp_setup(void)
 127{
 128        int i, num;
 129
 130        init_cpu_possible(cpumask_of(0));
 131        __cpu_number_map[0] = 0;
 132        __cpu_logical_map[0] = 0;
 133
 134        for (i = 1, num = 0; i < NR_CPUS; i++) {
 135                if (cfe_cpu_stop(i) == 0) {
 136                        set_cpu_possible(i, true);
 137                        __cpu_number_map[i] = ++num;
 138                        __cpu_logical_map[num] = i;
 139                }
 140        }
 141        printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
 142}
 143
 144static void __init bcm1480_prepare_cpus(unsigned int max_cpus)
 145{
 146}
 147
 148const struct plat_smp_ops bcm1480_smp_ops = {
 149        .send_ipi_single        = bcm1480_send_ipi_single,
 150        .send_ipi_mask          = bcm1480_send_ipi_mask,
 151        .init_secondary         = bcm1480_init_secondary,
 152        .smp_finish             = bcm1480_smp_finish,
 153        .boot_secondary         = bcm1480_boot_secondary,
 154        .smp_setup              = bcm1480_smp_setup,
 155        .prepare_cpus           = bcm1480_prepare_cpus,
 156};
 157
 158void bcm1480_mailbox_interrupt(void)
 159{
 160        int cpu = smp_processor_id();
 161        int irq = K_BCM1480_INT_MBOX_0_0;
 162        unsigned int action;
 163
 164        kstat_incr_irq_this_cpu(irq);
 165        /* Load the mailbox register to figure out what we're supposed to do */
 166        action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
 167
 168        /* Clear the mailbox to clear the interrupt */
 169        __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]);
 170
 171        if (action & SMP_RESCHEDULE_YOURSELF)
 172                scheduler_ipi();
 173
 174        if (action & SMP_CALL_FUNCTION) {
 175                irq_enter();
 176                generic_smp_call_function_interrupt();
 177                irq_exit();
 178        }
 179}
 180