Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[cascardo/linux.git] / arch / cris / arch-v32 / mach-fs / pinmux.c
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.
5  *
6  * Copyright (c) 2004-2007 Axis Communications AB.
7  */
8
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>
18
19 #undef DEBUG
20
21 #define PORT_PINS 18
22 #define PORTS 4
23
24 static char pins[PORTS][PORT_PINS];
25 static DEFINE_SPINLOCK(pinmux_lock);
26
27 static void crisv32_pinmux_set(int port);
28
29 int crisv32_pinmux_init(void)
30 {
31         static int initialized;
32
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);
44         }
45
46         return 0;
47 }
48
49 int
50 crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
51 {
52         int i;
53         unsigned long flags;
54
55         crisv32_pinmux_init();
56
57         if (port > PORTS || port < 0)
58                 return -EINVAL;
59
60         spin_lock_irqsave(&pinmux_lock, flags);
61
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;
71                 }
72         }
73
74         for (i = first_pin; i <= last_pin; i++)
75                 pins[port][i] = mode;
76
77         crisv32_pinmux_set(port);
78
79         spin_unlock_irqrestore(&pinmux_lock, flags);
80
81         return 0;
82 }
83
84 int crisv32_pinmux_alloc_fixed(enum fixed_function function)
85 {
86         int ret = -EINVAL;
87         char saved[sizeof pins];
88         unsigned long flags;
89
90         spin_lock_irqsave(&pinmux_lock, flags);
91
92         /* Save internal data for recovery */
93         memcpy(saved, pins, sizeof pins);
94
95         crisv32_pinmux_init();  /* Must be done before we read rw_hwprot */
96
97         reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
98
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;
156         }
157
158         if (!ret)
159                 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
160         else
161                 memcpy(pins, saved, sizeof pins);
162
163         spin_unlock_irqrestore(&pinmux_lock, flags);
164
165         return ret;
166 }
167
168 void crisv32_pinmux_set(int port)
169 {
170         int i;
171         int gpio_val = 0;
172         int iop_val = 0;
173
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);
179         }
180
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);
185
186 #ifdef DEBUG
187         crisv32_pinmux_dump();
188 #endif
189 }
190
191 int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
192 {
193         int i;
194         unsigned long flags;
195
196         crisv32_pinmux_init();
197
198         if (port > PORTS || port < 0)
199                 return -EINVAL;
200
201         spin_lock_irqsave(&pinmux_lock, flags);
202
203         for (i = first_pin; i <= last_pin; i++)
204                 pins[port][i] = pinmux_none;
205
206         crisv32_pinmux_set(port);
207         spin_unlock_irqrestore(&pinmux_lock, flags);
208
209         return 0;
210 }
211
212 int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
213 {
214         int ret = -EINVAL;
215         char saved[sizeof pins];
216         unsigned long flags;
217
218         spin_lock_irqsave(&pinmux_lock, flags);
219
220         /* Save internal data for recovery */
221         memcpy(saved, pins, sizeof pins);
222
223         crisv32_pinmux_init();  /* Must be done before we read rw_hwprot */
224
225         reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
226
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;
284         }
285
286         if (!ret)
287                 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
288         else
289                 memcpy(pins, saved, sizeof pins);
290
291         spin_unlock_irqrestore(&pinmux_lock, flags);
292
293         return ret;
294 }
295
296 void crisv32_pinmux_dump(void)
297 {
298         int i, j;
299
300         crisv32_pinmux_init();
301
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]);
306         }
307 }
308
309 __initcall(crisv32_pinmux_init);