aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorEric Miao <eric.miao@marvell.com>2009-01-15 03:42:56 -0500
committerEric Miao <eric.miao@marvell.com>2009-03-22 22:11:34 -0400
commitf8dec04d33b94a4cfa9358fd9666c01480bb164d (patch)
treebcf82252230a757f26d6de980749b9e4395cd8b9 /arch/arm
parent38f539a608c9a3b40b30f1892bd5f9a38f4e5ffe (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.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa27x.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa300.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa320.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h130
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa930.h1
-rw-r--r--arch/arm/mach-pxa/mfp-pxa3xx.c189
-rw-r--r--arch/arm/mach-pxa/pxa300.c10
-rw-r--r--arch/arm/mach-pxa/pxa320.c6
-rw-r--r--arch/arm/mach-pxa/pxa930.c6
-rw-r--r--arch/arm/plat-pxa/Makefile2
-rw-r--r--arch/arm/plat-pxa/include/plat/mfp.h369
-rw-r--r--arch/arm/plat-pxa/mfp.c278
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 */
216struct 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 */
234unsigned long pxa3xx_mfp_read(int mfp);
235void 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 */
242void 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 */
250void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *); 144static inline unsigned long pxa3xx_mfp_read(int mfp)
251void __init pxa3xx_init_mfp(void); 145{
146 return mfp_read(mfp);
147}
148
149static inline void pxa3xx_mfp_write(int mfp, unsigned long val)
150{
151 mfp_write(mfp, val);
152}
153
154static 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 */
31static DEFINE_SPINLOCK(mfp_spin_lock);
32
33static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
34
35struct 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
42static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
43
44/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
45static 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 */
55static 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 */
63static 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
84static 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
90static 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
101void 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
144unsigned 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
157void 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
169void __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
192void __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 */
208static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) 34static 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
219static int pxa3xx_mfp_resume(struct sys_device *d) 40static 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
26static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { 26static 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 */
75static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { 75static 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[] = {
98static int __init pxa300_init(void) 98static 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
26static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { 26static 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[] = {
86static int __init pxa320_init(void) 86static 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
21static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { 21static 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 = {
179static int __init pxa930_init(void) 179static 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
5obj-y := dma.o 5obj-y := dma.o mfp.o
6 6
7obj-$(CONFIG_GENERIC_GPIO) += gpio.o 7obj-$(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 */
22enum {
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
251typedef 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 */
339struct 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
353void __init mfp_init_base(unsigned long mfpr_base);
354void __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 */
362unsigned long mfp_read(int mfp);
363void mfp_write(int mfp, unsigned long mfpr_val);
364void mfp_config(unsigned long *mfp_cfgs, int num);
365void mfp_config_run(void);
366void 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 */
90static DEFINE_SPINLOCK(mfp_spin_lock);
91
92static void __iomem *mfpr_mmio_base;
93
94struct 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
101static struct mfp_pin mfp_table[MFP_PIN_MAX];
102
103/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
104static 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 */
114static 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 */
122static 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
143static 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
149static 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
160void 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
203unsigned 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
216void 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
228void __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
239void __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
262void 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
271void 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}