diff options
-rw-r--r-- | arch/arm/mach-pxa/Kconfig | 6 | ||||
-rw-r--r-- | arch/arm/mach-pxa/gpio.c | 47 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | 31 | ||||
-rw-r--r-- | arch/arm/mach-pxa/mfp-pxa2xx.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 8 |
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 | ||
397 | config CPU_PXA26x | ||
398 | bool | ||
399 | select PXA25x | ||
400 | help | ||
401 | Select code specific to PXA26x (codename Dalhart) | ||
402 | |||
397 | config PXA3xx | 403 | config 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 | ||
34 | int pxa_last_gpio; | 34 | int 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 | */ | ||
40 | static 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 | */ |
174 | static int __gpio_is_occupied(unsigned gpio) | 192 | static 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 | ||
182 | static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | 207 | 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) | |||
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 |
226 | static inline void pxa25x_mfp_init(void) {} | 233 | static 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 | ||
302 | void __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 | |||
301 | static struct platform_device *pxa25x_devices[] __initdata = { | 309 | static struct platform_device *pxa25x_devices[] __initdata = { |
302 | &pxa25x_device_udc, | 310 | &pxa25x_device_udc, |
303 | &pxa_device_ffuart, | 311 | &pxa_device_ffuart, |