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 | { | |
20 | return GPLR & GPIO_GPIO(offset); | |
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 DES |
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); | |
158 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | |
159 | ||
160 | return 0; | |
161 | } | |
162 | ||
163 | static struct irq_domain_ops sa1100_gpio_irqdomain_ops = { | |
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 | */ | |
175 | static void | |
176 | sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc) | |
177 | { | |
178 | unsigned int mask; | |
179 | ||
180 | mask = GEDR; | |
181 | do { | |
182 | /* | |
183 | * clear down all currently active IRQ sources. | |
184 | * We will be processing them all. | |
185 | */ | |
186 | GEDR = mask; | |
187 | ||
188 | irq = IRQ_GPIO0; | |
189 | do { | |
190 | if (mask & 1) | |
191 | generic_handle_irq(irq); | |
192 | mask >>= 1; | |
193 | irq++; | |
194 | } while (mask); | |
195 | ||
196 | mask = GEDR; | |
197 | } while (mask); | |
198 | } | |
199 | ||
200 | static int sa1100_gpio_suspend(void) | |
201 | { | |
202 | /* | |
203 | * Set the appropriate edges for wakeup. | |
204 | */ | |
205 | GRER = PWER & GPIO_IRQ_rising_edge; | |
206 | GFER = PWER & GPIO_IRQ_falling_edge; | |
207 | ||
208 | /* | |
209 | * Clear any pending GPIO interrupts. | |
210 | */ | |
211 | GEDR = GEDR; | |
212 | ||
213 | return 0; | |
214 | } | |
215 | ||
216 | static void sa1100_gpio_resume(void) | |
217 | { | |
218 | GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; | |
219 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; | |
220 | } | |
221 | ||
222 | static struct syscore_ops sa1100_gpio_syscore_ops = { | |
223 | .suspend = sa1100_gpio_suspend, | |
224 | .resume = sa1100_gpio_resume, | |
225 | }; | |
226 | ||
227 | static int __init sa1100_gpio_init_devicefs(void) | |
228 | { | |
229 | register_syscore_ops(&sa1100_gpio_syscore_ops); | |
230 | return 0; | |
231 | } | |
232 | ||
233 | device_initcall(sa1100_gpio_init_devicefs); | |
234 | ||
45528e38 DB |
235 | void __init sa1100_init_gpio(void) |
236 | { | |
a0ea298d DES |
237 | /* clear all GPIO edge detects */ |
238 | GFER = 0; | |
239 | GRER = 0; | |
240 | GEDR = -1; | |
241 | ||
45528e38 | 242 | gpiochip_add(&sa1100_gpio_chip); |
a0ea298d DES |
243 | |
244 | sa1100_gpio_irqdomain = irq_domain_add_simple(NULL, | |
245 | 28, IRQ_GPIO0, | |
246 | &sa1100_gpio_irqdomain_ops, NULL); | |
247 | ||
248 | /* | |
249 | * Install handlers for GPIO 0-10 edge detect interrupts | |
250 | */ | |
251 | irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler); | |
252 | irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler); | |
253 | irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler); | |
254 | irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler); | |
255 | irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler); | |
256 | irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler); | |
257 | irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler); | |
258 | irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler); | |
259 | irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler); | |
260 | irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler); | |
261 | irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler); | |
262 | /* | |
263 | * Install handler for GPIO 11-27 edge detect interrupts | |
264 | */ | |
265 | irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler); | |
266 | ||
45528e38 | 267 | } |