xref: /openbmc/linux/arch/mips/jazz/irq.c (revision 8ab00b9a)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * This file is subject to the terms and conditions of the GNU General Public
31da177e4SLinus Torvalds  * License.  See the file "COPYING" in the main directory of this archive
41da177e4SLinus Torvalds  * for more details.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (C) 1992 Linus Torvalds
71da177e4SLinus Torvalds  * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds #include <linux/init.h>
101da177e4SLinus Torvalds #include <linux/interrupt.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/spinlock.h>
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <asm/i8259.h>
151da177e4SLinus Torvalds #include <asm/io.h>
161da177e4SLinus Torvalds #include <asm/jazz.h>
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds extern asmlinkage void jazz_handle_int(void);
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds static DEFINE_SPINLOCK(r4030_lock);
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds static void enable_r4030_irq(unsigned int irq)
231da177e4SLinus Torvalds {
241da177e4SLinus Torvalds 	unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ);
251da177e4SLinus Torvalds 	unsigned long flags;
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 	spin_lock_irqsave(&r4030_lock, flags);
281da177e4SLinus Torvalds 	mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
291da177e4SLinus Torvalds 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
301da177e4SLinus Torvalds 	spin_unlock_irqrestore(&r4030_lock, flags);
311da177e4SLinus Torvalds }
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds static unsigned int startup_r4030_irq(unsigned int irq)
341da177e4SLinus Torvalds {
351da177e4SLinus Torvalds 	enable_r4030_irq(irq);
361da177e4SLinus Torvalds 	return 0; /* never anything pending */
371da177e4SLinus Torvalds }
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds #define shutdown_r4030_irq	disable_r4030_irq
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds void disable_r4030_irq(unsigned int irq)
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds 	unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
441da177e4SLinus Torvalds 	unsigned long flags;
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 	spin_lock_irqsave(&r4030_lock, flags);
471da177e4SLinus Torvalds 	mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
481da177e4SLinus Torvalds 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
491da177e4SLinus Torvalds 	spin_unlock_irqrestore(&r4030_lock, flags);
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds #define mask_and_ack_r4030_irq disable_r4030_irq
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds static void end_r4030_irq(unsigned int irq)
551da177e4SLinus Torvalds {
561da177e4SLinus Torvalds 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
571da177e4SLinus Torvalds 		enable_r4030_irq(irq);
581da177e4SLinus Torvalds }
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds static struct hw_interrupt_type r4030_irq_type = {
618ab00b9aSRalf Baechle 	.typename = "R4030",
628ab00b9aSRalf Baechle 	.startup = startup_r4030_irq,
638ab00b9aSRalf Baechle 	.shutdown = shutdown_r4030_irq,
648ab00b9aSRalf Baechle 	.enable = enable_r4030_irq,
658ab00b9aSRalf Baechle 	.disable = disable_r4030_irq,
668ab00b9aSRalf Baechle 	.ack = mask_and_ack_r4030_irq,
678ab00b9aSRalf Baechle 	.end = end_r4030_irq,
681da177e4SLinus Torvalds };
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds void __init init_r4030_ints(void)
711da177e4SLinus Torvalds {
721da177e4SLinus Torvalds 	int i;
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds 	for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) {
751da177e4SLinus Torvalds 		irq_desc[i].status     = IRQ_DISABLED;
761da177e4SLinus Torvalds 		irq_desc[i].action     = 0;
771da177e4SLinus Torvalds 		irq_desc[i].depth      = 1;
781da177e4SLinus Torvalds 		irq_desc[i].handler    = &r4030_irq_type;
791da177e4SLinus Torvalds 	}
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
821da177e4SLinus Torvalds 	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);		/* clear pending IRQs */
831da177e4SLinus Torvalds 	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);	/* clear error bits */
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds /*
871da177e4SLinus Torvalds  * On systems with i8259-style interrupt controllers we assume for
881da177e4SLinus Torvalds  * driver compatibility reasons interrupts 0 - 15 to be the i8259
891da177e4SLinus Torvalds  * interrupts even if the hardware uses a different interrupt numbering.
901da177e4SLinus Torvalds  */
911da177e4SLinus Torvalds void __init arch_init_irq(void)
921da177e4SLinus Torvalds {
931da177e4SLinus Torvalds 	set_except_vector(0, jazz_handle_int);
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	init_i8259_irqs();			/* Integrated i8259  */
961da177e4SLinus Torvalds 	init_r4030_ints();
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
991da177e4SLinus Torvalds }
100