diff options
Diffstat (limited to 'arch/arm/mach-pxa/gpio.c')
-rw-r--r-- | arch/arm/mach-pxa/gpio.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c index 14930cf8be7b..5fec1e479cb3 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/mach-pxa/gpio.c | |||
@@ -25,6 +25,18 @@ | |||
25 | 25 | ||
26 | #include "generic.h" | 26 | #include "generic.h" |
27 | 27 | ||
28 | #define GPIO0_BASE ((void __iomem *)io_p2v(0x40E00000)) | ||
29 | #define GPIO1_BASE ((void __iomem *)io_p2v(0x40E00004)) | ||
30 | #define GPIO2_BASE ((void __iomem *)io_p2v(0x40E00008)) | ||
31 | #define GPIO3_BASE ((void __iomem *)io_p2v(0x40E00100)) | ||
32 | |||
33 | #define GPLR_OFFSET 0x00 | ||
34 | #define GPDR_OFFSET 0x0C | ||
35 | #define GPSR_OFFSET 0x18 | ||
36 | #define GPCR_OFFSET 0x24 | ||
37 | #define GRER_OFFSET 0x30 | ||
38 | #define GFER_OFFSET 0x3C | ||
39 | #define GEDR_OFFSET 0x48 | ||
28 | 40 | ||
29 | struct pxa_gpio_chip { | 41 | struct pxa_gpio_chip { |
30 | struct gpio_chip chip; | 42 | struct gpio_chip chip; |
@@ -33,6 +45,18 @@ struct pxa_gpio_chip { | |||
33 | 45 | ||
34 | int pxa_last_gpio; | 46 | int pxa_last_gpio; |
35 | 47 | ||
48 | #ifdef CONFIG_CPU_PXA26x | ||
49 | /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, | ||
50 | * as well as their Alternate Function value being '1' for GPIO in GAFRx. | ||
51 | */ | ||
52 | static int __gpio_is_inverted(unsigned gpio) | ||
53 | { | ||
54 | return cpu_is_pxa25x() && gpio > 85; | ||
55 | } | ||
56 | #else | ||
57 | #define __gpio_is_inverted(gpio) (0) | ||
58 | #endif | ||
59 | |||
36 | /* | 60 | /* |
37 | * Configure pins for GPIO or other functions | 61 | * Configure pins for GPIO or other functions |
38 | */ | 62 | */ |
@@ -75,7 +99,10 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |||
75 | gpdr = pxa->regbase + GPDR_OFFSET; | 99 | gpdr = pxa->regbase + GPDR_OFFSET; |
76 | local_irq_save(flags); | 100 | local_irq_save(flags); |
77 | value = __raw_readl(gpdr); | 101 | value = __raw_readl(gpdr); |
78 | value &= ~mask; | 102 | if (__gpio_is_inverted(chip->base + offset)) |
103 | value |= mask; | ||
104 | else | ||
105 | value &= ~mask; | ||
79 | __raw_writel(value, gpdr); | 106 | __raw_writel(value, gpdr); |
80 | local_irq_restore(flags); | 107 | local_irq_restore(flags); |
81 | 108 | ||
@@ -97,7 +124,10 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, | |||
97 | gpdr = pxa->regbase + GPDR_OFFSET; | 124 | gpdr = pxa->regbase + GPDR_OFFSET; |
98 | local_irq_save(flags); | 125 | local_irq_save(flags); |
99 | tmp = __raw_readl(gpdr); | 126 | tmp = __raw_readl(gpdr); |
100 | tmp |= mask; | 127 | if (__gpio_is_inverted(chip->base + offset)) |
128 | tmp &= ~mask; | ||
129 | else | ||
130 | tmp |= mask; | ||
101 | __raw_writel(tmp, gpdr); | 131 | __raw_writel(tmp, gpdr); |
102 | local_irq_restore(flags); | 132 | local_irq_restore(flags); |
103 | 133 | ||
@@ -173,10 +203,17 @@ static unsigned long GPIO_IRQ_mask[4]; | |||
173 | */ | 203 | */ |
174 | static int __gpio_is_occupied(unsigned gpio) | 204 | static int __gpio_is_occupied(unsigned gpio) |
175 | { | 205 | { |
176 | if (cpu_is_pxa25x() || cpu_is_pxa27x()) | 206 | if (cpu_is_pxa27x() || cpu_is_pxa25x()) { |
177 | return GAFR(gpio) & (0x3 << (((gpio) & 0xf) * 2)); | 207 | int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; |
178 | else | 208 | int dir = GPDR(gpio) & GPIO_bit(gpio); |
179 | return 0; | 209 | |
210 | if (__gpio_is_inverted(gpio)) | ||
211 | return af != 1 || dir == 0; | ||
212 | else | ||
213 | return af != 0 || dir != 0; | ||
214 | } | ||
215 | |||
216 | return 0; | ||
180 | } | 217 | } |
181 | 218 | ||
182 | static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | 219 | static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) |
@@ -190,9 +227,8 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | |||
190 | /* Don't mess with enabled GPIOs using preconfigured edges or | 227 | /* Don't mess with enabled GPIOs using preconfigured edges or |
191 | * GPIOs set to alternate function or to output during probe | 228 | * GPIOs set to alternate function or to output during probe |
192 | */ | 229 | */ |
193 | if ((GPIO_IRQ_rising_edge[idx] | | 230 | if ((GPIO_IRQ_rising_edge[idx] & GPIO_bit(gpio)) || |
194 | GPIO_IRQ_falling_edge[idx] | | 231 | (GPIO_IRQ_falling_edge[idx] & GPIO_bit(gpio))) |
195 | GPDR(gpio)) & GPIO_bit(gpio)) | ||
196 | return 0; | 232 | return 0; |
197 | 233 | ||
198 | if (__gpio_is_occupied(gpio)) | 234 | if (__gpio_is_occupied(gpio)) |
@@ -201,7 +237,10 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | |||
201 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | 237 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; |
202 | } | 238 | } |
203 | 239 | ||
204 | GPDR(gpio) &= ~GPIO_bit(gpio); | 240 | if (__gpio_is_inverted(gpio)) |
241 | GPDR(gpio) |= GPIO_bit(gpio); | ||
242 | else | ||
243 | GPDR(gpio) &= ~GPIO_bit(gpio); | ||
205 | 244 | ||
206 | if (type & IRQ_TYPE_EDGE_RISING) | 245 | if (type & IRQ_TYPE_EDGE_RISING) |
207 | __set_bit(gpio, GPIO_IRQ_rising_edge); | 246 | __set_bit(gpio, GPIO_IRQ_rising_edge); |