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 | 19 | |
9eac6d0a LB |
20 | /* |
21 | * GPIO unit register offsets. | |
22 | */ | |
23 | #define GPIO_OUT_OFF 0x0000 | |
24 | #define GPIO_IO_CONF_OFF 0x0004 | |
25 | #define GPIO_BLINK_EN_OFF 0x0008 | |
26 | #define GPIO_IN_POL_OFF 0x000c | |
27 | #define GPIO_DATA_IN_OFF 0x0010 | |
28 | #define GPIO_EDGE_CAUSE_OFF 0x0014 | |
29 | #define GPIO_EDGE_MASK_OFF 0x0018 | |
30 | #define GPIO_LEVEL_MASK_OFF 0x001c | |
31 | ||
32 | struct orion_gpio_chip { | |
33 | struct gpio_chip chip; | |
34 | spinlock_t lock; | |
35 | void __iomem *base; | |
36 | unsigned long valid_input; | |
37 | unsigned long valid_output; | |
38 | int mask_offset; | |
39 | int secondary_irq_base; | |
40 | }; | |
41 | ||
42 | static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip) | |
43 | { | |
44 | return ochip->base + GPIO_OUT_OFF; | |
45 | } | |
46 | ||
47 | static void __iomem *GPIO_IO_CONF(struct orion_gpio_chip *ochip) | |
48 | { | |
49 | return ochip->base + GPIO_IO_CONF_OFF; | |
50 | } | |
51 | ||
52 | static void __iomem *GPIO_BLINK_EN(struct orion_gpio_chip *ochip) | |
53 | { | |
54 | return ochip->base + GPIO_BLINK_EN_OFF; | |
55 | } | |
56 | ||
57 | static void __iomem *GPIO_IN_POL(struct orion_gpio_chip *ochip) | |
58 | { | |
59 | return ochip->base + GPIO_IN_POL_OFF; | |
60 | } | |
61 | ||
62 | static void __iomem *GPIO_DATA_IN(struct orion_gpio_chip *ochip) | |
63 | { | |
64 | return ochip->base + GPIO_DATA_IN_OFF; | |
65 | } | |
66 | ||
67 | static void __iomem *GPIO_EDGE_CAUSE(struct orion_gpio_chip *ochip) | |
68 | { | |
69 | return ochip->base + GPIO_EDGE_CAUSE_OFF; | |
70 | } | |
71 | ||
72 | static void __iomem *GPIO_EDGE_MASK(struct orion_gpio_chip *ochip) | |
73 | { | |
74 | return ochip->base + ochip->mask_offset + GPIO_EDGE_MASK_OFF; | |
75 | } | |
76 | ||
77 | static void __iomem *GPIO_LEVEL_MASK(struct orion_gpio_chip *ochip) | |
78 | { | |
79 | return ochip->base + ochip->mask_offset + GPIO_LEVEL_MASK_OFF; | |
80 | } | |
81 | ||
9569dae7 | 82 | |
9eac6d0a LB |
83 | static struct orion_gpio_chip orion_gpio_chips[2]; |
84 | static int orion_gpio_chip_count; | |
85 | ||
86 | static inline void | |
87 | __set_direction(struct orion_gpio_chip *ochip, unsigned pin, int input) | |
9569dae7 LB |
88 | { |
89 | u32 u; | |
90 | ||
9eac6d0a | 91 | u = readl(GPIO_IO_CONF(ochip)); |
9569dae7 | 92 | if (input) |
9eac6d0a | 93 | u |= 1 << pin; |
9569dae7 | 94 | else |
9eac6d0a LB |
95 | u &= ~(1 << pin); |
96 | writel(u, GPIO_IO_CONF(ochip)); | |
9569dae7 LB |
97 | } |
98 | ||
9eac6d0a | 99 | static void __set_level(struct orion_gpio_chip *ochip, unsigned pin, int high) |
9569dae7 LB |
100 | { |
101 | u32 u; | |
102 | ||
9eac6d0a | 103 | u = readl(GPIO_OUT(ochip)); |
9569dae7 | 104 | if (high) |
9eac6d0a | 105 | u |= 1 << pin; |
9569dae7 | 106 | else |
9eac6d0a LB |
107 | u &= ~(1 << pin); |
108 | writel(u, GPIO_OUT(ochip)); | |
9569dae7 LB |
109 | } |
110 | ||
9eac6d0a LB |
111 | static inline void |
112 | __set_blinking(struct orion_gpio_chip *ochip, unsigned pin, int blink) | |
9569dae7 | 113 | { |
a8865655 | 114 | u32 u; |
9569dae7 | 115 | |
9eac6d0a | 116 | u = readl(GPIO_BLINK_EN(ochip)); |
a8865655 | 117 | if (blink) |
9eac6d0a | 118 | u |= 1 << pin; |
a8865655 | 119 | else |
9eac6d0a LB |
120 | u &= ~(1 << pin); |
121 | writel(u, GPIO_BLINK_EN(ochip)); | |
a8865655 | 122 | } |
9569dae7 | 123 | |
9eac6d0a LB |
124 | static inline int |
125 | orion_gpio_is_valid(struct orion_gpio_chip *ochip, unsigned pin, int mode) | |
a8865655 | 126 | { |
9eac6d0a LB |
127 | if (pin >= ochip->chip.ngpio) |
128 | goto err_out; | |
129 | ||
130 | if ((mode & GPIO_INPUT_OK) && !test_bit(pin, &ochip->valid_input)) | |
131 | goto err_out; | |
132 | ||
133 | if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, &ochip->valid_output)) | |
134 | goto err_out; | |
135 | ||
136 | return 1; | |
9569dae7 | 137 | |
a8865655 EB |
138 | err_out: |
139 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | |
140 | return false; | |
9569dae7 | 141 | } |
9569dae7 | 142 | |
a8865655 EB |
143 | /* |
144 | * GENERIC_GPIO primitives. | |
145 | */ | |
9eac6d0a LB |
146 | static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) |
147 | { | |
148 | struct orion_gpio_chip *ochip = | |
149 | container_of(chip, struct orion_gpio_chip, chip); | |
150 | ||
151 | if (orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK) || | |
152 | orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK)) | |
153 | return 0; | |
154 | ||
155 | return -EINVAL; | |
156 | } | |
157 | ||
a8865655 | 158 | static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin) |
9569dae7 | 159 | { |
9eac6d0a LB |
160 | struct orion_gpio_chip *ochip = |
161 | container_of(chip, struct orion_gpio_chip, chip); | |
9569dae7 | 162 | unsigned long flags; |
9569dae7 | 163 | |
9eac6d0a | 164 | if (!orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK)) |
9569dae7 | 165 | return -EINVAL; |
9569dae7 | 166 | |
9eac6d0a LB |
167 | spin_lock_irqsave(&ochip->lock, flags); |
168 | __set_direction(ochip, pin, 1); | |
169 | spin_unlock_irqrestore(&ochip->lock, flags); | |
9569dae7 LB |
170 | |
171 | return 0; | |
172 | } | |
9569dae7 | 173 | |
9eac6d0a | 174 | static int orion_gpio_get(struct gpio_chip *chip, unsigned pin) |
9569dae7 | 175 | { |
9eac6d0a LB |
176 | struct orion_gpio_chip *ochip = |
177 | container_of(chip, struct orion_gpio_chip, chip); | |
9569dae7 LB |
178 | int val; |
179 | ||
9eac6d0a LB |
180 | if (readl(GPIO_IO_CONF(ochip)) & (1 << pin)) { |
181 | val = readl(GPIO_DATA_IN(ochip)) ^ readl(GPIO_IN_POL(ochip)); | |
182 | } else { | |
183 | val = readl(GPIO_OUT(ochip)); | |
184 | } | |
9569dae7 | 185 | |
9eac6d0a | 186 | return (val >> pin) & 1; |
9569dae7 | 187 | } |
9569dae7 | 188 | |
9eac6d0a LB |
189 | static int |
190 | orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value) | |
9569dae7 | 191 | { |
9eac6d0a LB |
192 | struct orion_gpio_chip *ochip = |
193 | container_of(chip, struct orion_gpio_chip, chip); | |
9569dae7 | 194 | unsigned long flags; |
a8865655 | 195 | |
9eac6d0a | 196 | if (!orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK)) |
a8865655 | 197 | return -EINVAL; |
9569dae7 | 198 | |
9eac6d0a LB |
199 | spin_lock_irqsave(&ochip->lock, flags); |
200 | __set_blinking(ochip, pin, 0); | |
201 | __set_level(ochip, pin, value); | |
202 | __set_direction(ochip, pin, 0); | |
203 | spin_unlock_irqrestore(&ochip->lock, flags); | |
a8865655 EB |
204 | |
205 | return 0; | |
9569dae7 | 206 | } |
9569dae7 | 207 | |
9eac6d0a | 208 | static void orion_gpio_set(struct gpio_chip *chip, unsigned pin, int value) |
9569dae7 | 209 | { |
9eac6d0a LB |
210 | struct orion_gpio_chip *ochip = |
211 | container_of(chip, struct orion_gpio_chip, chip); | |
9569dae7 | 212 | unsigned long flags; |
9569dae7 | 213 | |
9eac6d0a LB |
214 | spin_lock_irqsave(&ochip->lock, flags); |
215 | __set_level(ochip, pin, value); | |
216 | spin_unlock_irqrestore(&ochip->lock, flags); | |
9569dae7 | 217 | } |
9569dae7 | 218 | |
9eac6d0a | 219 | static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin) |
9569dae7 | 220 | { |
9eac6d0a LB |
221 | struct orion_gpio_chip *ochip = |
222 | container_of(chip, struct orion_gpio_chip, chip); | |
9569dae7 | 223 | |
9eac6d0a | 224 | return ochip->secondary_irq_base + pin; |
a8865655 | 225 | } |
9569dae7 | 226 | |
9eac6d0a | 227 | |
9569dae7 LB |
228 | /* |
229 | * Orion-specific GPIO API extensions. | |
230 | */ | |
9eac6d0a LB |
231 | static struct orion_gpio_chip *orion_gpio_chip_find(int pin) |
232 | { | |
233 | int i; | |
234 | ||
235 | for (i = 0; i < orion_gpio_chip_count; i++) { | |
236 | struct orion_gpio_chip *ochip = orion_gpio_chips + i; | |
237 | struct gpio_chip *chip = &ochip->chip; | |
238 | ||
239 | if (pin >= chip->base && pin < chip->base + chip->ngpio) | |
240 | return ochip; | |
241 | } | |
242 | ||
243 | return NULL; | |
244 | } | |
245 | ||
9569dae7 LB |
246 | void __init orion_gpio_set_unused(unsigned pin) |
247 | { | |
9eac6d0a LB |
248 | struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); |
249 | ||
250 | if (ochip == NULL) | |
251 | return; | |
252 | ||
253 | pin -= ochip->chip.base; | |
254 | ||
a8865655 | 255 | /* Configure as output, drive low. */ |
9eac6d0a LB |
256 | __set_level(ochip, pin, 0); |
257 | __set_direction(ochip, pin, 0); | |
9569dae7 LB |
258 | } |
259 | ||
28d27cf4 | 260 | void __init orion_gpio_set_valid(unsigned pin, int mode) |
9569dae7 | 261 | { |
9eac6d0a LB |
262 | struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); |
263 | ||
264 | if (ochip == NULL) | |
265 | return; | |
266 | ||
267 | pin -= ochip->chip.base; | |
268 | ||
28d27cf4 NP |
269 | if (mode == 1) |
270 | mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; | |
9eac6d0a | 271 | |
28d27cf4 | 272 | if (mode & GPIO_INPUT_OK) |
9eac6d0a | 273 | __set_bit(pin, &ochip->valid_input); |
9569dae7 | 274 | else |
9eac6d0a LB |
275 | __clear_bit(pin, &ochip->valid_input); |
276 | ||
28d27cf4 | 277 | if (mode & GPIO_OUTPUT_OK) |
9eac6d0a | 278 | __set_bit(pin, &ochip->valid_output); |
28d27cf4 | 279 | else |
9eac6d0a | 280 | __clear_bit(pin, &ochip->valid_output); |
9569dae7 LB |
281 | } |
282 | ||
283 | void orion_gpio_set_blink(unsigned pin, int blink) | |
284 | { | |
9eac6d0a | 285 | struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); |
9569dae7 | 286 | unsigned long flags; |
9569dae7 | 287 | |
9eac6d0a LB |
288 | if (ochip == NULL) |
289 | return; | |
9569dae7 | 290 | |
9eac6d0a LB |
291 | spin_lock_irqsave(&ochip->lock, flags); |
292 | __set_level(ochip, pin, 0); | |
293 | __set_blinking(ochip, pin, blink); | |
294 | spin_unlock_irqrestore(&ochip->lock, flags); | |
9569dae7 LB |
295 | } |
296 | EXPORT_SYMBOL(orion_gpio_set_blink); | |
07332318 LB |
297 | |
298 | ||
299 | /***************************************************************************** | |
300 | * Orion GPIO IRQ | |
301 | * | |
302 | * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same | |
303 | * value of the line or the opposite value. | |
304 | * | |
305 | * Level IRQ handlers: DATA_IN is used directly as cause register. | |
306 | * Interrupt are masked by LEVEL_MASK registers. | |
307 | * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. | |
308 | * Interrupt are masked by EDGE_MASK registers. | |
309 | * Both-edge handlers: Similar to regular Edge handlers, but also swaps | |
310 | * the polarity to catch the next line transaction. | |
311 | * This is a race condition that might not perfectly | |
312 | * work on some use cases. | |
313 | * | |
314 | * Every eight GPIO lines are grouped (OR'ed) before going up to main | |
315 | * cause register. | |
316 | * | |
317 | * EDGE cause mask | |
318 | * data-in /--------| |-----| |----\ | |
319 | * -----| |----- ---- to main cause reg | |
320 | * X \----------------| |----/ | |
321 | * polarity LEVEL mask | |
322 | * | |
323 | ****************************************************************************/ | |
07332318 | 324 | |
3b0c8d40 | 325 | static int gpio_irq_set_type(struct irq_data *d, u32 type) |
07332318 | 326 | { |
e59347a1 TG |
327 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
328 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | |
329 | struct orion_gpio_chip *ochip = gc->private; | |
9eac6d0a | 330 | int pin; |
07332318 LB |
331 | u32 u; |
332 | ||
e59347a1 | 333 | pin = d->irq - gc->irq_base; |
9eac6d0a LB |
334 | |
335 | u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); | |
07332318 LB |
336 | if (!u) { |
337 | printk(KERN_ERR "orion gpio_irq_set_type failed " | |
3b0c8d40 | 338 | "(irq %d, pin %d).\n", d->irq, pin); |
07332318 LB |
339 | return -EINVAL; |
340 | } | |
341 | ||
e59347a1 TG |
342 | type &= IRQ_TYPE_SENSE_MASK; |
343 | if (type == IRQ_TYPE_NONE) | |
07332318 | 344 | return -EINVAL; |
e59347a1 TG |
345 | |
346 | /* Check if we need to change chip and handler */ | |
347 | if (!(ct->type & type)) | |
348 | if (irq_setup_alt_chip(d, type)) | |
349 | return -EINVAL; | |
07332318 LB |
350 | |
351 | /* | |
352 | * Configure interrupt polarity. | |
353 | */ | |
354 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) { | |
9eac6d0a LB |
355 | u = readl(GPIO_IN_POL(ochip)); |
356 | u &= ~(1 << pin); | |
357 | writel(u, GPIO_IN_POL(ochip)); | |
07332318 | 358 | } else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) { |
9eac6d0a LB |
359 | u = readl(GPIO_IN_POL(ochip)); |
360 | u |= 1 << pin; | |
361 | writel(u, GPIO_IN_POL(ochip)); | |
07332318 LB |
362 | } else if (type == IRQ_TYPE_EDGE_BOTH) { |
363 | u32 v; | |
364 | ||
9eac6d0a | 365 | v = readl(GPIO_IN_POL(ochip)) ^ readl(GPIO_DATA_IN(ochip)); |
07332318 LB |
366 | |
367 | /* | |
368 | * set initial polarity based on current input level | |
369 | */ | |
9eac6d0a LB |
370 | u = readl(GPIO_IN_POL(ochip)); |
371 | if (v & (1 << pin)) | |
372 | u |= 1 << pin; /* falling */ | |
07332318 | 373 | else |
9eac6d0a LB |
374 | u &= ~(1 << pin); /* rising */ |
375 | writel(u, GPIO_IN_POL(ochip)); | |
07332318 LB |
376 | } |
377 | ||
07332318 LB |
378 | return 0; |
379 | } | |
380 | ||
9eac6d0a LB |
381 | void __init orion_gpio_init(int gpio_base, int ngpio, |
382 | u32 base, int mask_offset, int secondary_irq_base) | |
383 | { | |
384 | struct orion_gpio_chip *ochip; | |
e59347a1 TG |
385 | struct irq_chip_generic *gc; |
386 | struct irq_chip_type *ct; | |
9eac6d0a LB |
387 | |
388 | if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) | |
389 | return; | |
390 | ||
391 | ochip = orion_gpio_chips + orion_gpio_chip_count; | |
392 | ochip->chip.label = "orion_gpio"; | |
393 | ochip->chip.request = orion_gpio_request; | |
394 | ochip->chip.direction_input = orion_gpio_direction_input; | |
395 | ochip->chip.get = orion_gpio_get; | |
396 | ochip->chip.direction_output = orion_gpio_direction_output; | |
397 | ochip->chip.set = orion_gpio_set; | |
398 | ochip->chip.to_irq = orion_gpio_to_irq; | |
399 | ochip->chip.base = gpio_base; | |
400 | ochip->chip.ngpio = ngpio; | |
401 | ochip->chip.can_sleep = 0; | |
402 | spin_lock_init(&ochip->lock); | |
403 | ochip->base = (void __iomem *)base; | |
404 | ochip->valid_input = 0; | |
405 | ochip->valid_output = 0; | |
406 | ochip->mask_offset = mask_offset; | |
407 | ochip->secondary_irq_base = secondary_irq_base; | |
408 | ||
409 | gpiochip_add(&ochip->chip); | |
410 | ||
411 | orion_gpio_chip_count++; | |
412 | ||
413 | /* | |
414 | * Mask and clear GPIO interrupts. | |
415 | */ | |
416 | writel(0, GPIO_EDGE_CAUSE(ochip)); | |
417 | writel(0, GPIO_EDGE_MASK(ochip)); | |
418 | writel(0, GPIO_LEVEL_MASK(ochip)); | |
419 | ||
e59347a1 TG |
420 | gc = irq_alloc_generic_chip("orion_gpio_irq", 2, secondary_irq_base, |
421 | ochip->base, handle_level_irq); | |
422 | gc->private = ochip; | |
423 | ||
424 | ct = gc->chip_types; | |
425 | ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF; | |
426 | ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; | |
427 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | |
428 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | |
429 | ct->chip.irq_set_type = gpio_irq_set_type; | |
430 | ||
431 | ct++; | |
432 | ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF; | |
433 | ct->regs.ack = GPIO_EDGE_CAUSE_OFF; | |
434 | ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | |
659fb32d | 435 | ct->chip.irq_ack = irq_gc_ack_clr_bit; |
e59347a1 TG |
436 | ct->chip.irq_mask = irq_gc_mask_clr_bit; |
437 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | |
438 | ct->chip.irq_set_type = gpio_irq_set_type; | |
439 | ct->handler = handle_edge_irq; | |
440 | ||
441 | irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE, | |
442 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); | |
9eac6d0a LB |
443 | } |
444 | ||
07332318 LB |
445 | void orion_gpio_irq_handler(int pinoff) |
446 | { | |
9eac6d0a | 447 | struct orion_gpio_chip *ochip; |
e83bbb11 | 448 | u32 cause, type; |
9eac6d0a | 449 | int i; |
07332318 | 450 | |
9eac6d0a LB |
451 | ochip = orion_gpio_chip_find(pinoff); |
452 | if (ochip == NULL) | |
453 | return; | |
07332318 | 454 | |
9eac6d0a LB |
455 | cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip)); |
456 | cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip)); | |
07332318 | 457 | |
9eac6d0a LB |
458 | for (i = 0; i < ochip->chip.ngpio; i++) { |
459 | int irq; | |
9eac6d0a LB |
460 | |
461 | irq = ochip->secondary_irq_base + i; | |
462 | ||
463 | if (!(cause & (1 << i))) | |
07332318 LB |
464 | continue; |
465 | ||
e83bbb11 TG |
466 | type = irqd_get_trigger_type(irq_get_irq_data(irq)); |
467 | if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { | |
07332318 LB |
468 | /* Swap polarity (race with GPIO line) */ |
469 | u32 polarity; | |
470 | ||
9eac6d0a LB |
471 | polarity = readl(GPIO_IN_POL(ochip)); |
472 | polarity ^= 1 << i; | |
473 | writel(polarity, GPIO_IN_POL(ochip)); | |
07332318 | 474 | } |
e83bbb11 | 475 | generic_handle_irq(irq); |
07332318 LB |
476 | } |
477 | } |