diff options
Diffstat (limited to 'arch/arm/mach-ixp2000/core.c')
-rw-r--r-- | arch/arm/mach-ixp2000/core.c | 520 |
1 files changed, 0 insertions, 520 deletions
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c deleted file mode 100644 index f214cdff01cb..000000000000 --- a/arch/arm/mach-ixp2000/core.c +++ /dev/null | |||
@@ -1,520 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-ixp2000/core.c | ||
3 | * | ||
4 | * Common routines used by all IXP2400/2800 based platforms. | ||
5 | * | ||
6 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
7 | * | ||
8 | * Copyright 2004 (C) MontaVista Software, Inc. | ||
9 | * | ||
10 | * Based on work Copyright (C) 2002-2003 Intel Corporation | ||
11 | * | ||
12 | * This file is licensed under the terms of the GNU General Public | ||
13 | * License version 2. This program is licensed "as is" without any | ||
14 | * warranty of any kind, whether express or implied. | ||
15 | */ | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/serial.h> | ||
24 | #include <linux/tty.h> | ||
25 | #include <linux/bitops.h> | ||
26 | #include <linux/serial_8250.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/export.h> | ||
29 | |||
30 | #include <asm/types.h> | ||
31 | #include <asm/setup.h> | ||
32 | #include <asm/memory.h> | ||
33 | #include <mach/hardware.h> | ||
34 | #include <asm/irq.h> | ||
35 | #include <asm/tlbflush.h> | ||
36 | #include <asm/pgtable.h> | ||
37 | |||
38 | #include <asm/mach/map.h> | ||
39 | #include <asm/mach/time.h> | ||
40 | #include <asm/mach/irq.h> | ||
41 | |||
42 | #include <mach/gpio-ixp2000.h> | ||
43 | |||
44 | static DEFINE_SPINLOCK(ixp2000_slowport_lock); | ||
45 | static unsigned long ixp2000_slowport_irq_flags; | ||
46 | |||
47 | /************************************************************************* | ||
48 | * Slowport access routines | ||
49 | *************************************************************************/ | ||
50 | void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg) | ||
51 | { | ||
52 | spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags); | ||
53 | |||
54 | old_cfg->CCR = *IXP2000_SLOWPORT_CCR; | ||
55 | old_cfg->WTC = *IXP2000_SLOWPORT_WTC2; | ||
56 | old_cfg->RTC = *IXP2000_SLOWPORT_RTC2; | ||
57 | old_cfg->PCR = *IXP2000_SLOWPORT_PCR; | ||
58 | old_cfg->ADC = *IXP2000_SLOWPORT_ADC; | ||
59 | |||
60 | ixp2000_reg_write(IXP2000_SLOWPORT_CCR, new_cfg->CCR); | ||
61 | ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC); | ||
62 | ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC); | ||
63 | ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR); | ||
64 | ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, new_cfg->ADC); | ||
65 | } | ||
66 | |||
67 | void ixp2000_release_slowport(struct slowport_cfg *old_cfg) | ||
68 | { | ||
69 | ixp2000_reg_write(IXP2000_SLOWPORT_CCR, old_cfg->CCR); | ||
70 | ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC); | ||
71 | ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC); | ||
72 | ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR); | ||
73 | ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, old_cfg->ADC); | ||
74 | |||
75 | spin_unlock_irqrestore(&ixp2000_slowport_lock, | ||
76 | ixp2000_slowport_irq_flags); | ||
77 | } | ||
78 | |||
79 | /************************************************************************* | ||
80 | * Chip specific mappings shared by all IXP2000 systems | ||
81 | *************************************************************************/ | ||
82 | static struct map_desc ixp2000_io_desc[] __initdata = { | ||
83 | { | ||
84 | .virtual = IXP2000_CAP_VIRT_BASE, | ||
85 | .pfn = __phys_to_pfn(IXP2000_CAP_PHYS_BASE), | ||
86 | .length = IXP2000_CAP_SIZE, | ||
87 | .type = MT_DEVICE, | ||
88 | }, { | ||
89 | .virtual = IXP2000_INTCTL_VIRT_BASE, | ||
90 | .pfn = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE), | ||
91 | .length = IXP2000_INTCTL_SIZE, | ||
92 | .type = MT_DEVICE, | ||
93 | }, { | ||
94 | .virtual = IXP2000_PCI_CREG_VIRT_BASE, | ||
95 | .pfn = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE), | ||
96 | .length = IXP2000_PCI_CREG_SIZE, | ||
97 | .type = MT_DEVICE, | ||
98 | }, { | ||
99 | .virtual = IXP2000_PCI_CSR_VIRT_BASE, | ||
100 | .pfn = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE), | ||
101 | .length = IXP2000_PCI_CSR_SIZE, | ||
102 | .type = MT_DEVICE, | ||
103 | }, { | ||
104 | .virtual = IXP2000_MSF_VIRT_BASE, | ||
105 | .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE), | ||
106 | .length = IXP2000_MSF_SIZE, | ||
107 | .type = MT_DEVICE, | ||
108 | }, { | ||
109 | .virtual = IXP2000_SCRATCH_RING_VIRT_BASE, | ||
110 | .pfn = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE), | ||
111 | .length = IXP2000_SCRATCH_RING_SIZE, | ||
112 | .type = MT_DEVICE, | ||
113 | }, { | ||
114 | .virtual = IXP2000_SRAM0_VIRT_BASE, | ||
115 | .pfn = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE), | ||
116 | .length = IXP2000_SRAM0_SIZE, | ||
117 | .type = MT_DEVICE, | ||
118 | }, { | ||
119 | .virtual = IXP2000_PCI_IO_VIRT_BASE, | ||
120 | .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), | ||
121 | .length = IXP2000_PCI_IO_SIZE, | ||
122 | .type = MT_DEVICE, | ||
123 | }, { | ||
124 | .virtual = IXP2000_PCI_CFG0_VIRT_BASE, | ||
125 | .pfn = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE), | ||
126 | .length = IXP2000_PCI_CFG0_SIZE, | ||
127 | .type = MT_DEVICE, | ||
128 | }, { | ||
129 | .virtual = IXP2000_PCI_CFG1_VIRT_BASE, | ||
130 | .pfn = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE), | ||
131 | .length = IXP2000_PCI_CFG1_SIZE, | ||
132 | .type = MT_DEVICE, | ||
133 | } | ||
134 | }; | ||
135 | |||
136 | void __init ixp2000_map_io(void) | ||
137 | { | ||
138 | iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc)); | ||
139 | |||
140 | /* Set slowport to 8-bit mode. */ | ||
141 | ixp2000_reg_wrb(IXP2000_SLOWPORT_FRM, 1); | ||
142 | } | ||
143 | |||
144 | |||
145 | /************************************************************************* | ||
146 | * Serial port support for IXP2000 | ||
147 | *************************************************************************/ | ||
148 | static struct plat_serial8250_port ixp2000_serial_port[] = { | ||
149 | { | ||
150 | .mapbase = IXP2000_UART_PHYS_BASE, | ||
151 | .membase = (char *)(IXP2000_UART_VIRT_BASE + 3), | ||
152 | .irq = IRQ_IXP2000_UART, | ||
153 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
154 | .iotype = UPIO_MEM, | ||
155 | .regshift = 2, | ||
156 | .uartclk = 50000000, | ||
157 | }, | ||
158 | { }, | ||
159 | }; | ||
160 | |||
161 | static struct resource ixp2000_uart_resource = { | ||
162 | .start = IXP2000_UART_PHYS_BASE, | ||
163 | .end = IXP2000_UART_PHYS_BASE + 0x1f, | ||
164 | .flags = IORESOURCE_MEM, | ||
165 | }; | ||
166 | |||
167 | static struct platform_device ixp2000_serial_device = { | ||
168 | .name = "serial8250", | ||
169 | .id = PLAT8250_DEV_PLATFORM, | ||
170 | .dev = { | ||
171 | .platform_data = ixp2000_serial_port, | ||
172 | }, | ||
173 | .num_resources = 1, | ||
174 | .resource = &ixp2000_uart_resource, | ||
175 | }; | ||
176 | |||
177 | void __init ixp2000_uart_init(void) | ||
178 | { | ||
179 | platform_device_register(&ixp2000_serial_device); | ||
180 | } | ||
181 | |||
182 | |||
183 | /************************************************************************* | ||
184 | * Timer-tick functions for IXP2000 | ||
185 | *************************************************************************/ | ||
186 | static unsigned ticks_per_jiffy; | ||
187 | static unsigned ticks_per_usec; | ||
188 | static unsigned next_jiffy_time; | ||
189 | static volatile unsigned long *missing_jiffy_timer_csr; | ||
190 | |||
191 | unsigned long ixp2000_gettimeoffset (void) | ||
192 | { | ||
193 | unsigned long offset; | ||
194 | |||
195 | offset = next_jiffy_time - *missing_jiffy_timer_csr; | ||
196 | |||
197 | return offset / ticks_per_usec; | ||
198 | } | ||
199 | |||
200 | static irqreturn_t ixp2000_timer_interrupt(int irq, void *dev_id) | ||
201 | { | ||
202 | /* clear timer 1 */ | ||
203 | ixp2000_reg_wrb(IXP2000_T1_CLR, 1); | ||
204 | |||
205 | while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr) | ||
206 | >= ticks_per_jiffy) { | ||
207 | timer_tick(); | ||
208 | next_jiffy_time -= ticks_per_jiffy; | ||
209 | } | ||
210 | |||
211 | return IRQ_HANDLED; | ||
212 | } | ||
213 | |||
214 | static struct irqaction ixp2000_timer_irq = { | ||
215 | .name = "IXP2000 Timer Tick", | ||
216 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
217 | .handler = ixp2000_timer_interrupt, | ||
218 | }; | ||
219 | |||
220 | void __init ixp2000_init_time(unsigned long tick_rate) | ||
221 | { | ||
222 | ticks_per_jiffy = (tick_rate + HZ/2) / HZ; | ||
223 | ticks_per_usec = tick_rate / 1000000; | ||
224 | |||
225 | /* | ||
226 | * We use timer 1 as our timer interrupt. | ||
227 | */ | ||
228 | ixp2000_reg_write(IXP2000_T1_CLR, 0); | ||
229 | ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1); | ||
230 | ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7)); | ||
231 | |||
232 | /* | ||
233 | * We use a second timer as a monotonic counter for tracking | ||
234 | * missed jiffies. The IXP2000 has four timers, but if we're | ||
235 | * on an A-step IXP2800, timer 2 and 3 don't work, so on those | ||
236 | * chips we use timer 4. Timer 4 is the only timer that can | ||
237 | * be used for the watchdog, so we use timer 2 if we're on a | ||
238 | * non-buggy chip. | ||
239 | */ | ||
240 | if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) { | ||
241 | printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n"); | ||
242 | |||
243 | ixp2000_reg_write(IXP2000_T4_CLR, 0); | ||
244 | ixp2000_reg_write(IXP2000_T4_CLD, -1); | ||
245 | ixp2000_reg_wrb(IXP2000_T4_CTL, (1 << 7)); | ||
246 | missing_jiffy_timer_csr = IXP2000_T4_CSR; | ||
247 | } else { | ||
248 | ixp2000_reg_write(IXP2000_T2_CLR, 0); | ||
249 | ixp2000_reg_write(IXP2000_T2_CLD, -1); | ||
250 | ixp2000_reg_wrb(IXP2000_T2_CTL, (1 << 7)); | ||
251 | missing_jiffy_timer_csr = IXP2000_T2_CSR; | ||
252 | } | ||
253 | next_jiffy_time = 0xffffffff; | ||
254 | |||
255 | /* register for interrupt */ | ||
256 | setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq); | ||
257 | } | ||
258 | |||
259 | /************************************************************************* | ||
260 | * GPIO helpers | ||
261 | *************************************************************************/ | ||
262 | static unsigned long GPIO_IRQ_falling_edge; | ||
263 | static unsigned long GPIO_IRQ_rising_edge; | ||
264 | static unsigned long GPIO_IRQ_level_low; | ||
265 | static unsigned long GPIO_IRQ_level_high; | ||
266 | |||
267 | static void update_gpio_int_csrs(void) | ||
268 | { | ||
269 | ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge); | ||
270 | ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge); | ||
271 | ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low); | ||
272 | ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high); | ||
273 | } | ||
274 | |||
275 | void gpio_line_config(int line, int direction) | ||
276 | { | ||
277 | unsigned long flags; | ||
278 | |||
279 | local_irq_save(flags); | ||
280 | if (direction == GPIO_OUT) { | ||
281 | /* if it's an output, it ain't an interrupt anymore */ | ||
282 | GPIO_IRQ_falling_edge &= ~(1 << line); | ||
283 | GPIO_IRQ_rising_edge &= ~(1 << line); | ||
284 | GPIO_IRQ_level_low &= ~(1 << line); | ||
285 | GPIO_IRQ_level_high &= ~(1 << line); | ||
286 | update_gpio_int_csrs(); | ||
287 | |||
288 | ixp2000_reg_wrb(IXP2000_GPIO_PDSR, 1 << line); | ||
289 | } else if (direction == GPIO_IN) { | ||
290 | ixp2000_reg_wrb(IXP2000_GPIO_PDCR, 1 << line); | ||
291 | } | ||
292 | local_irq_restore(flags); | ||
293 | } | ||
294 | EXPORT_SYMBOL(gpio_line_config); | ||
295 | |||
296 | |||
297 | /************************************************************************* | ||
298 | * IRQ handling IXP2000 | ||
299 | *************************************************************************/ | ||
300 | static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
301 | { | ||
302 | int i; | ||
303 | unsigned long status = *IXP2000_GPIO_INST; | ||
304 | |||
305 | for (i = 0; i <= 7; i++) { | ||
306 | if (status & (1<<i)) { | ||
307 | generic_handle_irq(i + IRQ_IXP2000_GPIO0); | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static int ixp2000_GPIO_irq_type(struct irq_data *d, unsigned int type) | ||
313 | { | ||
314 | int line = d->irq - IRQ_IXP2000_GPIO0; | ||
315 | |||
316 | /* | ||
317 | * First, configure this GPIO line as an input. | ||
318 | */ | ||
319 | ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line); | ||
320 | |||
321 | /* | ||
322 | * Then, set the proper trigger type. | ||
323 | */ | ||
324 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
325 | GPIO_IRQ_falling_edge |= 1 << line; | ||
326 | else | ||
327 | GPIO_IRQ_falling_edge &= ~(1 << line); | ||
328 | if (type & IRQ_TYPE_EDGE_RISING) | ||
329 | GPIO_IRQ_rising_edge |= 1 << line; | ||
330 | else | ||
331 | GPIO_IRQ_rising_edge &= ~(1 << line); | ||
332 | if (type & IRQ_TYPE_LEVEL_LOW) | ||
333 | GPIO_IRQ_level_low |= 1 << line; | ||
334 | else | ||
335 | GPIO_IRQ_level_low &= ~(1 << line); | ||
336 | if (type & IRQ_TYPE_LEVEL_HIGH) | ||
337 | GPIO_IRQ_level_high |= 1 << line; | ||
338 | else | ||
339 | GPIO_IRQ_level_high &= ~(1 << line); | ||
340 | update_gpio_int_csrs(); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static void ixp2000_GPIO_irq_mask_ack(struct irq_data *d) | ||
346 | { | ||
347 | unsigned int irq = d->irq; | ||
348 | |||
349 | ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0))); | ||
350 | |||
351 | ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0))); | ||
352 | ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0))); | ||
353 | ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0))); | ||
354 | } | ||
355 | |||
356 | static void ixp2000_GPIO_irq_mask(struct irq_data *d) | ||
357 | { | ||
358 | unsigned int irq = d->irq; | ||
359 | |||
360 | ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0))); | ||
361 | } | ||
362 | |||
363 | static void ixp2000_GPIO_irq_unmask(struct irq_data *d) | ||
364 | { | ||
365 | unsigned int irq = d->irq; | ||
366 | |||
367 | ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0))); | ||
368 | } | ||
369 | |||
370 | static struct irq_chip ixp2000_GPIO_irq_chip = { | ||
371 | .irq_ack = ixp2000_GPIO_irq_mask_ack, | ||
372 | .irq_mask = ixp2000_GPIO_irq_mask, | ||
373 | .irq_unmask = ixp2000_GPIO_irq_unmask, | ||
374 | .irq_set_type = ixp2000_GPIO_irq_type, | ||
375 | }; | ||
376 | |||
377 | static void ixp2000_pci_irq_mask(struct irq_data *d) | ||
378 | { | ||
379 | unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE; | ||
380 | if (d->irq == IRQ_IXP2000_PCIA) | ||
381 | ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26))); | ||
382 | else if (d->irq == IRQ_IXP2000_PCIB) | ||
383 | ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27))); | ||
384 | } | ||
385 | |||
386 | static void ixp2000_pci_irq_unmask(struct irq_data *d) | ||
387 | { | ||
388 | unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE; | ||
389 | if (d->irq == IRQ_IXP2000_PCIA) | ||
390 | ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26))); | ||
391 | else if (d->irq == IRQ_IXP2000_PCIB) | ||
392 | ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27))); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Error interrupts. These are used extensively by the microengine drivers | ||
397 | */ | ||
398 | static void ixp2000_err_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
399 | { | ||
400 | int i; | ||
401 | unsigned long status = *IXP2000_IRQ_ERR_STATUS; | ||
402 | |||
403 | for(i = 31; i >= 0; i--) { | ||
404 | if(status & (1 << i)) { | ||
405 | generic_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i); | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | |||
410 | static void ixp2000_err_irq_mask(struct irq_data *d) | ||
411 | { | ||
412 | ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR, | ||
413 | (1 << (d->irq - IRQ_IXP2000_DRAM0_MIN_ERR))); | ||
414 | } | ||
415 | |||
416 | static void ixp2000_err_irq_unmask(struct irq_data *d) | ||
417 | { | ||
418 | ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET, | ||
419 | (1 << (d->irq - IRQ_IXP2000_DRAM0_MIN_ERR))); | ||
420 | } | ||
421 | |||
422 | static struct irq_chip ixp2000_err_irq_chip = { | ||
423 | .irq_ack = ixp2000_err_irq_mask, | ||
424 | .irq_mask = ixp2000_err_irq_mask, | ||
425 | .irq_unmask = ixp2000_err_irq_unmask | ||
426 | }; | ||
427 | |||
428 | static struct irq_chip ixp2000_pci_irq_chip = { | ||
429 | .irq_ack = ixp2000_pci_irq_mask, | ||
430 | .irq_mask = ixp2000_pci_irq_mask, | ||
431 | .irq_unmask = ixp2000_pci_irq_unmask | ||
432 | }; | ||
433 | |||
434 | static void ixp2000_irq_mask(struct irq_data *d) | ||
435 | { | ||
436 | ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << d->irq)); | ||
437 | } | ||
438 | |||
439 | static void ixp2000_irq_unmask(struct irq_data *d) | ||
440 | { | ||
441 | ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << d->irq)); | ||
442 | } | ||
443 | |||
444 | static struct irq_chip ixp2000_irq_chip = { | ||
445 | .irq_ack = ixp2000_irq_mask, | ||
446 | .irq_mask = ixp2000_irq_mask, | ||
447 | .irq_unmask = ixp2000_irq_unmask | ||
448 | }; | ||
449 | |||
450 | void __init ixp2000_init_irq(void) | ||
451 | { | ||
452 | int irq; | ||
453 | |||
454 | /* | ||
455 | * Mask all sources | ||
456 | */ | ||
457 | ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff); | ||
458 | ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff); | ||
459 | |||
460 | /* clear all GPIO edge/level detects */ | ||
461 | ixp2000_reg_write(IXP2000_GPIO_REDR, 0); | ||
462 | ixp2000_reg_write(IXP2000_GPIO_FEDR, 0); | ||
463 | ixp2000_reg_write(IXP2000_GPIO_LSHR, 0); | ||
464 | ixp2000_reg_write(IXP2000_GPIO_LSLR, 0); | ||
465 | ixp2000_reg_write(IXP2000_GPIO_INCR, -1); | ||
466 | |||
467 | /* clear PCI interrupt sources */ | ||
468 | ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, 0); | ||
469 | |||
470 | /* | ||
471 | * Certain bits in the IRQ status register of the | ||
472 | * IXP2000 are reserved. Instead of trying to map | ||
473 | * things non 1:1 from bit position to IRQ number, | ||
474 | * we mark the reserved IRQs as invalid. This makes | ||
475 | * our mask/unmask code much simpler. | ||
476 | */ | ||
477 | for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { | ||
478 | if ((1 << irq) & IXP2000_VALID_IRQ_MASK) { | ||
479 | irq_set_chip_and_handler(irq, &ixp2000_irq_chip, | ||
480 | handle_level_irq); | ||
481 | set_irq_flags(irq, IRQF_VALID); | ||
482 | } else set_irq_flags(irq, 0); | ||
483 | } | ||
484 | |||
485 | for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) { | ||
486 | if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) & | ||
487 | IXP2000_VALID_ERR_IRQ_MASK) { | ||
488 | irq_set_chip_and_handler(irq, &ixp2000_err_irq_chip, | ||
489 | handle_level_irq); | ||
490 | set_irq_flags(irq, IRQF_VALID); | ||
491 | } | ||
492 | else | ||
493 | set_irq_flags(irq, 0); | ||
494 | } | ||
495 | irq_set_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler); | ||
496 | |||
497 | for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { | ||
498 | irq_set_chip_and_handler(irq, &ixp2000_GPIO_irq_chip, | ||
499 | handle_level_irq); | ||
500 | set_irq_flags(irq, IRQF_VALID); | ||
501 | } | ||
502 | irq_set_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler); | ||
503 | |||
504 | /* | ||
505 | * Enable PCI irqs. The actual PCI[AB] decoding is done in | ||
506 | * entry-macro.S, so we don't need a chained handler for the | ||
507 | * PCI interrupt source. | ||
508 | */ | ||
509 | ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI)); | ||
510 | for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) { | ||
511 | irq_set_chip_and_handler(irq, &ixp2000_pci_irq_chip, | ||
512 | handle_level_irq); | ||
513 | set_irq_flags(irq, IRQF_VALID); | ||
514 | } | ||
515 | } | ||
516 | |||
517 | void ixp2000_restart(char mode, const char *cmd) | ||
518 | { | ||
519 | ixp2000_reg_wrb(IXP2000_RESET0, RSTALL); | ||
520 | } | ||