aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/gpio.c
diff options
context:
space:
mode:
authorEric Miao <eric.miao@marvell.com>2008-11-26 05:12:04 -0500
committerEric Miao <eric.miao@marvell.com>2008-12-02 01:42:37 -0500
commit067455aa53a55404ded85227e87436478c2acc63 (patch)
tree44e1deef3e364e45199cdd7abade384bde6e6164 /arch/arm/mach-pxa/gpio.c
parente88db8b91f1f5de24ae6bb3241d92fecaae64abf (diff)
[ARM] pxa: add support for additional GPIOs on PXA26x
Original patch from Marek Vasut, the problems with PXA26x are: 1. there are additional 4 GPIOs 86,87,88,89 have their direction bits inverted in GPDR2, as well as their alternate function bits being '1' for their GPIO functionality in GAFRx 2. there is no easy way to decide if the processor is a pxa26x or a pxa250/pxa255 at run-time, so the assumption here is the pxa26x will be treated as one of the pxa25x variants, and board code should have a better knowledge of the processor it is featured Introduce pxa26x_init_irq() for the second purpose, and treat the additional GPIOs > 85 on PXA25x specially. Kconfig option CONFIG_CPU_PXA26x is introduced to optimize the code a bit when PXA26x support isn't needed. Board config options have to select this to enable the support for PXA26x. __gpio_is_inverted() will be optimized way when CONFIG_CPU_PXA26x isn't selected. Signed-off-by: Marek Vasut <marek.vasut@gmail.com> Signed-off-by: Eric Miao <eric.miao@marvell.com>
Diffstat (limited to 'arch/arm/mach-pxa/gpio.c')
-rw-r--r--arch/arm/mach-pxa/gpio.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
index 14930cf8be7b..843144ff1f61 100644
--- a/arch/arm/mach-pxa/gpio.c
+++ b/arch/arm/mach-pxa/gpio.c
@@ -33,6 +33,18 @@ struct pxa_gpio_chip {
33 33
34int pxa_last_gpio; 34int pxa_last_gpio;
35 35
36#ifdef CONFIG_CPU_PXA26x
37/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
38 * as well as their Alternate Function value being '1' for GPIO in GAFRx.
39 */
40static int __gpio_is_inverted(unsigned gpio)
41{
42 return cpu_is_pxa25x() && gpio > 85;
43}
44#else
45#define __gpio_is_inverted(gpio) (0)
46#endif
47
36/* 48/*
37 * Configure pins for GPIO or other functions 49 * Configure pins for GPIO or other functions
38 */ 50 */
@@ -75,7 +87,10 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
75 gpdr = pxa->regbase + GPDR_OFFSET; 87 gpdr = pxa->regbase + GPDR_OFFSET;
76 local_irq_save(flags); 88 local_irq_save(flags);
77 value = __raw_readl(gpdr); 89 value = __raw_readl(gpdr);
78 value &= ~mask; 90 if (__gpio_is_inverted(chip->base + offset))
91 value |= mask;
92 else
93 value &= ~mask;
79 __raw_writel(value, gpdr); 94 __raw_writel(value, gpdr);
80 local_irq_restore(flags); 95 local_irq_restore(flags);
81 96
@@ -97,7 +112,10 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,
97 gpdr = pxa->regbase + GPDR_OFFSET; 112 gpdr = pxa->regbase + GPDR_OFFSET;
98 local_irq_save(flags); 113 local_irq_save(flags);
99 tmp = __raw_readl(gpdr); 114 tmp = __raw_readl(gpdr);
100 tmp |= mask; 115 if (__gpio_is_inverted(chip->base + offset))
116 tmp &= ~mask;
117 else
118 tmp |= mask;
101 __raw_writel(tmp, gpdr); 119 __raw_writel(tmp, gpdr);
102 local_irq_restore(flags); 120 local_irq_restore(flags);
103 121
@@ -173,10 +191,17 @@ static unsigned long GPIO_IRQ_mask[4];
173 */ 191 */
174static int __gpio_is_occupied(unsigned gpio) 192static int __gpio_is_occupied(unsigned gpio)
175{ 193{
176 if (cpu_is_pxa25x() || cpu_is_pxa27x()) 194 if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
177 return GAFR(gpio) & (0x3 << (((gpio) & 0xf) * 2)); 195 int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
178 else 196 int dir = GPDR(gpio) & GPIO_bit(gpio);
179 return 0; 197
198 if (__gpio_is_inverted(gpio))
199 return af != 1 || dir == 0;
200 else
201 return af != 0 || dir != 0;
202 }
203
204 return 0;
180} 205}
181 206
182static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) 207static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
@@ -190,9 +215,8 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
190 /* Don't mess with enabled GPIOs using preconfigured edges or 215 /* Don't mess with enabled GPIOs using preconfigured edges or
191 * GPIOs set to alternate function or to output during probe 216 * GPIOs set to alternate function or to output during probe
192 */ 217 */
193 if ((GPIO_IRQ_rising_edge[idx] | 218 if ((GPIO_IRQ_rising_edge[idx] & GPIO_bit(gpio)) ||
194 GPIO_IRQ_falling_edge[idx] | 219 (GPIO_IRQ_falling_edge[idx] & GPIO_bit(gpio)))
195 GPDR(gpio)) & GPIO_bit(gpio))
196 return 0; 220 return 0;
197 221
198 if (__gpio_is_occupied(gpio)) 222 if (__gpio_is_occupied(gpio))
@@ -201,7 +225,10 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
201 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; 225 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
202 } 226 }
203 227
204 GPDR(gpio) &= ~GPIO_bit(gpio); 228 if (__gpio_is_inverted(gpio))
229 GPDR(gpio) |= GPIO_bit(gpio);
230 else
231 GPDR(gpio) &= ~GPIO_bit(gpio);
205 232
206 if (type & IRQ_TYPE_EDGE_RISING) 233 if (type & IRQ_TYPE_EDGE_RISING)
207 __set_bit(gpio, GPIO_IRQ_rising_edge); 234 __set_bit(gpio, GPIO_IRQ_rising_edge);