diff options
author | Eric Miao <eric.miao@marvell.com> | 2008-11-26 05:12:04 -0500 |
---|---|---|
committer | Eric Miao <eric.miao@marvell.com> | 2008-12-02 01:42:37 -0500 |
commit | 067455aa53a55404ded85227e87436478c2acc63 (patch) | |
tree | 44e1deef3e364e45199cdd7abade384bde6e6164 /arch/arm/mach-pxa/mfp-pxa2xx.c | |
parent | e88db8b91f1f5de24ae6bb3241d92fecaae64abf (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>
Diffstat (limited to 'arch/arm/mach-pxa/mfp-pxa2xx.c')
-rw-r--r-- | arch/arm/mach-pxa/mfp-pxa2xx.c | 19 |
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 |
226 | static inline void pxa25x_mfp_init(void) {} | 233 | static inline void pxa25x_mfp_init(void) {} |