15c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/*
25c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
35c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * reserved.
45c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
55c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * This software is available to you under a choice of one of two
65c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * licenses.  You may choose to be licensed under the terms of the GNU
75c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * General Public License (GPL) Version 2, available from the file
85c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * COPYING in the main directory of this source tree, or the NetLogic
95c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * license below:
105c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
115c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Redistribution and use in source and binary forms, with or without
125c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * modification, are permitted provided that the following conditions
135c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * are met:
145c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
155c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * 1. Redistributions of source code must retain the above copyright
165c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    notice, this list of conditions and the following disclaimer.
175c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * 2. Redistributions in binary form must reproduce the above copyright
185c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    notice, this list of conditions and the following disclaimer in
195c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    the documentation and/or other materials provided with the
205c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    distribution.
215c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
225c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
235c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
245c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
255c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
265c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
275c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
285c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
295c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
305c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
315c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
325c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
335c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C */
345c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
355c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/kernel.h>
365c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/delay.h>
375c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/init.h>
385c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/smp.h>
395c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/irq.h>
405c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
415c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/mmu_context.h>
425c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
435c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/interrupt.h>
445c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/mips-extns.h>
450c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C#include <asm/netlogic/haldefs.h>
460c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C#include <asm/netlogic/common.h>
475c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
4865040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#if defined(CONFIG_CPU_XLP)
4965040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#include <asm/netlogic/xlp-hal/iomap.h>
5066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C#include <asm/netlogic/xlp-hal/xlp.h>
5165040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#include <asm/netlogic/xlp-hal/pic.h>
5265040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#elif defined(CONFIG_CPU_XLR)
535c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/xlr/iomap.h>
545c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/xlr/pic.h>
5566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C#include <asm/netlogic/xlr/xlr.h>
5665040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#else
5765040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#error "Unknown CPU"
5865040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#endif
595c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
600c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran Cvoid nlm_send_ipi_single(int logical_cpu, unsigned int action)
615c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
6277ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	int cpu, node;
6377ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	uint64_t picbase;
6477ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C
6577ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	cpu = cpu_logical_map(logical_cpu);
6698d4884ca55883e8b16180bd969a8bccaa885c80Jayachandran C	node = nlm_cpuid_to_node(cpu);
6777ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	picbase = nlm_get_node(node)->picbase;
685c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
695c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	if (action & SMP_CALL_FUNCTION)
7077ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C		nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0);
710c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C	if (action & SMP_RESCHEDULE_YOURSELF)
7277ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C		nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
735c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
745c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
755c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
765c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
775c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	int cpu;
785c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
795c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	for_each_cpu(cpu, mask) {
800c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C		nlm_send_ipi_single(cpu, action);
815c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	}
825c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
835c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
845c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/* IRQ_IPI_SMP_FUNCTION Handler */
855c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
865c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
87220d9122e8c5a467fdeefc1857e077f29a623bfdJayachandran C	clear_c0_eimr(irq);
88220d9122e8c5a467fdeefc1857e077f29a623bfdJayachandran C	ack_c0_eirr(irq);
8965040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C	smp_call_function_interrupt();
90220d9122e8c5a467fdeefc1857e077f29a623bfdJayachandran C	set_c0_eimr(irq);
915c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
925c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
935c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/* IRQ_IPI_SMP_RESCHEDULE  handler */
945c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
955c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
96220d9122e8c5a467fdeefc1857e077f29a623bfdJayachandran C	clear_c0_eimr(irq);
97220d9122e8c5a467fdeefc1857e077f29a623bfdJayachandran C	ack_c0_eirr(irq);
9865040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C	scheduler_ipi();
99220d9122e8c5a467fdeefc1857e077f29a623bfdJayachandran C	set_c0_eimr(irq);
1005c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1015c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1025c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/*
1035c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Called before going into mips code, early cpu init
1045c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C */
1050c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran Cvoid nlm_early_init_secondary(int cpu)
1065c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
10765040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C	change_c0_config(CONF_CM_CMASK, 0x3);
10865040e224e5b214a93fa0c790add5d69b054ecaeJayachandran C#ifdef CONFIG_CPU_XLP
1095b6ff35d33cb0310c36f9081b9e39cd016715e9cJayachandran C	xlp_mmu_init();
1100c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C#endif
11177ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	write_c0_ebase(nlm_current_node()->ebase);
1125c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1135c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1145c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/*
1155c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Code to run on secondary just after probing the CPU
1165c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C */
117078a55fc824c1633b3a507e4ad48b4637c1dfc18Paul Gortmakerstatic void nlm_init_secondary(void)
1185c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
11938541742da05f65d77e514a70bae9b84251c4bc4Jayachandran C	int hwtid;
12038541742da05f65d77e514a70bae9b84251c4bc4Jayachandran C
12138541742da05f65d77e514a70bae9b84251c4bc4Jayachandran C	hwtid = hard_smp_processor_id();
12238541742da05f65d77e514a70bae9b84251c4bc4Jayachandran C	current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
123ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam	nlm_percpu_init(hwtid);
12438541742da05f65d77e514a70bae9b84251c4bc4Jayachandran C	nlm_smp_irq_init(hwtid);
1255c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1265c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
127b3ea581834c1e36cc76589e63dedcd99fd6abf51Hillf Dantonvoid nlm_prepare_cpus(unsigned int max_cpus)
128b3ea581834c1e36cc76589e63dedcd99fd6abf51Hillf Danton{
129b3ea581834c1e36cc76589e63dedcd99fd6abf51Hillf Danton	/* declare we are SMT capable */
130b3ea581834c1e36cc76589e63dedcd99fd6abf51Hillf Danton	smp_num_siblings = nlm_threads_per_core;
131b3ea581834c1e36cc76589e63dedcd99fd6abf51Hillf Danton}
132b3ea581834c1e36cc76589e63dedcd99fd6abf51Hillf Danton
1335c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid nlm_smp_finish(void)
1345c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
13539263eeb44308a5d6ea6117376721a6091d2b622Jayachandran C	local_irq_enable();
1365c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1375c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1385c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/*
1395c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Boot all other cpus in the system, initialize them, and bring them into
1405c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * the boot function
1415c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C */
1425c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cunsigned long nlm_next_gp;
1435c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cunsigned long nlm_next_sp;
14462b734d289989dd15ab7a52227879ce95db9a934Jayachandran Cstatic cpumask_t phys_cpu_present_mask;
1455c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1465c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
1475c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
14877ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	int cpu, node;
1495c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
15077ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	cpu = cpu_logical_map(logical_cpu);
15198d4884ca55883e8b16180bd969a8bccaa885c80Jayachandran C	node = nlm_cpuid_to_node(logical_cpu);
15277ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
15377ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nlm_next_gp = (unsigned long)task_thread_info(idle);
1545c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
15577ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	/* barrier for sp/gp store above */
1565c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	__sync();
15777ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nlm_pic_send_ipi(nlm_get_node(node)->picbase, cpu, 1, 1);  /* NMI */
1585c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1595c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1605c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid __init nlm_smp_setup(void)
1615c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
1625c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	unsigned int boot_cpu;
16398d4884ca55883e8b16180bd969a8bccaa885c80Jayachandran C	int num_cpus, i, ncore, node;
164919f9abb3723f088290c62648b12fbfc7600d923Jayachandran C	volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
16562b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	char buf[64];
1665c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1675c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	boot_cpu = hard_smp_processor_id();
16862b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	cpumask_clear(&phys_cpu_present_mask);
1695c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
17062b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	cpumask_set_cpu(boot_cpu, &phys_cpu_present_mask);
1715c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	__cpu_number_map[boot_cpu] = 0;
1725c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	__cpu_logical_map[0] = boot_cpu;
1730b5f9c005def154f9c21f9be0223b65b50d54368Rusty Russell	set_cpu_possible(0, true);
1745c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1755c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	num_cpus = 1;
1765c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	for (i = 0; i < NR_CPUS; i++) {
177b2788965baed868ce48ebd6d67f00acf617c9ee6Hillf Danton		/*
178919f9abb3723f088290c62648b12fbfc7600d923Jayachandran C		 * cpu_ready array is not set for the boot_cpu,
1790c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C		 * it is only set for ASPs (see smpboot.S)
180b2788965baed868ce48ebd6d67f00acf617c9ee6Hillf Danton		 */
181919f9abb3723f088290c62648b12fbfc7600d923Jayachandran C		if (cpu_ready[i]) {
18262b734d289989dd15ab7a52227879ce95db9a934Jayachandran C			cpumask_set_cpu(i, &phys_cpu_present_mask);
1835c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			__cpu_number_map[i] = num_cpus;
1845c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			__cpu_logical_map[num_cpus] = i;
1850b5f9c005def154f9c21f9be0223b65b50d54368Rusty Russell			set_cpu_possible(num_cpus, true);
18698d4884ca55883e8b16180bd969a8bccaa885c80Jayachandran C			node = nlm_cpuid_to_node(i);
18798d4884ca55883e8b16180bd969a8bccaa885c80Jayachandran C			cpumask_set_cpu(num_cpus, &nlm_get_node(node)->cpumask);
1885c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			++num_cpus;
1895c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		}
1905c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	}
1915c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
19262b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	cpumask_scnprintf(buf, ARRAY_SIZE(buf), &phys_cpu_present_mask);
19362b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	pr_info("Physical CPU mask: %s\n", buf);
19462b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
19562b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	pr_info("Possible CPU mask: %s\n", buf);
19662b734d289989dd15ab7a52227879ce95db9a934Jayachandran C
1972e240ddd09d41645e928a19a3ff3290a0f546834Jayachandran C	/* check with the cores we have woken up */
19877ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
19977ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C		ncore += hweight32(nlm_get_node(i)->coremask);
20077ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C
20177ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
20277ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C		nlm_threads_per_core, num_cpus);
20362b734d289989dd15ab7a52227879ce95db9a934Jayachandran C
20462b734d289989dd15ab7a52227879ce95db9a934Jayachandran C	/* switch NMI handler to boot CPUs */
20566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	nlm_set_nmi_handler(nlm_boot_secondary_cpus);
2065c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
2075c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
2082a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran Cstatic int nlm_parse_cpumask(cpumask_t *wakeup_mask)
20966d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C{
21066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	uint32_t core0_thr_mask, core_thr_mask;
2112a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C	int threadmode, i, j;
2122e240ddd09d41645e928a19a3ff3290a0f546834Jayachandran C	char buf[64];
21366d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
2142a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C	core0_thr_mask = 0;
21577ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	for (i = 0; i < NLM_THREADS_PER_CORE; i++)
2162a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C		if (cpumask_test_cpu(i, wakeup_mask))
2172a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C			core0_thr_mask |= (1 << i);
21866d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	switch (core0_thr_mask) {
21966d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	case 1:
22066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		nlm_threads_per_core = 1;
22166d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		threadmode = 0;
22266d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		break;
22366d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	case 3:
22466d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		nlm_threads_per_core = 2;
22566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		threadmode = 2;
22666d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		break;
22766d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	case 0xf:
22866d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		nlm_threads_per_core = 4;
22966d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		threadmode = 3;
23066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		break;
23166d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	default:
23266d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C		goto unsupp;
23366d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	}
23466d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
23566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	/* Verify other cores CPU masks */
23677ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	for (i = 0; i < NR_CPUS; i += NLM_THREADS_PER_CORE) {
2372a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C		core_thr_mask = 0;
23877ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C		for (j = 0; j < NLM_THREADS_PER_CORE; j++)
2392a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C			if (cpumask_test_cpu(i + j, wakeup_mask))
2402a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C				core_thr_mask |= (1 << j);
2412a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C		if (core_thr_mask != 0 && core_thr_mask != core0_thr_mask)
24266d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C				goto unsupp;
24366d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	}
24466d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	return threadmode;
24566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
24666d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran Cunsupp:
2472e240ddd09d41645e928a19a3ff3290a0f546834Jayachandran C	cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
2482e240ddd09d41645e928a19a3ff3290a0f546834Jayachandran C	panic("Unsupported CPU mask %s", buf);
24966d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	return 0;
25066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C}
25166d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
252078a55fc824c1633b3a507e4ad48b4637c1dfc18Paul Gortmakerint nlm_wakeup_secondary_cpus(void)
25366d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C{
25453c832197f3adc5a360336f75fe34a95fe2d796bJayachandran C	u32 *reset_data;
25566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	int threadmode;
25666d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
25766d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	/* verify the mask and setup core config variables */
2582a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C	threadmode = nlm_parse_cpumask(&nlm_cpumask);
25966d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
26066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	/* Setup CPU init parameters */
26153c832197f3adc5a360336f75fe34a95fe2d796bJayachandran C	reset_data = nlm_get_boot_data(BOOT_THREAD_MODE);
26253c832197f3adc5a360336f75fe34a95fe2d796bJayachandran C	*reset_data = threadmode;
26366d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
26466d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C#ifdef CONFIG_CPU_XLP
26566d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	xlp_wakeup_secondary_cpus();
26666d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C#else
26766d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	xlr_wakeup_secondary_cpus();
26866d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C#endif
26966d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C	return 0;
27066d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C}
27166d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
2725c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cstruct plat_smp_ops nlm_smp_ops = {
2735c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.send_ipi_single	= nlm_send_ipi_single,
2745c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.send_ipi_mask		= nlm_send_ipi_mask,
2755c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.init_secondary		= nlm_init_secondary,
2765c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.smp_finish		= nlm_smp_finish,
2775c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.boot_secondary		= nlm_boot_secondary,
2785c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.smp_setup		= nlm_smp_setup,
2795c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	.prepare_cpus		= nlm_prepare_cpus,
2805c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C};
281