PageRenderTime 47ms CodeModel.GetById 12ms app.highlight 28ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/mips/sni/irq.c

https://bitbucket.org/evzijst/gittest
C | 194 lines | 125 code | 32 blank | 37 comment | 11 complexity | 0831fea47fe9dca0b59cbe0eea856e37 MD5 | raw file
  1/*
  2 * This file is subject to the terms and conditions of the GNU General Public
  3 * License.  See the file "COPYING" in the main directory of this archive
  4 * for more details.
  5 *
  6 * Copyright (C) 1992 Linus Torvalds
  7 * Copyright (C) 1994 - 2000 Ralf Baechle
  8 */
  9#include <linux/delay.h>
 10#include <linux/init.h>
 11#include <linux/interrupt.h>
 12#include <linux/irq.h>
 13#include <linux/kernel.h>
 14#include <linux/spinlock.h>
 15
 16#include <asm/i8259.h>
 17#include <asm/io.h>
 18#include <asm/sni.h>
 19
 20DEFINE_SPINLOCK(pciasic_lock);
 21
 22extern asmlinkage void sni_rm200_pci_handle_int(void);
 23
 24static void enable_pciasic_irq(unsigned int irq)
 25{
 26	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
 27	unsigned long flags;
 28
 29	spin_lock_irqsave(&pciasic_lock, flags);
 30	*(volatile u8 *) PCIMT_IRQSEL |= mask;
 31	spin_unlock_irqrestore(&pciasic_lock, flags);
 32}
 33
 34static unsigned int startup_pciasic_irq(unsigned int irq)
 35{
 36	enable_pciasic_irq(irq);
 37	return 0; /* never anything pending */
 38}
 39
 40#define shutdown_pciasic_irq	disable_pciasic_irq
 41
 42void disable_pciasic_irq(unsigned int irq)
 43{
 44	unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
 45	unsigned long flags;
 46
 47	spin_lock_irqsave(&pciasic_lock, flags);
 48	*(volatile u8 *) PCIMT_IRQSEL &= mask;
 49	spin_unlock_irqrestore(&pciasic_lock, flags);
 50}
 51
 52#define mask_and_ack_pciasic_irq disable_pciasic_irq
 53
 54static void end_pciasic_irq(unsigned int irq)
 55{
 56	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 57		enable_pciasic_irq(irq);
 58}
 59
 60static struct hw_interrupt_type pciasic_irq_type = {
 61	"ASIC-PCI",
 62	startup_pciasic_irq,
 63	shutdown_pciasic_irq,
 64	enable_pciasic_irq,
 65	disable_pciasic_irq,
 66	mask_and_ack_pciasic_irq,
 67	end_pciasic_irq,
 68	NULL
 69};
 70
 71/*
 72 * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
 73 * button interrupts.  Later ...
 74 */
 75void pciasic_hwint0(struct pt_regs *regs)
 76{
 77	panic("Received int0 but no handler yet ...");
 78}
 79
 80/* This interrupt was used for the com1 console on the first prototypes.  */
 81void pciasic_hwint2(struct pt_regs *regs)
 82{
 83	/* I think this shouldn't happen on production machines.  */
 84	panic("hwint2 and no handler yet");
 85}
 86
 87/* hwint5 is the r4k count / compare interrupt  */
 88void pciasic_hwint5(struct pt_regs *regs)
 89{
 90	panic("hwint5 and no handler yet");
 91}
 92
 93static unsigned int ls1bit8(unsigned int x)
 94{
 95	int b = 7, s;
 96
 97	s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
 98	s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s;
 99	s = 1; if ((x & 0x40) == 0) s = 0; b -= s;
100
101	return b;
102}
103
104/*
105 * hwint 1 deals with EISA and SCSI interrupts,
106 * 
107 * The EISA_INT bit in CSITPEND is high active, all others are low active.
108 */
109void pciasic_hwint1(struct pt_regs *regs)
110{
111	u8 pend = *(volatile char *)PCIMT_CSITPEND;
112	unsigned long flags;
113
114	if (pend & IT_EISA) {
115		int irq;
116		/*
117		 * Note: ASIC PCI's builtin interrupt achknowledge feature is
118		 * broken.  Using it may result in loss of some or all i8259
119		 * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
120		 */
121		irq = i8259_irq();
122		if (unlikely(irq < 0))
123			return;
124
125		do_IRQ(irq, regs);
126	}
127
128	if (!(pend & IT_SCSI)) {
129		flags = read_c0_status();
130		clear_c0_status(ST0_IM);
131		do_IRQ(PCIMT_IRQ_SCSI, regs);
132		write_c0_status(flags);
133	}
134}
135
136/*
137 * hwint 3 should deal with the PCI A - D interrupts,
138 */
139void pciasic_hwint3(struct pt_regs *regs)
140{
141	u8 pend = *(volatile char *)PCIMT_CSITPEND;
142	int irq;
143
144	pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
145	clear_c0_status(IE_IRQ3);
146	irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
147	do_IRQ(irq, regs);
148	set_c0_status(IE_IRQ3);
149}
150
151/*
152 * hwint 4 is used for only the onboard PCnet 32.
153 */
154void pciasic_hwint4(struct pt_regs *regs)
155{
156	clear_c0_status(IE_IRQ4);
157	do_IRQ(PCIMT_IRQ_ETHERNET, regs);
158	set_c0_status(IE_IRQ4);
159}
160
161void __init init_pciasic(void)
162{
163	unsigned long flags;
164
165	spin_lock_irqsave(&pciasic_lock, flags);
166	* (volatile u8 *) PCIMT_IRQSEL =
167		IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
168	spin_unlock_irqrestore(&pciasic_lock, flags);
169}
170
171/*
172 * On systems with i8259-style interrupt controllers we assume for
173 * driver compatibility reasons interrupts 0 - 15 to be the i8295
174 * interrupts even if the hardware uses a different interrupt numbering.
175 */
176void __init arch_init_irq(void)
177{
178	int i;
179
180	set_except_vector(0, sni_rm200_pci_handle_int);
181
182	init_i8259_irqs();			/* Integrated i8259  */
183	init_pciasic();
184
185	/* Actually we've got more interrupts to handle ...  */
186	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
187		irq_desc[i].status     = IRQ_DISABLED;
188		irq_desc[i].action     = 0;
189		irq_desc[i].depth      = 1;
190		irq_desc[i].handler    = &pciasic_irq_type;
191	}
192
193	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
194}