aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/mfp-pxa2xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa/mfp-pxa2xx.c')
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c19
1 files changed, 13 insertions, 6 deletions
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) {}