smp.c (4013B)
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}