aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/arm/mach-pxa/Kconfig6
-rw-r--r--arch/arm/mach-pxa/gpio.c47
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa25x.h31
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c19
-rw-r--r--arch/arm/mach-pxa/pxa25x.c8
5 files changed, 95 insertions, 16 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index a062235e83a8..6c59f989a61a 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -394,6 +394,12 @@ config PXA27x
394 help 394 help
395 Select code specific to PXA27x variants 395 Select code specific to PXA27x variants
396 396
397config CPU_PXA26x
398 bool
399 select PXA25x
400 help
401 Select code specific to PXA26x (codename Dalhart)
402
397config PXA3xx 403config PXA3xx
398 bool 404 bool
399 help 405 help
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);
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
index 617cab2cc8d0..a72869b73ee3 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
@@ -158,4 +158,35 @@
158#define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW) 158#define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW)
159#define GPIO77_LCD_BIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW) 159#define GPIO77_LCD_BIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW)
160 160
161#ifdef CONFIG_CPU_PXA26x
162/* GPIO */
163#define GPIO85_GPIO MFP_CFG_IN(GPIO85, AF0)
164#define GPIO86_GPIO MFP_CFG_IN(GPIO86, AF1)
165#define GPIO87_GPIO MFP_CFG_IN(GPIO87, AF1)
166#define GPIO88_GPIO MFP_CFG_IN(GPIO88, AF1)
167#define GPIO89_GPIO MFP_CFG_IN(GPIO89, AF1)
168
169/* SDRAM */
170#define GPIO86_nSDCS2 MFP_CFG_OUT(GPIO86, AF0, DRIVE_HIGH)
171#define GPIO87_nSDCS3 MFP_CFG_OUT(GPIO87, AF0, DRIVE_HIGH)
172#define GPIO88_RDnWR MFP_CFG_OUT(GPIO88, AF0, DRIVE_HIGH)
173#define GPIO89_nACRESET MFP_CFG_OUT(GPIO89, AF0, DRIVE_HIGH)
174
175/* USB */
176#define GPIO9_USB_RCV MFP_CFG_IN(GPIO9, AF1)
177#define GPIO32_USB_VP MFP_CFG_IN(GPIO32, AF2)
178#define GPIO34_USB_VM MFP_CFG_IN(GPIO34, AF2)
179#define GPIO39_USB_VPO MFP_CFG_OUT(GPIO39, AF3, DRIVE_LOW)
180#define GPIO56_USB_VMO MFP_CFG_OUT(GPIO56, AF1, DRIVE_LOW)
181#define GPIO57_USB_nOE MFP_CFG_OUT(GPIO57, AF1, DRIVE_HIGH)
182
183/* ASSP */
184#define GPIO28_ASSP_BITCLK_IN MFP_CFG_IN(GPIO28, AF3)
185#define GPIO28_ASSP_BITCLK_OUT MFP_CFG_OUT(GPIO28, AF3, DRIVE_LOW)
186#define GPIO29_ASSP_RXD MFP_CFG_IN(GPIO29, AF3)
187#define GPIO30_ASSP_TXD MFP_CFG_OUT(GPIO30, AF3, DRIVE_LOW)
188#define GPIO31_ASSP_SFRM_IN MFP_CFG_IN(GPIO31, AF1)
189#define GPIO31_ASSP_SFRM_OUT MFP_CFG_OUT(GPIO31, AF3, DRIVE_LOW)
190#endif
191
161#endif /* __ASM_ARCH_MFP_PXA25X_H */ 192#endif /* __ASM_ARCH_MFP_PXA25X_H */
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index 1f2298759077..33626de8cbf6 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -38,6 +38,7 @@ struct gpio_desc {
38 unsigned valid : 1; 38 unsigned valid : 1;
39 unsigned can_wakeup : 1; 39 unsigned can_wakeup : 1;
40 unsigned keypad_gpio : 1; 40 unsigned keypad_gpio : 1;
41 unsigned dir_inverted : 1;
41 unsigned int mask; /* bit mask in PWER or PKWR */ 42 unsigned int mask; /* bit mask in PWER or PKWR */
42 unsigned int mux_mask; /* bit mask of muxed gpio bits, 0 if no mux */ 43 unsigned int mux_mask; /* bit mask of muxed gpio bits, 0 if no mux */
43 unsigned long config; 44 unsigned long config;
@@ -54,7 +55,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
54 int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */ 55 int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */
55 int shft = (gpio & 0xf) << 1; 56 int shft = (gpio & 0xf) << 1;
56 int fn = MFP_AF(c); 57 int fn = MFP_AF(c);
57 int dir = c & MFP_DIR_OUT; 58 int is_out = (c & MFP_DIR_OUT) ? 1 : 0;
58 59
59 if (fn > 3) 60 if (fn > 3)
60 return -EINVAL; 61 return -EINVAL;
@@ -68,7 +69,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
68 else 69 else
69 GAFR_U(bank) = gafr; 70 GAFR_U(bank) = gafr;
70 71
71 if (dir == MFP_DIR_OUT) 72 if (is_out ^ gpio_desc[gpio].dir_inverted)
72 GPDR(gpio) |= mask; 73 GPDR(gpio) |= mask;
73 else 74 else
74 GPDR(gpio) &= ~mask; 75 GPDR(gpio) &= ~mask;
@@ -77,11 +78,11 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
77 switch (c & MFP_LPM_STATE_MASK) { 78 switch (c & MFP_LPM_STATE_MASK) {
78 case MFP_LPM_DRIVE_HIGH: 79 case MFP_LPM_DRIVE_HIGH:
79 PGSR(bank) |= mask; 80 PGSR(bank) |= mask;
80 dir = MFP_DIR_OUT; 81 is_out = 1;
81 break; 82 break;
82 case MFP_LPM_DRIVE_LOW: 83 case MFP_LPM_DRIVE_LOW:
83 PGSR(bank) &= ~mask; 84 PGSR(bank) &= ~mask;
84 dir = MFP_DIR_OUT; 85 is_out = 1;
85 break; 86 break;
86 case MFP_LPM_DEFAULT: 87 case MFP_LPM_DEFAULT:
87 break; 88 break;
@@ -92,7 +93,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
92 break; 93 break;
93 } 94 }
94 95
95 if (dir == MFP_DIR_OUT) 96 if (is_out ^ gpio_desc[gpio].dir_inverted)
96 gpdr_lpm[bank] |= mask; 97 gpdr_lpm[bank] |= mask;
97 else 98 else
98 gpdr_lpm[bank] &= ~mask; 99 gpdr_lpm[bank] &= ~mask;
@@ -106,7 +107,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
106 return -EINVAL; 107 return -EINVAL;
107 } 108 }
108 109
109 if ((c & MFP_LPM_CAN_WAKEUP) && (dir == MFP_DIR_OUT)) { 110 if ((c & MFP_LPM_CAN_WAKEUP) && is_out) {
110 pr_warning("%s: output GPIO%d unable to wakeup\n", 111 pr_warning("%s: output GPIO%d unable to wakeup\n",
111 __func__, gpio); 112 __func__, gpio);
112 return -EINVAL; 113 return -EINVAL;
@@ -221,6 +222,12 @@ static void __init pxa25x_mfp_init(void)
221 gpio_desc[i].can_wakeup = 1; 222 gpio_desc[i].can_wakeup = 1;
222 gpio_desc[i].mask = GPIO_bit(i); 223 gpio_desc[i].mask = GPIO_bit(i);
223 } 224 }
225
226 /* PXA26x has additional 4 GPIOs (86/87/88/89) which has the
227 * direction bit inverted in GPDR2. See PXA26x DM 4.1.1.
228 */
229 for (i = 86; i <= pxa_last_gpio; i++)
230 gpio_desc[i].dir_inverted = 1;
224} 231}
225#else 232#else
226static inline void pxa25x_mfp_init(void) {} 233static inline void pxa25x_mfp_init(void) {}
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 6543321a2df4..0f672998b2eb 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -298,6 +298,14 @@ void __init pxa25x_init_irq(void)
298 pxa_init_gpio(85, pxa25x_set_wake); 298 pxa_init_gpio(85, pxa25x_set_wake);
299} 299}
300 300
301#ifdef CONFIG_CPU_PXA26x
302void __init pxa26x_init_irq(void)
303{
304 pxa_init_irq(32, pxa25x_set_wake);
305 pxa_init_gpio(90, pxa25x_set_wake);
306}
307#endif
308
301static struct platform_device *pxa25x_devices[] __initdata = { 309static struct platform_device *pxa25x_devices[] __initdata = {
302 &pxa25x_device_udc, 310 &pxa25x_device_udc,
303 &pxa_device_ffuart, 311 &pxa_device_ffuart,