1 /*
2 * Copyright 2004 PMC-Sierra Inc.
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 *
5 * arch/mips/pmc-sierra/big_sur/big_sur_irq.c
6 * Interrupt routines for Xilinx system controller. Interrupt numbers
7 * are assigned from BIG_SUR_IRQ_BASE to BIG_SUR_IRQ_BASE + 10
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15 #include <linux/interrupt.h>
16 #include <linux/kernel.h>
17 #include <asm/ptrace.h>
18 #include <linux/config.h>
19 #include <linux/sched.h>
20 #include <linux/kernel_stat.h>
21 #include <asm/io.h>
22 #include <asm/irq.h>
23
24 #include "xilinx_irq.h"
25
26 #define BIG_SUR_IRQ_BASE 16
27
28 /* mask off an interrupt -- 1 is enable, 0 is disable */
mask_big_sur_irq(unsigned int irq)29 static inline void mask_big_sur_irq(unsigned int irq)
30 {
31 unsigned long reg_data;
32
33 reg_data = BIG_SUR_READ(BIG_SUR_INTERRUPT_MASK_1);
34 reg_data &= ~(1 << (irq - BIG_SUR_IRQ_BASE));
35 BIG_SUR_WRITE(BIG_SUR_INTERRUPT_MASK_1, reg_data);
36 }
37
38 /* unmask an interrupt -- 1 is enable, 0 is disable */
unmask_big_sur_irq(unsigned int irq)39 static inline void unmask_big_sur_irq(unsigned int irq)
40 {
41 unsigned long reg_data;
42
43 reg_data = BIG_SUR_READ(BIG_SUR_INTERRUPT_MASK_1);
44 reg_data |= (1 << (irq - BIG_SUR_IRQ_BASE));
45 BIG_SUR_WRITE(BIG_SUR_INTERRUPT_MASK_1, reg_data);
46 }
47
48 /* Enable IRQ on the Xilinx FPGA */
enable_big_sur_irq(unsigned int irq)49 static void enable_big_sur_irq(unsigned int irq)
50 {
51 unmask_big_sur_irq(irq);
52 }
53
54 /* Initialize IRQ on the Xilinx FPGA */
startup_big_sur_irq(unsigned int irq)55 static unsigned int startup_big_sur_irq(unsigned int irq)
56 {
57 unmask_big_sur_irq(irq);
58 return 0;
59 }
60
61 /* Disable the IRQ on the Xilinx FPGA */
disable_big_sur_irq(unsigned int irq)62 static void disable_big_sur_irq(unsigned int irq)
63 {
64 mask_big_sur_irq(irq);
65 }
66
67 /* Mask and ack an IRQ on the Xilinx FPGA */
mask_and_ack_big_sur_irq(unsigned int irq)68 static void mask_and_ack_big_sur_irq(unsigned int irq)
69 {
70 mask_big_sur_irq(irq);
71 }
72
73 /* End IRQ processing on the Xilinx FPGA */
end_big_sur_irq(unsigned int irq)74 static void end_big_sur_irq(unsigned int irq)
75 {
76 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
77 unmask_big_sur_irq(irq);
78 }
79
80 /*
81 * Main interrupt handler for the Xilinx FPGA on the
82 * Big Sur board. These interrupts could be coming
83 * from the IDE, PCI, UART etc.
84 */
big_sur_irq_handler(struct pt_regs * regs)85 void big_sur_irq_handler(struct pt_regs *regs)
86 {
87 unsigned long reg_data;
88
89 reg_data = BIG_SUR_READ(BIG_SUR_INTERRUPT_STATUS_1);
90
91 /* Now check for the UART 1 interrupts */
92 if (reg_data & 0x38)
93 do_IRQ(BIG_SUR_UART1_IRQ + BIG_SUR_IRQ_BASE, regs);
94
95 /* Now check for the UART 2 interrupts */
96 if (reg_data & 0x1c0)
97 do_IRQ(BIG_SUR_UART2_IRQ + BIG_SUR_IRQ_BASE, regs);
98
99 /* Now check for the Timer interrupt */
100 if (reg_data & 0x800)
101 do_IRQ(BIG_SUR_TIMER_IRQ + BIG_SUR_IRQ_BASE, regs);
102
103 /* Now check for the PCI interrupt, INTA */
104 if (reg_data & 0x2)
105 do_IRQ(BIG_SUR_PCI_IRQ + BIG_SUR_IRQ_BASE, regs);
106
107 /* Now check for the IDE interrupts */
108 if (reg_data & 0x1)
109 do_IRQ(BIG_SUR_IDE_IRQ + BIG_SUR_IRQ_BASE, regs);
110 }
111
112 #define shutdown_big_sur_irq disable_big_sur_irq
113
114 struct hw_interrupt_type big_sur_irq_type = {
115 "BIG-SUR",
116 startup_big_sur_irq,
117 shutdown_big_sur_irq,
118 enable_big_sur_irq,
119 disable_big_sur_irq,
120 mask_and_ack_big_sur_irq,
121 end_big_sur_irq,
122 NULL
123 };
124
big_sur_irq_init(void)125 void big_sur_irq_init(void)
126 {
127 int i;
128
129 /* Reset irq handlers pointers to NULL */
130 for (i = BIG_SUR_IRQ_BASE; i < (BIG_SUR_IRQ_BASE + 10); i++) {
131 irq_desc[i].status = IRQ_DISABLED;
132 irq_desc[i].action = 0;
133 irq_desc[i].depth = 2;
134 irq_desc[i].handler = &big_sur_irq_type;
135 }
136 }
137
138