/*
 * 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) 1992 Linus Torvalds
 * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
 */
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>

#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/jazz.h>

static DEFINE_SPINLOCK(r4030_lock);

static void enable_r4030_irq(unsigned int irq)
{
	unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ);
	unsigned long flags;

	spin_lock_irqsave(&r4030_lock, flags);
	mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
	spin_unlock_irqrestore(&r4030_lock, flags);
}

void disable_r4030_irq(unsigned int irq)
{
	unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
	unsigned long flags;

	spin_lock_irqsave(&r4030_lock, flags);
	mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
	spin_unlock_irqrestore(&r4030_lock, flags);
}

static struct irq_chip r4030_irq_type = {
	.name = "R4030",
	.ack = disable_r4030_irq,
	.mask = disable_r4030_irq,
	.mask_ack = disable_r4030_irq,
	.unmask = enable_r4030_irq,
};

void __init init_r4030_ints(void)
{
	int i;

	for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++)
		set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq);

	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);		/* clear pending IRQs */
	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);	/* clear error bits */
}

/*
 * On systems with i8259-style interrupt controllers we assume for
 * driver compatibility reasons interrupts 0 - 15 to be the i8259
 * interrupts even if the hardware uses a different interrupt numbering.
 */
void __init arch_init_irq(void)
{
	init_i8259_irqs();			/* Integrated i8259  */
	init_r4030_ints();

	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
}

static void loc_call(unsigned int irq, unsigned int mask)
{
	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
	do_IRQ(irq);
	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
}

static void ll_local_dev(void)
{
	switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
	case 0:
		panic("Unimplemented loc_no_irq handler");
		break;
	case 4:
		loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_PARALLEL);
		break;
	case 8:
		loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_FLOPPY);
		break;
	case 12:
		panic("Unimplemented loc_sound handler");
		break;
	case 16:
		panic("Unimplemented loc_video handler");
		break;
	case 20:
		loc_call(JAZZ_ETHERNET_IRQ, JAZZ_IE_ETHERNET);
		break;
	case 24:
		loc_call(JAZZ_SCSI_IRQ, JAZZ_IE_SCSI);
		break;
	case 28:
		loc_call(JAZZ_KEYBOARD_IRQ, JAZZ_IE_KEYBOARD);
		break;
	case 32:
		loc_call(JAZZ_MOUSE_IRQ, JAZZ_IE_MOUSE);
		break;
	case 36:
		loc_call(JAZZ_SERIAL1_IRQ, JAZZ_IE_SERIAL1);
		break;
	case 40:
		loc_call(JAZZ_SERIAL2_IRQ, JAZZ_IE_SERIAL2);
		break;
	}
}

asmlinkage void plat_irq_dispatch(void)
{
	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;

	if (pending & IE_IRQ5)
		write_c0_compare(0);
	else if (pending & IE_IRQ4) {
		r4030_read_reg32(JAZZ_TIMER_REGISTER);
		do_IRQ(JAZZ_TIMER_IRQ);
	} else if (pending & IE_IRQ3)
		panic("Unimplemented ISA NMI handler");
	else if (pending & IE_IRQ2)
		do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK));
	else if (pending & IE_IRQ1) {
		ll_local_dev();
	} else if (unlikely(pending & IE_IRQ0))
		panic("Unimplemented local_dma handler");
	else if (pending & IE_SW1) {
		clear_c0_cause(IE_SW1);
		panic("Unimplemented sw1 handler");
	} else if (pending & IE_SW0) {
		clear_c0_cause(IE_SW0);
		panic("Unimplemented sw0 handler");
	}
}
