diff options
Diffstat (limited to 'arch/mips/loongson/loongson-3')
-rw-r--r-- | arch/mips/loongson/loongson-3/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/loongson/loongson-3/cop2-ex.c | 63 | ||||
-rw-r--r-- | arch/mips/loongson/loongson-3/irq.c | 26 | ||||
-rw-r--r-- | arch/mips/loongson/loongson-3/numa.c | 291 | ||||
-rw-r--r-- | arch/mips/loongson/loongson-3/smp.c | 387 | ||||
-rw-r--r-- | arch/mips/loongson/loongson-3/smp.h | 37 |
6 files changed, 688 insertions, 120 deletions
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile index 70152b252ddc..b4df775b9f30 100644 --- a/arch/mips/loongson/loongson-3/Makefile +++ b/arch/mips/loongson/loongson-3/Makefile | |||
@@ -1,6 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for Loongson-3 family machines | 2 | # Makefile for Loongson-3 family machines |
3 | # | 3 | # |
4 | obj-y += irq.o | 4 | obj-y += irq.o cop2-ex.o |
5 | 5 | ||
6 | obj-$(CONFIG_SMP) += smp.o | 6 | obj-$(CONFIG_SMP) += smp.o |
7 | |||
8 | obj-$(CONFIG_NUMA) += numa.o | ||
diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c new file mode 100644 index 000000000000..9182e8d2967c --- /dev/null +++ b/arch/mips/loongson/loongson-3/cop2-ex.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2014 Lemote Corporation. | ||
7 | * written by Huacai Chen <chenhc@lemote.com> | ||
8 | * | ||
9 | * based on arch/mips/cavium-octeon/cpu.c | ||
10 | * Copyright (C) 2009 Wind River Systems, | ||
11 | * written by Ralf Baechle <ralf@linux-mips.org> | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/notifier.h> | ||
16 | |||
17 | #include <asm/fpu.h> | ||
18 | #include <asm/cop2.h> | ||
19 | #include <asm/current.h> | ||
20 | #include <asm/mipsregs.h> | ||
21 | |||
22 | static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action, | ||
23 | void *data) | ||
24 | { | ||
25 | int fpu_enabled; | ||
26 | int fr = !test_thread_flag(TIF_32BIT_FPREGS); | ||
27 | |||
28 | switch (action) { | ||
29 | case CU2_EXCEPTION: | ||
30 | preempt_disable(); | ||
31 | fpu_enabled = read_c0_status() & ST0_CU1; | ||
32 | if (!fr) | ||
33 | set_c0_status(ST0_CU1 | ST0_CU2); | ||
34 | else | ||
35 | set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR); | ||
36 | enable_fpu_hazard(); | ||
37 | KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2); | ||
38 | if (fr) | ||
39 | KSTK_STATUS(current) |= ST0_FR; | ||
40 | else | ||
41 | KSTK_STATUS(current) &= ~ST0_FR; | ||
42 | /* If FPU is enabled, we needn't init or restore fp */ | ||
43 | if(!fpu_enabled) { | ||
44 | set_thread_flag(TIF_USEDFPU); | ||
45 | if (!used_math()) { | ||
46 | _init_fpu(); | ||
47 | set_used_math(); | ||
48 | } else | ||
49 | _restore_fp(current); | ||
50 | } | ||
51 | preempt_enable(); | ||
52 | |||
53 | return NOTIFY_STOP; /* Don't call default notifier */ | ||
54 | } | ||
55 | |||
56 | return NOTIFY_OK; /* Let default notifier send signals */ | ||
57 | } | ||
58 | |||
59 | static int __init loongson_cu2_setup(void) | ||
60 | { | ||
61 | return cu2_notifier(loongson_cu2_call, 0); | ||
62 | } | ||
63 | early_initcall(loongson_cu2_setup); | ||
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c index f240828181ff..ca1c62af5188 100644 --- a/arch/mips/loongson/loongson-3/irq.c +++ b/arch/mips/loongson/loongson-3/irq.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <asm/i8259.h> | 7 | #include <asm/i8259.h> |
8 | #include <asm/mipsregs.h> | 8 | #include <asm/mipsregs.h> |
9 | 9 | ||
10 | #include "smp.h" | ||
11 | |||
10 | unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15}; | 12 | unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15}; |
11 | 13 | ||
12 | static void ht_irqdispatch(void) | 14 | static void ht_irqdispatch(void) |
@@ -53,9 +55,15 @@ static inline void mask_loongson_irq(struct irq_data *d) | |||
53 | /* Workaround: UART IRQ may deliver to any core */ | 55 | /* Workaround: UART IRQ may deliver to any core */ |
54 | if (d->irq == LOONGSON_UART_IRQ) { | 56 | if (d->irq == LOONGSON_UART_IRQ) { |
55 | int cpu = smp_processor_id(); | 57 | int cpu = smp_processor_id(); |
56 | 58 | int node_id = cpu / loongson_sysconf.cores_per_node; | |
57 | LOONGSON_INT_ROUTER_INTENCLR = 1 << 10; | 59 | int core_id = cpu % loongson_sysconf.cores_per_node; |
58 | LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu); | 60 | u64 intenclr_addr = smp_group[node_id] | |
61 | (u64)(&LOONGSON_INT_ROUTER_INTENCLR); | ||
62 | u64 introuter_lpc_addr = smp_group[node_id] | | ||
63 | (u64)(&LOONGSON_INT_ROUTER_LPC); | ||
64 | |||
65 | *(volatile u32 *)intenclr_addr = 1 << 10; | ||
66 | *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id); | ||
59 | } | 67 | } |
60 | } | 68 | } |
61 | 69 | ||
@@ -64,9 +72,15 @@ static inline void unmask_loongson_irq(struct irq_data *d) | |||
64 | /* Workaround: UART IRQ may deliver to any core */ | 72 | /* Workaround: UART IRQ may deliver to any core */ |
65 | if (d->irq == LOONGSON_UART_IRQ) { | 73 | if (d->irq == LOONGSON_UART_IRQ) { |
66 | int cpu = smp_processor_id(); | 74 | int cpu = smp_processor_id(); |
67 | 75 | int node_id = cpu / loongson_sysconf.cores_per_node; | |
68 | LOONGSON_INT_ROUTER_INTENSET = 1 << 10; | 76 | int core_id = cpu % loongson_sysconf.cores_per_node; |
69 | LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu); | 77 | u64 intenset_addr = smp_group[node_id] | |
78 | (u64)(&LOONGSON_INT_ROUTER_INTENSET); | ||
79 | u64 introuter_lpc_addr = smp_group[node_id] | | ||
80 | (u64)(&LOONGSON_INT_ROUTER_LPC); | ||
81 | |||
82 | *(volatile u32 *)intenset_addr = 1 << 10; | ||
83 | *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id); | ||
70 | } | 84 | } |
71 | 85 | ||
72 | set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); | 86 | set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); |
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c new file mode 100644 index 000000000000..ca025a6ba559 --- /dev/null +++ b/arch/mips/loongson/loongson-3/numa.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & | ||
3 | * Insititute of Computing Technology | ||
4 | * Author: Xiang Gao, gaoxiang@ict.ac.cn | ||
5 | * Huacai Chen, chenhc@lemote.com | ||
6 | * Xiaofu Meng, Shuangshuang Zhang | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/mmzone.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/nodemask.h> | ||
19 | #include <linux/swap.h> | ||
20 | #include <linux/memblock.h> | ||
21 | #include <linux/bootmem.h> | ||
22 | #include <linux/pfn.h> | ||
23 | #include <linux/highmem.h> | ||
24 | #include <asm/page.h> | ||
25 | #include <asm/pgalloc.h> | ||
26 | #include <asm/sections.h> | ||
27 | #include <linux/bootmem.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/irq.h> | ||
30 | #include <asm/bootinfo.h> | ||
31 | #include <asm/mc146818-time.h> | ||
32 | #include <asm/time.h> | ||
33 | #include <asm/wbflush.h> | ||
34 | #include <boot_param.h> | ||
35 | |||
36 | static struct node_data prealloc__node_data[MAX_NUMNODES]; | ||
37 | unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES]; | ||
38 | struct node_data *__node_data[MAX_NUMNODES]; | ||
39 | EXPORT_SYMBOL(__node_data); | ||
40 | |||
41 | static void enable_lpa(void) | ||
42 | { | ||
43 | unsigned long value; | ||
44 | |||
45 | value = __read_32bit_c0_register($16, 3); | ||
46 | value |= 0x00000080; | ||
47 | __write_32bit_c0_register($16, 3, value); | ||
48 | value = __read_32bit_c0_register($16, 3); | ||
49 | pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value); | ||
50 | |||
51 | value = __read_32bit_c0_register($5, 1); | ||
52 | value |= 0x20000000; | ||
53 | __write_32bit_c0_register($5, 1, value); | ||
54 | value = __read_32bit_c0_register($5, 1); | ||
55 | pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value); | ||
56 | } | ||
57 | |||
58 | static void cpu_node_probe(void) | ||
59 | { | ||
60 | int i; | ||
61 | |||
62 | nodes_clear(node_possible_map); | ||
63 | nodes_clear(node_online_map); | ||
64 | for (i = 0; i < loongson_sysconf.nr_nodes; i++) { | ||
65 | node_set_state(num_online_nodes(), N_POSSIBLE); | ||
66 | node_set_online(num_online_nodes()); | ||
67 | } | ||
68 | |||
69 | pr_info("NUMA: Discovered %d cpus on %d nodes\n", | ||
70 | loongson_sysconf.nr_cpus, num_online_nodes()); | ||
71 | } | ||
72 | |||
73 | static int __init compute_node_distance(int row, int col) | ||
74 | { | ||
75 | int package_row = row * loongson_sysconf.cores_per_node / | ||
76 | loongson_sysconf.cores_per_package; | ||
77 | int package_col = col * loongson_sysconf.cores_per_node / | ||
78 | loongson_sysconf.cores_per_package; | ||
79 | |||
80 | if (col == row) | ||
81 | return 0; | ||
82 | else if (package_row == package_col) | ||
83 | return 40; | ||
84 | else | ||
85 | return 100; | ||
86 | } | ||
87 | |||
88 | static void __init init_topology_matrix(void) | ||
89 | { | ||
90 | int row, col; | ||
91 | |||
92 | for (row = 0; row < MAX_NUMNODES; row++) | ||
93 | for (col = 0; col < MAX_NUMNODES; col++) | ||
94 | __node_distances[row][col] = -1; | ||
95 | |||
96 | for_each_online_node(row) { | ||
97 | for_each_online_node(col) { | ||
98 | __node_distances[row][col] = | ||
99 | compute_node_distance(row, col); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static unsigned long nid_to_addroffset(unsigned int nid) | ||
105 | { | ||
106 | unsigned long result; | ||
107 | switch (nid) { | ||
108 | case 0: | ||
109 | default: | ||
110 | result = NODE0_ADDRSPACE_OFFSET; | ||
111 | break; | ||
112 | case 1: | ||
113 | result = NODE1_ADDRSPACE_OFFSET; | ||
114 | break; | ||
115 | case 2: | ||
116 | result = NODE2_ADDRSPACE_OFFSET; | ||
117 | break; | ||
118 | case 3: | ||
119 | result = NODE3_ADDRSPACE_OFFSET; | ||
120 | break; | ||
121 | } | ||
122 | return result; | ||
123 | } | ||
124 | |||
125 | static void __init szmem(unsigned int node) | ||
126 | { | ||
127 | u32 i, mem_type; | ||
128 | static unsigned long num_physpages = 0; | ||
129 | u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size; | ||
130 | |||
131 | /* Parse memory information and activate */ | ||
132 | for (i = 0; i < loongson_memmap->nr_map; i++) { | ||
133 | node_id = loongson_memmap->map[i].node_id; | ||
134 | if (node_id != node) | ||
135 | continue; | ||
136 | |||
137 | mem_type = loongson_memmap->map[i].mem_type; | ||
138 | mem_size = loongson_memmap->map[i].mem_size; | ||
139 | mem_start = loongson_memmap->map[i].mem_start; | ||
140 | |||
141 | switch (mem_type) { | ||
142 | case SYSTEM_RAM_LOW: | ||
143 | start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT; | ||
144 | node_psize = (mem_size << 20) >> PAGE_SHIFT; | ||
145 | end_pfn = start_pfn + node_psize; | ||
146 | num_physpages += node_psize; | ||
147 | pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", | ||
148 | (u32)node_id, mem_type, mem_start, mem_size); | ||
149 | pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", | ||
150 | start_pfn, end_pfn, num_physpages); | ||
151 | add_memory_region((node_id << 44) + mem_start, | ||
152 | (u64)mem_size << 20, BOOT_MEM_RAM); | ||
153 | memblock_add_node(PFN_PHYS(start_pfn), | ||
154 | PFN_PHYS(end_pfn - start_pfn), node); | ||
155 | break; | ||
156 | case SYSTEM_RAM_HIGH: | ||
157 | start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT; | ||
158 | node_psize = (mem_size << 20) >> PAGE_SHIFT; | ||
159 | end_pfn = start_pfn + node_psize; | ||
160 | num_physpages += node_psize; | ||
161 | pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", | ||
162 | (u32)node_id, mem_type, mem_start, mem_size); | ||
163 | pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", | ||
164 | start_pfn, end_pfn, num_physpages); | ||
165 | add_memory_region((node_id << 44) + mem_start, | ||
166 | (u64)mem_size << 20, BOOT_MEM_RAM); | ||
167 | memblock_add_node(PFN_PHYS(start_pfn), | ||
168 | PFN_PHYS(end_pfn - start_pfn), node); | ||
169 | break; | ||
170 | case MEM_RESERVED: | ||
171 | pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", | ||
172 | (u32)node_id, mem_type, mem_start, mem_size); | ||
173 | add_memory_region((node_id << 44) + mem_start, | ||
174 | (u64)mem_size << 20, BOOT_MEM_RESERVED); | ||
175 | memblock_reserve(((node_id << 44) + mem_start), | ||
176 | mem_size << 20); | ||
177 | break; | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | static void __init node_mem_init(unsigned int node) | ||
183 | { | ||
184 | unsigned long bootmap_size; | ||
185 | unsigned long node_addrspace_offset; | ||
186 | unsigned long start_pfn, end_pfn, freepfn; | ||
187 | |||
188 | node_addrspace_offset = nid_to_addroffset(node); | ||
189 | pr_info("Node%d's addrspace_offset is 0x%lx\n", | ||
190 | node, node_addrspace_offset); | ||
191 | |||
192 | get_pfn_range_for_nid(node, &start_pfn, &end_pfn); | ||
193 | freepfn = start_pfn; | ||
194 | if (node == 0) | ||
195 | freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */ | ||
196 | pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n", | ||
197 | node, start_pfn, end_pfn, freepfn); | ||
198 | |||
199 | __node_data[node] = prealloc__node_data + node; | ||
200 | |||
201 | NODE_DATA(node)->bdata = &bootmem_node_data[node]; | ||
202 | NODE_DATA(node)->node_start_pfn = start_pfn; | ||
203 | NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; | ||
204 | |||
205 | bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn, | ||
206 | start_pfn, end_pfn); | ||
207 | free_bootmem_with_active_regions(node, end_pfn); | ||
208 | if (node == 0) /* used by finalize_initrd() */ | ||
209 | max_low_pfn = end_pfn; | ||
210 | |||
211 | /* This is reserved for the kernel and bdata->node_bootmem_map */ | ||
212 | reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT, | ||
213 | ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size, | ||
214 | BOOTMEM_DEFAULT); | ||
215 | |||
216 | if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) { | ||
217 | /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */ | ||
218 | reserve_bootmem_node(NODE_DATA(node), | ||
219 | (node_addrspace_offset | 0xff800000), | ||
220 | 8 << 20, BOOTMEM_DEFAULT); | ||
221 | } | ||
222 | |||
223 | sparse_memory_present_with_active_regions(node); | ||
224 | } | ||
225 | |||
226 | static __init void prom_meminit(void) | ||
227 | { | ||
228 | unsigned int node, cpu; | ||
229 | |||
230 | cpu_node_probe(); | ||
231 | init_topology_matrix(); | ||
232 | |||
233 | for (node = 0; node < loongson_sysconf.nr_nodes; node++) { | ||
234 | if (node_online(node)) { | ||
235 | szmem(node); | ||
236 | node_mem_init(node); | ||
237 | cpus_clear(__node_data[(node)]->cpumask); | ||
238 | } | ||
239 | } | ||
240 | for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) { | ||
241 | node = cpu / loongson_sysconf.cores_per_node; | ||
242 | if (node >= num_online_nodes()) | ||
243 | node = 0; | ||
244 | pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node); | ||
245 | cpu_set(cpu, __node_data[(node)]->cpumask); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | void __init paging_init(void) | ||
250 | { | ||
251 | unsigned node; | ||
252 | unsigned long zones_size[MAX_NR_ZONES] = {0, }; | ||
253 | |||
254 | pagetable_init(); | ||
255 | |||
256 | for_each_online_node(node) { | ||
257 | unsigned long start_pfn, end_pfn; | ||
258 | |||
259 | get_pfn_range_for_nid(node, &start_pfn, &end_pfn); | ||
260 | |||
261 | if (end_pfn > max_low_pfn) | ||
262 | max_low_pfn = end_pfn; | ||
263 | } | ||
264 | #ifdef CONFIG_ZONE_DMA32 | ||
265 | zones_size[ZONE_DMA32] = MAX_DMA32_PFN; | ||
266 | #endif | ||
267 | zones_size[ZONE_NORMAL] = max_low_pfn; | ||
268 | free_area_init_nodes(zones_size); | ||
269 | } | ||
270 | |||
271 | void __init mem_init(void) | ||
272 | { | ||
273 | high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT); | ||
274 | free_all_bootmem(); | ||
275 | setup_zero_pages(); /* This comes from node 0 */ | ||
276 | mem_init_print_info(NULL); | ||
277 | } | ||
278 | |||
279 | /* All PCI device belongs to logical Node-0 */ | ||
280 | int pcibus_to_node(struct pci_bus *bus) | ||
281 | { | ||
282 | return 0; | ||
283 | } | ||
284 | EXPORT_SYMBOL(pcibus_to_node); | ||
285 | |||
286 | void __init prom_init_numa_memory(void) | ||
287 | { | ||
288 | enable_lpa(); | ||
289 | prom_meminit(); | ||
290 | } | ||
291 | EXPORT_SYMBOL(prom_init_numa_memory); | ||
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c index 1e8894020ea5..74e827b4ec8f 100644 --- a/arch/mips/loongson/loongson-3/smp.c +++ b/arch/mips/loongson/loongson-3/smp.c | |||
@@ -31,6 +31,12 @@ | |||
31 | DEFINE_PER_CPU(int, cpu_state); | 31 | DEFINE_PER_CPU(int, cpu_state); |
32 | DEFINE_PER_CPU(uint32_t, core0_c0count); | 32 | DEFINE_PER_CPU(uint32_t, core0_c0count); |
33 | 33 | ||
34 | static void *ipi_set0_regs[16]; | ||
35 | static void *ipi_clear0_regs[16]; | ||
36 | static void *ipi_status0_regs[16]; | ||
37 | static void *ipi_en0_regs[16]; | ||
38 | static void *ipi_mailbox_buf[16]; | ||
39 | |||
34 | /* read a 32bit value from ipi register */ | 40 | /* read a 32bit value from ipi register */ |
35 | #define loongson3_ipi_read32(addr) readl(addr) | 41 | #define loongson3_ipi_read32(addr) readl(addr) |
36 | /* read a 64bit value from ipi register */ | 42 | /* read a 64bit value from ipi register */ |
@@ -48,100 +54,185 @@ DEFINE_PER_CPU(uint32_t, core0_c0count); | |||
48 | __wbflush(); \ | 54 | __wbflush(); \ |
49 | } while (0) | 55 | } while (0) |
50 | 56 | ||
51 | static void *ipi_set0_regs[] = { | 57 | static void ipi_set0_regs_init(void) |
52 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0), | 58 | { |
53 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0), | 59 | ipi_set0_regs[0] = (void *) |
54 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0), | 60 | (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0); |
55 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0), | 61 | ipi_set0_regs[1] = (void *) |
56 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0), | 62 | (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0); |
57 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0), | 63 | ipi_set0_regs[2] = (void *) |
58 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0), | 64 | (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0); |
59 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0), | 65 | ipi_set0_regs[3] = (void *) |
60 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0), | 66 | (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0); |
61 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0), | 67 | ipi_set0_regs[4] = (void *) |
62 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0), | 68 | (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0); |
63 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0), | 69 | ipi_set0_regs[5] = (void *) |
64 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0), | 70 | (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0); |
65 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0), | 71 | ipi_set0_regs[6] = (void *) |
66 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0), | 72 | (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0); |
67 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0), | 73 | ipi_set0_regs[7] = (void *) |
68 | }; | 74 | (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0); |
75 | ipi_set0_regs[8] = (void *) | ||
76 | (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0); | ||
77 | ipi_set0_regs[9] = (void *) | ||
78 | (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0); | ||
79 | ipi_set0_regs[10] = (void *) | ||
80 | (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0); | ||
81 | ipi_set0_regs[11] = (void *) | ||
82 | (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0); | ||
83 | ipi_set0_regs[12] = (void *) | ||
84 | (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0); | ||
85 | ipi_set0_regs[13] = (void *) | ||
86 | (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0); | ||
87 | ipi_set0_regs[14] = (void *) | ||
88 | (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0); | ||
89 | ipi_set0_regs[15] = (void *) | ||
90 | (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0); | ||
91 | } | ||
69 | 92 | ||
70 | static void *ipi_clear0_regs[] = { | 93 | static void ipi_clear0_regs_init(void) |
71 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0), | 94 | { |
72 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0), | 95 | ipi_clear0_regs[0] = (void *) |
73 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0), | 96 | (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0); |
74 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0), | 97 | ipi_clear0_regs[1] = (void *) |
75 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0), | 98 | (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0); |
76 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0), | 99 | ipi_clear0_regs[2] = (void *) |
77 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0), | 100 | (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0); |
78 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0), | 101 | ipi_clear0_regs[3] = (void *) |
79 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0), | 102 | (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0); |
80 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0), | 103 | ipi_clear0_regs[4] = (void *) |
81 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0), | 104 | (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0); |
82 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0), | 105 | ipi_clear0_regs[5] = (void *) |
83 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0), | 106 | (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0); |
84 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0), | 107 | ipi_clear0_regs[6] = (void *) |
85 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0), | 108 | (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0); |
86 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0), | 109 | ipi_clear0_regs[7] = (void *) |
87 | }; | 110 | (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0); |
111 | ipi_clear0_regs[8] = (void *) | ||
112 | (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0); | ||
113 | ipi_clear0_regs[9] = (void *) | ||
114 | (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0); | ||
115 | ipi_clear0_regs[10] = (void *) | ||
116 | (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0); | ||
117 | ipi_clear0_regs[11] = (void *) | ||
118 | (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0); | ||
119 | ipi_clear0_regs[12] = (void *) | ||
120 | (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0); | ||
121 | ipi_clear0_regs[13] = (void *) | ||
122 | (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0); | ||
123 | ipi_clear0_regs[14] = (void *) | ||
124 | (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0); | ||
125 | ipi_clear0_regs[15] = (void *) | ||
126 | (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0); | ||
127 | } | ||
88 | 128 | ||
89 | static void *ipi_status0_regs[] = { | 129 | static void ipi_status0_regs_init(void) |
90 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0), | 130 | { |
91 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0), | 131 | ipi_status0_regs[0] = (void *) |
92 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0), | 132 | (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0); |
93 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0), | 133 | ipi_status0_regs[1] = (void *) |
94 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0), | 134 | (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0); |
95 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0), | 135 | ipi_status0_regs[2] = (void *) |
96 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0), | 136 | (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0); |
97 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0), | 137 | ipi_status0_regs[3] = (void *) |
98 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0), | 138 | (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0); |
99 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0), | 139 | ipi_status0_regs[4] = (void *) |
100 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0), | 140 | (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0); |
101 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0), | 141 | ipi_status0_regs[5] = (void *) |
102 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0), | 142 | (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0); |
103 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0), | 143 | ipi_status0_regs[6] = (void *) |
104 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0), | 144 | (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0); |
105 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0), | 145 | ipi_status0_regs[7] = (void *) |
106 | }; | 146 | (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0); |
147 | ipi_status0_regs[8] = (void *) | ||
148 | (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0); | ||
149 | ipi_status0_regs[9] = (void *) | ||
150 | (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0); | ||
151 | ipi_status0_regs[10] = (void *) | ||
152 | (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0); | ||
153 | ipi_status0_regs[11] = (void *) | ||
154 | (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0); | ||
155 | ipi_status0_regs[12] = (void *) | ||
156 | (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0); | ||
157 | ipi_status0_regs[13] = (void *) | ||
158 | (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0); | ||
159 | ipi_status0_regs[14] = (void *) | ||
160 | (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0); | ||
161 | ipi_status0_regs[15] = (void *) | ||
162 | (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0); | ||
163 | } | ||
107 | 164 | ||
108 | static void *ipi_en0_regs[] = { | 165 | static void ipi_en0_regs_init(void) |
109 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0), | 166 | { |
110 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0), | 167 | ipi_en0_regs[0] = (void *) |
111 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0), | 168 | (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0); |
112 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0), | 169 | ipi_en0_regs[1] = (void *) |
113 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0), | 170 | (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0); |
114 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0), | 171 | ipi_en0_regs[2] = (void *) |
115 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0), | 172 | (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0); |
116 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0), | 173 | ipi_en0_regs[3] = (void *) |
117 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0), | 174 | (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0); |
118 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0), | 175 | ipi_en0_regs[4] = (void *) |
119 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0), | 176 | (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0); |
120 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0), | 177 | ipi_en0_regs[5] = (void *) |
121 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0), | 178 | (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0); |
122 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0), | 179 | ipi_en0_regs[6] = (void *) |
123 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0), | 180 | (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0); |
124 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0), | 181 | ipi_en0_regs[7] = (void *) |
125 | }; | 182 | (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0); |
183 | ipi_en0_regs[8] = (void *) | ||
184 | (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0); | ||
185 | ipi_en0_regs[9] = (void *) | ||
186 | (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0); | ||
187 | ipi_en0_regs[10] = (void *) | ||
188 | (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0); | ||
189 | ipi_en0_regs[11] = (void *) | ||
190 | (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0); | ||
191 | ipi_en0_regs[12] = (void *) | ||
192 | (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0); | ||
193 | ipi_en0_regs[13] = (void *) | ||
194 | (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0); | ||
195 | ipi_en0_regs[14] = (void *) | ||
196 | (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0); | ||
197 | ipi_en0_regs[15] = (void *) | ||
198 | (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0); | ||
199 | } | ||
126 | 200 | ||
127 | static void *ipi_mailbox_buf[] = { | 201 | static void ipi_mailbox_buf_init(void) |
128 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF), | 202 | { |
129 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF), | 203 | ipi_mailbox_buf[0] = (void *) |
130 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF), | 204 | (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF); |
131 | (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF), | 205 | ipi_mailbox_buf[1] = (void *) |
132 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF), | 206 | (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF); |
133 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF), | 207 | ipi_mailbox_buf[2] = (void *) |
134 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF), | 208 | (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF); |
135 | (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF), | 209 | ipi_mailbox_buf[3] = (void *) |
136 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF), | 210 | (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF); |
137 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF), | 211 | ipi_mailbox_buf[4] = (void *) |
138 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF), | 212 | (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF); |
139 | (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF), | 213 | ipi_mailbox_buf[5] = (void *) |
140 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF), | 214 | (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF); |
141 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF), | 215 | ipi_mailbox_buf[6] = (void *) |
142 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF), | 216 | (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF); |
143 | (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF), | 217 | ipi_mailbox_buf[7] = (void *) |
144 | }; | 218 | (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF); |
219 | ipi_mailbox_buf[8] = (void *) | ||
220 | (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF); | ||
221 | ipi_mailbox_buf[9] = (void *) | ||
222 | (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF); | ||
223 | ipi_mailbox_buf[10] = (void *) | ||
224 | (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF); | ||
225 | ipi_mailbox_buf[11] = (void *) | ||
226 | (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF); | ||
227 | ipi_mailbox_buf[12] = (void *) | ||
228 | (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF); | ||
229 | ipi_mailbox_buf[13] = (void *) | ||
230 | (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF); | ||
231 | ipi_mailbox_buf[14] = (void *) | ||
232 | (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF); | ||
233 | ipi_mailbox_buf[15] = (void *) | ||
234 | (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF); | ||
235 | } | ||
145 | 236 | ||
146 | /* | 237 | /* |
147 | * Simple enough, just poke the appropriate ipi register | 238 | * Simple enough, just poke the appropriate ipi register |
@@ -203,6 +294,8 @@ static void loongson3_init_secondary(void) | |||
203 | for (i = 0; i < loongson_sysconf.nr_cpus; i++) | 294 | for (i = 0; i < loongson_sysconf.nr_cpus; i++) |
204 | loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]); | 295 | loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]); |
205 | 296 | ||
297 | cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package; | ||
298 | cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package; | ||
206 | per_cpu(cpu_state, cpu) = CPU_ONLINE; | 299 | per_cpu(cpu_state, cpu) = CPU_ONLINE; |
207 | 300 | ||
208 | i = 0; | 301 | i = 0; |
@@ -246,6 +339,11 @@ static void __init loongson3_smp_setup(void) | |||
246 | __cpu_number_map[i] = ++num; | 339 | __cpu_number_map[i] = ++num; |
247 | __cpu_logical_map[num] = i; | 340 | __cpu_logical_map[num] = i; |
248 | } | 341 | } |
342 | ipi_set0_regs_init(); | ||
343 | ipi_clear0_regs_init(); | ||
344 | ipi_status0_regs_init(); | ||
345 | ipi_en0_regs_init(); | ||
346 | ipi_mailbox_buf_init(); | ||
249 | pr_info("Detected %i available secondary CPU(s)\n", num); | 347 | pr_info("Detected %i available secondary CPU(s)\n", num); |
250 | } | 348 | } |
251 | 349 | ||
@@ -313,7 +411,7 @@ static void loongson3_cpu_die(unsigned int cpu) | |||
313 | * flush all L1 entries at first. Then, another core (usually Core 0) can | 411 | * flush all L1 entries at first. Then, another core (usually Core 0) can |
314 | * safely disable the clock of the target core. loongson3_play_dead() is | 412 | * safely disable the clock of the target core. loongson3_play_dead() is |
315 | * called via CKSEG1 (uncached and unmmaped) */ | 413 | * called via CKSEG1 (uncached and unmmaped) */ |
316 | static void loongson3_play_dead(int *state_addr) | 414 | static void loongson3a_play_dead(int *state_addr) |
317 | { | 415 | { |
318 | register int val; | 416 | register int val; |
319 | register long cpuid, core, node, count; | 417 | register long cpuid, core, node, count; |
@@ -375,6 +473,70 @@ static void loongson3_play_dead(int *state_addr) | |||
375 | : "a1"); | 473 | : "a1"); |
376 | } | 474 | } |
377 | 475 | ||
476 | static void loongson3b_play_dead(int *state_addr) | ||
477 | { | ||
478 | register int val; | ||
479 | register long cpuid, core, node, count; | ||
480 | register void *addr, *base, *initfunc; | ||
481 | |||
482 | __asm__ __volatile__( | ||
483 | " .set push \n" | ||
484 | " .set noreorder \n" | ||
485 | " li %[addr], 0x80000000 \n" /* KSEG0 */ | ||
486 | "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */ | ||
487 | " cache 0, 1(%[addr]) \n" | ||
488 | " cache 0, 2(%[addr]) \n" | ||
489 | " cache 0, 3(%[addr]) \n" | ||
490 | " cache 1, 0(%[addr]) \n" /* flush L1 DCache */ | ||
491 | " cache 1, 1(%[addr]) \n" | ||
492 | " cache 1, 2(%[addr]) \n" | ||
493 | " cache 1, 3(%[addr]) \n" | ||
494 | " addiu %[sets], %[sets], -1 \n" | ||
495 | " bnez %[sets], 1b \n" | ||
496 | " addiu %[addr], %[addr], 0x20 \n" | ||
497 | " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ | ||
498 | " sw %[val], (%[state_addr]) \n" | ||
499 | " sync \n" | ||
500 | " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */ | ||
501 | " .set pop \n" | ||
502 | : [addr] "=&r" (addr), [val] "=&r" (val) | ||
503 | : [state_addr] "r" (state_addr), | ||
504 | [sets] "r" (cpu_data[smp_processor_id()].dcache.sets)); | ||
505 | |||
506 | __asm__ __volatile__( | ||
507 | " .set push \n" | ||
508 | " .set noreorder \n" | ||
509 | " .set mips64 \n" | ||
510 | " mfc0 %[cpuid], $15, 1 \n" | ||
511 | " andi %[cpuid], 0x3ff \n" | ||
512 | " dli %[base], 0x900000003ff01000 \n" | ||
513 | " andi %[core], %[cpuid], 0x3 \n" | ||
514 | " sll %[core], 8 \n" /* get core id */ | ||
515 | " or %[base], %[base], %[core] \n" | ||
516 | " andi %[node], %[cpuid], 0xc \n" | ||
517 | " dsll %[node], 42 \n" /* get node id */ | ||
518 | " or %[base], %[base], %[node] \n" | ||
519 | " dsrl %[node], 30 \n" /* 15:14 */ | ||
520 | " or %[base], %[base], %[node] \n" | ||
521 | "1: li %[count], 0x100 \n" /* wait for init loop */ | ||
522 | "2: bnez %[count], 2b \n" /* limit mailbox access */ | ||
523 | " addiu %[count], -1 \n" | ||
524 | " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ | ||
525 | " beqz %[initfunc], 1b \n" | ||
526 | " nop \n" | ||
527 | " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ | ||
528 | " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ | ||
529 | " ld $a1, 0x38(%[base]) \n" | ||
530 | " jr %[initfunc] \n" /* jump to initial PC */ | ||
531 | " nop \n" | ||
532 | " .set pop \n" | ||
533 | : [core] "=&r" (core), [node] "=&r" (node), | ||
534 | [base] "=&r" (base), [cpuid] "=&r" (cpuid), | ||
535 | [count] "=&r" (count), [initfunc] "=&r" (initfunc) | ||
536 | : /* No Input */ | ||
537 | : "a1"); | ||
538 | } | ||
539 | |||
378 | void play_dead(void) | 540 | void play_dead(void) |
379 | { | 541 | { |
380 | int *state_addr; | 542 | int *state_addr; |
@@ -382,13 +544,48 @@ void play_dead(void) | |||
382 | void (*play_dead_at_ckseg1)(int *); | 544 | void (*play_dead_at_ckseg1)(int *); |
383 | 545 | ||
384 | idle_task_exit(); | 546 | idle_task_exit(); |
385 | play_dead_at_ckseg1 = | 547 | switch (loongson_sysconf.cputype) { |
386 | (void *)CKSEG1ADDR((unsigned long)loongson3_play_dead); | 548 | case Loongson_3A: |
549 | default: | ||
550 | play_dead_at_ckseg1 = | ||
551 | (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead); | ||
552 | break; | ||
553 | case Loongson_3B: | ||
554 | play_dead_at_ckseg1 = | ||
555 | (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead); | ||
556 | break; | ||
557 | } | ||
387 | state_addr = &per_cpu(cpu_state, cpu); | 558 | state_addr = &per_cpu(cpu_state, cpu); |
388 | mb(); | 559 | mb(); |
389 | play_dead_at_ckseg1(state_addr); | 560 | play_dead_at_ckseg1(state_addr); |
390 | } | 561 | } |
391 | 562 | ||
563 | void loongson3_disable_clock(int cpu) | ||
564 | { | ||
565 | uint64_t core_id = cpu_data[cpu].core; | ||
566 | uint64_t package_id = cpu_data[cpu].package; | ||
567 | |||
568 | if (loongson_sysconf.cputype == Loongson_3A) { | ||
569 | LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); | ||
570 | } else if (loongson_sysconf.cputype == Loongson_3B) { | ||
571 | if (!cpuhotplug_workaround) | ||
572 | LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | void loongson3_enable_clock(int cpu) | ||
577 | { | ||
578 | uint64_t core_id = cpu_data[cpu].core; | ||
579 | uint64_t package_id = cpu_data[cpu].package; | ||
580 | |||
581 | if (loongson_sysconf.cputype == Loongson_3A) { | ||
582 | LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); | ||
583 | } else if (loongson_sysconf.cputype == Loongson_3B) { | ||
584 | if (!cpuhotplug_workaround) | ||
585 | LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); | ||
586 | } | ||
587 | } | ||
588 | |||
392 | #define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN) | 589 | #define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN) |
393 | static int loongson3_cpu_callback(struct notifier_block *nfb, | 590 | static int loongson3_cpu_callback(struct notifier_block *nfb, |
394 | unsigned long action, void *hcpu) | 591 | unsigned long action, void *hcpu) |
@@ -399,12 +596,12 @@ static int loongson3_cpu_callback(struct notifier_block *nfb, | |||
399 | case CPU_POST_DEAD: | 596 | case CPU_POST_DEAD: |
400 | case CPU_POST_DEAD_FROZEN: | 597 | case CPU_POST_DEAD_FROZEN: |
401 | pr_info("Disable clock for CPU#%d\n", cpu); | 598 | pr_info("Disable clock for CPU#%d\n", cpu); |
402 | LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu)); | 599 | loongson3_disable_clock(cpu); |
403 | break; | 600 | break; |
404 | case CPU_UP_PREPARE: | 601 | case CPU_UP_PREPARE: |
405 | case CPU_UP_PREPARE_FROZEN: | 602 | case CPU_UP_PREPARE_FROZEN: |
406 | pr_info("Enable clock for CPU#%d\n", cpu); | 603 | pr_info("Enable clock for CPU#%d\n", cpu); |
407 | LOONGSON_CHIPCFG0 |= 1 << (12 + cpu); | 604 | loongson3_enable_clock(cpu); |
408 | break; | 605 | break; |
409 | } | 606 | } |
410 | 607 | ||
diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h index 3453e8c4f2f0..d98ff654b7d7 100644 --- a/arch/mips/loongson/loongson-3/smp.h +++ b/arch/mips/loongson/loongson-3/smp.h | |||
@@ -1,29 +1,30 @@ | |||
1 | #ifndef __LOONGSON_SMP_H_ | 1 | #ifndef __LOONGSON_SMP_H_ |
2 | #define __LOONGSON_SMP_H_ | 2 | #define __LOONGSON_SMP_H_ |
3 | 3 | ||
4 | /* for Loongson-3A smp support */ | 4 | /* for Loongson-3 smp support */ |
5 | extern unsigned long long smp_group[4]; | ||
5 | 6 | ||
6 | /* 4 groups(nodes) in maximum in numa case */ | 7 | /* 4 groups(nodes) in maximum in numa case */ |
7 | #define SMP_CORE_GROUP0_BASE 0x900000003ff01000 | 8 | #define SMP_CORE_GROUP0_BASE (smp_group[0]) |
8 | #define SMP_CORE_GROUP1_BASE 0x900010003ff01000 | 9 | #define SMP_CORE_GROUP1_BASE (smp_group[1]) |
9 | #define SMP_CORE_GROUP2_BASE 0x900020003ff01000 | 10 | #define SMP_CORE_GROUP2_BASE (smp_group[2]) |
10 | #define SMP_CORE_GROUP3_BASE 0x900030003ff01000 | 11 | #define SMP_CORE_GROUP3_BASE (smp_group[3]) |
11 | 12 | ||
12 | /* 4 cores in each group(node) */ | 13 | /* 4 cores in each group(node) */ |
13 | #define SMP_CORE0_OFFSET 0x000 | 14 | #define SMP_CORE0_OFFSET 0x000 |
14 | #define SMP_CORE1_OFFSET 0x100 | 15 | #define SMP_CORE1_OFFSET 0x100 |
15 | #define SMP_CORE2_OFFSET 0x200 | 16 | #define SMP_CORE2_OFFSET 0x200 |
16 | #define SMP_CORE3_OFFSET 0x300 | 17 | #define SMP_CORE3_OFFSET 0x300 |
17 | 18 | ||
18 | /* ipi registers offsets */ | 19 | /* ipi registers offsets */ |
19 | #define STATUS0 0x00 | 20 | #define STATUS0 0x00 |
20 | #define EN0 0x04 | 21 | #define EN0 0x04 |
21 | #define SET0 0x08 | 22 | #define SET0 0x08 |
22 | #define CLEAR0 0x0c | 23 | #define CLEAR0 0x0c |
23 | #define STATUS1 0x10 | 24 | #define STATUS1 0x10 |
24 | #define MASK1 0x14 | 25 | #define MASK1 0x14 |
25 | #define SET1 0x18 | 26 | #define SET1 0x18 |
26 | #define CLEAR1 0x1c | 27 | #define CLEAR1 0x1c |
27 | #define BUF 0x20 | 28 | #define BUF 0x20 |
28 | 29 | ||
29 | #endif | 30 | #endif |