/*
 * This file is subject to the terms and conditions of the GNU General
 * Public License.  See the file "COPYING" in the main directory of this
 * archive for more details.
 *
 * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
 * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
 */
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/topology.h>
#include <linux/nodemask.h>

#include <asm/page.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/sn/agent.h>
#include <asm/sn/arch.h>
#include <asm/sn/gda.h>
#include <asm/sn/intr.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/launch.h>
#include <asm/sn/mapped_kernel.h>
#include <asm/sn/types.h>

#include "ip27-common.h"

static int node_scan_cpus(nasid_t nasid, int highest)
{
	static int cpus_found;
	lboard_t *brd;
	klcpu_t *acpu;
	cpuid_t cpuid;

	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);

	do {
		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
		while (acpu) {
			cpuid = acpu->cpu_info.virtid;
			/* Only let it join in if it's marked enabled */
			if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
			    (cpus_found != NR_CPUS)) {
				if (cpuid > highest)
					highest = cpuid;
				set_cpu_possible(cpuid, true);
				cputonasid(cpus_found) = nasid;
				cputoslice(cpus_found) = acpu->cpu_info.physid;
				sn_cpu_info[cpus_found].p_speed =
							acpu->cpu_speed;
				cpus_found++;
			}
			acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
								KLSTRUCT_CPU);
		}
		brd = KLCF_NEXT(brd);
		if (!brd)
			break;

		brd = find_lboard(brd, KLTYPE_IP27);
	} while (brd);

	return highest;
}

void cpu_node_probe(void)
{
	int i, highest = 0;
	gda_t *gdap = GDA;

	nodes_clear(node_online_map);
	nodes_clear(node_possible_map);
	for (i = 0; i < MAX_NUMNODES; i++) {
		nasid_t nasid = gdap->g_nasidtable[i];
		if (nasid == INVALID_NASID)
			break;
		node_set_online(nasid);
		node_set(nasid, node_possible_map);
		highest = node_scan_cpus(nasid, highest);
	}

	printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes());
}

static __init void intr_clear_all(nasid_t nasid)
{
	int i;

	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);

	for (i = 0; i < 128; i++)
		REMOTE_HUB_CLR_INTR(nasid, i);
}

static void ip27_send_ipi_single(int destid, unsigned int action)
{
	int irq;

	switch (action) {
	case SMP_RESCHEDULE_YOURSELF:
		irq = CPU_RESCHED_A_IRQ;
		break;
	case SMP_CALL_FUNCTION:
		irq = CPU_CALL_A_IRQ;
		break;
	default:
		panic("sendintr");
	}

	irq += cputoslice(destid);

	/*
	 * Set the interrupt bit associated with the CPU we want to
	 * send the interrupt to.
	 */
	REMOTE_HUB_SEND_INTR(cpu_to_node(destid), irq);
}

static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action)
{
	unsigned int i;

	for_each_cpu(i, mask)
		ip27_send_ipi_single(i, action);
}

static void ip27_init_cpu(void)
{
	per_cpu_init();
}

static void ip27_smp_finish(void)
{
	hub_rt_clock_event_init();
	local_irq_enable();
}

/*
 * Launch a slave into smp_bootstrap().	 It doesn't take an argument, and we
 * set sp to the kernel stack of the newly created idle process, gp to the proc
 * struct so that current_thread_info() will work.
 */
static int ip27_boot_secondary(int cpu, struct task_struct *idle)
{
	unsigned long gp = (unsigned long)task_thread_info(idle);
	unsigned long sp = __KSTK_TOS(idle);

	LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
		(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
		0, (void *) sp, (void *) gp);
	return 0;
}

static void __init ip27_smp_setup(void)
{
	nasid_t nasid;

	for_each_online_node(nasid) {
		if (nasid == 0)
			continue;
		intr_clear_all(nasid);
	}

	replicate_kernel_text();

	/*
	 * PROM sets up system, that boot cpu is always first CPU on nasid 0
	 */
	cputonasid(0) = 0;
	cputoslice(0) = LOCAL_HUB_L(PI_CPU_NUM);
}

static void __init ip27_prepare_cpus(unsigned int max_cpus)
{
	/* We already did everything necessary earlier */
}

const struct plat_smp_ops ip27_smp_ops = {
	.send_ipi_single	= ip27_send_ipi_single,
	.send_ipi_mask		= ip27_send_ipi_mask,
	.init_secondary		= ip27_init_cpu,
	.smp_finish		= ip27_smp_finish,
	.boot_secondary		= ip27_boot_secondary,
	.smp_setup		= ip27_smp_setup,
	.prepare_cpus		= ip27_prepare_cpus,
	.prepare_boot_cpu	= ip27_init_cpu,
};
