]>
Commit | Line | Data |
---|---|---|
45528e38 DB |
1 | /* |
2 | * linux/arch/arm/mach-sa1100/gpio.c | |
3 | * | |
4 | * Generic SA-1100 GPIO handling | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | */ | |
2f8163ba | 10 | #include <linux/gpio.h> |
45528e38 DB |
11 | #include <linux/init.h> |
12 | #include <linux/module.h> | |
40ca061b | 13 | #include <linux/io.h> |
a0ea298d | 14 | #include <linux/syscore_ops.h> |
a09e64fb | 15 | #include <mach/hardware.h> |
f314f33b | 16 | #include <mach/irqs.h> |
45528e38 DB |
17 | |
18 | static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) | |
19 | { | |
6a681b61 | 20 | return !!(GPLR & GPIO_GPIO(offset)); |
45528e38 DB |
21 | } |
22 | ||
23 | static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |
24 | { | |
25 | if (value) | |
26 | GPSR = GPIO_GPIO(offset); | |
27 | else | |
28 | GPCR = GPIO_GPIO(offset); | |
29 | } | |
30 | ||
31 | static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) | |
32 | { | |
33 | unsigned long flags; | |
34 | ||
35 | local_irq_save(flags); | |
36 | GPDR &= ~GPIO_GPIO(offset); | |
37 | local_irq_restore(flags); | |
38 | return 0; | |
39 | } | |
40 | ||
41 | static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value) | |
42 | { | |
43 | unsigned long flags; | |
44 | ||
45 | local_irq_save(flags); | |
46 | sa1100_gpio_set(chip, offset, value); | |
47 | GPDR |= GPIO_GPIO(offset); | |
48 | local_irq_restore(flags); | |
49 | return 0; | |
50 | } | |
51 | ||
f408c985 RK |
52 | static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset) |
53 | { | |
83508093 | 54 | return IRQ_GPIO0 + offset; |
f408c985 RK |
55 | } |
56 | ||
45528e38 DB |
57 | static struct gpio_chip sa1100_gpio_chip = { |
58 | .label = "gpio", | |
59 | .direction_input = sa1100_direction_input, | |
60 | .direction_output = sa1100_direction_output, | |
61 | .set = sa1100_gpio_set, | |
62 | .get = sa1100_gpio_get, | |
f408c985 | 63 | .to_irq = sa1100_to_irq, |
45528e38 DB |
64 | .base = 0, |
65 | .ngpio = GPIO_MAX + 1, | |
66 | }; | |
67 | ||
a0ea298d DB |
68 | /* |
69 | * SA1100 GPIO edge detection for IRQs: | |
70 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. | |
71 | * Use this instead of directly setting GRER/GFER. | |
72 | */ | |
73 | static int GPIO_IRQ_rising_edge; | |
74 | static int GPIO_IRQ_falling_edge; | |
75 | static int GPIO_IRQ_mask; | |
76 | ||
77 | static int sa1100_gpio_type(struct irq_data *d, unsigned int type) | |
78 | { | |
79 | unsigned int mask; | |
80 | ||
81 | mask = BIT(d->hwirq); | |
82 | ||
83 | if (type == IRQ_TYPE_PROBE) { | |
84 | if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) | |
85 | return 0; | |
86 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | |
87 | } | |
88 | ||
89 | if (type & IRQ_TYPE_EDGE_RISING) | |
90 | GPIO_IRQ_rising_edge |= mask; | |
91 | else | |
92 | GPIO_IRQ_rising_edge &= ~mask; | |
93 | if (type & IRQ_TYPE_EDGE_FALLING) | |
94 | GPIO_IRQ_falling_edge |= mask; | |
95 | else | |
96 | GPIO_IRQ_falling_edge &= ~mask; | |
97 | ||
98 | GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; | |
99 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; | |
100 | ||
101 | return 0; | |
102 | } | |
103 | ||
104 | /* | |
105 | * GPIO IRQs must be acknowledged. | |
106 | */ | |
107 | static void sa1100_gpio_ack(struct irq_data *d) | |
108 | { | |
109 | GEDR = BIT(d->hwirq); | |
110 | } | |
111 | ||
112 | static void sa1100_gpio_mask(struct irq_data *d) | |
113 | { | |
114 | unsigned int mask = BIT(d->hwirq); | |
115 | ||
116 | GPIO_IRQ_mask &= ~mask; | |
117 | ||
118 | GRER &= ~mask; | |
119 | GFER &= ~mask; | |
120 | } | |
121 | ||
122 | static void sa1100_gpio_unmask(struct irq_data *d) | |
123 | { | |
124 | unsigned int mask = BIT(d->hwirq); | |
125 | ||
126 | GPIO_IRQ_mask |= mask; | |
127 | ||
128 | GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; | |
129 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; | |
130 | } | |
131 | ||
132 | static int sa1100_gpio_wake(struct irq_data *d, unsigned int on) | |
133 | { | |
134 | if (on) | |
135 | PWER |= BIT(d->hwirq); | |
136 | else | |
137 | PWER &= ~BIT(d->hwirq); | |
138 | return 0; | |
139 | } | |
140 | ||
141 | /* | |
142 | * This is for GPIO IRQs | |
143 | */ | |
144 | static struct irq_chip sa1100_gpio_irq_chip = { | |
145 | .name = "GPIO", | |
146 | .irq_ack = sa1100_gpio_ack, | |
147 | .irq_mask = sa1100_gpio_mask, | |
148 | .irq_unmask = sa1100_gpio_unmask, | |
149 | .irq_set_type = sa1100_gpio_type, | |
150 | .irq_set_wake = sa1100_gpio_wake, | |
151 | }; | |
152 | ||
153 | static int sa1100_gpio_irqdomain_map(struct irq_domain *d, | |
154 | unsigned int irq, irq_hw_number_t hwirq) | |
155 | { | |
156 | irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, | |
157 | handle_edge_irq); | |
23393d49 | 158 | irq_set_noprobe(irq); |
a0ea298d DB |
159 | |
160 | return 0; | |
161 | } | |
162 | ||
0b354dc4 | 163 | static const struct irq_domain_ops sa1100_gpio_irqdomain_ops = { |
a0ea298d DB |
164 | .map = sa1100_gpio_irqdomain_map, |
165 | .xlate = irq_domain_xlate_onetwocell, | |
166 | }; | |
167 | ||
168 | static struct irq_domain *sa1100_gpio_irqdomain; | |
169 | ||
170 | /* | |
171 | * IRQ 0-11 (GPIO) handler. We enter here with the | |
172 | * irq_controller_lock held, and IRQs disabled. Decode the IRQ | |
173 | * and call the handler. | |
174 | */ | |
bd0b9ac4 | 175 | static void sa1100_gpio_handler(struct irq_desc *desc) |
a0ea298d | 176 | { |
2951a799 | 177 | unsigned int irq, mask; |
a0ea298d DB |
178 | |
179 | mask = GEDR; | |
180 | do { | |
181 | /* | |
182 | * clear down all currently active IRQ sources. | |
183 | * We will be processing them all. | |
184 | */ | |
185 | GEDR = mask; | |
186 | ||
187 | irq = IRQ_GPIO0; | |
188 | do { | |
189 | if (mask & 1) | |
190 | generic_handle_irq(irq); | |
191 | mask >>= 1; | |
192 | irq++; | |
193 | } while (mask); | |
194 | ||
195 | mask = GEDR; | |
196 | } while (mask); | |
197 | } | |
198 | ||
199 | static int sa1100_gpio_suspend(void) | |
200 | { | |
201 | /* | |
202 | * Set the appropriate edges for wakeup. | |
203 | */ | |
204 | GRER = PWER & GPIO_IRQ_rising_edge; | |
205 | GFER = PWER & GPIO_IRQ_falling_edge; | |
206 | ||
207 | /* | |
208 | * Clear any pending GPIO interrupts. | |
209 | */ | |
210 | GEDR = GEDR; | |
211 | ||
212 | return 0; | |
213 | } | |
214 | ||
215 | static void sa1100_gpio_resume(void) | |
216 | { | |
217 | GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; | |
218 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; | |
219 | } | |
220 | ||
221 | static struct syscore_ops sa1100_gpio_syscore_ops = { | |
222 | .suspend = sa1100_gpio_suspend, | |
223 | .resume = sa1100_gpio_resume, | |
224 | }; | |
225 | ||
226 | static int __init sa1100_gpio_init_devicefs(void) | |
227 | { | |
228 | register_syscore_ops(&sa1100_gpio_syscore_ops); | |
229 | return 0; | |
230 | } | |
231 | ||
232 | device_initcall(sa1100_gpio_init_devicefs); | |
233 | ||
45528e38 DB |
234 | void __init sa1100_init_gpio(void) |
235 | { | |
a0ea298d DB |
236 | /* clear all GPIO edge detects */ |
237 | GFER = 0; | |
238 | GRER = 0; | |
239 | GEDR = -1; | |
240 | ||
4eab22e7 | 241 | gpiochip_add_data(&sa1100_gpio_chip, NULL); |
a0ea298d DB |
242 | |
243 | sa1100_gpio_irqdomain = irq_domain_add_simple(NULL, | |
244 | 28, IRQ_GPIO0, | |
245 | &sa1100_gpio_irqdomain_ops, NULL); | |
246 | ||
247 | /* | |
248 | * Install handlers for GPIO 0-10 edge detect interrupts | |
249 | */ | |
250 | irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler); | |
251 | irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler); | |
252 | irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler); | |
253 | irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler); | |
254 | irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler); | |
255 | irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler); | |
256 | irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler); | |
257 | irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler); | |
258 | irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler); | |
259 | irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler); | |
260 | irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler); | |
261 | /* | |
262 | * Install handler for GPIO 11-27 edge detect interrupts | |
263 | */ | |
264 | irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler); | |
265 | ||
45528e38 | 266 | } |