Commit | Line | Data |
---|---|---|
9569dae7 LB |
1 | /* |
2 | * arch/arm/plat-orion/gpio.c | |
3 | * | |
4 | * Marvell Orion SoC GPIO handling. | |
5 | * | |
6 | * This file is licensed under the terms of the GNU General Public | |
7 | * License version 2. This program is licensed "as is" without any | |
8 | * warranty of any kind, whether express or implied. | |
9 | */ | |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
07332318 | 13 | #include <linux/irq.h> |
9569dae7 LB |
14 | #include <linux/module.h> |
15 | #include <linux/spinlock.h> | |
16 | #include <linux/bitops.h> | |
17 | #include <linux/io.h> | |
a8865655 | 18 | #include <linux/gpio.h> |
9569dae7 LB |
19 | |
20 | static DEFINE_SPINLOCK(gpio_lock); | |
28d27cf4 NP |
21 | static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; |
22 | static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; | |
9569dae7 LB |
23 | |
24 | static inline void __set_direction(unsigned pin, int input) | |
25 | { | |
26 | u32 u; | |
27 | ||
28 | u = readl(GPIO_IO_CONF(pin)); | |
29 | if (input) | |
30 | u |= 1 << (pin & 31); | |
31 | else | |
32 | u &= ~(1 << (pin & 31)); | |
33 | writel(u, GPIO_IO_CONF(pin)); | |
34 | } | |
35 | ||
36 | static void __set_level(unsigned pin, int high) | |
37 | { | |
38 | u32 u; | |
39 | ||
40 | u = readl(GPIO_OUT(pin)); | |
41 | if (high) | |
42 | u |= 1 << (pin & 31); | |
43 | else | |
44 | u &= ~(1 << (pin & 31)); | |
45 | writel(u, GPIO_OUT(pin)); | |
46 | } | |
47 | ||
a8865655 | 48 | static inline void __set_blinking(unsigned pin, int blink) |
9569dae7 | 49 | { |
a8865655 | 50 | u32 u; |
9569dae7 | 51 | |
a8865655 EB |
52 | u = readl(GPIO_BLINK_EN(pin)); |
53 | if (blink) | |
54 | u |= 1 << (pin & 31); | |
55 | else | |
56 | u &= ~(1 << (pin & 31)); | |
57 | writel(u, GPIO_BLINK_EN(pin)); | |
58 | } | |
9569dae7 | 59 | |
a8865655 EB |
60 | static inline int orion_gpio_is_valid(unsigned pin, int mode) |
61 | { | |
62 | if (pin < GPIO_MAX) { | |
63 | if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input)) | |
64 | goto err_out; | |
65 | if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output)) | |
66 | goto err_out; | |
67 | return true; | |
68 | } | |
9569dae7 | 69 | |
a8865655 EB |
70 | err_out: |
71 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | |
72 | return false; | |
9569dae7 | 73 | } |
9569dae7 | 74 | |
a8865655 EB |
75 | /* |
76 | * GENERIC_GPIO primitives. | |
77 | */ | |
78 | static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin) | |
9569dae7 LB |
79 | { |
80 | unsigned long flags; | |
9569dae7 | 81 | |
a8865655 | 82 | if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK)) |
9569dae7 | 83 | return -EINVAL; |
9569dae7 LB |
84 | |
85 | spin_lock_irqsave(&gpio_lock, flags); | |
86 | ||
a8865655 EB |
87 | /* Configure GPIO direction. */ |
88 | __set_direction(pin, 1); | |
9569dae7 LB |
89 | |
90 | spin_unlock_irqrestore(&gpio_lock, flags); | |
91 | ||
92 | return 0; | |
93 | } | |
9569dae7 | 94 | |
a8865655 | 95 | static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin) |
9569dae7 LB |
96 | { |
97 | int val; | |
98 | ||
99 | if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31))) | |
100 | val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin)); | |
101 | else | |
102 | val = readl(GPIO_OUT(pin)); | |
103 | ||
104 | return (val >> (pin & 31)) & 1; | |
105 | } | |
9569dae7 | 106 | |
a8865655 EB |
107 | static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, |
108 | int value) | |
9569dae7 LB |
109 | { |
110 | unsigned long flags; | |
a8865655 EB |
111 | |
112 | if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK)) | |
113 | return -EINVAL; | |
9569dae7 LB |
114 | |
115 | spin_lock_irqsave(&gpio_lock, flags); | |
116 | ||
a8865655 EB |
117 | /* Disable blinking. */ |
118 | __set_blinking(pin, 0); | |
9569dae7 | 119 | |
a8865655 | 120 | /* Configure GPIO output value. */ |
9569dae7 LB |
121 | __set_level(pin, value); |
122 | ||
a8865655 EB |
123 | /* Configure GPIO direction. */ |
124 | __set_direction(pin, 0); | |
125 | ||
9569dae7 | 126 | spin_unlock_irqrestore(&gpio_lock, flags); |
a8865655 EB |
127 | |
128 | return 0; | |
9569dae7 | 129 | } |
9569dae7 | 130 | |
a8865655 EB |
131 | static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin, |
132 | int value) | |
9569dae7 LB |
133 | { |
134 | unsigned long flags; | |
9569dae7 LB |
135 | |
136 | spin_lock_irqsave(&gpio_lock, flags); | |
9569dae7 | 137 | |
a8865655 EB |
138 | /* Configure GPIO output value. */ |
139 | __set_level(pin, value); | |
140 | ||
141 | spin_unlock_irqrestore(&gpio_lock, flags); | |
9569dae7 | 142 | } |
9569dae7 | 143 | |
a8865655 | 144 | static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) |
9569dae7 | 145 | { |
a8865655 EB |
146 | if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) || |
147 | orion_gpio_is_valid(pin, GPIO_OUTPUT_OK)) | |
148 | return 0; | |
149 | return -EINVAL; | |
9569dae7 | 150 | } |
9569dae7 | 151 | |
a8865655 EB |
152 | static struct gpio_chip orion_gpiochip = { |
153 | .label = "orion_gpio", | |
154 | .direction_input = orion_gpio_direction_input, | |
155 | .get = orion_gpio_get_value, | |
156 | .direction_output = orion_gpio_direction_output, | |
157 | .set = orion_gpio_set_value, | |
158 | .request = orion_gpio_request, | |
159 | .base = 0, | |
160 | .ngpio = GPIO_MAX, | |
161 | .can_sleep = 0, | |
162 | }; | |
163 | ||
164 | void __init orion_gpio_init(void) | |
165 | { | |
166 | gpiochip_add(&orion_gpiochip); | |
167 | } | |
9569dae7 LB |
168 | |
169 | /* | |
170 | * Orion-specific GPIO API extensions. | |
171 | */ | |
172 | void __init orion_gpio_set_unused(unsigned pin) | |
173 | { | |
a8865655 | 174 | /* Configure as output, drive low. */ |
9569dae7 LB |
175 | __set_level(pin, 0); |
176 | __set_direction(pin, 0); | |
177 | } | |
178 | ||
28d27cf4 | 179 | void __init orion_gpio_set_valid(unsigned pin, int mode) |
9569dae7 | 180 | { |
28d27cf4 NP |
181 | if (mode == 1) |
182 | mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; | |
183 | if (mode & GPIO_INPUT_OK) | |
184 | __set_bit(pin, gpio_valid_input); | |
9569dae7 | 185 | else |
28d27cf4 NP |
186 | __clear_bit(pin, gpio_valid_input); |
187 | if (mode & GPIO_OUTPUT_OK) | |
188 | __set_bit(pin, gpio_valid_output); | |
189 | else | |
190 | __clear_bit(pin, gpio_valid_output); | |
9569dae7 LB |
191 | } |
192 | ||
193 | void orion_gpio_set_blink(unsigned pin, int blink) | |
194 | { | |
195 | unsigned long flags; | |
9569dae7 LB |
196 | |
197 | spin_lock_irqsave(&gpio_lock, flags); | |
198 | ||
a8865655 | 199 | /* Set output value to zero. */ |
9569dae7 LB |
200 | __set_level(pin, 0); |
201 | ||
a8865655 EB |
202 | /* Set blinking. */ |
203 | __set_blinking(pin, blink); | |
9569dae7 LB |
204 | |
205 | spin_unlock_irqrestore(&gpio_lock, flags); | |
206 | } | |
207 | EXPORT_SYMBOL(orion_gpio_set_blink); | |
07332318 LB |
208 | |
209 | ||
210 | /***************************************************************************** | |
211 | * Orion GPIO IRQ | |
212 | * | |
213 | * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same | |
214 | * value of the line or the opposite value. | |
215 | * | |
216 | * Level IRQ handlers: DATA_IN is used directly as cause register. | |
217 | * Interrupt are masked by LEVEL_MASK registers. | |
218 | * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. | |
219 | * Interrupt are masked by EDGE_MASK registers. | |
220 | * Both-edge handlers: Similar to regular Edge handlers, but also swaps | |
221 | * the polarity to catch the next line transaction. | |
222 | * This is a race condition that might not perfectly | |
223 | * work on some use cases. | |
224 | * | |
225 | * Every eight GPIO lines are grouped (OR'ed) before going up to main | |
226 | * cause register. | |
227 | * | |
228 | * EDGE cause mask | |
229 | * data-in /--------| |-----| |----\ | |
230 | * -----| |----- ---- to main cause reg | |
231 | * X \----------------| |----/ | |
232 | * polarity LEVEL mask | |
233 | * | |
234 | ****************************************************************************/ | |
07332318 | 235 | |
fd4b9b36 | 236 | static void gpio_irq_ack(u32 irq) |
07332318 | 237 | { |
fd4b9b36 NP |
238 | int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK; |
239 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | |
240 | int pin = irq_to_gpio(irq); | |
241 | writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin)); | |
242 | } | |
07332318 LB |
243 | } |
244 | ||
fd4b9b36 | 245 | static void gpio_irq_mask(u32 irq) |
07332318 LB |
246 | { |
247 | int pin = irq_to_gpio(irq); | |
fd4b9b36 NP |
248 | int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK; |
249 | u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? | |
250 | GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); | |
251 | u32 u = readl(reg); | |
07332318 | 252 | u &= ~(1 << (pin & 31)); |
fd4b9b36 | 253 | writel(u, reg); |
07332318 LB |
254 | } |
255 | ||
fd4b9b36 | 256 | static void gpio_irq_unmask(u32 irq) |
07332318 LB |
257 | { |
258 | int pin = irq_to_gpio(irq); | |
fd4b9b36 NP |
259 | int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK; |
260 | u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? | |
261 | GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); | |
262 | u32 u = readl(reg); | |
07332318 | 263 | u |= 1 << (pin & 31); |
fd4b9b36 | 264 | writel(u, reg); |
07332318 LB |
265 | } |
266 | ||
267 | static int gpio_irq_set_type(u32 irq, u32 type) | |
268 | { | |
269 | int pin = irq_to_gpio(irq); | |
270 | struct irq_desc *desc; | |
271 | u32 u; | |
272 | ||
273 | u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)); | |
274 | if (!u) { | |
275 | printk(KERN_ERR "orion gpio_irq_set_type failed " | |
276 | "(irq %d, pin %d).\n", irq, pin); | |
277 | return -EINVAL; | |
278 | } | |
279 | ||
280 | desc = irq_desc + irq; | |
281 | ||
282 | /* | |
283 | * Set edge/level type. | |
284 | */ | |
285 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | |
fd4b9b36 | 286 | desc->handle_irq = handle_edge_irq; |
07332318 | 287 | } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { |
fd4b9b36 | 288 | desc->handle_irq = handle_level_irq; |
07332318 LB |
289 | } else { |
290 | printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type); | |
291 | return -EINVAL; | |
292 | } | |
293 | ||
294 | /* | |
295 | * Configure interrupt polarity. | |
296 | */ | |
297 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) { | |
298 | u = readl(GPIO_IN_POL(pin)); | |
299 | u &= ~(1 << (pin & 31)); | |
300 | writel(u, GPIO_IN_POL(pin)); | |
301 | } else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) { | |
302 | u = readl(GPIO_IN_POL(pin)); | |
303 | u |= 1 << (pin & 31); | |
304 | writel(u, GPIO_IN_POL(pin)); | |
305 | } else if (type == IRQ_TYPE_EDGE_BOTH) { | |
306 | u32 v; | |
307 | ||
308 | v = readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin)); | |
309 | ||
310 | /* | |
311 | * set initial polarity based on current input level | |
312 | */ | |
313 | u = readl(GPIO_IN_POL(pin)); | |
314 | if (v & (1 << (pin & 31))) | |
315 | u |= 1 << (pin & 31); /* falling */ | |
316 | else | |
317 | u &= ~(1 << (pin & 31)); /* rising */ | |
318 | writel(u, GPIO_IN_POL(pin)); | |
319 | } | |
320 | ||
321 | desc->status = (desc->status & ~IRQ_TYPE_SENSE_MASK) | type; | |
322 | ||
323 | return 0; | |
324 | } | |
325 | ||
fd4b9b36 | 326 | struct irq_chip orion_gpio_irq_chip = { |
a8865655 | 327 | .name = "orion_gpio_irq", |
fd4b9b36 NP |
328 | .ack = gpio_irq_ack, |
329 | .mask = gpio_irq_mask, | |
330 | .unmask = gpio_irq_unmask, | |
07332318 LB |
331 | .set_type = gpio_irq_set_type, |
332 | }; | |
333 | ||
334 | void orion_gpio_irq_handler(int pinoff) | |
335 | { | |
336 | u32 cause; | |
337 | int pin; | |
338 | ||
339 | cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff)); | |
340 | cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff)); | |
341 | ||
342 | for (pin = pinoff; pin < pinoff + 8; pin++) { | |
343 | int irq = gpio_to_irq(pin); | |
344 | struct irq_desc *desc = irq_desc + irq; | |
345 | ||
346 | if (!(cause & (1 << (pin & 31)))) | |
347 | continue; | |
348 | ||
349 | if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { | |
350 | /* Swap polarity (race with GPIO line) */ | |
351 | u32 polarity; | |
352 | ||
353 | polarity = readl(GPIO_IN_POL(pin)); | |
354 | polarity ^= 1 << (pin & 31); | |
355 | writel(polarity, GPIO_IN_POL(pin)); | |
356 | } | |
357 | desc_handle_irq(irq, desc); | |
358 | } | |
359 | } |