diff options
author | Eric Miao <eric.miao@marvell.com> | 2009-01-15 03:42:56 -0500 |
---|---|---|
committer | Eric Miao <eric.miao@marvell.com> | 2009-03-22 22:11:34 -0400 |
commit | f8dec04d33b94a4cfa9358fd9666c01480bb164d (patch) | |
tree | bcf82252230a757f26d6de980749b9e4395cd8b9 /arch/arm | |
parent | 38f539a608c9a3b40b30f1892bd5f9a38f4e5ffe (diff) |
[ARM] pxa: move common MFP handling code into plat-pxa
Signed-off-by: Eric Miao <eric.miao@marvell.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa300.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa320.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h | 130 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa930.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/mfp-pxa3xx.c | 189 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa300.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa320.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa930.c | 6 | ||||
-rw-r--r-- | arch/arm/plat-pxa/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-pxa/include/plat/mfp.h | 369 | ||||
-rw-r--r-- | arch/arm/plat-pxa/mfp.c | 278 |
14 files changed, 680 insertions, 317 deletions
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h index a72869b73ee3..b13dc0269a6d 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | |||
@@ -1,7 +1,6 @@ | |||
1 | #ifndef __ASM_ARCH_MFP_PXA25X_H | 1 | #ifndef __ASM_ARCH_MFP_PXA25X_H |
2 | #define __ASM_ARCH_MFP_PXA25X_H | 2 | #define __ASM_ARCH_MFP_PXA25X_H |
3 | 3 | ||
4 | #include <mach/mfp.h> | ||
5 | #include <mach/mfp-pxa2xx.h> | 4 | #include <mach/mfp-pxa2xx.h> |
6 | 5 | ||
7 | /* GPIO */ | 6 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index da4f85a4f990..6543c05f47ed 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | |||
@@ -8,7 +8,6 @@ | |||
8 | * specific controller, and this should work in most cases. | 8 | * specific controller, and this should work in most cases. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <mach/mfp.h> | ||
12 | #include <mach/mfp-pxa2xx.h> | 11 | #include <mach/mfp-pxa2xx.h> |
13 | 12 | ||
14 | /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN | 13 | /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index 3e9211591e20..658b28ed129b 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __ASM_ARCH_MFP_PXA2XX_H | 1 | #ifndef __ASM_ARCH_MFP_PXA2XX_H |
2 | #define __ASM_ARCH_MFP_PXA2XX_H | 2 | #define __ASM_ARCH_MFP_PXA2XX_H |
3 | 3 | ||
4 | #include <mach/mfp.h> | 4 | #include <plat/mfp.h> |
5 | 5 | ||
6 | /* | 6 | /* |
7 | * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: | 7 | * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index 928fbef9cbf3..ae8441192ef0 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h | |||
@@ -15,7 +15,6 @@ | |||
15 | #ifndef __ASM_ARCH_MFP_PXA300_H | 15 | #ifndef __ASM_ARCH_MFP_PXA300_H |
16 | #define __ASM_ARCH_MFP_PXA300_H | 16 | #define __ASM_ARCH_MFP_PXA300_H |
17 | 17 | ||
18 | #include <mach/mfp.h> | ||
19 | #include <mach/mfp-pxa3xx.h> | 18 | #include <mach/mfp-pxa3xx.h> |
20 | 19 | ||
21 | /* GPIO */ | 20 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h index 80a0da9e092d..07897e61d05a 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h | |||
@@ -15,7 +15,6 @@ | |||
15 | #ifndef __ASM_ARCH_MFP_PXA320_H | 15 | #ifndef __ASM_ARCH_MFP_PXA320_H |
16 | #define __ASM_ARCH_MFP_PXA320_H | 16 | #define __ASM_ARCH_MFP_PXA320_H |
17 | 17 | ||
18 | #include <mach/mfp.h> | ||
19 | #include <mach/mfp-pxa3xx.h> | 18 | #include <mach/mfp-pxa3xx.h> |
20 | 19 | ||
21 | /* GPIO */ | 20 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h index 1f6b35c015d0..d375195d982b 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h | |||
@@ -1,68 +1,9 @@ | |||
1 | #ifndef __ASM_ARCH_MFP_PXA3XX_H | 1 | #ifndef __ASM_ARCH_MFP_PXA3XX_H |
2 | #define __ASM_ARCH_MFP_PXA3XX_H | 2 | #define __ASM_ARCH_MFP_PXA3XX_H |
3 | 3 | ||
4 | #define MFPR_BASE (0x40e10000) | 4 | #include <plat/mfp.h> |
5 | #define MFPR_SIZE (PAGE_SIZE) | ||
6 | |||
7 | /* MFPR register bit definitions */ | ||
8 | #define MFPR_PULL_SEL (0x1 << 15) | ||
9 | #define MFPR_PULLUP_EN (0x1 << 14) | ||
10 | #define MFPR_PULLDOWN_EN (0x1 << 13) | ||
11 | #define MFPR_SLEEP_SEL (0x1 << 9) | ||
12 | #define MFPR_SLEEP_OE_N (0x1 << 7) | ||
13 | #define MFPR_EDGE_CLEAR (0x1 << 6) | ||
14 | #define MFPR_EDGE_FALL_EN (0x1 << 5) | ||
15 | #define MFPR_EDGE_RISE_EN (0x1 << 4) | ||
16 | |||
17 | #define MFPR_SLEEP_DATA(x) ((x) << 8) | ||
18 | #define MFPR_DRIVE(x) (((x) & 0x7) << 10) | ||
19 | #define MFPR_AF_SEL(x) (((x) & 0x7) << 0) | ||
20 | 5 | ||
21 | #define MFPR_EDGE_NONE (0) | 6 | #define MFPR_BASE (0x40e10000) |
22 | #define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) | ||
23 | #define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) | ||
24 | #define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) | ||
25 | |||
26 | /* | ||
27 | * Table that determines the low power modes outputs, with actual settings | ||
28 | * used in parentheses for don't-care values. Except for the float output, | ||
29 | * the configured driven and pulled levels match, so if there is a need for | ||
30 | * non-LPM pulled output, the same configuration could probably be used. | ||
31 | * | ||
32 | * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel | ||
33 | * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) | ||
34 | * | ||
35 | * Input 0 X(0) X(0) X(0) 0 | ||
36 | * Drive 0 0 0 0 X(1) 0 | ||
37 | * Drive 1 0 1 X(1) 0 0 | ||
38 | * Pull hi (1) 1 X(1) 1 0 0 | ||
39 | * Pull lo (0) 1 X(0) 0 1 0 | ||
40 | * Z (float) 1 X(0) 0 0 0 | ||
41 | */ | ||
42 | #define MFPR_LPM_INPUT (0) | ||
43 | #define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) | ||
44 | #define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) | ||
45 | #define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) | ||
46 | #define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) | ||
47 | #define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) | ||
48 | #define MFPR_LPM_MASK (0xe080) | ||
49 | |||
50 | /* | ||
51 | * The pullup and pulldown state of the MFP pin at run mode is by default | ||
52 | * determined by the selected alternate function. In case that some buggy | ||
53 | * devices need to override this default behavior, the definitions below | ||
54 | * indicates the setting of corresponding MFPR bits | ||
55 | * | ||
56 | * Definition pull_sel pullup_en pulldown_en | ||
57 | * MFPR_PULL_NONE 0 0 0 | ||
58 | * MFPR_PULL_LOW 1 0 1 | ||
59 | * MFPR_PULL_HIGH 1 1 0 | ||
60 | * MFPR_PULL_BOTH 1 1 1 | ||
61 | */ | ||
62 | #define MFPR_PULL_NONE (0) | ||
63 | #define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) | ||
64 | #define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) | ||
65 | #define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) | ||
66 | 7 | ||
67 | /* PXA3xx common MFP configurations - processor specific ones defined | 8 | /* PXA3xx common MFP configurations - processor specific ones defined |
68 | * in mfp-pxa300.h and mfp-pxa320.h | 9 | * in mfp-pxa300.h and mfp-pxa320.h |
@@ -197,56 +138,21 @@ | |||
197 | #define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0) | 138 | #define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0) |
198 | #define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0) | 139 | #define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0) |
199 | 140 | ||
200 | /* | 141 | /* NOTE: usage of these two functions is not recommended, |
201 | * each MFP pin will have a MFPR register, since the offset of the | 142 | * use pxa3xx_mfp_config() instead. |
202 | * register varies between processors, the processor specific code | ||
203 | * should initialize the pin offsets by pxa3xx_mfp_init_addr() | ||
204 | * | ||
205 | * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map" | ||
206 | * structure, which represents a range of MFP pins from "start" to | ||
207 | * "end", with the offset begining at "offset", to define a single | ||
208 | * pin, let "end" = -1 | ||
209 | * | ||
210 | * use | ||
211 | * | ||
212 | * MFP_ADDR_X() to define a range of pins | ||
213 | * MFP_ADDR() to define a single pin | ||
214 | * MFP_ADDR_END to signal the end of pin offset definitions | ||
215 | */ | ||
216 | struct pxa3xx_mfp_addr_map { | ||
217 | unsigned int start; | ||
218 | unsigned int end; | ||
219 | unsigned long offset; | ||
220 | }; | ||
221 | |||
222 | #define MFP_ADDR_X(start, end, offset) \ | ||
223 | { MFP_PIN_##start, MFP_PIN_##end, offset } | ||
224 | |||
225 | #define MFP_ADDR(pin, offset) \ | ||
226 | { MFP_PIN_##pin, -1, offset } | ||
227 | |||
228 | #define MFP_ADDR_END { MFP_PIN_INVALID, 0 } | ||
229 | |||
230 | /* | ||
231 | * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access | ||
232 | * to the MFPR register | ||
233 | */ | ||
234 | unsigned long pxa3xx_mfp_read(int mfp); | ||
235 | void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val); | ||
236 | |||
237 | /* | ||
238 | * pxa3xx_mfp_config - configure the MFPR registers | ||
239 | * | ||
240 | * used by board specific initialization code | ||
241 | */ | ||
242 | void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num); | ||
243 | |||
244 | /* | ||
245 | * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin | ||
246 | * index and MFPR register offset | ||
247 | * | ||
248 | * used by processor specific code | ||
249 | */ | 143 | */ |
250 | void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *); | 144 | static inline unsigned long pxa3xx_mfp_read(int mfp) |
251 | void __init pxa3xx_init_mfp(void); | 145 | { |
146 | return mfp_read(mfp); | ||
147 | } | ||
148 | |||
149 | static inline void pxa3xx_mfp_write(int mfp, unsigned long val) | ||
150 | { | ||
151 | mfp_write(mfp, val); | ||
152 | } | ||
153 | |||
154 | static inline void pxa3xx_mfp_config(unsigned long *mfp_cfg, int num) | ||
155 | { | ||
156 | mfp_config(mfp_cfg, num); | ||
157 | } | ||
252 | #endif /* __ASM_ARCH_MFP_PXA3XX_H */ | 158 | #endif /* __ASM_ARCH_MFP_PXA3XX_H */ |
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h index fa73f56a1372..0d119d3b9221 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h | |||
@@ -13,7 +13,6 @@ | |||
13 | #ifndef __ASM_ARCH_MFP_PXA9xx_H | 13 | #ifndef __ASM_ARCH_MFP_PXA9xx_H |
14 | #define __ASM_ARCH_MFP_PXA9xx_H | 14 | #define __ASM_ARCH_MFP_PXA9xx_H |
15 | 15 | ||
16 | #include <mach/mfp.h> | ||
17 | #include <mach/mfp-pxa3xx.h> | 16 | #include <mach/mfp-pxa3xx.h> |
18 | 17 | ||
19 | /* GPIO */ | 18 | /* GPIO */ |
diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c index eb197a6e8e94..7a270eecd480 100644 --- a/arch/arm/mach-pxa/mfp-pxa3xx.c +++ b/arch/arm/mach-pxa/mfp-pxa3xx.c | |||
@@ -20,183 +20,9 @@ | |||
20 | #include <linux/sysdev.h> | 20 | #include <linux/sysdev.h> |
21 | 21 | ||
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | #include <mach/mfp.h> | ||
24 | #include <mach/mfp-pxa3xx.h> | 23 | #include <mach/mfp-pxa3xx.h> |
25 | #include <mach/pxa3xx-regs.h> | 24 | #include <mach/pxa3xx-regs.h> |
26 | 25 | ||
27 | /* mfp_spin_lock is used to ensure that MFP register configuration | ||
28 | * (most likely a read-modify-write operation) is atomic, and that | ||
29 | * mfp_table[] is consistent | ||
30 | */ | ||
31 | static DEFINE_SPINLOCK(mfp_spin_lock); | ||
32 | |||
33 | static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); | ||
34 | |||
35 | struct pxa3xx_mfp_pin { | ||
36 | unsigned long config; /* -1 for not configured */ | ||
37 | unsigned long mfpr_off; /* MFPRxx Register offset */ | ||
38 | unsigned long mfpr_run; /* Run-Mode Register Value */ | ||
39 | unsigned long mfpr_lpm; /* Low Power Mode Register Value */ | ||
40 | }; | ||
41 | |||
42 | static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; | ||
43 | |||
44 | /* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ | ||
45 | static const unsigned long mfpr_lpm[] = { | ||
46 | MFPR_LPM_INPUT, | ||
47 | MFPR_LPM_DRIVE_LOW, | ||
48 | MFPR_LPM_DRIVE_HIGH, | ||
49 | MFPR_LPM_PULL_LOW, | ||
50 | MFPR_LPM_PULL_HIGH, | ||
51 | MFPR_LPM_FLOAT, | ||
52 | }; | ||
53 | |||
54 | /* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ | ||
55 | static const unsigned long mfpr_pull[] = { | ||
56 | MFPR_PULL_NONE, | ||
57 | MFPR_PULL_LOW, | ||
58 | MFPR_PULL_HIGH, | ||
59 | MFPR_PULL_BOTH, | ||
60 | }; | ||
61 | |||
62 | /* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ | ||
63 | static const unsigned long mfpr_edge[] = { | ||
64 | MFPR_EDGE_NONE, | ||
65 | MFPR_EDGE_RISE, | ||
66 | MFPR_EDGE_FALL, | ||
67 | MFPR_EDGE_BOTH, | ||
68 | }; | ||
69 | |||
70 | #define mfpr_readl(off) \ | ||
71 | __raw_readl(mfpr_mmio_base + (off)) | ||
72 | |||
73 | #define mfpr_writel(off, val) \ | ||
74 | __raw_writel(val, mfpr_mmio_base + (off)) | ||
75 | |||
76 | #define mfp_configured(p) ((p)->config != -1) | ||
77 | |||
78 | /* | ||
79 | * perform a read-back of any MFPR register to make sure the | ||
80 | * previous writings are finished | ||
81 | */ | ||
82 | #define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) | ||
83 | |||
84 | static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p) | ||
85 | { | ||
86 | if (mfp_configured(p)) | ||
87 | mfpr_writel(p->mfpr_off, p->mfpr_run); | ||
88 | } | ||
89 | |||
90 | static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) | ||
91 | { | ||
92 | if (mfp_configured(p)) { | ||
93 | unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; | ||
94 | if (mfpr_clr != p->mfpr_run) | ||
95 | mfpr_writel(p->mfpr_off, mfpr_clr); | ||
96 | if (p->mfpr_lpm != mfpr_clr) | ||
97 | mfpr_writel(p->mfpr_off, p->mfpr_lpm); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) | ||
102 | { | ||
103 | unsigned long flags; | ||
104 | int i; | ||
105 | |||
106 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
107 | |||
108 | for (i = 0; i < num; i++, mfp_cfgs++) { | ||
109 | unsigned long tmp, c = *mfp_cfgs; | ||
110 | struct pxa3xx_mfp_pin *p; | ||
111 | int pin, af, drv, lpm, edge, pull; | ||
112 | |||
113 | pin = MFP_PIN(c); | ||
114 | BUG_ON(pin >= MFP_PIN_MAX); | ||
115 | p = &mfp_table[pin]; | ||
116 | |||
117 | af = MFP_AF(c); | ||
118 | drv = MFP_DS(c); | ||
119 | lpm = MFP_LPM_STATE(c); | ||
120 | edge = MFP_LPM_EDGE(c); | ||
121 | pull = MFP_PULL(c); | ||
122 | |||
123 | /* run-mode pull settings will conflict with MFPR bits of | ||
124 | * low power mode state, calculate mfpr_run and mfpr_lpm | ||
125 | * individually if pull != MFP_PULL_NONE | ||
126 | */ | ||
127 | tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); | ||
128 | |||
129 | if (likely(pull == MFP_PULL_NONE)) { | ||
130 | p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
131 | p->mfpr_lpm = p->mfpr_run; | ||
132 | } else { | ||
133 | p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
134 | p->mfpr_run = tmp | mfpr_pull[pull]; | ||
135 | } | ||
136 | |||
137 | p->config = c; __mfp_config_run(p); | ||
138 | } | ||
139 | |||
140 | mfpr_sync(); | ||
141 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
142 | } | ||
143 | |||
144 | unsigned long pxa3xx_mfp_read(int mfp) | ||
145 | { | ||
146 | unsigned long val, flags; | ||
147 | |||
148 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
149 | |||
150 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
151 | val = mfpr_readl(mfp_table[mfp].mfpr_off); | ||
152 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
153 | |||
154 | return val; | ||
155 | } | ||
156 | |||
157 | void pxa3xx_mfp_write(int mfp, unsigned long val) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | |||
161 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
162 | |||
163 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
164 | mfpr_writel(mfp_table[mfp].mfpr_off, val); | ||
165 | mfpr_sync(); | ||
166 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
167 | } | ||
168 | |||
169 | void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map) | ||
170 | { | ||
171 | struct pxa3xx_mfp_addr_map *p; | ||
172 | unsigned long offset, flags; | ||
173 | int i; | ||
174 | |||
175 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
176 | |||
177 | for (p = map; p->start != MFP_PIN_INVALID; p++) { | ||
178 | offset = p->offset; | ||
179 | i = p->start; | ||
180 | |||
181 | do { | ||
182 | mfp_table[i].mfpr_off = offset; | ||
183 | mfp_table[i].mfpr_run = 0; | ||
184 | mfp_table[i].mfpr_lpm = 0; | ||
185 | offset += 4; i++; | ||
186 | } while ((i <= p->end) && (p->end != -1)); | ||
187 | } | ||
188 | |||
189 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
190 | } | ||
191 | |||
192 | void __init pxa3xx_init_mfp(void) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | for (i = 0; i < ARRAY_SIZE(mfp_table); i++) | ||
197 | mfp_table[i].config = -1; | ||
198 | } | ||
199 | |||
200 | #ifdef CONFIG_PM | 26 | #ifdef CONFIG_PM |
201 | /* | 27 | /* |
202 | * Configure the MFPs appropriately for suspend/resume. | 28 | * Configure the MFPs appropriately for suspend/resume. |
@@ -207,23 +33,13 @@ void __init pxa3xx_init_mfp(void) | |||
207 | */ | 33 | */ |
208 | static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) | 34 | static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) |
209 | { | 35 | { |
210 | int pin; | 36 | mfp_config_lpm(); |
211 | |||
212 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { | ||
213 | struct pxa3xx_mfp_pin *p = &mfp_table[pin]; | ||
214 | __mfp_config_lpm(p); | ||
215 | } | ||
216 | return 0; | 37 | return 0; |
217 | } | 38 | } |
218 | 39 | ||
219 | static int pxa3xx_mfp_resume(struct sys_device *d) | 40 | static int pxa3xx_mfp_resume(struct sys_device *d) |
220 | { | 41 | { |
221 | int pin; | 42 | mfp_config_run(); |
222 | |||
223 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { | ||
224 | struct pxa3xx_mfp_pin *p = &mfp_table[pin]; | ||
225 | __mfp_config_run(p); | ||
226 | } | ||
227 | 43 | ||
228 | /* clear RDH bit when MFP settings are restored | 44 | /* clear RDH bit when MFP settings are restored |
229 | * | 45 | * |
@@ -231,7 +47,6 @@ static int pxa3xx_mfp_resume(struct sys_device *d) | |||
231 | * preserve them here in case they will be referenced later | 47 | * preserve them here in case they will be referenced later |
232 | */ | 48 | */ |
233 | ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); | 49 | ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); |
234 | |||
235 | return 0; | 50 | return 0; |
236 | } | 51 | } |
237 | #else | 52 | #else |
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 37bb12d13ca2..4ba6d21f851c 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "devices.h" | 23 | #include "devices.h" |
24 | #include "clock.h" | 24 | #include "clock.h" |
25 | 25 | ||
26 | static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { | 26 | static struct mfp_addr_map pxa300_mfp_addr_map[] __initdata = { |
27 | 27 | ||
28 | MFP_ADDR_X(GPIO0, GPIO2, 0x00b4), | 28 | MFP_ADDR_X(GPIO0, GPIO2, 0x00b4), |
29 | MFP_ADDR_X(GPIO3, GPIO26, 0x027c), | 29 | MFP_ADDR_X(GPIO3, GPIO26, 0x027c), |
@@ -72,7 +72,7 @@ static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* override pxa300 MFP register addresses */ | 74 | /* override pxa300 MFP register addresses */ |
75 | static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { | 75 | static struct mfp_addr_map pxa310_mfp_addr_map[] __initdata = { |
76 | MFP_ADDR_X(GPIO30, GPIO98, 0x0418), | 76 | MFP_ADDR_X(GPIO30, GPIO98, 0x0418), |
77 | MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C), | 77 | MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C), |
78 | 78 | ||
@@ -98,13 +98,13 @@ static struct clk_lookup pxa310_clkregs[] = { | |||
98 | static int __init pxa300_init(void) | 98 | static int __init pxa300_init(void) |
99 | { | 99 | { |
100 | if (cpu_is_pxa300() || cpu_is_pxa310()) { | 100 | if (cpu_is_pxa300() || cpu_is_pxa310()) { |
101 | pxa3xx_init_mfp(); | 101 | mfp_init_base(io_p2v(MFPR_BASE)); |
102 | pxa3xx_mfp_init_addr(pxa300_mfp_addr_map); | 102 | mfp_init_addr(pxa300_mfp_addr_map); |
103 | clks_register(ARRAY_AND_SIZE(common_clkregs)); | 103 | clks_register(ARRAY_AND_SIZE(common_clkregs)); |
104 | } | 104 | } |
105 | 105 | ||
106 | if (cpu_is_pxa310()) { | 106 | if (cpu_is_pxa310()) { |
107 | pxa3xx_mfp_init_addr(pxa310_mfp_addr_map); | 107 | mfp_init_addr(pxa310_mfp_addr_map); |
108 | clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); | 108 | clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); |
109 | } | 109 | } |
110 | 110 | ||
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index e708f4e0ecaf..8b3d97efadab 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "devices.h" | 23 | #include "devices.h" |
24 | #include "clock.h" | 24 | #include "clock.h" |
25 | 25 | ||
26 | static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { | 26 | static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = { |
27 | 27 | ||
28 | MFP_ADDR_X(GPIO0, GPIO4, 0x0124), | 28 | MFP_ADDR_X(GPIO0, GPIO4, 0x0124), |
29 | MFP_ADDR_X(GPIO5, GPIO9, 0x028C), | 29 | MFP_ADDR_X(GPIO5, GPIO9, 0x028C), |
@@ -86,8 +86,8 @@ static struct clk_lookup pxa320_clkregs[] = { | |||
86 | static int __init pxa320_init(void) | 86 | static int __init pxa320_init(void) |
87 | { | 87 | { |
88 | if (cpu_is_pxa320()) { | 88 | if (cpu_is_pxa320()) { |
89 | pxa3xx_init_mfp(); | 89 | mfp_init_base(io_p2v(MFPR_BASE)); |
90 | pxa3xx_mfp_init_addr(pxa320_mfp_addr_map); | 90 | mfp_init_addr(pxa320_mfp_addr_map); |
91 | clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); | 91 | clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); |
92 | } | 92 | } |
93 | 93 | ||
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c index f15dfa55f27f..71131742fffd 100644 --- a/arch/arm/mach-pxa/pxa930.c +++ b/arch/arm/mach-pxa/pxa930.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | #include <mach/pxa930.h> | 19 | #include <mach/pxa930.h> |
20 | 20 | ||
21 | static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { | 21 | static struct mfp_addr_map pxa930_mfp_addr_map[] __initdata = { |
22 | 22 | ||
23 | MFP_ADDR(GPIO0, 0x02e0), | 23 | MFP_ADDR(GPIO0, 0x02e0), |
24 | MFP_ADDR(GPIO1, 0x02dc), | 24 | MFP_ADDR(GPIO1, 0x02dc), |
@@ -179,8 +179,8 @@ static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { | |||
179 | static int __init pxa930_init(void) | 179 | static int __init pxa930_init(void) |
180 | { | 180 | { |
181 | if (cpu_is_pxa930()) { | 181 | if (cpu_is_pxa930()) { |
182 | pxa3xx_init_mfp(); | 182 | mfp_init_base(io_p2v(MFPR_BASE)); |
183 | pxa3xx_mfp_init_addr(pxa930_mfp_addr_map); | 183 | mfp_init_addr(pxa930_mfp_addr_map); |
184 | } | 184 | } |
185 | 185 | ||
186 | return 0; | 186 | return 0; |
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index b837df440483..4be37235f57b 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile | |||
@@ -2,6 +2,6 @@ | |||
2 | # Makefile for code common across different PXA processor families | 2 | # Makefile for code common across different PXA processor families |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dma.o | 5 | obj-y := dma.o mfp.o |
6 | 6 | ||
7 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o | 7 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o |
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h new file mode 100644 index 000000000000..a22229cde096 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/mfp.h | |||
@@ -0,0 +1,369 @@ | |||
1 | /* | ||
2 | * arch/arm/plat-pxa/include/plat/mfp.h | ||
3 | * | ||
4 | * Common Multi-Function Pin Definitions | ||
5 | * | ||
6 | * Copyright (C) 2007 Marvell International Ltd. | ||
7 | * | ||
8 | * 2007-8-21: eric miao <eric.miao@marvell.com> | ||
9 | * initial version | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef __ASM_PLAT_MFP_H | ||
17 | #define __ASM_PLAT_MFP_H | ||
18 | |||
19 | #define mfp_to_gpio(m) ((m) % 128) | ||
20 | |||
21 | /* list of all the configurable MFP pins */ | ||
22 | enum { | ||
23 | MFP_PIN_INVALID = -1, | ||
24 | |||
25 | MFP_PIN_GPIO0 = 0, | ||
26 | MFP_PIN_GPIO1, | ||
27 | MFP_PIN_GPIO2, | ||
28 | MFP_PIN_GPIO3, | ||
29 | MFP_PIN_GPIO4, | ||
30 | MFP_PIN_GPIO5, | ||
31 | MFP_PIN_GPIO6, | ||
32 | MFP_PIN_GPIO7, | ||
33 | MFP_PIN_GPIO8, | ||
34 | MFP_PIN_GPIO9, | ||
35 | MFP_PIN_GPIO10, | ||
36 | MFP_PIN_GPIO11, | ||
37 | MFP_PIN_GPIO12, | ||
38 | MFP_PIN_GPIO13, | ||
39 | MFP_PIN_GPIO14, | ||
40 | MFP_PIN_GPIO15, | ||
41 | MFP_PIN_GPIO16, | ||
42 | MFP_PIN_GPIO17, | ||
43 | MFP_PIN_GPIO18, | ||
44 | MFP_PIN_GPIO19, | ||
45 | MFP_PIN_GPIO20, | ||
46 | MFP_PIN_GPIO21, | ||
47 | MFP_PIN_GPIO22, | ||
48 | MFP_PIN_GPIO23, | ||
49 | MFP_PIN_GPIO24, | ||
50 | MFP_PIN_GPIO25, | ||
51 | MFP_PIN_GPIO26, | ||
52 | MFP_PIN_GPIO27, | ||
53 | MFP_PIN_GPIO28, | ||
54 | MFP_PIN_GPIO29, | ||
55 | MFP_PIN_GPIO30, | ||
56 | MFP_PIN_GPIO31, | ||
57 | MFP_PIN_GPIO32, | ||
58 | MFP_PIN_GPIO33, | ||
59 | MFP_PIN_GPIO34, | ||
60 | MFP_PIN_GPIO35, | ||
61 | MFP_PIN_GPIO36, | ||
62 | MFP_PIN_GPIO37, | ||
63 | MFP_PIN_GPIO38, | ||
64 | MFP_PIN_GPIO39, | ||
65 | MFP_PIN_GPIO40, | ||
66 | MFP_PIN_GPIO41, | ||
67 | MFP_PIN_GPIO42, | ||
68 | MFP_PIN_GPIO43, | ||
69 | MFP_PIN_GPIO44, | ||
70 | MFP_PIN_GPIO45, | ||
71 | MFP_PIN_GPIO46, | ||
72 | MFP_PIN_GPIO47, | ||
73 | MFP_PIN_GPIO48, | ||
74 | MFP_PIN_GPIO49, | ||
75 | MFP_PIN_GPIO50, | ||
76 | MFP_PIN_GPIO51, | ||
77 | MFP_PIN_GPIO52, | ||
78 | MFP_PIN_GPIO53, | ||
79 | MFP_PIN_GPIO54, | ||
80 | MFP_PIN_GPIO55, | ||
81 | MFP_PIN_GPIO56, | ||
82 | MFP_PIN_GPIO57, | ||
83 | MFP_PIN_GPIO58, | ||
84 | MFP_PIN_GPIO59, | ||
85 | MFP_PIN_GPIO60, | ||
86 | MFP_PIN_GPIO61, | ||
87 | MFP_PIN_GPIO62, | ||
88 | MFP_PIN_GPIO63, | ||
89 | MFP_PIN_GPIO64, | ||
90 | MFP_PIN_GPIO65, | ||
91 | MFP_PIN_GPIO66, | ||
92 | MFP_PIN_GPIO67, | ||
93 | MFP_PIN_GPIO68, | ||
94 | MFP_PIN_GPIO69, | ||
95 | MFP_PIN_GPIO70, | ||
96 | MFP_PIN_GPIO71, | ||
97 | MFP_PIN_GPIO72, | ||
98 | MFP_PIN_GPIO73, | ||
99 | MFP_PIN_GPIO74, | ||
100 | MFP_PIN_GPIO75, | ||
101 | MFP_PIN_GPIO76, | ||
102 | MFP_PIN_GPIO77, | ||
103 | MFP_PIN_GPIO78, | ||
104 | MFP_PIN_GPIO79, | ||
105 | MFP_PIN_GPIO80, | ||
106 | MFP_PIN_GPIO81, | ||
107 | MFP_PIN_GPIO82, | ||
108 | MFP_PIN_GPIO83, | ||
109 | MFP_PIN_GPIO84, | ||
110 | MFP_PIN_GPIO85, | ||
111 | MFP_PIN_GPIO86, | ||
112 | MFP_PIN_GPIO87, | ||
113 | MFP_PIN_GPIO88, | ||
114 | MFP_PIN_GPIO89, | ||
115 | MFP_PIN_GPIO90, | ||
116 | MFP_PIN_GPIO91, | ||
117 | MFP_PIN_GPIO92, | ||
118 | MFP_PIN_GPIO93, | ||
119 | MFP_PIN_GPIO94, | ||
120 | MFP_PIN_GPIO95, | ||
121 | MFP_PIN_GPIO96, | ||
122 | MFP_PIN_GPIO97, | ||
123 | MFP_PIN_GPIO98, | ||
124 | MFP_PIN_GPIO99, | ||
125 | MFP_PIN_GPIO100, | ||
126 | MFP_PIN_GPIO101, | ||
127 | MFP_PIN_GPIO102, | ||
128 | MFP_PIN_GPIO103, | ||
129 | MFP_PIN_GPIO104, | ||
130 | MFP_PIN_GPIO105, | ||
131 | MFP_PIN_GPIO106, | ||
132 | MFP_PIN_GPIO107, | ||
133 | MFP_PIN_GPIO108, | ||
134 | MFP_PIN_GPIO109, | ||
135 | MFP_PIN_GPIO110, | ||
136 | MFP_PIN_GPIO111, | ||
137 | MFP_PIN_GPIO112, | ||
138 | MFP_PIN_GPIO113, | ||
139 | MFP_PIN_GPIO114, | ||
140 | MFP_PIN_GPIO115, | ||
141 | MFP_PIN_GPIO116, | ||
142 | MFP_PIN_GPIO117, | ||
143 | MFP_PIN_GPIO118, | ||
144 | MFP_PIN_GPIO119, | ||
145 | MFP_PIN_GPIO120, | ||
146 | MFP_PIN_GPIO121, | ||
147 | MFP_PIN_GPIO122, | ||
148 | MFP_PIN_GPIO123, | ||
149 | MFP_PIN_GPIO124, | ||
150 | MFP_PIN_GPIO125, | ||
151 | MFP_PIN_GPIO126, | ||
152 | MFP_PIN_GPIO127, | ||
153 | MFP_PIN_GPIO0_2, | ||
154 | MFP_PIN_GPIO1_2, | ||
155 | MFP_PIN_GPIO2_2, | ||
156 | MFP_PIN_GPIO3_2, | ||
157 | MFP_PIN_GPIO4_2, | ||
158 | MFP_PIN_GPIO5_2, | ||
159 | MFP_PIN_GPIO6_2, | ||
160 | MFP_PIN_GPIO7_2, | ||
161 | MFP_PIN_GPIO8_2, | ||
162 | MFP_PIN_GPIO9_2, | ||
163 | MFP_PIN_GPIO10_2, | ||
164 | MFP_PIN_GPIO11_2, | ||
165 | MFP_PIN_GPIO12_2, | ||
166 | MFP_PIN_GPIO13_2, | ||
167 | MFP_PIN_GPIO14_2, | ||
168 | MFP_PIN_GPIO15_2, | ||
169 | MFP_PIN_GPIO16_2, | ||
170 | MFP_PIN_GPIO17_2, | ||
171 | |||
172 | MFP_PIN_ULPI_STP, | ||
173 | MFP_PIN_ULPI_NXT, | ||
174 | MFP_PIN_ULPI_DIR, | ||
175 | |||
176 | MFP_PIN_nXCVREN, | ||
177 | MFP_PIN_DF_CLE_nOE, | ||
178 | MFP_PIN_DF_nADV1_ALE, | ||
179 | MFP_PIN_DF_SCLK_E, | ||
180 | MFP_PIN_DF_SCLK_S, | ||
181 | MFP_PIN_nBE0, | ||
182 | MFP_PIN_nBE1, | ||
183 | MFP_PIN_DF_nADV2_ALE, | ||
184 | MFP_PIN_DF_INT_RnB, | ||
185 | MFP_PIN_DF_nCS0, | ||
186 | MFP_PIN_DF_nCS1, | ||
187 | MFP_PIN_nLUA, | ||
188 | MFP_PIN_nLLA, | ||
189 | MFP_PIN_DF_nWE, | ||
190 | MFP_PIN_DF_ALE_nWE, | ||
191 | MFP_PIN_DF_nRE_nOE, | ||
192 | MFP_PIN_DF_ADDR0, | ||
193 | MFP_PIN_DF_ADDR1, | ||
194 | MFP_PIN_DF_ADDR2, | ||
195 | MFP_PIN_DF_ADDR3, | ||
196 | MFP_PIN_DF_IO0, | ||
197 | MFP_PIN_DF_IO1, | ||
198 | MFP_PIN_DF_IO2, | ||
199 | MFP_PIN_DF_IO3, | ||
200 | MFP_PIN_DF_IO4, | ||
201 | MFP_PIN_DF_IO5, | ||
202 | MFP_PIN_DF_IO6, | ||
203 | MFP_PIN_DF_IO7, | ||
204 | MFP_PIN_DF_IO8, | ||
205 | MFP_PIN_DF_IO9, | ||
206 | MFP_PIN_DF_IO10, | ||
207 | MFP_PIN_DF_IO11, | ||
208 | MFP_PIN_DF_IO12, | ||
209 | MFP_PIN_DF_IO13, | ||
210 | MFP_PIN_DF_IO14, | ||
211 | MFP_PIN_DF_IO15, | ||
212 | |||
213 | /* additional pins on PXA930 */ | ||
214 | MFP_PIN_GSIM_UIO, | ||
215 | MFP_PIN_GSIM_UCLK, | ||
216 | MFP_PIN_GSIM_UDET, | ||
217 | MFP_PIN_GSIM_nURST, | ||
218 | MFP_PIN_PMIC_INT, | ||
219 | MFP_PIN_RDY, | ||
220 | |||
221 | MFP_PIN_MAX, | ||
222 | }; | ||
223 | |||
224 | /* | ||
225 | * a possible MFP configuration is represented by a 32-bit integer | ||
226 | * | ||
227 | * bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) | ||
228 | * bit 10..12 - Alternate Function Selection | ||
229 | * bit 13..15 - Drive Strength | ||
230 | * bit 16..18 - Low Power Mode State | ||
231 | * bit 19..20 - Low Power Mode Edge Detection | ||
232 | * bit 21..22 - Run Mode Pull State | ||
233 | * | ||
234 | * to facilitate the definition, the following macros are provided | ||
235 | * | ||
236 | * MFP_CFG_DEFAULT - default MFP configuration value, with | ||
237 | * alternate function = 0, | ||
238 | * drive strength = fast 3mA (MFP_DS03X) | ||
239 | * low power mode = default | ||
240 | * edge detection = none | ||
241 | * | ||
242 | * MFP_CFG - default MFPR value with alternate function | ||
243 | * MFP_CFG_DRV - default MFPR value with alternate function and | ||
244 | * pin drive strength | ||
245 | * MFP_CFG_LPM - default MFPR value with alternate function and | ||
246 | * low power mode | ||
247 | * MFP_CFG_X - default MFPR value with alternate function, | ||
248 | * pin drive strength and low power mode | ||
249 | */ | ||
250 | |||
251 | typedef unsigned long mfp_cfg_t; | ||
252 | |||
253 | #define MFP_PIN(x) ((x) & 0x3ff) | ||
254 | |||
255 | #define MFP_AF0 (0x0 << 10) | ||
256 | #define MFP_AF1 (0x1 << 10) | ||
257 | #define MFP_AF2 (0x2 << 10) | ||
258 | #define MFP_AF3 (0x3 << 10) | ||
259 | #define MFP_AF4 (0x4 << 10) | ||
260 | #define MFP_AF5 (0x5 << 10) | ||
261 | #define MFP_AF6 (0x6 << 10) | ||
262 | #define MFP_AF7 (0x7 << 10) | ||
263 | #define MFP_AF_MASK (0x7 << 10) | ||
264 | #define MFP_AF(x) (((x) >> 10) & 0x7) | ||
265 | |||
266 | #define MFP_DS01X (0x0 << 13) | ||
267 | #define MFP_DS02X (0x1 << 13) | ||
268 | #define MFP_DS03X (0x2 << 13) | ||
269 | #define MFP_DS04X (0x3 << 13) | ||
270 | #define MFP_DS06X (0x4 << 13) | ||
271 | #define MFP_DS08X (0x5 << 13) | ||
272 | #define MFP_DS10X (0x6 << 13) | ||
273 | #define MFP_DS13X (0x7 << 13) | ||
274 | #define MFP_DS_MASK (0x7 << 13) | ||
275 | #define MFP_DS(x) (((x) >> 13) & 0x7) | ||
276 | |||
277 | #define MFP_LPM_DEFAULT (0x0 << 16) | ||
278 | #define MFP_LPM_DRIVE_LOW (0x1 << 16) | ||
279 | #define MFP_LPM_DRIVE_HIGH (0x2 << 16) | ||
280 | #define MFP_LPM_PULL_LOW (0x3 << 16) | ||
281 | #define MFP_LPM_PULL_HIGH (0x4 << 16) | ||
282 | #define MFP_LPM_FLOAT (0x5 << 16) | ||
283 | #define MFP_LPM_INPUT (0x6 << 16) | ||
284 | #define MFP_LPM_STATE_MASK (0x7 << 16) | ||
285 | #define MFP_LPM_STATE(x) (((x) >> 16) & 0x7) | ||
286 | |||
287 | #define MFP_LPM_EDGE_NONE (0x0 << 19) | ||
288 | #define MFP_LPM_EDGE_RISE (0x1 << 19) | ||
289 | #define MFP_LPM_EDGE_FALL (0x2 << 19) | ||
290 | #define MFP_LPM_EDGE_BOTH (0x3 << 19) | ||
291 | #define MFP_LPM_EDGE_MASK (0x3 << 19) | ||
292 | #define MFP_LPM_EDGE(x) (((x) >> 19) & 0x3) | ||
293 | |||
294 | #define MFP_PULL_NONE (0x0 << 21) | ||
295 | #define MFP_PULL_LOW (0x1 << 21) | ||
296 | #define MFP_PULL_HIGH (0x2 << 21) | ||
297 | #define MFP_PULL_BOTH (0x3 << 21) | ||
298 | #define MFP_PULL_MASK (0x3 << 21) | ||
299 | #define MFP_PULL(x) (((x) >> 21) & 0x3) | ||
300 | |||
301 | #define MFP_CFG_DEFAULT (MFP_AF0 | MFP_DS03X | MFP_LPM_DEFAULT |\ | ||
302 | MFP_LPM_EDGE_NONE | MFP_PULL_NONE) | ||
303 | |||
304 | #define MFP_CFG(pin, af) \ | ||
305 | ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\ | ||
306 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af)) | ||
307 | |||
308 | #define MFP_CFG_DRV(pin, af, drv) \ | ||
309 | ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK)) |\ | ||
310 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv)) | ||
311 | |||
312 | #define MFP_CFG_LPM(pin, af, lpm) \ | ||
313 | ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_LPM_STATE_MASK)) |\ | ||
314 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_LPM_##lpm)) | ||
315 | |||
316 | #define MFP_CFG_X(pin, af, drv, lpm) \ | ||
317 | ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\ | ||
318 | (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm)) | ||
319 | |||
320 | #if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP) | ||
321 | /* | ||
322 | * each MFP pin will have a MFPR register, since the offset of the | ||
323 | * register varies between processors, the processor specific code | ||
324 | * should initialize the pin offsets by mfp_init() | ||
325 | * | ||
326 | * mfp_init_base() - accepts a virtual base for all MFPR registers and | ||
327 | * initialize the MFP table to a default state | ||
328 | * | ||
329 | * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which | ||
330 | * represents a range of MFP pins from "start" to "end", with the offset | ||
331 | * begining at "offset", to define a single pin, let "end" = -1. | ||
332 | * | ||
333 | * use | ||
334 | * | ||
335 | * MFP_ADDR_X() to define a range of pins | ||
336 | * MFP_ADDR() to define a single pin | ||
337 | * MFP_ADDR_END to signal the end of pin offset definitions | ||
338 | */ | ||
339 | struct mfp_addr_map { | ||
340 | unsigned int start; | ||
341 | unsigned int end; | ||
342 | unsigned long offset; | ||
343 | }; | ||
344 | |||
345 | #define MFP_ADDR_X(start, end, offset) \ | ||
346 | { MFP_PIN_##start, MFP_PIN_##end, offset } | ||
347 | |||
348 | #define MFP_ADDR(pin, offset) \ | ||
349 | { MFP_PIN_##pin, -1, offset } | ||
350 | |||
351 | #define MFP_ADDR_END { MFP_PIN_INVALID, 0 } | ||
352 | |||
353 | void __init mfp_init_base(unsigned long mfpr_base); | ||
354 | void __init mfp_init_addr(struct mfp_addr_map *map); | ||
355 | |||
356 | /* | ||
357 | * mfp_{read, write}() - for direct read/write access to the MFPR register | ||
358 | * mfp_config() - for configuring a group of MFPR registers | ||
359 | * mfp_config_lpm() - configuring all low power MFPR registers for suspend | ||
360 | * mfp_config_run() - configuring all run time MFPR registers after resume | ||
361 | */ | ||
362 | unsigned long mfp_read(int mfp); | ||
363 | void mfp_write(int mfp, unsigned long mfpr_val); | ||
364 | void mfp_config(unsigned long *mfp_cfgs, int num); | ||
365 | void mfp_config_run(void); | ||
366 | void mfp_config_lpm(void); | ||
367 | #endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */ | ||
368 | |||
369 | #endif /* __ASM_PLAT_MFP_H */ | ||
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c new file mode 100644 index 000000000000..e716c622a17c --- /dev/null +++ b/arch/arm/plat-pxa/mfp.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-pxa/mfp.c | ||
3 | * | ||
4 | * Multi-Function Pin Support | ||
5 | * | ||
6 | * Copyright (C) 2007 Marvell Internation Ltd. | ||
7 | * | ||
8 | * 2007-08-21: eric miao <eric.miao@marvell.com> | ||
9 | * initial version | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/sysdev.h> | ||
21 | |||
22 | #include <plat/mfp.h> | ||
23 | |||
24 | #define MFPR_SIZE (PAGE_SIZE) | ||
25 | |||
26 | /* MFPR register bit definitions */ | ||
27 | #define MFPR_PULL_SEL (0x1 << 15) | ||
28 | #define MFPR_PULLUP_EN (0x1 << 14) | ||
29 | #define MFPR_PULLDOWN_EN (0x1 << 13) | ||
30 | #define MFPR_SLEEP_SEL (0x1 << 9) | ||
31 | #define MFPR_SLEEP_OE_N (0x1 << 7) | ||
32 | #define MFPR_EDGE_CLEAR (0x1 << 6) | ||
33 | #define MFPR_EDGE_FALL_EN (0x1 << 5) | ||
34 | #define MFPR_EDGE_RISE_EN (0x1 << 4) | ||
35 | |||
36 | #define MFPR_SLEEP_DATA(x) ((x) << 8) | ||
37 | #define MFPR_DRIVE(x) (((x) & 0x7) << 10) | ||
38 | #define MFPR_AF_SEL(x) (((x) & 0x7) << 0) | ||
39 | |||
40 | #define MFPR_EDGE_NONE (0) | ||
41 | #define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) | ||
42 | #define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) | ||
43 | #define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) | ||
44 | |||
45 | /* | ||
46 | * Table that determines the low power modes outputs, with actual settings | ||
47 | * used in parentheses for don't-care values. Except for the float output, | ||
48 | * the configured driven and pulled levels match, so if there is a need for | ||
49 | * non-LPM pulled output, the same configuration could probably be used. | ||
50 | * | ||
51 | * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel | ||
52 | * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) | ||
53 | * | ||
54 | * Input 0 X(0) X(0) X(0) 0 | ||
55 | * Drive 0 0 0 0 X(1) 0 | ||
56 | * Drive 1 0 1 X(1) 0 0 | ||
57 | * Pull hi (1) 1 X(1) 1 0 0 | ||
58 | * Pull lo (0) 1 X(0) 0 1 0 | ||
59 | * Z (float) 1 X(0) 0 0 0 | ||
60 | */ | ||
61 | #define MFPR_LPM_INPUT (0) | ||
62 | #define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) | ||
63 | #define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) | ||
64 | #define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) | ||
65 | #define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) | ||
66 | #define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) | ||
67 | #define MFPR_LPM_MASK (0xe080) | ||
68 | |||
69 | /* | ||
70 | * The pullup and pulldown state of the MFP pin at run mode is by default | ||
71 | * determined by the selected alternate function. In case that some buggy | ||
72 | * devices need to override this default behavior, the definitions below | ||
73 | * indicates the setting of corresponding MFPR bits | ||
74 | * | ||
75 | * Definition pull_sel pullup_en pulldown_en | ||
76 | * MFPR_PULL_NONE 0 0 0 | ||
77 | * MFPR_PULL_LOW 1 0 1 | ||
78 | * MFPR_PULL_HIGH 1 1 0 | ||
79 | * MFPR_PULL_BOTH 1 1 1 | ||
80 | */ | ||
81 | #define MFPR_PULL_NONE (0) | ||
82 | #define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) | ||
83 | #define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) | ||
84 | #define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) | ||
85 | |||
86 | /* mfp_spin_lock is used to ensure that MFP register configuration | ||
87 | * (most likely a read-modify-write operation) is atomic, and that | ||
88 | * mfp_table[] is consistent | ||
89 | */ | ||
90 | static DEFINE_SPINLOCK(mfp_spin_lock); | ||
91 | |||
92 | static void __iomem *mfpr_mmio_base; | ||
93 | |||
94 | struct mfp_pin { | ||
95 | unsigned long config; /* -1 for not configured */ | ||
96 | unsigned long mfpr_off; /* MFPRxx Register offset */ | ||
97 | unsigned long mfpr_run; /* Run-Mode Register Value */ | ||
98 | unsigned long mfpr_lpm; /* Low Power Mode Register Value */ | ||
99 | }; | ||
100 | |||
101 | static struct mfp_pin mfp_table[MFP_PIN_MAX]; | ||
102 | |||
103 | /* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ | ||
104 | static const unsigned long mfpr_lpm[] = { | ||
105 | MFPR_LPM_INPUT, | ||
106 | MFPR_LPM_DRIVE_LOW, | ||
107 | MFPR_LPM_DRIVE_HIGH, | ||
108 | MFPR_LPM_PULL_LOW, | ||
109 | MFPR_LPM_PULL_HIGH, | ||
110 | MFPR_LPM_FLOAT, | ||
111 | }; | ||
112 | |||
113 | /* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ | ||
114 | static const unsigned long mfpr_pull[] = { | ||
115 | MFPR_PULL_NONE, | ||
116 | MFPR_PULL_LOW, | ||
117 | MFPR_PULL_HIGH, | ||
118 | MFPR_PULL_BOTH, | ||
119 | }; | ||
120 | |||
121 | /* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ | ||
122 | static const unsigned long mfpr_edge[] = { | ||
123 | MFPR_EDGE_NONE, | ||
124 | MFPR_EDGE_RISE, | ||
125 | MFPR_EDGE_FALL, | ||
126 | MFPR_EDGE_BOTH, | ||
127 | }; | ||
128 | |||
129 | #define mfpr_readl(off) \ | ||
130 | __raw_readl(mfpr_mmio_base + (off)) | ||
131 | |||
132 | #define mfpr_writel(off, val) \ | ||
133 | __raw_writel(val, mfpr_mmio_base + (off)) | ||
134 | |||
135 | #define mfp_configured(p) ((p)->config != -1) | ||
136 | |||
137 | /* | ||
138 | * perform a read-back of any MFPR register to make sure the | ||
139 | * previous writings are finished | ||
140 | */ | ||
141 | #define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) | ||
142 | |||
143 | static inline void __mfp_config_run(struct mfp_pin *p) | ||
144 | { | ||
145 | if (mfp_configured(p)) | ||
146 | mfpr_writel(p->mfpr_off, p->mfpr_run); | ||
147 | } | ||
148 | |||
149 | static inline void __mfp_config_lpm(struct mfp_pin *p) | ||
150 | { | ||
151 | if (mfp_configured(p)) { | ||
152 | unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; | ||
153 | if (mfpr_clr != p->mfpr_run) | ||
154 | mfpr_writel(p->mfpr_off, mfpr_clr); | ||
155 | if (p->mfpr_lpm != mfpr_clr) | ||
156 | mfpr_writel(p->mfpr_off, p->mfpr_lpm); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | void mfp_config(unsigned long *mfp_cfgs, int num) | ||
161 | { | ||
162 | unsigned long flags; | ||
163 | int i; | ||
164 | |||
165 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
166 | |||
167 | for (i = 0; i < num; i++, mfp_cfgs++) { | ||
168 | unsigned long tmp, c = *mfp_cfgs; | ||
169 | struct mfp_pin *p; | ||
170 | int pin, af, drv, lpm, edge, pull; | ||
171 | |||
172 | pin = MFP_PIN(c); | ||
173 | BUG_ON(pin >= MFP_PIN_MAX); | ||
174 | p = &mfp_table[pin]; | ||
175 | |||
176 | af = MFP_AF(c); | ||
177 | drv = MFP_DS(c); | ||
178 | lpm = MFP_LPM_STATE(c); | ||
179 | edge = MFP_LPM_EDGE(c); | ||
180 | pull = MFP_PULL(c); | ||
181 | |||
182 | /* run-mode pull settings will conflict with MFPR bits of | ||
183 | * low power mode state, calculate mfpr_run and mfpr_lpm | ||
184 | * individually if pull != MFP_PULL_NONE | ||
185 | */ | ||
186 | tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); | ||
187 | |||
188 | if (likely(pull == MFP_PULL_NONE)) { | ||
189 | p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
190 | p->mfpr_lpm = p->mfpr_run; | ||
191 | } else { | ||
192 | p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; | ||
193 | p->mfpr_run = tmp | mfpr_pull[pull]; | ||
194 | } | ||
195 | |||
196 | p->config = c; __mfp_config_run(p); | ||
197 | } | ||
198 | |||
199 | mfpr_sync(); | ||
200 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
201 | } | ||
202 | |||
203 | unsigned long mfp_read(int mfp) | ||
204 | { | ||
205 | unsigned long val, flags; | ||
206 | |||
207 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
208 | |||
209 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
210 | val = mfpr_readl(mfp_table[mfp].mfpr_off); | ||
211 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
212 | |||
213 | return val; | ||
214 | } | ||
215 | |||
216 | void mfp_write(int mfp, unsigned long val) | ||
217 | { | ||
218 | unsigned long flags; | ||
219 | |||
220 | BUG_ON(mfp >= MFP_PIN_MAX); | ||
221 | |||
222 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
223 | mfpr_writel(mfp_table[mfp].mfpr_off, val); | ||
224 | mfpr_sync(); | ||
225 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
226 | } | ||
227 | |||
228 | void __init mfp_init_base(unsigned long mfpr_base) | ||
229 | { | ||
230 | int i; | ||
231 | |||
232 | /* initialize the table with default - unconfigured */ | ||
233 | for (i = 0; i < ARRAY_SIZE(mfp_table); i++) | ||
234 | mfp_table[i].config = -1; | ||
235 | |||
236 | mfpr_mmio_base = (void __iomem *)mfpr_base; | ||
237 | } | ||
238 | |||
239 | void __init mfp_init_addr(struct mfp_addr_map *map) | ||
240 | { | ||
241 | struct mfp_addr_map *p; | ||
242 | unsigned long offset, flags; | ||
243 | int i; | ||
244 | |||
245 | spin_lock_irqsave(&mfp_spin_lock, flags); | ||
246 | |||
247 | for (p = map; p->start != MFP_PIN_INVALID; p++) { | ||
248 | offset = p->offset; | ||
249 | i = p->start; | ||
250 | |||
251 | do { | ||
252 | mfp_table[i].mfpr_off = offset; | ||
253 | mfp_table[i].mfpr_run = 0; | ||
254 | mfp_table[i].mfpr_lpm = 0; | ||
255 | offset += 4; i++; | ||
256 | } while ((i <= p->end) && (p->end != -1)); | ||
257 | } | ||
258 | |||
259 | spin_unlock_irqrestore(&mfp_spin_lock, flags); | ||
260 | } | ||
261 | |||
262 | void mfp_config_lpm(void) | ||
263 | { | ||
264 | struct mfp_pin *p = &mfp_table[0]; | ||
265 | int pin; | ||
266 | |||
267 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) | ||
268 | __mfp_config_lpm(p); | ||
269 | } | ||
270 | |||
271 | void mfp_config_run(void) | ||
272 | { | ||
273 | struct mfp_pin *p = &mfp_table[0]; | ||
274 | int pin; | ||
275 | |||
276 | for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) | ||
277 | __mfp_config_run(p); | ||
278 | } | ||