diff options
Diffstat (limited to 'arch/arm/mach-lh7a40x/irq-lpd7a40x.c')
-rw-r--r-- | arch/arm/mach-lh7a40x/irq-lpd7a40x.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c new file mode 100644 index 000000000000..6262d449120c --- /dev/null +++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* arch/arm/mach-lh7a40x/irq-lpd7a40x.c | ||
2 | * | ||
3 | * Copyright (C) 2004 Coastal Environmental Systems | ||
4 | * Copyright (C) 2004 Logic Product Development | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/ptrace.h> | ||
16 | |||
17 | #include <asm/hardware.h> | ||
18 | #include <asm/irq.h> | ||
19 | #include <asm/mach/irq.h> | ||
20 | #include <asm/arch/irqs.h> | ||
21 | |||
22 | |||
23 | static void lh7a40x_ack_cpld_irq (u32 irq) | ||
24 | { | ||
25 | /* CPLD doesn't have ack capability */ | ||
26 | } | ||
27 | |||
28 | static void lh7a40x_mask_cpld_irq (u32 irq) | ||
29 | { | ||
30 | switch (irq) { | ||
31 | case IRQ_LPD7A40X_ETH_INT: | ||
32 | CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4; | ||
33 | break; | ||
34 | case IRQ_LPD7A400_TS: | ||
35 | CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8; | ||
36 | break; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static void lh7a40x_unmask_cpld_irq (u32 irq) | ||
41 | { | ||
42 | switch (irq) { | ||
43 | case IRQ_LPD7A40X_ETH_INT: | ||
44 | CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4; | ||
45 | break; | ||
46 | case IRQ_LPD7A400_TS: | ||
47 | CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8; | ||
48 | break; | ||
49 | } | ||
50 | } | ||
51 | |||
52 | static struct irqchip lh7a40x_cpld_chip = { | ||
53 | .ack = lh7a40x_ack_cpld_irq, | ||
54 | .mask = lh7a40x_mask_cpld_irq, | ||
55 | .unmask = lh7a40x_unmask_cpld_irq, | ||
56 | }; | ||
57 | |||
58 | static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc, | ||
59 | struct pt_regs *regs) | ||
60 | { | ||
61 | unsigned int mask = CPLD_INTERRUPTS; | ||
62 | |||
63 | desc->chip->ack (irq); | ||
64 | |||
65 | if ((mask & 0x1) == 0) /* WLAN */ | ||
66 | IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT); | ||
67 | |||
68 | if ((mask & 0x2) == 0) /* Touch */ | ||
69 | IRQ_DISPATCH (IRQ_LPD7A400_TS); | ||
70 | |||
71 | desc->chip->unmask (irq); /* Level-triggered need this */ | ||
72 | } | ||
73 | |||
74 | |||
75 | /* IRQ initialization */ | ||
76 | |||
77 | void __init lh7a40x_init_board_irq (void) | ||
78 | { | ||
79 | int irq; | ||
80 | |||
81 | /* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs. | ||
82 | PF7 supports the CPLD. | ||
83 | Rev B (v3.4): PF0, PF1, and PF2 are available IRQs. | ||
84 | PF3 supports the CPLD. | ||
85 | (Some) LPD7A404 prerelease boards report a version | ||
86 | number of 0x16, but we force an override since the | ||
87 | hardware is of the newer variety. | ||
88 | */ | ||
89 | |||
90 | unsigned char cpld_version = CPLD_REVISION; | ||
91 | int pinCPLD; | ||
92 | |||
93 | #if defined CONFIG_MACH_LPD7A404 | ||
94 | cpld_version = 0x34; /* Override, for now */ | ||
95 | #endif | ||
96 | pinCPLD = (cpld_version == 0x28) ? 7 : 3; | ||
97 | |||
98 | /* First, configure user controlled GPIOF interrupts */ | ||
99 | |||
100 | GPIO_PFDD &= ~0x0f; /* PF0-3 are inputs */ | ||
101 | GPIO_INTTYPE1 &= ~0x0f; /* PF0-3 are level triggered */ | ||
102 | GPIO_INTTYPE2 &= ~0x0f; /* PF0-3 are active low */ | ||
103 | barrier (); | ||
104 | GPIO_GPIOFINTEN |= 0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */ | ||
105 | |||
106 | /* Then, configure CPLD interrupt */ | ||
107 | |||
108 | CPLD_INTERRUPTS = 0x0c; /* Disable all CPLD interrupts */ | ||
109 | GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */ | ||
110 | GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */ | ||
111 | GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */ | ||
112 | barrier (); | ||
113 | GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */ | ||
114 | |||
115 | /* Cascade CPLD interrupts */ | ||
116 | |||
117 | for (irq = IRQ_BOARD_START; | ||
118 | irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { | ||
119 | set_irq_chip (irq, &lh7a40x_cpld_chip); | ||
120 | set_irq_handler (irq, do_edge_IRQ); | ||
121 | set_irq_flags (irq, IRQF_VALID); | ||
122 | } | ||
123 | |||
124 | set_irq_chained_handler ((cpld_version == 0x28) | ||
125 | ? IRQ_CPLD_V28 | ||
126 | : IRQ_CPLD_V34, | ||
127 | lh7a40x_cpld_handler); | ||
128 | } | ||