/*
 * Cell Internal Interrupt Controller
 *
 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
 *
 * Author: Arnd Bergmann <arndb@de.ibm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/percpu.h>
#include <linux/types.h>

#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/ptrace.h>

#include "interrupt.h"

struct iic_pending_bits {
	u32 data;
	u8 flags;
	u8 class;
	u8 source;
	u8 prio;
};

enum iic_pending_flags {
	IIC_VALID = 0x80,
	IIC_IPI   = 0x40,
};

struct iic_regs {
	struct iic_pending_bits pending;
	struct iic_pending_bits pending_destr;
	u64 generate;
	u64 prio;
};

struct iic {
	struct iic_regs __iomem *regs;
	u8 target_id;
};

static DEFINE_PER_CPU(struct iic, iic);

void iic_local_enable(void)
{
	out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
}

void iic_local_disable(void)
{
	out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
}

static unsigned int iic_startup(unsigned int irq)
{
	return 0;
}

static void iic_enable(unsigned int irq)
{
	iic_local_enable();
}

static void iic_disable(unsigned int irq)
{
}

static void iic_end(unsigned int irq)
{
	iic_local_enable();
}

static struct hw_interrupt_type iic_pic = {
	.typename = " CELL-IIC ",
	.startup = iic_startup,
	.enable = iic_enable,
	.disable = iic_disable,
	.end = iic_end,
};

static int iic_external_get_irq(struct iic_pending_bits pending)
{
	int irq;
	unsigned char node, unit;

	node = pending.source >> 4;
	unit = pending.source & 0xf;
	irq = -1;

	/*
	 * This mapping is specific to the Cell Broadband
	 * Engine. We might need to get the numbers
	 * from the device tree to support future CPUs.
	 */
	switch (unit) {
	case 0x00:
	case 0x0b:
		/*
		 * One of these units can be connected
		 * to an external interrupt controller.
		 */
		if (pending.prio > 0x3f ||
		    pending.class != 2)
			break;
		irq = IIC_EXT_OFFSET
			+ spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
			+ node * IIC_NODE_STRIDE;
		break;
	case 0x01 ... 0x04:
	case 0x07 ... 0x0a:
		/*
		 * These units are connected to the SPEs
		 */
		if (pending.class > 2)
			break;
		irq = IIC_SPE_OFFSET
			+ pending.class * IIC_CLASS_STRIDE
			+ node * IIC_NODE_STRIDE
			+ unit;
		break;
	}
	if (irq == -1)
		printk(KERN_WARNING "Unexpected interrupt class %02x, "
			"source %02x, prio %02x, cpu %02x\n", pending.class,
			pending.source, pending.prio, smp_processor_id());
	return irq;
}

/* Get an IRQ number from the pending state register of the IIC */
int iic_get_irq(struct pt_regs *regs)
{
	struct iic *iic;
	int irq;
	struct iic_pending_bits pending;

	iic = &__get_cpu_var(iic);
	*(unsigned long *) &pending = 
		in_be64((unsigned long __iomem *) &iic->regs->pending_destr);

	irq = -1;
	if (pending.flags & IIC_VALID) {
		if (pending.flags & IIC_IPI) {
			irq = IIC_IPI_OFFSET + (pending.prio >> 4);
/*
			if (irq > 0x80)
				printk(KERN_WARNING "Unexpected IPI prio %02x"
					"on CPU %02x\n", pending.prio,
							smp_processor_id());
*/
		} else {
			irq = iic_external_get_irq(pending);
		}
	}
	return irq;
}

static int setup_iic(int cpu, struct iic *iic)
{
	struct device_node *np;
	int nodeid = cpu / 2;
	unsigned long regs;

	for (np = of_find_node_by_type(NULL, "cpu");
	     np;
	     np = of_find_node_by_type(np, "cpu")) {
		if (nodeid == *(int *)get_property(np, "node-id", NULL))
			break;
	}

	if (!np) {
		printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
		iic->regs = NULL;
		iic->target_id = 0xff;
		return -ENODEV;
	}

	regs = *(long *)get_property(np, "iic", NULL);

	/* hack until we have decided on the devtree info */
	regs += 0x400;
	if (cpu & 1)
		regs += 0x20;

	printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
	iic->regs = __ioremap(regs, sizeof(struct iic_regs),
					 _PAGE_NO_CACHE);
	iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
	return 0;
}

#ifdef CONFIG_SMP

/* Use the highest interrupt priorities for IPI */
static inline int iic_ipi_to_irq(int ipi)
{
	return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi;
}

static inline int iic_irq_to_ipi(int irq)
{
	return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET);
}

void iic_setup_cpu(void)
{
	out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
}

void iic_cause_IPI(int cpu, int mesg)
{
	out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
}

u8 iic_get_target_id(int cpu)
{
	return per_cpu(iic, cpu).target_id;
}
EXPORT_SYMBOL_GPL(iic_get_target_id);

static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
	smp_message_recv(iic_irq_to_ipi(irq), regs);
	return IRQ_HANDLED;
}

static void iic_request_ipi(int ipi, const char *name)
{
	int irq;

	irq = iic_ipi_to_irq(ipi);
	/* IPIs are marked SA_INTERRUPT as they must run with irqs
	 * disabled */
	get_irq_desc(irq)->handler = &iic_pic;
	get_irq_desc(irq)->status |= IRQ_PER_CPU;
	request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL);
}

void iic_request_IPIs(void)
{
	iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
	iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
#ifdef CONFIG_DEBUGGER
	iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
#endif /* CONFIG_DEBUGGER */
}
#endif /* CONFIG_SMP */

static void iic_setup_spe_handlers(void)
{
	int be, isrc;

	/* Assume two threads per BE are present */
	for (be=0; be < num_present_cpus() / 2; be++) {
		for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
			int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
			get_irq_desc(irq)->handler = &iic_pic;
		}
	}
}

void iic_init_IRQ(void)
{
	int cpu, irq_offset;
	struct iic *iic;

	irq_offset = 0;
	for_each_cpu(cpu) {
		iic = &per_cpu(iic, cpu);
		setup_iic(cpu, iic);
		if (iic->regs)
			out_be64(&iic->regs->prio, 0xff);
	}
	iic_setup_spe_handlers();
}
