diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/momentum/ocelot_g/gt-irq.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/mips/momentum/ocelot_g/gt-irq.c')
-rw-r--r-- | arch/mips/momentum/ocelot_g/gt-irq.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c new file mode 100644 index 000000000000..d0b5c9dd0ea4 --- /dev/null +++ b/arch/mips/momentum/ocelot_g/gt-irq.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright 2002 Momentum Computer | ||
4 | * Author: mdharm@momenco.com | ||
5 | * | ||
6 | * arch/mips/momentum/ocelot_g/gt_irq.c | ||
7 | * Interrupt routines for gt64240. Currently it only handles timer irq. | ||
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 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <asm/ptrace.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/kernel_stat.h> | ||
21 | #include <asm/gt64240.h> | ||
22 | #include <asm/io.h> | ||
23 | |||
24 | unsigned long bus_clock; | ||
25 | |||
26 | /* | ||
27 | * These are interrupt handlers for the GT on-chip interrupts. They | ||
28 | * all come in to the MIPS on a single interrupt line, and have to | ||
29 | * be handled and ack'ed differently than other MIPS interrupts. | ||
30 | */ | ||
31 | |||
32 | #if CURRENTLY_UNUSED | ||
33 | |||
34 | struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; | ||
35 | void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); | ||
36 | |||
37 | /* | ||
38 | * Hooks IRQ handler to the system. When the system is interrupted | ||
39 | * the interrupt service routine is called. | ||
40 | * | ||
41 | * Inputs : | ||
42 | * int_cause - The interrupt cause number. In EVB64120 two parameters | ||
43 | * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. | ||
44 | * bit_num - Indicates which bit number in the cause register | ||
45 | * isr_ptr - Pointer to the interrupt service routine | ||
46 | */ | ||
47 | void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) | ||
48 | { | ||
49 | irq_handlers[int_cause][bit_num].routine = isr_ptr; | ||
50 | } | ||
51 | |||
52 | |||
53 | /* | ||
54 | * Enables the IRQ on Galileo Chip | ||
55 | * | ||
56 | * Inputs : | ||
57 | * int_cause - The interrupt cause number. In EVB64120 two parameters | ||
58 | * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. | ||
59 | * bit_num - Indicates which bit number in the cause register | ||
60 | * | ||
61 | * Outputs : | ||
62 | * 1 if succesful, 0 if failure | ||
63 | */ | ||
64 | int enable_galileo_irq(int int_cause, int bit_num) | ||
65 | { | ||
66 | if (int_cause == INT_CAUSE_MAIN) | ||
67 | SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); | ||
68 | else if (int_cause == INT_CAUSE_HIGH) | ||
69 | SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, | ||
70 | (1 << bit_num)); | ||
71 | else | ||
72 | return 0; | ||
73 | |||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Disables the IRQ on Galileo Chip | ||
79 | * | ||
80 | * Inputs : | ||
81 | * int_cause - The interrupt cause number. In EVB64120 two parameters | ||
82 | * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. | ||
83 | * bit_num - Indicates which bit number in the cause register | ||
84 | * | ||
85 | * Outputs : | ||
86 | * 1 if succesful, 0 if failure | ||
87 | */ | ||
88 | int disable_galileo_irq(int int_cause, int bit_num) | ||
89 | { | ||
90 | if (int_cause == INT_CAUSE_MAIN) | ||
91 | RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, | ||
92 | (1 << bit_num)); | ||
93 | else if (int_cause == INT_CAUSE_HIGH) | ||
94 | RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, | ||
95 | (1 << bit_num)); | ||
96 | else | ||
97 | return 0; | ||
98 | return 1; | ||
99 | } | ||
100 | #endif /* UNUSED */ | ||
101 | |||
102 | /* | ||
103 | * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#. | ||
104 | * | ||
105 | * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this | ||
106 | * routine can handle, for now. | ||
107 | * | ||
108 | * In the future, we'll route more interrupts to this pin, and that's why | ||
109 | * we keep this particular structure in the function. | ||
110 | */ | ||
111 | |||
112 | static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs) | ||
113 | { | ||
114 | uint32_t irq_src, irq_src_mask; | ||
115 | int handled; | ||
116 | |||
117 | /* get the low interrupt cause register */ | ||
118 | irq_src = MV_READ(LOW_INTERRUPT_CAUSE_REGISTER); | ||
119 | |||
120 | /* get the mask register for this pin */ | ||
121 | irq_src_mask = MV_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW); | ||
122 | |||
123 | /* mask off only the interrupts we're interested in */ | ||
124 | irq_src = irq_src & irq_src_mask; | ||
125 | |||
126 | handled = IRQ_NONE; | ||
127 | |||
128 | /* Check for timer interrupt */ | ||
129 | if (irq_src & 0x00000100) { | ||
130 | handled = IRQ_HANDLED; | ||
131 | irq_src &= ~0x00000100; | ||
132 | |||
133 | /* Clear any pending cause bits */ | ||
134 | MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0); | ||
135 | |||
136 | /* handle the timer call */ | ||
137 | do_timer(regs); | ||
138 | #ifndef CONFIG_SMP | ||
139 | update_process_times(user_mode(regs)); | ||
140 | #endif | ||
141 | } | ||
142 | |||
143 | if (irq_src) { | ||
144 | printk(KERN_INFO | ||
145 | "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n", | ||
146 | irq_src); | ||
147 | } | ||
148 | |||
149 | return handled; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Initializes timer using galileo's built in timer. | ||
154 | */ | ||
155 | |||
156 | /* | ||
157 | * This will ignore the standard MIPS timer interrupt handler | ||
158 | * that is passed in as *irq (=irq0 in ../kernel/time.c). | ||
159 | * We will do our own timer interrupt handling. | ||
160 | */ | ||
161 | void gt64240_time_init(void) | ||
162 | { | ||
163 | static struct irqaction timer; | ||
164 | |||
165 | /* Stop the timer -- we'll use timer #0 */ | ||
166 | MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0); | ||
167 | |||
168 | /* Load timer value for 100 Hz */ | ||
169 | MV_WRITE(TIMER_COUNTER0, bus_clock / 100); | ||
170 | |||
171 | /* | ||
172 | * Create the IRQ structure entry for the timer. Since we're too early | ||
173 | * in the boot process to use the "request_irq()" call, we'll hard-code | ||
174 | * the values to the correct interrupt line. | ||
175 | */ | ||
176 | timer.handler = >64240_p0int_irq; | ||
177 | timer.flags = SA_SHIRQ | SA_INTERRUPT; | ||
178 | timer.name = "timer"; | ||
179 | timer.dev_id = NULL; | ||
180 | timer.next = NULL; | ||
181 | timer.mask = 0; | ||
182 | irq_desc[6].action = &timer; | ||
183 | |||
184 | enable_irq(6); | ||
185 | |||
186 | /* Clear any pending cause bits */ | ||
187 | MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0); | ||
188 | |||
189 | /* Enable the interrupt for timer 0 */ | ||
190 | MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1); | ||
191 | |||
192 | /* Enable the timer interrupt for GT-64240 pin P0_INT# */ | ||
193 | MV_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100); | ||
194 | |||
195 | /* Configure and start the timer */ | ||
196 | MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3); | ||
197 | } | ||
198 | |||
199 | void gt64240_irq_init(void) | ||
200 | { | ||
201 | #if CURRENTLY_UNUSED | ||
202 | int i, j; | ||
203 | |||
204 | /* Reset irq handlers pointers to NULL */ | ||
205 | for (i = 0; i < MAX_CAUSE_REGS; i++) { | ||
206 | for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { | ||
207 | irq_handlers[i][j].next = NULL; | ||
208 | irq_handlers[i][j].sync = 0; | ||
209 | irq_handlers[i][j].routine = NULL; | ||
210 | irq_handlers[i][j].data = NULL; | ||
211 | } | ||
212 | } | ||
213 | #endif | ||
214 | } | ||