/*
 * ARC700 Simulation-only Extensions for SMP
 *
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Vineet Gupta    - 2012 : split off arch common and plat specific SMP
 *  Rajeshwar Ranga - 2007 : Interrupt Distribution Unit API's
 */

#include <linux/smp.h>
#include <linux/irq.h>
#include <plat/irq.h>
#include <plat/smp.h>

static char smp_cpuinfo_buf[128];

/*
 *-------------------------------------------------------------------
 * Platform specific callbacks expected by arch SMP code
 *-------------------------------------------------------------------
 */

/*
 * Master kick starting another CPU
 */
static void iss_model_smp_wakeup_cpu(int cpu, unsigned long pc)
{
	/* setup the start PC */
	write_aux_reg(ARC_AUX_XTL_REG_PARAM, pc);

	/* Trigger WRITE_PC cmd for this cpu */
	write_aux_reg(ARC_AUX_XTL_REG_CMD,
			(ARC_XTL_CMD_WRITE_PC | (cpu << 8)));

	/* Take the cpu out of Halt */
	write_aux_reg(ARC_AUX_XTL_REG_CMD,
			(ARC_XTL_CMD_CLEAR_HALT | (cpu << 8)));

}

/*
 * Any SMP specific init any CPU does when it comes up.
 * Here we setup the CPU to enable Inter-Processor-Interrupts
 * Called for each CPU
 * -Master      : init_IRQ()
 * -Other(s)    : start_kernel_secondary()
 */
void iss_model_init_smp(unsigned int cpu)
{
	/* Check if CPU is configured for more than 16 interrupts */
	if (NR_IRQS <= 16 || get_hw_config_num_irq() <= 16)
		panic("[arcfpga] IRQ system can't support IDU IPI\n");

	idu_disable();

	/****************************************************************
	 * IDU provides a set of Common IRQs, each of which can be dynamically
	 * attached to (1|many|all) CPUs.
	 * The Common IRQs [0-15] are mapped as CPU pvt [16-31]
	 *
	 * Here we use a simple 1:1 mapping:
	 * A CPU 'x' is wired to Common IRQ 'x'.
	 * So an IDU ASSERT on IRQ 'x' will trigger Interupt on CPU 'x', which
	 * makes up for our simple IPI plumbing.
	 *
	 * TBD: Have a dedicated multicast IRQ for sending IPIs to all CPUs
	 *      w/o having to do one-at-a-time
	 ******************************************************************/

	/*
	 * Claim an IRQ which would trigger IPI on this CPU.
	 * In IDU parlance it involves setting up a cpu bitmask for the IRQ
	 * The bitmap here contains only 1 CPU (self).
	 */
	idu_irq_set_tgtcpu(cpu, 0x1 << cpu);

	/* Set the IRQ destination to use the bitmask above */
	idu_irq_set_mode(cpu, 7, /* XXX: IDU_IRQ_MOD_TCPU_ALLRECP: ISS bug */
			 IDU_IRQ_MODE_PULSE_TRIG);

	idu_enable();

	/* Attach the arch-common IPI ISR to our IDU IRQ */
	smp_ipi_irq_setup(cpu, IDU_INTERRUPT_0 + cpu);
}

static void iss_model_ipi_send(void *arg)
{
	struct cpumask *callmap = arg;
	unsigned int cpu;

	for_each_cpu(cpu, callmap)
		idu_irq_assert(cpu);
}

static void iss_model_ipi_clear(int cpu, int irq)
{
	idu_irq_clear(IDU_INTERRUPT_0 + cpu);
}

void iss_model_init_early_smp(void)
{
#define IS_AVAIL1(var, str)    ((var) ? str : "")

	struct bcr_mp mp;

	READ_BCR(ARC_REG_MP_BCR, mp);

	sprintf(smp_cpuinfo_buf, "Extn [ISS-SMP]: v%d, arch(%d) %s %s %s\n",
		mp.ver, mp.mp_arch, IS_AVAIL1(mp.scu, "SCU"),
		IS_AVAIL1(mp.idu, "IDU"), IS_AVAIL1(mp.sdu, "SDU"));

	plat_smp_ops.info = smp_cpuinfo_buf;

	plat_smp_ops.cpu_kick = iss_model_smp_wakeup_cpu;
	plat_smp_ops.ipi_send = iss_model_ipi_send;
	plat_smp_ops.ipi_clear = iss_model_ipi_clear;
}

/*
 *-------------------------------------------------------------------
 * Low level Platform IPI Providers
 *-------------------------------------------------------------------
 */

/* Set the Mode for the Common IRQ */
void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode)
{
	uint32_t par = IDU_IRQ_MODE_PARAM(dest_mode, trig_mode);

	IDU_SET_PARAM(par);
	IDU_SET_COMMAND(irq, IDU_IRQ_WMODE);
}

/* Set the target cpu Bitmask for Common IRQ */
void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask)
{
	IDU_SET_PARAM(mask);
	IDU_SET_COMMAND(irq, IDU_IRQ_WBITMASK);
}

/* Get the Interrupt Acknowledged status for IRQ (as CPU Bitmask) */
bool idu_irq_get_ack(uint8_t irq)
{
	uint32_t val;

	IDU_SET_COMMAND(irq, IDU_IRQ_ACK);
	val = IDU_GET_PARAM();

	return val & (1 << irq);
}

/*
 * Get the Interrupt Pending status for IRQ (as CPU Bitmask)
 * -Pending means CPU has not yet noticed the IRQ (e.g. disabled)
 * -After Interrupt has been taken, the IPI expcitily needs to be
 *  cleared, to be acknowledged.
 */
bool idu_irq_get_pend(uint8_t irq)
{
	uint32_t val;

	IDU_SET_COMMAND(irq, IDU_IRQ_PEND);
	val = IDU_GET_PARAM();

	return val & (1 << irq);
}
