Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/sibyte/sb1250/smp.c
26481 views
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
20
static 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
25
static 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
30
static 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
*/
38
void 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
*/
56
static void sb1250_send_ipi_single(int cpu, unsigned int action)
57
{
58
__raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
59
}
60
61
static 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
*/
73
static 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
*/
84
static 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
*/
96
static 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
*/
115
static 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
133
static void __init sb1250_prepare_cpus(unsigned int max_cpus)
134
{
135
}
136
137
const 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
147
void 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
170