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