From 067455aa53a55404ded85227e87436478c2acc63 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 26 Nov 2008 18:12:04 +0800 Subject: [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 Signed-off-by: Eric Miao --- arch/arm/mach-pxa/gpio.c | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'arch/arm/mach-pxa/gpio.c') 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 { int pxa_last_gpio; +#ifdef CONFIG_CPU_PXA26x +/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static int __gpio_is_inverted(unsigned gpio) +{ + return cpu_is_pxa25x() && gpio > 85; +} +#else +#define __gpio_is_inverted(gpio) (0) +#endif + /* * Configure pins for GPIO or other functions */ @@ -75,7 +87,10 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) gpdr = pxa->regbase + GPDR_OFFSET; local_irq_save(flags); value = __raw_readl(gpdr); - value &= ~mask; + if (__gpio_is_inverted(chip->base + offset)) + value |= mask; + else + value &= ~mask; __raw_writel(value, gpdr); local_irq_restore(flags); @@ -97,7 +112,10 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, gpdr = pxa->regbase + GPDR_OFFSET; local_irq_save(flags); tmp = __raw_readl(gpdr); - tmp |= mask; + if (__gpio_is_inverted(chip->base + offset)) + tmp &= ~mask; + else + tmp |= mask; __raw_writel(tmp, gpdr); local_irq_restore(flags); @@ -173,10 +191,17 @@ static unsigned long GPIO_IRQ_mask[4]; */ static int __gpio_is_occupied(unsigned gpio) { - if (cpu_is_pxa25x() || cpu_is_pxa27x()) - return GAFR(gpio) & (0x3 << (((gpio) & 0xf) * 2)); - else - return 0; + if (cpu_is_pxa27x() || cpu_is_pxa25x()) { + int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; + int dir = GPDR(gpio) & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + return af != 1 || dir == 0; + else + return af != 0 || dir != 0; + } + + return 0; } static 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) /* Don't mess with enabled GPIOs using preconfigured edges or * GPIOs set to alternate function or to output during probe */ - if ((GPIO_IRQ_rising_edge[idx] | - GPIO_IRQ_falling_edge[idx] | - GPDR(gpio)) & GPIO_bit(gpio)) + if ((GPIO_IRQ_rising_edge[idx] & GPIO_bit(gpio)) || + (GPIO_IRQ_falling_edge[idx] & GPIO_bit(gpio))) return 0; if (__gpio_is_occupied(gpio)) @@ -201,7 +225,10 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } - GPDR(gpio) &= ~GPIO_bit(gpio); + if (__gpio_is_inverted(gpio)) + GPDR(gpio) |= GPIO_bit(gpio); + else + GPDR(gpio) &= ~GPIO_bit(gpio); if (type & IRQ_TYPE_EDGE_RISING) __set_bit(gpio, GPIO_IRQ_rising_edge); -- cgit v1.2.3 From f1647e4c068139b5f6c988b0862eb1d233dfffe2 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 28 Nov 2008 14:54:39 +0800 Subject: [ARM] pxa: move GPIOx_BASE and GPIO register offsets to gpio.c Signed-off-by: Eric Miao --- arch/arm/mach-pxa/gpio.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/arm/mach-pxa/gpio.c') diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c index 843144ff1f61..5fec1e479cb3 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/mach-pxa/gpio.c @@ -25,6 +25,18 @@ #include "generic.h" +#define GPIO0_BASE ((void __iomem *)io_p2v(0x40E00000)) +#define GPIO1_BASE ((void __iomem *)io_p2v(0x40E00004)) +#define GPIO2_BASE ((void __iomem *)io_p2v(0x40E00008)) +#define GPIO3_BASE ((void __iomem *)io_p2v(0x40E00100)) + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 struct pxa_gpio_chip { struct gpio_chip chip; -- cgit v1.2.3