Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux/fpc-iii.git] / arch / cris / arch-v32 / mach-fs / pinmux.c
blob38f29eec14a617af2691c8ce35545f1fcc8a4422
1 /*
2 * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
3 * Unassigned pins and GPIO pins can be allocated to a fixed interface
4 * or the I/O processor instead.
6 * Copyright (c) 2004-2007 Axis Communications AB.
7 */
9 #include <linux/init.h>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/spinlock.h>
14 #include <hwregs/reg_map.h>
15 #include <hwregs/reg_rdwr.h>
16 #include <pinmux.h>
17 #include <hwregs/pinmux_defs.h>
19 #undef DEBUG
21 #define PORT_PINS 18
22 #define PORTS 4
24 static char pins[PORTS][PORT_PINS];
25 static DEFINE_SPINLOCK(pinmux_lock);
27 static void crisv32_pinmux_set(int port);
29 int crisv32_pinmux_init(void)
31 static int initialized;
33 if (!initialized) {
34 reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa);
35 initialized = 1;
36 REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
37 pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
38 pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
39 REG_WR(pinmux, regi_pinmux, rw_pa, pa);
40 crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
41 crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
42 crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
43 crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
46 return 0;
49 int
50 crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
52 int i;
53 unsigned long flags;
55 crisv32_pinmux_init();
57 if (port > PORTS || port < 0)
58 return -EINVAL;
60 spin_lock_irqsave(&pinmux_lock, flags);
62 for (i = first_pin; i <= last_pin; i++) {
63 if ((pins[port][i] != pinmux_none)
64 && (pins[port][i] != pinmux_gpio)
65 && (pins[port][i] != mode)) {
66 spin_unlock_irqrestore(&pinmux_lock, flags);
67 #ifdef DEBUG
68 panic("Pinmux alloc failed!\n");
69 #endif
70 return -EPERM;
74 for (i = first_pin; i <= last_pin; i++)
75 pins[port][i] = mode;
77 crisv32_pinmux_set(port);
79 spin_unlock_irqrestore(&pinmux_lock, flags);
81 return 0;
84 int crisv32_pinmux_alloc_fixed(enum fixed_function function)
86 int ret = -EINVAL;
87 char saved[sizeof pins];
88 unsigned long flags;
90 spin_lock_irqsave(&pinmux_lock, flags);
92 /* Save internal data for recovery */
93 memcpy(saved, pins, sizeof pins);
95 crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
97 reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
99 switch (function) {
100 case pinmux_ser1:
101 ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
102 hwprot.ser1 = regk_pinmux_yes;
103 break;
104 case pinmux_ser2:
105 ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
106 hwprot.ser2 = regk_pinmux_yes;
107 break;
108 case pinmux_ser3:
109 ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
110 hwprot.ser3 = regk_pinmux_yes;
111 break;
112 case pinmux_sser0:
113 ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
114 ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
115 hwprot.sser0 = regk_pinmux_yes;
116 break;
117 case pinmux_sser1:
118 ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
119 hwprot.sser1 = regk_pinmux_yes;
120 break;
121 case pinmux_ata0:
122 ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
123 ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
124 hwprot.ata0 = regk_pinmux_yes;
125 break;
126 case pinmux_ata1:
127 ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
128 ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
129 hwprot.ata1 = regk_pinmux_yes;
130 break;
131 case pinmux_ata2:
132 ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
133 ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
134 hwprot.ata2 = regk_pinmux_yes;
135 break;
136 case pinmux_ata3:
137 ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
138 ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
139 hwprot.ata2 = regk_pinmux_yes;
140 break;
141 case pinmux_ata:
142 ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
143 ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
144 hwprot.ata = regk_pinmux_yes;
145 break;
146 case pinmux_eth1:
147 ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
148 hwprot.eth1 = regk_pinmux_yes;
149 hwprot.eth1_mgm = regk_pinmux_yes;
150 break;
151 case pinmux_timer:
152 ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
153 hwprot.timer = regk_pinmux_yes;
154 spin_unlock_irqrestore(&pinmux_lock, flags);
155 return ret;
158 if (!ret)
159 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
160 else
161 memcpy(pins, saved, sizeof pins);
163 spin_unlock_irqrestore(&pinmux_lock, flags);
165 return ret;
168 void crisv32_pinmux_set(int port)
170 int i;
171 int gpio_val = 0;
172 int iop_val = 0;
174 for (i = 0; i < PORT_PINS; i++) {
175 if (pins[port][i] == pinmux_gpio)
176 gpio_val |= (1 << i);
177 else if (pins[port][i] == pinmux_iop)
178 iop_val |= (1 << i);
181 REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8 * port,
182 gpio_val);
183 REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8 * port,
184 iop_val);
186 #ifdef DEBUG
187 crisv32_pinmux_dump();
188 #endif
191 int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
193 int i;
194 unsigned long flags;
196 crisv32_pinmux_init();
198 if (port > PORTS || port < 0)
199 return -EINVAL;
201 spin_lock_irqsave(&pinmux_lock, flags);
203 for (i = first_pin; i <= last_pin; i++)
204 pins[port][i] = pinmux_none;
206 crisv32_pinmux_set(port);
207 spin_unlock_irqrestore(&pinmux_lock, flags);
209 return 0;
212 int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
214 int ret = -EINVAL;
215 char saved[sizeof pins];
216 unsigned long flags;
218 spin_lock_irqsave(&pinmux_lock, flags);
220 /* Save internal data for recovery */
221 memcpy(saved, pins, sizeof pins);
223 crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
225 reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
227 switch (function) {
228 case pinmux_ser1:
229 ret = crisv32_pinmux_dealloc(PORT_C, 4, 7);
230 hwprot.ser1 = regk_pinmux_no;
231 break;
232 case pinmux_ser2:
233 ret = crisv32_pinmux_dealloc(PORT_C, 8, 11);
234 hwprot.ser2 = regk_pinmux_no;
235 break;
236 case pinmux_ser3:
237 ret = crisv32_pinmux_dealloc(PORT_C, 12, 15);
238 hwprot.ser3 = regk_pinmux_no;
239 break;
240 case pinmux_sser0:
241 ret = crisv32_pinmux_dealloc(PORT_C, 0, 3);
242 ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16);
243 hwprot.sser0 = regk_pinmux_no;
244 break;
245 case pinmux_sser1:
246 ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
247 hwprot.sser1 = regk_pinmux_no;
248 break;
249 case pinmux_ata0:
250 ret = crisv32_pinmux_dealloc(PORT_D, 5, 7);
251 ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17);
252 hwprot.ata0 = regk_pinmux_no;
253 break;
254 case pinmux_ata1:
255 ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
256 ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17);
257 hwprot.ata1 = regk_pinmux_no;
258 break;
259 case pinmux_ata2:
260 ret = crisv32_pinmux_dealloc(PORT_C, 11, 15);
261 ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3);
262 hwprot.ata2 = regk_pinmux_no;
263 break;
264 case pinmux_ata3:
265 ret = crisv32_pinmux_dealloc(PORT_C, 8, 10);
266 ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2);
267 hwprot.ata2 = regk_pinmux_no;
268 break;
269 case pinmux_ata:
270 ret = crisv32_pinmux_dealloc(PORT_B, 0, 15);
271 ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15);
272 hwprot.ata = regk_pinmux_no;
273 break;
274 case pinmux_eth1:
275 ret = crisv32_pinmux_dealloc(PORT_E, 0, 17);
276 hwprot.eth1 = regk_pinmux_no;
277 hwprot.eth1_mgm = regk_pinmux_no;
278 break;
279 case pinmux_timer:
280 ret = crisv32_pinmux_dealloc(PORT_C, 16, 16);
281 hwprot.timer = regk_pinmux_no;
282 spin_unlock_irqrestore(&pinmux_lock, flags);
283 return ret;
286 if (!ret)
287 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
288 else
289 memcpy(pins, saved, sizeof pins);
291 spin_unlock_irqrestore(&pinmux_lock, flags);
293 return ret;
296 void crisv32_pinmux_dump(void)
298 int i, j;
300 crisv32_pinmux_init();
302 for (i = 0; i < PORTS; i++) {
303 printk(KERN_DEBUG "Port %c\n", 'B' + i);
304 for (j = 0; j < PORT_PINS; j++)
305 printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
309 __initcall(crisv32_pinmux_init);