[ARM] 4635/1: pxa: Change Eric Miao's email address to eric.miao@marvell.com
[linux-2.6/verdex.git] / arch / arm / mach-pxa / mfp.c
blob436f965749641abd7bb80fb4c957aee91641c5ad
1 /*
2 * linux/arch/arm/mach-pxa/mfp.c
4 * PXA3xx Multi-Function Pin Support
6 * Copyright (C) 2007 Marvell Internation Ltd.
8 * 2007-08-21: eric miao <eric.miao@marvell.com>
9 * initial version
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.
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/io.h>
21 #include <asm/hardware.h>
22 #include <asm/arch/mfp.h>
24 /* mfp_spin_lock is used to ensure that MFP register configuration
25 * (most likely a read-modify-write operation) is atomic, and that
26 * mfp_table[] is consistent
28 static DEFINE_SPINLOCK(mfp_spin_lock);
30 static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
31 static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
33 #define mfpr_readl(off) \
34 __raw_readl(mfpr_mmio_base + (off))
36 #define mfpr_writel(off, val) \
37 __raw_writel(val, mfpr_mmio_base + (off))
40 * perform a read-back of any MFPR register to make sure the
41 * previous writings are finished
43 #define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
45 static inline void __mfp_config(int pin, unsigned long val)
47 unsigned long off = mfp_table[pin].mfpr_off;
49 mfp_table[pin].mfpr_val = val;
50 mfpr_writel(off, val);
53 void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num)
55 int i, pin;
56 unsigned long val, flags;
57 mfp_cfg_t *mfp_cfg = mfp_cfgs;
59 spin_lock_irqsave(&mfp_spin_lock, flags);
61 for (i = 0; i < num; i++, mfp_cfg++) {
62 pin = MFP_CFG_PIN(*mfp_cfg);
63 val = MFP_CFG_VAL(*mfp_cfg);
65 BUG_ON(pin >= MFP_PIN_MAX);
67 __mfp_config(pin, val);
70 mfpr_sync();
71 spin_unlock_irqrestore(&mfp_spin_lock, flags);
74 unsigned long pxa3xx_mfp_read(int mfp)
76 unsigned long val, flags;
78 BUG_ON(mfp >= MFP_PIN_MAX);
80 spin_lock_irqsave(&mfp_spin_lock, flags);
81 val = mfpr_readl(mfp_table[mfp].mfpr_off);
82 spin_unlock_irqrestore(&mfp_spin_lock, flags);
84 return val;
87 void pxa3xx_mfp_write(int mfp, unsigned long val)
89 unsigned long flags;
91 BUG_ON(mfp >= MFP_PIN_MAX);
93 spin_lock_irqsave(&mfp_spin_lock, flags);
94 mfpr_writel(mfp_table[mfp].mfpr_off, val);
95 mfpr_sync();
96 spin_unlock_irqrestore(&mfp_spin_lock, flags);
99 void pxa3xx_mfp_set_afds(int mfp, int af, int ds)
101 uint32_t mfpr_off, mfpr_val;
102 unsigned long flags;
104 BUG_ON(mfp >= MFP_PIN_MAX);
106 spin_lock_irqsave(&mfp_spin_lock, flags);
107 mfpr_off = mfp_table[mfp].mfpr_off;
109 mfpr_val = mfpr_readl(mfpr_off);
110 mfpr_val &= ~(MFPR_AF_MASK | MFPR_DRV_MASK);
111 mfpr_val |= (((af & 0x7) << MFPR_ALT_OFFSET) |
112 ((ds & 0x7) << MFPR_DRV_OFFSET));
114 mfpr_writel(mfpr_off, mfpr_val);
115 mfpr_sync();
117 spin_unlock_irqrestore(&mfp_spin_lock, flags);
120 void pxa3xx_mfp_set_rdh(int mfp, int rdh)
122 uint32_t mfpr_off, mfpr_val;
123 unsigned long flags;
125 BUG_ON(mfp >= MFP_PIN_MAX);
127 spin_lock_irqsave(&mfp_spin_lock, flags);
129 mfpr_off = mfp_table[mfp].mfpr_off;
131 mfpr_val = mfpr_readl(mfpr_off);
132 mfpr_val &= ~MFPR_RDH_MASK;
134 if (likely(rdh))
135 mfpr_val |= (1u << MFPR_SS_OFFSET);
137 mfpr_writel(mfpr_off, mfpr_val);
138 mfpr_sync();
140 spin_unlock_irqrestore(&mfp_spin_lock, flags);
143 void pxa3xx_mfp_set_lpm(int mfp, int lpm)
145 uint32_t mfpr_off, mfpr_val;
146 unsigned long flags;
148 BUG_ON(mfp >= MFP_PIN_MAX);
150 spin_lock_irqsave(&mfp_spin_lock, flags);
152 mfpr_off = mfp_table[mfp].mfpr_off;
153 mfpr_val = mfpr_readl(mfpr_off);
154 mfpr_val &= ~MFPR_LPM_MASK;
156 if (lpm & 0x1) mfpr_val |= 1u << MFPR_SON_OFFSET;
157 if (lpm & 0x2) mfpr_val |= 1u << MFPR_SD_OFFSET;
158 if (lpm & 0x4) mfpr_val |= 1u << MFPR_PU_OFFSET;
159 if (lpm & 0x8) mfpr_val |= 1u << MFPR_PD_OFFSET;
160 if (lpm &0x10) mfpr_val |= 1u << MFPR_PS_OFFSET;
162 mfpr_writel(mfpr_off, mfpr_val);
163 mfpr_sync();
165 spin_unlock_irqrestore(&mfp_spin_lock, flags);
168 void pxa3xx_mfp_set_pull(int mfp, int pull)
170 uint32_t mfpr_off, mfpr_val;
171 unsigned long flags;
173 BUG_ON(mfp >= MFP_PIN_MAX);
175 spin_lock_irqsave(&mfp_spin_lock, flags);
177 mfpr_off = mfp_table[mfp].mfpr_off;
178 mfpr_val = mfpr_readl(mfpr_off);
179 mfpr_val &= ~MFPR_PULL_MASK;
180 mfpr_val |= ((pull & 0x7u) << MFPR_PD_OFFSET);
182 mfpr_writel(mfpr_off, mfpr_val);
183 mfpr_sync();
185 spin_unlock_irqrestore(&mfp_spin_lock, flags);
188 void pxa3xx_mfp_set_edge(int mfp, int edge)
190 uint32_t mfpr_off, mfpr_val;
191 unsigned long flags;
193 BUG_ON(mfp >= MFP_PIN_MAX);
195 spin_lock_irqsave(&mfp_spin_lock, flags);
197 mfpr_off = mfp_table[mfp].mfpr_off;
198 mfpr_val = mfpr_readl(mfpr_off);
200 mfpr_val &= ~MFPR_EDGE_MASK;
201 mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;
202 mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;
204 mfpr_writel(mfpr_off, mfpr_val);
205 mfpr_sync();
207 spin_unlock_irqrestore(&mfp_spin_lock, flags);
210 void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
212 struct pxa3xx_mfp_addr_map *p;
213 unsigned long offset, flags;
214 int i;
216 spin_lock_irqsave(&mfp_spin_lock, flags);
218 for (p = map; p->start != MFP_PIN_INVALID; p++) {
219 offset = p->offset;
220 i = p->start;
222 do {
223 mfp_table[i].mfpr_off = offset;
224 mfp_table[i].mfpr_val = 0;
225 offset += 4; i++;
226 } while ((i <= p->end) && (p->end != -1));
229 spin_unlock_irqrestore(&mfp_spin_lock, flags);
232 void __init pxa3xx_init_mfp(void)
234 memset(mfp_table, 0, sizeof(mfp_table));