1 From 49da9bd487e54164a75503e0037a054cce697ed5 Mon Sep 17 00:00:00 2001
2 From: Philipp Zabel <philipp.zabel@gmail.com>
3 Date: Tue, 12 Feb 2008 04:38:12 +0300
4 Subject: [PATCH 23/64] This adds gpiolib support for the PXA architecture:
5 - move all GPIO API functions from generic.c into gpio.c
6 - convert the gpio_get/set_value macros into inline functions
8 This makes it easier to hook up GPIOs provided by external chips like
11 Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
12 Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
13 Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
14 Cc: Jean Delvare <khali@linux-fr.org>
15 Cc: Eric Miao <eric.miao@marvell.com>
16 Cc: Sam Ravnborg <sam@ravnborg.org>
17 Cc: Haavard Skinnemoen <hskinnemoen@atmel.com>
18 Cc: Ben Gardner <bgardner@wabtec.com>
19 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
21 arch/arm/Kconfig | 1 +
22 arch/arm/mach-pxa/Makefile | 3 +-
23 arch/arm/mach-pxa/generic.c | 93 ----------------
24 arch/arm/mach-pxa/generic.h | 1 +
25 arch/arm/mach-pxa/gpio.c | 197 +++++++++++++++++++++++++++++++++++
26 arch/arm/mach-pxa/irq.c | 2 +
27 include/asm-arm/arch-pxa/gpio.h | 48 ++++-----
28 include/asm-arm/arch-pxa/pxa-regs.h | 13 +++
29 8 files changed, 236 insertions(+), 122 deletions(-)
30 create mode 100644 arch/arm/mach-pxa/gpio.c
32 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
33 index 06ca241..423e953 100644
34 --- a/arch/arm/Kconfig
35 +++ b/arch/arm/Kconfig
36 @@ -346,6 +346,7 @@ config ARCH_PXA
38 select GENERIC_CLOCKEVENTS
40 + select HAVE_GPIO_LIB
42 Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
44 diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
45 index 4263527..5cb0216 100644
46 --- a/arch/arm/mach-pxa/Makefile
47 +++ b/arch/arm/mach-pxa/Makefile
51 # Common support (must be linked before board specific support)
52 -obj-y += clock.o generic.o irq.o dma.o time.o
53 +obj-y += clock.o generic.o irq.o dma.o \
55 obj-$(CONFIG_PXA25x) += pxa25x.o
56 obj-$(CONFIG_PXA27x) += pxa27x.o
57 obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o
58 diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
59 index 1c34946..6c07292 100644
60 --- a/arch/arm/mach-pxa/generic.c
61 +++ b/arch/arm/mach-pxa/generic.c
63 #include <asm/mach/map.h>
65 #include <asm/arch/pxa-regs.h>
66 -#include <asm/arch/gpio.h>
67 #include <asm/arch/udc.h>
68 #include <asm/arch/pxafb.h>
69 #include <asm/arch/mmc.h>
70 @@ -73,97 +72,6 @@ unsigned int get_memclk_frequency_10khz(void)
71 EXPORT_SYMBOL(get_memclk_frequency_10khz);
74 - * Handy function to set GPIO alternate functions
78 -int pxa_gpio_mode(int gpio_mode)
80 - unsigned long flags;
81 - int gpio = gpio_mode & GPIO_MD_MASK_NR;
82 - int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
85 - if (gpio > pxa_last_gpio)
88 - local_irq_save(flags);
89 - if (gpio_mode & GPIO_DFLT_LOW)
90 - GPCR(gpio) = GPIO_bit(gpio);
91 - else if (gpio_mode & GPIO_DFLT_HIGH)
92 - GPSR(gpio) = GPIO_bit(gpio);
93 - if (gpio_mode & GPIO_MD_MASK_DIR)
94 - GPDR(gpio) |= GPIO_bit(gpio);
96 - GPDR(gpio) &= ~GPIO_bit(gpio);
97 - gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
98 - GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
99 - local_irq_restore(flags);
104 -EXPORT_SYMBOL(pxa_gpio_mode);
106 -int gpio_direction_input(unsigned gpio)
108 - unsigned long flags;
111 - if (gpio > pxa_last_gpio)
114 - mask = GPIO_bit(gpio);
115 - local_irq_save(flags);
116 - GPDR(gpio) &= ~mask;
117 - local_irq_restore(flags);
121 -EXPORT_SYMBOL(gpio_direction_input);
123 -int gpio_direction_output(unsigned gpio, int value)
125 - unsigned long flags;
128 - if (gpio > pxa_last_gpio)
131 - mask = GPIO_bit(gpio);
132 - local_irq_save(flags);
137 - GPDR(gpio) |= mask;
138 - local_irq_restore(flags);
142 -EXPORT_SYMBOL(gpio_direction_output);
145 - * Return GPIO level
147 -int pxa_gpio_get_value(unsigned gpio)
149 - return __gpio_get_value(gpio);
152 -EXPORT_SYMBOL(pxa_gpio_get_value);
155 - * Set output GPIO level
157 -void pxa_gpio_set_value(unsigned gpio, int value)
159 - __gpio_set_value(gpio, value);
162 -EXPORT_SYMBOL(pxa_gpio_set_value);
165 * Routine to safely enable or disable a clock in the CKEN
167 void __pxa_set_cken(int clock, int enable)
168 @@ -178,7 +86,6 @@ void __pxa_set_cken(int clock, int enable)
170 local_irq_restore(flags);
173 EXPORT_SYMBOL(__pxa_set_cken);
176 diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
177 index b30f240..727a9f5 100644
178 --- a/arch/arm/mach-pxa/generic.h
179 +++ b/arch/arm/mach-pxa/generic.h
180 @@ -16,6 +16,7 @@ extern void __init pxa_init_irq_low(void);
181 extern void __init pxa_init_irq_high(void);
182 extern void __init pxa_init_irq_gpio(int gpio_nr);
183 extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
184 +extern void __init pxa_init_gpio(int gpio_nr);
185 extern void __init pxa25x_init_irq(void);
186 extern void __init pxa27x_init_irq(void);
187 extern void __init pxa3xx_init_irq(void);
188 diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
190 index 0000000..8638dd7
192 +++ b/arch/arm/mach-pxa/gpio.c
195 + * linux/arch/arm/mach-pxa/gpio.c
197 + * Generic PXA GPIO handling
199 + * Author: Nicolas Pitre
200 + * Created: Jun 15, 2001
201 + * Copyright: MontaVista Software Inc.
203 + * This program is free software; you can redistribute it and/or modify
204 + * it under the terms of the GNU General Public License version 2 as
205 + * published by the Free Software Foundation.
208 +#include <linux/init.h>
209 +#include <linux/module.h>
211 +#include <asm/gpio.h>
212 +#include <asm/hardware.h>
214 +#include <asm/arch/pxa-regs.h>
216 +#include "generic.h"
219 +struct pxa_gpio_chip {
220 + struct gpio_chip chip;
221 + void __iomem *regbase;
227 + * Configure pins for GPIO or other functions
229 +int pxa_gpio_mode(int gpio_mode)
231 + unsigned long flags;
232 + int gpio = gpio_mode & GPIO_MD_MASK_NR;
233 + int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
236 + if (gpio > pxa_last_gpio)
239 + local_irq_save(flags);
240 + if (gpio_mode & GPIO_DFLT_LOW)
241 + GPCR(gpio) = GPIO_bit(gpio);
242 + else if (gpio_mode & GPIO_DFLT_HIGH)
243 + GPSR(gpio) = GPIO_bit(gpio);
244 + if (gpio_mode & GPIO_MD_MASK_DIR)
245 + GPDR(gpio) |= GPIO_bit(gpio);
247 + GPDR(gpio) &= ~GPIO_bit(gpio);
248 + gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
249 + GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
250 + local_irq_restore(flags);
254 +EXPORT_SYMBOL(pxa_gpio_mode);
256 +static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
258 + unsigned long flags;
259 + u32 mask = 1 << offset;
261 + struct pxa_gpio_chip *pxa;
262 + void __iomem *gpdr;
264 + pxa = container_of(chip, struct pxa_gpio_chip, chip);
265 + gpdr = pxa->regbase + GPDR_OFFSET;
266 + local_irq_save(flags);
267 + value = __raw_readl(gpdr);
269 + __raw_writel(value, gpdr);
270 + local_irq_restore(flags);
275 +static int pxa_gpio_direction_output(struct gpio_chip *chip,
276 + unsigned offset, int value)
278 + unsigned long flags;
279 + u32 mask = 1 << offset;
281 + struct pxa_gpio_chip *pxa;
282 + void __iomem *gpdr;
284 + pxa = container_of(chip, struct pxa_gpio_chip, chip);
286 + pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
287 + gpdr = pxa->regbase + GPDR_OFFSET;
288 + local_irq_save(flags);
289 + tmp = __raw_readl(gpdr);
291 + __raw_writel(tmp, gpdr);
292 + local_irq_restore(flags);
298 + * Return GPIO level
300 +static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
302 + u32 mask = 1 << offset;
303 + struct pxa_gpio_chip *pxa;
305 + pxa = container_of(chip, struct pxa_gpio_chip, chip);
306 + return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
310 + * Set output GPIO level
312 +static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
314 + u32 mask = 1 << offset;
315 + struct pxa_gpio_chip *pxa;
317 + pxa = container_of(chip, struct pxa_gpio_chip, chip);
320 + __raw_writel(mask, pxa->regbase + GPSR_OFFSET);
322 + __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
325 +static struct pxa_gpio_chip pxa_gpio_chip[] = {
327 + .regbase = GPIO0_BASE,
330 + .direction_input = pxa_gpio_direction_input,
331 + .direction_output = pxa_gpio_direction_output,
332 + .get = pxa_gpio_get,
333 + .set = pxa_gpio_set,
339 + .regbase = GPIO1_BASE,
342 + .direction_input = pxa_gpio_direction_input,
343 + .direction_output = pxa_gpio_direction_output,
344 + .get = pxa_gpio_get,
345 + .set = pxa_gpio_set,
351 + .regbase = GPIO2_BASE,
354 + .direction_input = pxa_gpio_direction_input,
355 + .direction_output = pxa_gpio_direction_output,
356 + .get = pxa_gpio_get,
357 + .set = pxa_gpio_set,
359 + .ngpio = 32, /* 21 for PXA25x */
362 +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
364 + .regbase = GPIO3_BASE,
367 + .direction_input = pxa_gpio_direction_input,
368 + .direction_output = pxa_gpio_direction_output,
369 + .get = pxa_gpio_get,
370 + .set = pxa_gpio_set,
378 +void __init pxa_init_gpio(int gpio_nr)
382 + /* add a GPIO chip for each register bank.
383 + * the last PXA25x register only contains 21 GPIOs
385 + for (i = 0; i < gpio_nr; i += 32) {
386 + if (i+32 > gpio_nr)
387 + pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
388 + gpiochip_add(&pxa_gpio_chip[i/32].chip);
391 diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
392 index 07acb45..d0965ef 100644
393 --- a/arch/arm/mach-pxa/irq.c
394 +++ b/arch/arm/mach-pxa/irq.c
395 @@ -310,6 +310,8 @@ void __init pxa_init_irq_gpio(int gpio_nr)
396 /* Install handler for GPIO>=2 edge detect interrupts */
397 set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
398 set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
400 + pxa_init_gpio(gpio_nr);
403 void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
404 diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
405 index 9dbc2dc..bdbf5f9 100644
406 --- a/include/asm-arm/arch-pxa/gpio.h
407 +++ b/include/asm-arm/arch-pxa/gpio.h
410 #include <asm/hardware.h>
412 -static inline int gpio_request(unsigned gpio, const char *label)
416 +#include <asm-generic/gpio.h>
418 -static inline void gpio_free(unsigned gpio)
423 -extern int gpio_direction_input(unsigned gpio);
424 -extern int gpio_direction_output(unsigned gpio, int value);
425 +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
426 + * Those cases currently cause holes in the GPIO number space.
428 +#define NR_BUILTIN_GPIO 128
430 -static inline int __gpio_get_value(unsigned gpio)
431 +static inline int gpio_get_value(unsigned gpio)
433 - return GPLR(gpio) & GPIO_bit(gpio);
434 + if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
435 + return GPLR(gpio) & GPIO_bit(gpio);
437 + return __gpio_get_value(gpio);
440 -#define gpio_get_value(gpio) \
441 - (__builtin_constant_p(gpio) ? \
442 - __gpio_get_value(gpio) : \
443 - pxa_gpio_get_value(gpio))
445 -static inline void __gpio_set_value(unsigned gpio, int value)
446 +static inline void gpio_set_value(unsigned gpio, int value)
449 - GPSR(gpio) = GPIO_bit(gpio);
451 - GPCR(gpio) = GPIO_bit(gpio);
452 + if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
454 + GPSR(gpio) = GPIO_bit(gpio);
456 + GPCR(gpio) = GPIO_bit(gpio);
458 + __gpio_set_value(gpio, value);
462 -#define gpio_set_value(gpio,value) \
463 - (__builtin_constant_p(gpio) ? \
464 - __gpio_set_value(gpio, value) : \
465 - pxa_gpio_set_value(gpio, value))
467 -#include <asm-generic/gpio.h> /* cansleep wrappers */
468 +#define gpio_cansleep __gpio_cansleep
470 #define gpio_to_irq(gpio) IRQ_GPIO(gpio)
471 #define irq_to_gpio(irq) IRQ_TO_GPIO(irq)
472 diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
473 index 1bd398d..bd57417 100644
474 --- a/include/asm-arm/arch-pxa/pxa-regs.h
475 +++ b/include/asm-arm/arch-pxa/pxa-regs.h
476 @@ -1131,6 +1131,19 @@
477 * General Purpose I/O
480 +#define GPIO0_BASE ((void __iomem *)io_p2v(0x40E00000))
481 +#define GPIO1_BASE ((void __iomem *)io_p2v(0x40E00004))
482 +#define GPIO2_BASE ((void __iomem *)io_p2v(0x40E00008))
483 +#define GPIO3_BASE ((void __iomem *)io_p2v(0x40E00100))
485 +#define GPLR_OFFSET 0x00
486 +#define GPDR_OFFSET 0x0C
487 +#define GPSR_OFFSET 0x18
488 +#define GPCR_OFFSET 0x24
489 +#define GRER_OFFSET 0x30
490 +#define GFER_OFFSET 0x3C
491 +#define GEDR_OFFSET 0x48
493 #define GPLR0 __REG(0x40E00000) /* GPIO Pin-Level Register GPIO<31:0> */
494 #define GPLR1 __REG(0x40E00004) /* GPIO Pin-Level Register GPIO<63:32> */
495 #define GPLR2 __REG(0x40E00008) /* GPIO Pin-Level Register GPIO<80:64> */