xref: /linux/arch/mips/sibyte/bcm1480/smp.c (revision 937a801576f954bd030d7c4a5a94571710d87c0b)
1f137e463SAndrew Isaacson /*
2f137e463SAndrew Isaacson  * Copyright (C) 2001,2002,2004 Broadcom Corporation
3f137e463SAndrew Isaacson  *
4f137e463SAndrew Isaacson  * This program is free software; you can redistribute it and/or
5f137e463SAndrew Isaacson  * modify it under the terms of the GNU General Public License
6f137e463SAndrew Isaacson  * as published by the Free Software Foundation; either version 2
7f137e463SAndrew Isaacson  * of the License, or (at your option) any later version.
8f137e463SAndrew Isaacson  *
9f137e463SAndrew Isaacson  * This program is distributed in the hope that it will be useful,
10f137e463SAndrew Isaacson  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11f137e463SAndrew Isaacson  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12f137e463SAndrew Isaacson  * GNU General Public License for more details.
13f137e463SAndrew Isaacson  *
14f137e463SAndrew Isaacson  * You should have received a copy of the GNU General Public License
15f137e463SAndrew Isaacson  * along with this program; if not, write to the Free Software
16f137e463SAndrew Isaacson  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17f137e463SAndrew Isaacson  */
18f137e463SAndrew Isaacson 
19f137e463SAndrew Isaacson #include <linux/init.h>
20f137e463SAndrew Isaacson #include <linux/delay.h>
21f137e463SAndrew Isaacson #include <linux/smp.h>
22f137e463SAndrew Isaacson #include <linux/kernel_stat.h>
23f137e463SAndrew Isaacson 
24f137e463SAndrew Isaacson #include <asm/mmu_context.h>
25f137e463SAndrew Isaacson #include <asm/io.h>
26f137e463SAndrew Isaacson #include <asm/sibyte/sb1250.h>
27f137e463SAndrew Isaacson #include <asm/sibyte/bcm1480_regs.h>
28f137e463SAndrew Isaacson #include <asm/sibyte/bcm1480_int.h>
29f137e463SAndrew Isaacson 
30f137e463SAndrew Isaacson extern void smp_call_function_interrupt(void);
31f137e463SAndrew Isaacson 
32f137e463SAndrew Isaacson /*
33f137e463SAndrew Isaacson  * These are routines for dealing with the bcm1480 smp capabilities
34f137e463SAndrew Isaacson  * independent of board/firmware
35f137e463SAndrew Isaacson  */
36f137e463SAndrew Isaacson 
37f137e463SAndrew Isaacson static void *mailbox_0_set_regs[] = {
38f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
39f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
40f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
41f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
42f137e463SAndrew Isaacson };
43f137e463SAndrew Isaacson 
44f137e463SAndrew Isaacson static void *mailbox_0_clear_regs[] = {
45f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
46f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
47f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
48f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
49f137e463SAndrew Isaacson };
50f137e463SAndrew Isaacson 
51f137e463SAndrew Isaacson static void *mailbox_0_regs[] = {
52f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
53f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
54f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
55f137e463SAndrew Isaacson 	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
56f137e463SAndrew Isaacson };
57f137e463SAndrew Isaacson 
58f137e463SAndrew Isaacson /*
59f137e463SAndrew Isaacson  * SMP init and finish on secondary CPUs
60f137e463SAndrew Isaacson  */
61f137e463SAndrew Isaacson void bcm1480_smp_init(void)
62f137e463SAndrew Isaacson {
63f137e463SAndrew Isaacson 	unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
64f137e463SAndrew Isaacson 		STATUSF_IP1 | STATUSF_IP0;
65f137e463SAndrew Isaacson 
66f137e463SAndrew Isaacson 	/* Set interrupt mask, but don't enable */
67f137e463SAndrew Isaacson 	change_c0_status(ST0_IM, imask);
68f137e463SAndrew Isaacson }
69f137e463SAndrew Isaacson 
70f137e463SAndrew Isaacson void bcm1480_smp_finish(void)
71f137e463SAndrew Isaacson {
72f137e463SAndrew Isaacson 	extern void bcm1480_time_init(void);
73f137e463SAndrew Isaacson 	bcm1480_time_init();
74f137e463SAndrew Isaacson 	local_irq_enable();
75f137e463SAndrew Isaacson }
76f137e463SAndrew Isaacson 
77f137e463SAndrew Isaacson /*
78f137e463SAndrew Isaacson  * These are routines for dealing with the sb1250 smp capabilities
79f137e463SAndrew Isaacson  * independent of board/firmware
80f137e463SAndrew Isaacson  */
81f137e463SAndrew Isaacson 
82f137e463SAndrew Isaacson /*
83f137e463SAndrew Isaacson  * Simple enough; everything is set up, so just poke the appropriate mailbox
84f137e463SAndrew Isaacson  * register, and we should be set
85f137e463SAndrew Isaacson  */
86f137e463SAndrew Isaacson void core_send_ipi(int cpu, unsigned int action)
87f137e463SAndrew Isaacson {
88f137e463SAndrew Isaacson 	__raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
89f137e463SAndrew Isaacson }
90f137e463SAndrew Isaacson 
91*937a8015SRalf Baechle void bcm1480_mailbox_interrupt(void)
92f137e463SAndrew Isaacson {
93f137e463SAndrew Isaacson 	int cpu = smp_processor_id();
94f137e463SAndrew Isaacson 	unsigned int action;
95f137e463SAndrew Isaacson 
96f137e463SAndrew Isaacson 	kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
97f137e463SAndrew Isaacson 	/* Load the mailbox register to figure out what we're supposed to do */
98f137e463SAndrew Isaacson 	action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
99f137e463SAndrew Isaacson 
100f137e463SAndrew Isaacson 	/* Clear the mailbox to clear the interrupt */
101f137e463SAndrew Isaacson 	__raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]);
102f137e463SAndrew Isaacson 
103f137e463SAndrew Isaacson 	/*
104f137e463SAndrew Isaacson 	 * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
105f137e463SAndrew Isaacson 	 * interrupt will do the reschedule for us
106f137e463SAndrew Isaacson 	 */
107f137e463SAndrew Isaacson 
108f137e463SAndrew Isaacson 	if (action & SMP_CALL_FUNCTION)
109f137e463SAndrew Isaacson 		smp_call_function_interrupt();
110f137e463SAndrew Isaacson }
111