Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/sibyte/bcm1480/smp.c
26481 views
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
25
static 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
32
static 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
39
static 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
*/
49
void 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
*/
67
static void bcm1480_send_ipi_single(int cpu, unsigned int action)
68
{
69
__raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
70
}
71
72
static 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
*/
84
static 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
*/
95
static 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
*/
107
static 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
*/
126
static 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
144
static void __init bcm1480_prepare_cpus(unsigned int max_cpus)
145
{
146
}
147
148
const 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
158
void 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
181