diff options
author | Haojian Zhuang <haojian.zhuang@marvell.com> | 2011-10-17 08:37:52 -0400 |
---|---|---|
committer | Haojian Zhuang <hzhuang1@hexinfolabs.org> | 2011-11-15 06:08:27 -0500 |
commit | 157d2644cb0c1e71a18baaffca56d2b1d0ebf10f (patch) | |
tree | e33d224362ce8ac0706725f02ecd8b89c3645934 /drivers/gpio/gpio-pxa.c | |
parent | 9bf448c66d4b4cb03813b39195d408701ecf1fab (diff) |
ARM: pxa: change gpio to platform device
Remove most gpio macros and change gpio driver to platform driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Diffstat (limited to 'drivers/gpio/gpio-pxa.c')
-rw-r--r-- | drivers/gpio/gpio-pxa.c | 135 |
1 files changed, 125 insertions, 10 deletions
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 31d2da4100cd..079f97fde2c7 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c | |||
@@ -12,13 +12,42 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
15 | #include <linux/gpio-pxa.h> | ||
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
16 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/platform_device.h> | ||
18 | #include <linux/syscore_ops.h> | 20 | #include <linux/syscore_ops.h> |
19 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
20 | 22 | ||
21 | #include <mach/gpio-pxa.h> | 23 | /* |
24 | * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with | ||
25 | * one set of registers. The register offsets are organized below: | ||
26 | * | ||
27 | * GPLR GPDR GPSR GPCR GRER GFER GEDR | ||
28 | * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 | ||
29 | * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C | ||
30 | * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 | ||
31 | * | ||
32 | * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 | ||
33 | * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C | ||
34 | * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 | ||
35 | * | ||
36 | * NOTE: | ||
37 | * BANK 3 is only available on PXA27x and later processors. | ||
38 | * BANK 4 and 5 are only available on PXA935 | ||
39 | */ | ||
40 | |||
41 | #define GPLR_OFFSET 0x00 | ||
42 | #define GPDR_OFFSET 0x0C | ||
43 | #define GPSR_OFFSET 0x18 | ||
44 | #define GPCR_OFFSET 0x24 | ||
45 | #define GRER_OFFSET 0x30 | ||
46 | #define GFER_OFFSET 0x3C | ||
47 | #define GEDR_OFFSET 0x48 | ||
48 | #define GAFR_OFFSET 0x54 | ||
49 | |||
50 | #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) | ||
22 | 51 | ||
23 | int pxa_last_gpio; | 52 | int pxa_last_gpio; |
24 | 53 | ||
@@ -52,6 +81,7 @@ enum { | |||
52 | static DEFINE_SPINLOCK(gpio_lock); | 81 | static DEFINE_SPINLOCK(gpio_lock); |
53 | static struct pxa_gpio_chip *pxa_gpio_chips; | 82 | static struct pxa_gpio_chip *pxa_gpio_chips; |
54 | static int gpio_type; | 83 | static int gpio_type; |
84 | static void __iomem *gpio_reg_base; | ||
55 | 85 | ||
56 | #define for_each_gpio_chip(i, c) \ | 86 | #define for_each_gpio_chip(i, c) \ |
57 | for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) | 87 | for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) |
@@ -76,6 +106,53 @@ static inline int gpio_is_mmp_type(int type) | |||
76 | return (type & MMP_GPIO) != 0; | 106 | return (type & MMP_GPIO) != 0; |
77 | } | 107 | } |
78 | 108 | ||
109 | /* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted, | ||
110 | * as well as their Alternate Function value being '1' for GPIO in GAFRx. | ||
111 | */ | ||
112 | static inline int __gpio_is_inverted(int gpio) | ||
113 | { | ||
114 | if ((gpio_type == PXA26X_GPIO) && (gpio > 85)) | ||
115 | return 1; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate | ||
121 | * function of a GPIO, and GPDRx cannot be altered once configured. It | ||
122 | * is attributed as "occupied" here (I know this terminology isn't | ||
123 | * accurate, you are welcome to propose a better one :-) | ||
124 | */ | ||
125 | static inline int __gpio_is_occupied(unsigned gpio) | ||
126 | { | ||
127 | struct pxa_gpio_chip *pxachip; | ||
128 | void __iomem *base; | ||
129 | unsigned long gafr = 0, gpdr = 0; | ||
130 | int ret, af = 0, dir = 0; | ||
131 | |||
132 | pxachip = gpio_to_pxachip(gpio); | ||
133 | base = gpio_chip_base(&pxachip->chip); | ||
134 | gpdr = readl_relaxed(base + GPDR_OFFSET); | ||
135 | |||
136 | switch (gpio_type) { | ||
137 | case PXA25X_GPIO: | ||
138 | case PXA26X_GPIO: | ||
139 | case PXA27X_GPIO: | ||
140 | gafr = readl_relaxed(base + GAFR_OFFSET); | ||
141 | af = (gafr >> ((gpio & 0xf) * 2)) & 0x3; | ||
142 | dir = gpdr & GPIO_bit(gpio); | ||
143 | |||
144 | if (__gpio_is_inverted(gpio)) | ||
145 | ret = (af != 1) || (dir == 0); | ||
146 | else | ||
147 | ret = (af != 0) || (dir != 0); | ||
148 | break; | ||
149 | default: | ||
150 | ret = gpdr & GPIO_bit(gpio); | ||
151 | break; | ||
152 | } | ||
153 | return ret; | ||
154 | } | ||
155 | |||
79 | #ifdef CONFIG_ARCH_PXA | 156 | #ifdef CONFIG_ARCH_PXA |
80 | static inline int __pxa_gpio_to_irq(int gpio) | 157 | static inline int __pxa_gpio_to_irq(int gpio) |
81 | { | 158 | { |
@@ -187,7 +264,7 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
187 | (value ? GPSR_OFFSET : GPCR_OFFSET)); | 264 | (value ? GPSR_OFFSET : GPCR_OFFSET)); |
188 | } | 265 | } |
189 | 266 | ||
190 | static int __init pxa_init_gpio_chip(int gpio_end) | 267 | static int __devinit pxa_init_gpio_chip(int gpio_end) |
191 | { | 268 | { |
192 | int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; | 269 | int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; |
193 | struct pxa_gpio_chip *chips; | 270 | struct pxa_gpio_chip *chips; |
@@ -202,7 +279,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) | |||
202 | struct gpio_chip *c = &chips[i].chip; | 279 | struct gpio_chip *c = &chips[i].chip; |
203 | 280 | ||
204 | sprintf(chips[i].label, "gpio-%d", i); | 281 | sprintf(chips[i].label, "gpio-%d", i); |
205 | chips[i].regbase = GPIO_BANK(i); | 282 | chips[i].regbase = gpio_reg_base + BANK_OFF(i); |
206 | 283 | ||
207 | c->base = gpio; | 284 | c->base = gpio; |
208 | c->label = chips[i].label; | 285 | c->label = chips[i].label; |
@@ -384,17 +461,35 @@ static int pxa_gpio_nums(void) | |||
384 | return count; | 461 | return count; |
385 | } | 462 | } |
386 | 463 | ||
387 | void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) | 464 | static int __devinit pxa_gpio_probe(struct platform_device *pdev) |
388 | { | 465 | { |
389 | struct pxa_gpio_chip *c; | 466 | struct pxa_gpio_chip *c; |
467 | struct resource *res; | ||
390 | int gpio, irq; | 468 | int gpio, irq; |
469 | int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; | ||
391 | 470 | ||
392 | pxa_last_gpio = pxa_gpio_nums(); | 471 | pxa_last_gpio = pxa_gpio_nums(); |
393 | if (!pxa_last_gpio) | 472 | if (!pxa_last_gpio) |
394 | return; | 473 | return -EINVAL; |
474 | |||
475 | irq0 = platform_get_irq_byname(pdev, "gpio0"); | ||
476 | irq1 = platform_get_irq_byname(pdev, "gpio1"); | ||
477 | irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); | ||
478 | if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) | ||
479 | || (irq_mux <= 0)) | ||
480 | return -EINVAL; | ||
481 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
482 | if (!res) | ||
483 | return -EINVAL; | ||
484 | gpio_reg_base = ioremap(res->start, resource_size(res)); | ||
485 | if (!gpio_reg_base) | ||
486 | return -EINVAL; | ||
487 | |||
488 | if (irq0 > 0) | ||
489 | gpio_offset = 2; | ||
395 | 490 | ||
396 | /* Initialize GPIO chips */ | 491 | /* Initialize GPIO chips */ |
397 | pxa_init_gpio_chip(end); | 492 | pxa_init_gpio_chip(pxa_last_gpio); |
398 | 493 | ||
399 | /* clear all GPIO edge detects */ | 494 | /* clear all GPIO edge detects */ |
400 | for_each_gpio_chip(gpio, c) { | 495 | for_each_gpio_chip(gpio, c) { |
@@ -417,16 +512,29 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) | |||
417 | irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); | 512 | irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); |
418 | #endif | 513 | #endif |
419 | 514 | ||
420 | for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { | 515 | for (irq = gpio_to_irq(gpio_offset); |
516 | irq <= gpio_to_irq(pxa_last_gpio); irq++) { | ||
421 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | 517 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, |
422 | handle_edge_irq); | 518 | handle_edge_irq); |
423 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 519 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
424 | } | 520 | } |
425 | 521 | ||
426 | /* Install handler for GPIO>=2 edge detect interrupts */ | 522 | irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); |
427 | irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); | 523 | return 0; |
428 | pxa_muxed_gpio_chip.irq_set_wake = fn; | 524 | } |
525 | |||
526 | static struct platform_driver pxa_gpio_driver = { | ||
527 | .probe = pxa_gpio_probe, | ||
528 | .driver = { | ||
529 | .name = "pxa-gpio", | ||
530 | }, | ||
531 | }; | ||
532 | |||
533 | static int __init pxa_gpio_init(void) | ||
534 | { | ||
535 | return platform_driver_register(&pxa_gpio_driver); | ||
429 | } | 536 | } |
537 | postcore_initcall(pxa_gpio_init); | ||
430 | 538 | ||
431 | #ifdef CONFIG_PM | 539 | #ifdef CONFIG_PM |
432 | static int pxa_gpio_suspend(void) | 540 | static int pxa_gpio_suspend(void) |
@@ -470,3 +578,10 @@ struct syscore_ops pxa_gpio_syscore_ops = { | |||
470 | .suspend = pxa_gpio_suspend, | 578 | .suspend = pxa_gpio_suspend, |
471 | .resume = pxa_gpio_resume, | 579 | .resume = pxa_gpio_resume, |
472 | }; | 580 | }; |
581 | |||
582 | static int __init pxa_gpio_sysinit(void) | ||
583 | { | ||
584 | register_syscore_ops(&pxa_gpio_syscore_ops); | ||
585 | return 0; | ||
586 | } | ||
587 | postcore_initcall(pxa_gpio_sysinit); | ||