diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2010-07-20 13:18:51 -0400 |
---|---|---|
committer | Nicolas Ferre <nicolas.ferre@atmel.com> | 2012-03-01 07:38:50 -0500 |
commit | 582d5fbd4e81e7debe5f3a0e6ce1a0bcdf636c6e (patch) | |
tree | dd51bedcd86e887b44d85b79b9d506a79599af0f /arch | |
parent | 9a9fe01ecf68c9b100499908122944597c63f21f (diff) |
ARM: at91/pio: add new PIO3 features
This patch adds the support for new PIO controller found on some
at91sam SOCs.
- more peripheral multiplexing
- more features to configure on a PIO (pull-down, Schmitt trigger, debouncer)
- support for several IRQ triggering features (type and polarity)
Support for those new features are retrieved from the device tree
compatibility string.
Debugfs at91_gpio file is updated to monitor configuration.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boot/dts/at91sam9x5.dtsi | 8 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-dt.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-at91/gpio.c | 262 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91_pio.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/gpio.h | 5 |
5 files changed, 281 insertions, 20 deletions
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index bb0c676b3393..a02e636d8a57 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi | |||
@@ -89,7 +89,7 @@ | |||
89 | }; | 89 | }; |
90 | 90 | ||
91 | pioA: gpio@fffff400 { | 91 | pioA: gpio@fffff400 { |
92 | compatible = "atmel,at91rm9200-gpio"; | 92 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; |
93 | reg = <0xfffff400 0x100>; | 93 | reg = <0xfffff400 0x100>; |
94 | interrupts = <2 4>; | 94 | interrupts = <2 4>; |
95 | #gpio-cells = <2>; | 95 | #gpio-cells = <2>; |
@@ -98,7 +98,7 @@ | |||
98 | }; | 98 | }; |
99 | 99 | ||
100 | pioB: gpio@fffff600 { | 100 | pioB: gpio@fffff600 { |
101 | compatible = "atmel,at91rm9200-gpio"; | 101 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; |
102 | reg = <0xfffff600 0x100>; | 102 | reg = <0xfffff600 0x100>; |
103 | interrupts = <2 4>; | 103 | interrupts = <2 4>; |
104 | #gpio-cells = <2>; | 104 | #gpio-cells = <2>; |
@@ -107,7 +107,7 @@ | |||
107 | }; | 107 | }; |
108 | 108 | ||
109 | pioC: gpio@fffff800 { | 109 | pioC: gpio@fffff800 { |
110 | compatible = "atmel,at91rm9200-gpio"; | 110 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; |
111 | reg = <0xfffff800 0x100>; | 111 | reg = <0xfffff800 0x100>; |
112 | interrupts = <3 4>; | 112 | interrupts = <3 4>; |
113 | #gpio-cells = <2>; | 113 | #gpio-cells = <2>; |
@@ -116,7 +116,7 @@ | |||
116 | }; | 116 | }; |
117 | 117 | ||
118 | pioD: gpio@fffffa00 { | 118 | pioD: gpio@fffffa00 { |
119 | compatible = "atmel,at91rm9200-gpio"; | 119 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; |
120 | reg = <0xfffffa00 0x100>; | 120 | reg = <0xfffffa00 0x100>; |
121 | interrupts = <3 4>; | 121 | interrupts = <3 4>; |
122 | #gpio-cells = <2>; | 122 | #gpio-cells = <2>; |
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index acbe23c5b260..583b72472ad9 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c | |||
@@ -86,6 +86,7 @@ static const struct of_device_id irq_of_match[] __initconst = { | |||
86 | 86 | ||
87 | { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, | 87 | { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, |
88 | { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup }, | 88 | { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup }, |
89 | { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup }, | ||
89 | { /*sentinel*/ } | 90 | { /*sentinel*/ } |
90 | }; | 91 | }; |
91 | 92 | ||
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index 567df654a2e1..325837a264c9 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c | |||
@@ -76,6 +76,14 @@ static struct at91_gpio_chip gpio_chip[] = { | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | static int gpio_banks; | 78 | static int gpio_banks; |
79 | static unsigned long at91_gpio_caps; | ||
80 | |||
81 | /* All PIO controllers support PIO3 features */ | ||
82 | #define AT91_GPIO_CAP_PIO3 (1 << 0) | ||
83 | |||
84 | #define has_pio3() (at91_gpio_caps & AT91_GPIO_CAP_PIO3) | ||
85 | |||
86 | /*--------------------------------------------------------------------------*/ | ||
79 | 87 | ||
80 | static inline void __iomem *pin_to_controller(unsigned pin) | 88 | static inline void __iomem *pin_to_controller(unsigned pin) |
81 | { | 89 | { |
@@ -92,6 +100,25 @@ static inline unsigned pin_to_mask(unsigned pin) | |||
92 | } | 100 | } |
93 | 101 | ||
94 | 102 | ||
103 | static char peripheral_function(void __iomem *pio, unsigned mask) | ||
104 | { | ||
105 | char ret = 'X'; | ||
106 | u8 select; | ||
107 | |||
108 | if (pio) { | ||
109 | if (has_pio3()) { | ||
110 | select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask); | ||
111 | select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1); | ||
112 | ret = 'A' + select; | ||
113 | } else { | ||
114 | ret = __raw_readl(pio + PIO_ABSR) & mask ? | ||
115 | 'B' : 'A'; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
95 | /*--------------------------------------------------------------------------*/ | 122 | /*--------------------------------------------------------------------------*/ |
96 | 123 | ||
97 | /* Not all hardware capabilities are exposed through these calls; they | 124 | /* Not all hardware capabilities are exposed through these calls; they |
@@ -139,7 +166,14 @@ int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup) | |||
139 | 166 | ||
140 | __raw_writel(mask, pio + PIO_IDR); | 167 | __raw_writel(mask, pio + PIO_IDR); |
141 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | 168 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); |
142 | __raw_writel(mask, pio + PIO_ASR); | 169 | if (has_pio3()) { |
170 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, | ||
171 | pio + PIO_ABCDSR1); | ||
172 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask, | ||
173 | pio + PIO_ABCDSR2); | ||
174 | } else { | ||
175 | __raw_writel(mask, pio + PIO_ASR); | ||
176 | } | ||
143 | __raw_writel(mask, pio + PIO_PDR); | 177 | __raw_writel(mask, pio + PIO_PDR); |
144 | return 0; | 178 | return 0; |
145 | } | 179 | } |
@@ -159,7 +193,14 @@ int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup) | |||
159 | 193 | ||
160 | __raw_writel(mask, pio + PIO_IDR); | 194 | __raw_writel(mask, pio + PIO_IDR); |
161 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | 195 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); |
162 | __raw_writel(mask, pio + PIO_BSR); | 196 | if (has_pio3()) { |
197 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, | ||
198 | pio + PIO_ABCDSR1); | ||
199 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask, | ||
200 | pio + PIO_ABCDSR2); | ||
201 | } else { | ||
202 | __raw_writel(mask, pio + PIO_BSR); | ||
203 | } | ||
163 | __raw_writel(mask, pio + PIO_PDR); | 204 | __raw_writel(mask, pio + PIO_PDR); |
164 | return 0; | 205 | return 0; |
165 | } | 206 | } |
@@ -167,8 +208,50 @@ EXPORT_SYMBOL(at91_set_B_periph); | |||
167 | 208 | ||
168 | 209 | ||
169 | /* | 210 | /* |
170 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and | 211 | * mux the pin to the "C" internal peripheral role. |
171 | * configure it for an input. | 212 | */ |
213 | int __init_or_module at91_set_C_periph(unsigned pin, int use_pullup) | ||
214 | { | ||
215 | void __iomem *pio = pin_to_controller(pin); | ||
216 | unsigned mask = pin_to_mask(pin); | ||
217 | |||
218 | if (!pio || !has_pio3()) | ||
219 | return -EINVAL; | ||
220 | |||
221 | __raw_writel(mask, pio + PIO_IDR); | ||
222 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | ||
223 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1); | ||
224 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2); | ||
225 | __raw_writel(mask, pio + PIO_PDR); | ||
226 | return 0; | ||
227 | } | ||
228 | EXPORT_SYMBOL(at91_set_C_periph); | ||
229 | |||
230 | |||
231 | /* | ||
232 | * mux the pin to the "D" internal peripheral role. | ||
233 | */ | ||
234 | int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup) | ||
235 | { | ||
236 | void __iomem *pio = pin_to_controller(pin); | ||
237 | unsigned mask = pin_to_mask(pin); | ||
238 | |||
239 | if (!pio || !has_pio3()) | ||
240 | return -EINVAL; | ||
241 | |||
242 | __raw_writel(mask, pio + PIO_IDR); | ||
243 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | ||
244 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1); | ||
245 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2); | ||
246 | __raw_writel(mask, pio + PIO_PDR); | ||
247 | return 0; | ||
248 | } | ||
249 | EXPORT_SYMBOL(at91_set_D_periph); | ||
250 | |||
251 | |||
252 | /* | ||
253 | * mux the pin to the gpio controller (instead of "A", "B", "C" | ||
254 | * or "D" peripheral), and configure it for an input. | ||
172 | */ | 255 | */ |
173 | int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup) | 256 | int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup) |
174 | { | 257 | { |
@@ -188,8 +271,8 @@ EXPORT_SYMBOL(at91_set_gpio_input); | |||
188 | 271 | ||
189 | 272 | ||
190 | /* | 273 | /* |
191 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), | 274 | * mux the pin to the gpio controller (instead of "A", "B", "C" |
192 | * and configure it for an output. | 275 | * or "D" peripheral), and configure it for an output. |
193 | */ | 276 | */ |
194 | int __init_or_module at91_set_gpio_output(unsigned pin, int value) | 277 | int __init_or_module at91_set_gpio_output(unsigned pin, int value) |
195 | { | 278 | { |
@@ -219,12 +302,37 @@ int __init_or_module at91_set_deglitch(unsigned pin, int is_on) | |||
219 | 302 | ||
220 | if (!pio) | 303 | if (!pio) |
221 | return -EINVAL; | 304 | return -EINVAL; |
305 | |||
306 | if (has_pio3() && is_on) | ||
307 | __raw_writel(mask, pio + PIO_IFSCDR); | ||
222 | __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); | 308 | __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); |
223 | return 0; | 309 | return 0; |
224 | } | 310 | } |
225 | EXPORT_SYMBOL(at91_set_deglitch); | 311 | EXPORT_SYMBOL(at91_set_deglitch); |
226 | 312 | ||
227 | /* | 313 | /* |
314 | * enable/disable the debounce filter; | ||
315 | */ | ||
316 | int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div) | ||
317 | { | ||
318 | void __iomem *pio = pin_to_controller(pin); | ||
319 | unsigned mask = pin_to_mask(pin); | ||
320 | |||
321 | if (!pio || !has_pio3()) | ||
322 | return -EINVAL; | ||
323 | |||
324 | if (is_on) { | ||
325 | __raw_writel(mask, pio + PIO_IFSCER); | ||
326 | __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR); | ||
327 | __raw_writel(mask, pio + PIO_IFER); | ||
328 | } else { | ||
329 | __raw_writel(mask, pio + PIO_IFDR); | ||
330 | } | ||
331 | return 0; | ||
332 | } | ||
333 | EXPORT_SYMBOL(at91_set_debounce); | ||
334 | |||
335 | /* | ||
228 | * enable/disable the multi-driver; This is only valid for output and | 336 | * enable/disable the multi-driver; This is only valid for output and |
229 | * allows the output pin to run as an open collector output. | 337 | * allows the output pin to run as an open collector output. |
230 | */ | 338 | */ |
@@ -242,6 +350,41 @@ int __init_or_module at91_set_multi_drive(unsigned pin, int is_on) | |||
242 | EXPORT_SYMBOL(at91_set_multi_drive); | 350 | EXPORT_SYMBOL(at91_set_multi_drive); |
243 | 351 | ||
244 | /* | 352 | /* |
353 | * enable/disable the pull-down. | ||
354 | * If pull-up already enabled while calling the function, we disable it. | ||
355 | */ | ||
356 | int __init_or_module at91_set_pulldown(unsigned pin, int is_on) | ||
357 | { | ||
358 | void __iomem *pio = pin_to_controller(pin); | ||
359 | unsigned mask = pin_to_mask(pin); | ||
360 | |||
361 | if (!pio || !has_pio3()) | ||
362 | return -EINVAL; | ||
363 | |||
364 | /* Disable pull-up anyway */ | ||
365 | __raw_writel(mask, pio + PIO_PUDR); | ||
366 | __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR)); | ||
367 | return 0; | ||
368 | } | ||
369 | EXPORT_SYMBOL(at91_set_pulldown); | ||
370 | |||
371 | /* | ||
372 | * disable Schmitt trigger | ||
373 | */ | ||
374 | int __init_or_module at91_disable_schmitt_trig(unsigned pin) | ||
375 | { | ||
376 | void __iomem *pio = pin_to_controller(pin); | ||
377 | unsigned mask = pin_to_mask(pin); | ||
378 | |||
379 | if (!pio || !has_pio3()) | ||
380 | return -EINVAL; | ||
381 | |||
382 | __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT); | ||
383 | return 0; | ||
384 | } | ||
385 | EXPORT_SYMBOL(at91_disable_schmitt_trig); | ||
386 | |||
387 | /* | ||
245 | * assuming the pin is muxed as a gpio output, set its value. | 388 | * assuming the pin is muxed as a gpio output, set its value. |
246 | */ | 389 | */ |
247 | int at91_set_gpio_value(unsigned pin, int value) | 390 | int at91_set_gpio_value(unsigned pin, int value) |
@@ -347,7 +490,10 @@ void at91_gpio_resume(void) | |||
347 | * To use any AT91_PIN_* as an externally triggered IRQ, first call | 490 | * To use any AT91_PIN_* as an externally triggered IRQ, first call |
348 | * at91_set_gpio_input() then maybe enable its glitch filter. | 491 | * at91_set_gpio_input() then maybe enable its glitch filter. |
349 | * Then just request_irq() with the pin ID; it works like any ARM IRQ | 492 | * Then just request_irq() with the pin ID; it works like any ARM IRQ |
350 | * handler, though it always triggers on rising and falling edges. | 493 | * handler. |
494 | * First implementation always triggers on rising and falling edges | ||
495 | * whereas the newer PIO3 can be additionally configured to trigger on | ||
496 | * level, edge with any polarity. | ||
351 | * | 497 | * |
352 | * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after | 498 | * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after |
353 | * configuring them with at91_set_a_periph() or at91_set_b_periph(). | 499 | * configuring them with at91_set_a_periph() or at91_set_b_periph(). |
@@ -385,12 +531,55 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) | |||
385 | } | 531 | } |
386 | } | 532 | } |
387 | 533 | ||
534 | /* Alternate irq type for PIO3 support */ | ||
535 | static int alt_gpio_irq_type(struct irq_data *d, unsigned type) | ||
536 | { | ||
537 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); | ||
538 | void __iomem *pio = at91_gpio->regbase; | ||
539 | unsigned mask = 1 << d->hwirq; | ||
540 | |||
541 | switch (type) { | ||
542 | case IRQ_TYPE_EDGE_RISING: | ||
543 | __raw_writel(mask, pio + PIO_ESR); | ||
544 | __raw_writel(mask, pio + PIO_REHLSR); | ||
545 | break; | ||
546 | case IRQ_TYPE_EDGE_FALLING: | ||
547 | __raw_writel(mask, pio + PIO_ESR); | ||
548 | __raw_writel(mask, pio + PIO_FELLSR); | ||
549 | break; | ||
550 | case IRQ_TYPE_LEVEL_LOW: | ||
551 | __raw_writel(mask, pio + PIO_LSR); | ||
552 | __raw_writel(mask, pio + PIO_FELLSR); | ||
553 | break; | ||
554 | case IRQ_TYPE_LEVEL_HIGH: | ||
555 | __raw_writel(mask, pio + PIO_LSR); | ||
556 | __raw_writel(mask, pio + PIO_REHLSR); | ||
557 | break; | ||
558 | case IRQ_TYPE_EDGE_BOTH: | ||
559 | /* | ||
560 | * disable additional interrupt modes: | ||
561 | * fall back to default behavior | ||
562 | */ | ||
563 | __raw_writel(mask, pio + PIO_AIMDR); | ||
564 | return 0; | ||
565 | case IRQ_TYPE_NONE: | ||
566 | default: | ||
567 | pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq)); | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | |||
571 | /* enable additional interrupt modes */ | ||
572 | __raw_writel(mask, pio + PIO_AIMER); | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
388 | static struct irq_chip gpio_irqchip = { | 577 | static struct irq_chip gpio_irqchip = { |
389 | .name = "GPIO", | 578 | .name = "GPIO", |
390 | .irq_disable = gpio_irq_mask, | 579 | .irq_disable = gpio_irq_mask, |
391 | .irq_mask = gpio_irq_mask, | 580 | .irq_mask = gpio_irq_mask, |
392 | .irq_unmask = gpio_irq_unmask, | 581 | .irq_unmask = gpio_irq_unmask, |
393 | .irq_set_type = gpio_irq_type, | 582 | /* .irq_set_type is set dynamically */ |
394 | .irq_set_wake = gpio_irq_set_wake, | 583 | .irq_set_wake = gpio_irq_set_wake, |
395 | }; | 584 | }; |
396 | 585 | ||
@@ -433,6 +622,33 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
433 | 622 | ||
434 | #ifdef CONFIG_DEBUG_FS | 623 | #ifdef CONFIG_DEBUG_FS |
435 | 624 | ||
625 | static void gpio_printf(struct seq_file *s, void __iomem *pio, unsigned mask) | ||
626 | { | ||
627 | char *trigger = NULL; | ||
628 | char *polarity = NULL; | ||
629 | |||
630 | if (__raw_readl(pio + PIO_IMR) & mask) { | ||
631 | if (!has_pio3() || !(__raw_readl(pio + PIO_AIMMR) & mask )) { | ||
632 | trigger = "edge"; | ||
633 | polarity = "both"; | ||
634 | } else { | ||
635 | if (__raw_readl(pio + PIO_ELSR) & mask) { | ||
636 | trigger = "level"; | ||
637 | polarity = __raw_readl(pio + PIO_FRLHSR) & mask ? | ||
638 | "high" : "low"; | ||
639 | } else { | ||
640 | trigger = "edge"; | ||
641 | polarity = __raw_readl(pio + PIO_FRLHSR) & mask ? | ||
642 | "rising" : "falling"; | ||
643 | } | ||
644 | } | ||
645 | seq_printf(s, "IRQ:%s-%s\t", trigger, polarity); | ||
646 | } else { | ||
647 | seq_printf(s, "GPIO:%s\t\t", | ||
648 | __raw_readl(pio + PIO_PDSR) & mask ? "1" : "0"); | ||
649 | } | ||
650 | } | ||
651 | |||
436 | static int at91_gpio_show(struct seq_file *s, void *unused) | 652 | static int at91_gpio_show(struct seq_file *s, void *unused) |
437 | { | 653 | { |
438 | int bank, j; | 654 | int bank, j; |
@@ -440,7 +656,7 @@ static int at91_gpio_show(struct seq_file *s, void *unused) | |||
440 | /* print heading */ | 656 | /* print heading */ |
441 | seq_printf(s, "Pin\t"); | 657 | seq_printf(s, "Pin\t"); |
442 | for (bank = 0; bank < gpio_banks; bank++) { | 658 | for (bank = 0; bank < gpio_banks; bank++) { |
443 | seq_printf(s, "PIO%c\t", 'A' + bank); | 659 | seq_printf(s, "PIO%c\t\t", 'A' + bank); |
444 | }; | 660 | }; |
445 | seq_printf(s, "\n\n"); | 661 | seq_printf(s, "\n\n"); |
446 | 662 | ||
@@ -454,11 +670,10 @@ static int at91_gpio_show(struct seq_file *s, void *unused) | |||
454 | unsigned mask = pin_to_mask(pin); | 670 | unsigned mask = pin_to_mask(pin); |
455 | 671 | ||
456 | if (__raw_readl(pio + PIO_PSR) & mask) | 672 | if (__raw_readl(pio + PIO_PSR) & mask) |
457 | seq_printf(s, "GPIO:%s", __raw_readl(pio + PIO_PDSR) & mask ? "1" : "0"); | 673 | gpio_printf(s, pio, mask); |
458 | else | 674 | else |
459 | seq_printf(s, "%s", __raw_readl(pio + PIO_ABSR) & mask ? "B" : "A"); | 675 | seq_printf(s, "%c\t\t", |
460 | 676 | peripheral_function(pio, mask)); | |
461 | seq_printf(s, "\t"); | ||
462 | } | 677 | } |
463 | 678 | ||
464 | seq_printf(s, "\n"); | 679 | seq_printf(s, "\n"); |
@@ -529,6 +744,12 @@ int __init at91_gpio_of_irq_setup(struct device_node *node, | |||
529 | int alias_idx = of_alias_get_id(node, "gpio"); | 744 | int alias_idx = of_alias_get_id(node, "gpio"); |
530 | struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx]; | 745 | struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx]; |
531 | 746 | ||
747 | /* Setup proper .irq_set_type function */ | ||
748 | if (has_pio3()) | ||
749 | gpio_irqchip.irq_set_type = alt_gpio_irq_type; | ||
750 | else | ||
751 | gpio_irqchip.irq_set_type = gpio_irq_type; | ||
752 | |||
532 | /* Disable irqs of this PIO controller */ | 753 | /* Disable irqs of this PIO controller */ |
533 | __raw_writel(~0, at91_gpio->regbase + PIO_IDR); | 754 | __raw_writel(~0, at91_gpio->regbase + PIO_IDR); |
534 | 755 | ||
@@ -593,6 +814,12 @@ void __init at91_gpio_irq_setup(void) | |||
593 | int gpio_irqnbr = 0; | 814 | int gpio_irqnbr = 0; |
594 | struct at91_gpio_chip *this, *prev; | 815 | struct at91_gpio_chip *this, *prev; |
595 | 816 | ||
817 | /* Setup proper .irq_set_type function */ | ||
818 | if (has_pio3()) | ||
819 | gpio_irqchip.irq_set_type = alt_gpio_irq_type; | ||
820 | else | ||
821 | gpio_irqchip.irq_set_type = gpio_irq_type; | ||
822 | |||
596 | for (pioc = 0, this = gpio_chip, prev = NULL; | 823 | for (pioc = 0, this = gpio_chip, prev = NULL; |
597 | pioc++ < gpio_banks; | 824 | pioc++ < gpio_banks; |
598 | prev = this, this++) { | 825 | prev = this, this++) { |
@@ -696,9 +923,8 @@ static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
696 | at91_get_gpio_value(pin) ? | 923 | at91_get_gpio_value(pin) ? |
697 | "set" : "clear"); | 924 | "set" : "clear"); |
698 | else | 925 | else |
699 | seq_printf(s, "[periph %s]\n", | 926 | seq_printf(s, "[periph %c]\n", |
700 | __raw_readl(pio + PIO_ABSR) & | 927 | peripheral_function(pio, mask)); |
701 | mask ? "B" : "A"); | ||
702 | } | 928 | } |
703 | } | 929 | } |
704 | } | 930 | } |
@@ -781,6 +1007,10 @@ static void __init of_at91_gpio_init_one(struct device_node *np) | |||
781 | goto ioremap_err; | 1007 | goto ioremap_err; |
782 | } | 1008 | } |
783 | 1009 | ||
1010 | /* Get capabilities from compatibility property */ | ||
1011 | if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio")) | ||
1012 | at91_gpio_caps |= AT91_GPIO_CAP_PIO3; | ||
1013 | |||
784 | /* Setup clock */ | 1014 | /* Setup clock */ |
785 | if (at91_gpio_setup_clk(alias_idx)) | 1015 | if (at91_gpio_setup_clk(alias_idx)) |
786 | goto ioremap_err; | 1016 | goto ioremap_err; |
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index c6a31bf8a5c6..732b11c37f1a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h | |||
@@ -40,10 +40,35 @@ | |||
40 | #define PIO_PUER 0x64 /* Pull-up Enable Register */ | 40 | #define PIO_PUER 0x64 /* Pull-up Enable Register */ |
41 | #define PIO_PUSR 0x68 /* Pull-up Status Register */ | 41 | #define PIO_PUSR 0x68 /* Pull-up Status Register */ |
42 | #define PIO_ASR 0x70 /* Peripheral A Select Register */ | 42 | #define PIO_ASR 0x70 /* Peripheral A Select Register */ |
43 | #define PIO_ABCDSR1 0x70 /* Peripheral ABCD Select Register 1 [some sam9 only] */ | ||
43 | #define PIO_BSR 0x74 /* Peripheral B Select Register */ | 44 | #define PIO_BSR 0x74 /* Peripheral B Select Register */ |
45 | #define PIO_ABCDSR2 0x74 /* Peripheral ABCD Select Register 2 [some sam9 only] */ | ||
44 | #define PIO_ABSR 0x78 /* AB Status Register */ | 46 | #define PIO_ABSR 0x78 /* AB Status Register */ |
47 | #define PIO_IFSCDR 0x80 /* Input Filter Slow Clock Disable Register */ | ||
48 | #define PIO_IFSCER 0x84 /* Input Filter Slow Clock Enable Register */ | ||
49 | #define PIO_IFSCSR 0x88 /* Input Filter Slow Clock Status Register */ | ||
50 | #define PIO_SCDR 0x8c /* Slow Clock Divider Debouncing Register */ | ||
51 | #define PIO_SCDR_DIV (0x3fff << 0) /* Slow Clock Divider Mask */ | ||
52 | #define PIO_PPDDR 0x90 /* Pad Pull-down Disable Register */ | ||
53 | #define PIO_PPDER 0x94 /* Pad Pull-down Enable Register */ | ||
54 | #define PIO_PPDSR 0x98 /* Pad Pull-down Status Register */ | ||
45 | #define PIO_OWER 0xa0 /* Output Write Enable Register */ | 55 | #define PIO_OWER 0xa0 /* Output Write Enable Register */ |
46 | #define PIO_OWDR 0xa4 /* Output Write Disable Register */ | 56 | #define PIO_OWDR 0xa4 /* Output Write Disable Register */ |
47 | #define PIO_OWSR 0xa8 /* Output Write Status Register */ | 57 | #define PIO_OWSR 0xa8 /* Output Write Status Register */ |
58 | #define PIO_AIMER 0xb0 /* Additional Interrupt Modes Enable Register */ | ||
59 | #define PIO_AIMDR 0xb4 /* Additional Interrupt Modes Disable Register */ | ||
60 | #define PIO_AIMMR 0xb8 /* Additional Interrupt Modes Mask Register */ | ||
61 | #define PIO_ESR 0xc0 /* Edge Select Register */ | ||
62 | #define PIO_LSR 0xc4 /* Level Select Register */ | ||
63 | #define PIO_ELSR 0xc8 /* Edge/Level Status Register */ | ||
64 | #define PIO_FELLSR 0xd0 /* Falling Edge/Low Level Select Register */ | ||
65 | #define PIO_REHLSR 0xd4 /* Rising Edge/ High Level Select Register */ | ||
66 | #define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */ | ||
67 | #define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */ | ||
68 | |||
69 | #define ABCDSR_PERIPH_A 0x0 | ||
70 | #define ABCDSR_PERIPH_B 0x1 | ||
71 | #define ABCDSR_PERIPH_C 0x2 | ||
72 | #define ABCDSR_PERIPH_D 0x3 | ||
48 | 73 | ||
49 | #endif | 74 | #endif |
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index 7cf009be8d0d..eed465ab0dd7 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h | |||
@@ -191,10 +191,15 @@ | |||
191 | extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup); | 191 | extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup); |
192 | extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); | 192 | extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); |
193 | extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup); | 193 | extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup); |
194 | extern int __init_or_module at91_set_C_periph(unsigned pin, int use_pullup); | ||
195 | extern int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup); | ||
194 | extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup); | 196 | extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup); |
195 | extern int __init_or_module at91_set_gpio_output(unsigned pin, int value); | 197 | extern int __init_or_module at91_set_gpio_output(unsigned pin, int value); |
196 | extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on); | 198 | extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on); |
199 | extern int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div); | ||
197 | extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on); | 200 | extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on); |
201 | extern int __init_or_module at91_set_pulldown(unsigned pin, int is_on); | ||
202 | extern int __init_or_module at91_disable_schmitt_trig(unsigned pin); | ||
198 | 203 | ||
199 | /* callable at any time */ | 204 | /* callable at any time */ |
200 | extern int at91_set_gpio_value(unsigned pin, int value); | 205 | extern int at91_set_gpio_value(unsigned pin, int value); |