aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/xlp
diff options
context:
space:
mode:
authorJayachandran C <jayachandranc@netlogicmicro.com>2011-11-15 19:21:29 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:04:56 -0500
commit66d29985fab8207b1b2c03ac34a2c294c5b47a30 (patch)
treef73145e09c53606716266577eef5e14262129ed9 /arch/mips/netlogic/xlp
parent8da24631e60438631112e6fdd198ef62416ff14a (diff)
MIPS: Netlogic: Merge some of XLR/XLP wakup code
Create a common NMI and reset handler in smpboot.S and use this for both XLR and XLP. In the earlier code, the woken up CPUs would busy wait until released, switch this to wakeup by NMI. The initial wakeup code or XLR and XLP are differ since they are started from different bootloaders (XLP from u-boot and XLR from netlogic bootloader). But in both platforms the woken up CPUs wait and are released by sending an NMI. Add support for starting XLR and XLP in 1/2/4 threads per core. Signed-off-by: Jayachandran C <jayachandranc@netlogicmicro.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2970/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/netlogic/xlp')
-rw-r--r--arch/mips/netlogic/xlp/Makefile2
-rw-r--r--arch/mips/netlogic/xlp/setup.c4
-rw-r--r--arch/mips/netlogic/xlp/smpboot.S217
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c93
4 files changed, 28 insertions, 288 deletions
diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index 1940d1c946d0..b93ed83474ec 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -1,2 +1,2 @@
1obj-y += setup.o platform.o nlm_hal.o 1obj-y += setup.o platform.o nlm_hal.o
2obj-$(CONFIG_SMP) += smpboot.o wakeup.o 2obj-$(CONFIG_SMP) += wakeup.o
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index f40a0e73580f..acb677a1227c 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -51,6 +51,10 @@
51 51
52unsigned long nlm_common_ebase = 0x0; 52unsigned long nlm_common_ebase = 0x0;
53 53
54/* default to uniprocessor */
55uint32_t nlm_coremask = 1, nlm_cpumask = 1;
56int nlm_threads_per_core = 1;
57
54static void nlm_linux_exit(void) 58static void nlm_linux_exit(void)
55{ 59{
56 nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1); 60 nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1);
diff --git a/arch/mips/netlogic/xlp/smpboot.S b/arch/mips/netlogic/xlp/smpboot.S
deleted file mode 100644
index 7dd323234d70..000000000000
--- a/arch/mips/netlogic/xlp/smpboot.S
+++ /dev/null
@@ -1,217 +0,0 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the NetLogic
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <linux/init.h>
36
37#include <asm/asm.h>
38#include <asm/asm-offsets.h>
39#include <asm/regdef.h>
40#include <asm/mipsregs.h>
41#include <asm/stackframe.h>
42#include <asm/asmmacro.h>
43#include <asm/addrspace.h>
44
45#include <asm/netlogic/xlp-hal/iomap.h>
46#include <asm/netlogic/xlp-hal/xlp.h>
47#include <asm/netlogic/xlp-hal/sys.h>
48#include <asm/netlogic/xlp-hal/cpucontrol.h>
49
50#define CP0_EBASE $15
51#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
52 XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \
53 SYS_CPU_NONCOHERENT_MODE * 4
54
55.macro __config_lsu
56 li t0, LSU_DEFEATURE
57 mfcr t1, t0
58
59 lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */
60 or t1, t1, t2
61 li t2, ~0xe /* S1RCM */
62 and t1, t1, t2
63 mtcr t1, t0
64
65 li t0, SCHED_DEFEATURE
66 lui t1, 0x0100 /* Experimental: Disable BRU accepting ALU ops */
67 mtcr t1, t0
68.endm
69
70 .set noreorder
71 .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */
72
73 __CPUINIT
74EXPORT(nlm_reset_entry)
75 mfc0 t0, CP0_EBASE, 1
76 mfc0 t1, CP0_EBASE, 1
77 srl t1, 5
78 andi t1, 0x3 /* t1 <- node */
79 li t2, 0x40000
80 mul t3, t2, t1 /* t3 = node * 0x40000 */
81 srl t0, t0, 2
82 and t0, t0, 0x7 /* t0 <- core */
83 li t1, 0x1
84 sll t0, t1, t0
85 nor t0, t0, zero /* t0 <- ~(1 << core) */
86 li t2, SYS_CPU_COHERENT_BASE(0)
87 add t2, t2, t3 /* t2 <- SYS offset for node */
88 lw t1, 0(t2)
89 and t1, t1, t0
90 sw t1, 0(t2)
91
92 /* read back to ensure complete */
93 lw t1, 0(t2)
94 sync
95
96 /* Configure LSU on Non-0 Cores. */
97 __config_lsu
98
99/*
100 * Wake up sibling threads from the initial thread in
101 * a core.
102 */
103EXPORT(nlm_boot_siblings)
104 li t0, CKSEG1ADDR(RESET_DATA_PHYS)
105 lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */
106 li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE)
107 mfcr t2, t0
108 or t2, t2, t1
109 mtcr t2, t0
110
111 /*
112 * The new hardware thread starts at the next instruction
113 * For all the cases other than core 0 thread 0, we will
114 * jump to the secondary wait function.
115 */
116 mfc0 v0, CP0_EBASE, 1
117 andi v0, 0x7f /* v0 <- node/core */
118
119#if 1
120 /* A0 errata - Write MMU_SETUP after changing thread mode register. */
121 andi v1, v0, 0x3 /* v1 <- thread id */
122 bnez v1, 2f
123 nop
124
125 li t0, MMU_SETUP
126 li t1, 0
127 mtcr t1, t0
128 ehb
129#endif
130
1312: beqz v0, 3f
132 nop
133
134 /* setup status reg */
135 mfc0 t1, CP0_STATUS
136 li t0, ST0_BEV
137 or t1, t0
138 xor t1, t0
139#ifdef CONFIG_64BIT
140 ori t1, ST0_KX
141#endif
142 mtc0 t1, CP0_STATUS
143
144 /* SETUP TLBs for a mapped kernel here */
145 PTR_LA t0, prom_pre_boot_secondary_cpus
146 jalr t0
147 nop
148
149 /*
150 * For the boot CPU, we have to restore registers and
151 * return
152 */
1533: dmfc0 t0, $4, 2 /* restore SP from UserLocal */
154 li t1, 0xfadebeef
155 dmtc0 t1, $4, 2 /* restore SP from UserLocal */
156 PTR_SUBU sp, t0, PT_SIZE
157 RESTORE_ALL
158 jr ra
159 nop
160EXPORT(nlm_reset_entry_end)
161
162EXPORT(nlm_boot_core0_siblings) /* "Master" (n0c0t0) cpu starts from here */
163 __config_lsu
164 dmtc0 sp, $4, 2 /* SP saved in UserLocal */
165 SAVE_ALL
166 sync
167 /* find the location to which nlm_boot_siblings was relocated */
168 li t0, CKSEG1ADDR(RESET_VEC_PHYS)
169 dla t1, nlm_reset_entry
170 dla t2, nlm_boot_siblings
171 dsubu t2, t1
172 daddu t2, t0
173 /* call it */
174 jr t2
175 nop
176 __FINIT
177
178 __CPUINIT
179NESTED(prom_pre_boot_secondary_cpus, 16, sp)
180 .set mips64
181 mfc0 a0, CP0_EBASE, 1 /* read ebase */
182 andi a0, 0x3ff /* a0 has the processor_id() */
183 sll t0, a0, 2 /* offset in cpu array */
184
185 PTR_LA t1, nlm_cpu_ready /* mark CPU ready */
186 PTR_ADDU t1, t0
187 li t2, 1
188 sw t2, 0(t1)
189
190 PTR_LA t1, nlm_cpu_unblock
191 PTR_ADDU t1, t0
1921: lw t2, 0(t1) /* wait till unblocked */
193 bnez t2, 2f
194 nop
195 nop
196 nop
197 nop
198 nop
199 nop
200 j 1b
201 nop
202
2032: PTR_LA t1, nlm_next_sp
204 PTR_L sp, 0(t1)
205 PTR_LA t1, nlm_next_gp
206 PTR_L gp, 0(t1)
207
208 /* a0 has the processor id */
209 PTR_LA t0, nlm_early_init_secondary
210 jalr t0
211 nop
212
213 PTR_LA t0, smp_bootstrap
214 jr t0
215 nop
216END(prom_pre_boot_secondary_cpus)
217 __FINIT
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index e081a778678e..44d923ff3846 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -51,18 +51,20 @@
51#include <asm/netlogic/xlp-hal/xlp.h> 51#include <asm/netlogic/xlp-hal/xlp.h>
52#include <asm/netlogic/xlp-hal/sys.h> 52#include <asm/netlogic/xlp-hal/sys.h>
53 53
54unsigned long secondary_entry; 54static void xlp_enable_secondary_cores(void)
55uint32_t nlm_coremask;
56unsigned int nlm_threads_per_core;
57unsigned int nlm_threadmode;
58
59static void nlm_enable_secondary_cores(unsigned int cores_bitmap)
60{ 55{
61 uint32_t core, value, coremask; 56 uint32_t core, value, coremask, syscoremask;
57 int count;
58
59 /* read cores in reset from SYS block */
60 syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
61
62 /* update user specified */
63 nlm_coremask = nlm_coremask & (syscoremask | 1);
62 64
63 for (core = 1; core < 8; core++) { 65 for (core = 1; core < 8; core++) {
64 coremask = 1 << core; 66 coremask = 1 << core;
65 if ((cores_bitmap & coremask) == 0) 67 if ((nlm_coremask & coremask) == 0)
66 continue; 68 continue;
67 69
68 /* Enable CPU clock */ 70 /* Enable CPU clock */
@@ -76,74 +78,25 @@ static void nlm_enable_secondary_cores(unsigned int cores_bitmap)
76 nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value); 78 nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value);
77 79
78 /* Poll for CPU to mark itself coherent */ 80 /* Poll for CPU to mark itself coherent */
81 count = 100000;
79 do { 82 do {
80 value = nlm_read_sys_reg(nlm_sys_base, 83 value = nlm_read_sys_reg(nlm_sys_base,
81 SYS_CPU_NONCOHERENT_MODE); 84 SYS_CPU_NONCOHERENT_MODE);
82 } while ((value & coremask) != 0); 85 } while ((value & coremask) != 0 && count-- > 0);
83 }
84}
85
86
87static void nlm_parse_cpumask(u32 cpu_mask)
88{
89 uint32_t core0_thr_mask, core_thr_mask;
90 int i;
91 86
92 core0_thr_mask = cpu_mask & 0xf; 87 if (count == 0)
93 switch (core0_thr_mask) { 88 pr_err("Failed to enable core %d\n", core);
94 case 1:
95 nlm_threads_per_core = 1;
96 nlm_threadmode = 0;
97 break;
98 case 3:
99 nlm_threads_per_core = 2;
100 nlm_threadmode = 2;
101 break;
102 case 0xf:
103 nlm_threads_per_core = 4;
104 nlm_threadmode = 3;
105 break;
106 default:
107 goto unsupp;
108 } 89 }
109
110 /* Verify other cores CPU masks */
111 nlm_coremask = 1;
112 for (i = 1; i < 8; i++) {
113 core_thr_mask = (cpu_mask >> (i * 4)) & 0xf;
114 if (core_thr_mask) {
115 if (core_thr_mask != core0_thr_mask)
116 goto unsupp;
117 nlm_coremask |= 1 << i;
118 }
119 }
120 return;
121
122unsupp:
123 panic("Unsupported CPU mask %x\n", cpu_mask);
124} 90}
125 91
126int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) 92void xlp_wakeup_secondary_cpus(void)
127{ 93{
128 unsigned long reset_vec; 94 /*
129 unsigned int *reset_data; 95 * In case of u-boot, the secondaries are in reset
130 96 * first wakeup core 0 threads
131 /* Update reset entry point with CPU init code */ 97 */
132 reset_vec = CKSEG1ADDR(RESET_VEC_PHYS); 98 xlp_boot_core0_siblings();
133 memcpy((void *)reset_vec, (void *)nlm_reset_entry, 99
134 (nlm_reset_entry_end - nlm_reset_entry)); 100 /* now get other cores out of reset */
135 101 xlp_enable_secondary_cores();
136 /* verify the mask and setup core config variables */
137 nlm_parse_cpumask(wakeup_mask);
138
139 /* Setup CPU init parameters */
140 reset_data = (unsigned int *)CKSEG1ADDR(RESET_DATA_PHYS);
141 reset_data[BOOT_THREAD_MODE] = nlm_threadmode;
142
143 /* first wakeup core 0 siblings */
144 nlm_boot_core0_siblings();
145
146 /* enable the reset of the cores */
147 nlm_enable_secondary_cores(nlm_coremask);
148 return 0;
149} 102}