Merge branch 'linus' into x86/cleanups
[linux-2.6] / arch / cris / arch-v32 / mach-a3 / 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) 2005-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 #include <hwregs/clkgen_defs.h>
19
20 #undef DEBUG
21
22 #define PINS 80
23 #define PORT_PINS 32
24 #define PORTS 3
25
26 static char pins[PINS];
27 static DEFINE_SPINLOCK(pinmux_lock);
28
29 static void crisv32_pinmux_set(int port);
30
31 int
32 crisv32_pinmux_init(void)
33 {
34         static int initialized;
35
36         if (!initialized) {
37                 initialized = 1;
38                 REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
39                 crisv32_pinmux_alloc(PORT_A, 0, 31, pinmux_gpio);
40                 crisv32_pinmux_alloc(PORT_B, 0, 31, pinmux_gpio);
41                 crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_gpio);
42         }
43
44         return 0;
45 }
46
47 int
48 crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
49 {
50         int i;
51         unsigned long flags;
52
53         crisv32_pinmux_init();
54
55         if (port >= PORTS)
56                 return -EINVAL;
57
58         spin_lock_irqsave(&pinmux_lock, flags);
59
60         for (i = first_pin; i <= last_pin; i++) {
61                 if ((pins[port * PORT_PINS + i] != pinmux_none) &&
62                     (pins[port * PORT_PINS + i] != pinmux_gpio) &&
63                     (pins[port * PORT_PINS + i] != mode)) {
64                         spin_unlock_irqrestore(&pinmux_lock, flags);
65 #ifdef DEBUG
66                         panic("Pinmux alloc failed!\n");
67 #endif
68                         return -EPERM;
69                 }
70         }
71
72         for (i = first_pin; i <= last_pin; i++)
73                 pins[port * PORT_PINS + i] = mode;
74
75         crisv32_pinmux_set(port);
76
77         spin_unlock_irqrestore(&pinmux_lock, flags);
78
79         return 0;
80 }
81
82 int
83 crisv32_pinmux_alloc_fixed(enum fixed_function function)
84 {
85         int ret = -EINVAL;
86         char saved[sizeof pins];
87         unsigned long flags;
88
89         spin_lock_irqsave(&pinmux_lock, flags);
90
91         /* Save internal data for recovery */
92         memcpy(saved, pins, sizeof pins);
93
94         crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
95
96         reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
97         reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
98                 rw_clk_ctrl);
99
100         switch (function) {
101         case pinmux_eth:
102                 clk_ctrl.eth = regk_clkgen_yes;
103                 clk_ctrl.dma0_1_eth = regk_clkgen_yes;
104                 ret = crisv32_pinmux_alloc(PORT_B, 8, 23, pinmux_fixed);
105                 ret |= crisv32_pinmux_alloc(PORT_B, 24, 25, pinmux_fixed);
106                 hwprot.eth = hwprot.eth_mdio = regk_pinmux_yes;
107                 break;
108         case pinmux_geth:
109                 ret = crisv32_pinmux_alloc(PORT_B, 0, 7, pinmux_fixed);
110                 hwprot.geth = regk_pinmux_yes;
111                 break;
112         case pinmux_tg_cmos:
113                 clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
114                 ret = crisv32_pinmux_alloc(PORT_B, 27, 29, pinmux_fixed);
115                 hwprot.tg_clk = regk_pinmux_yes;
116                 break;
117         case pinmux_tg_ccd:
118                 clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
119                 ret = crisv32_pinmux_alloc(PORT_B, 27, 31, pinmux_fixed);
120                 ret |= crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_fixed);
121                 hwprot.tg = hwprot.tg_clk = regk_pinmux_yes;
122                 break;
123         case pinmux_vout:
124                 clk_ctrl.strdma0_2_video = regk_clkgen_yes;
125                 ret = crisv32_pinmux_alloc(PORT_A, 8, 18, pinmux_fixed);
126                 hwprot.vout = hwprot.vout_sync = regk_pinmux_yes;
127                 break;
128         case pinmux_ser1:
129                 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
130                 ret = crisv32_pinmux_alloc(PORT_A, 24, 25, pinmux_fixed);
131                 hwprot.ser1 = regk_pinmux_yes;
132                 break;
133         case pinmux_ser2:
134                 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
135                 ret = crisv32_pinmux_alloc(PORT_A, 26, 27, pinmux_fixed);
136                 hwprot.ser2 = regk_pinmux_yes;
137                 break;
138         case pinmux_ser3:
139                 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
140                 ret = crisv32_pinmux_alloc(PORT_A, 28, 29, pinmux_fixed);
141                 hwprot.ser3 = regk_pinmux_yes;
142                 break;
143         case pinmux_ser4:
144                 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
145                 ret = crisv32_pinmux_alloc(PORT_A, 30, 31, pinmux_fixed);
146                 hwprot.ser4 = regk_pinmux_yes;
147                 break;
148         case pinmux_sser:
149                 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
150                 ret = crisv32_pinmux_alloc(PORT_A, 19, 23, pinmux_fixed);
151                 hwprot.sser = regk_pinmux_yes;
152                 break;
153         case pinmux_pio:
154                 hwprot.pio = regk_pinmux_yes;
155                 ret = 0;
156                 break;
157         case pinmux_pwm0:
158                 ret = crisv32_pinmux_alloc(PORT_A, 30, 30, pinmux_fixed);
159                 hwprot.pwm0 = regk_pinmux_yes;
160                 break;
161         case pinmux_pwm1:
162                 ret = crisv32_pinmux_alloc(PORT_A, 31, 31, pinmux_fixed);
163                 hwprot.pwm1 = regk_pinmux_yes;
164                 break;
165         case pinmux_pwm2:
166                 ret = crisv32_pinmux_alloc(PORT_B, 26, 26, pinmux_fixed);
167                 hwprot.pwm2 = regk_pinmux_yes;
168                 break;
169         case pinmux_i2c0:
170                 ret = crisv32_pinmux_alloc(PORT_A, 0, 1, pinmux_fixed);
171                 hwprot.i2c0 = regk_pinmux_yes;
172                 break;
173         case pinmux_i2c1:
174                 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
175                 hwprot.i2c1 = regk_pinmux_yes;
176                 break;
177         case pinmux_i2c1_3wire:
178                 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
179                 ret |= crisv32_pinmux_alloc(PORT_A, 7, 7, pinmux_fixed);
180                 hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_yes;
181                 break;
182         case pinmux_i2c1_sda1:
183                 ret = crisv32_pinmux_alloc(PORT_A, 2, 4, pinmux_fixed);
184                 hwprot.i2c1 = hwprot.i2c1_sda1 = regk_pinmux_yes;
185                 break;
186         case pinmux_i2c1_sda2:
187                 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
188                 ret |= crisv32_pinmux_alloc(PORT_A, 5, 5, pinmux_fixed);
189                 hwprot.i2c1 = hwprot.i2c1_sda2 = regk_pinmux_yes;
190                 break;
191         case pinmux_i2c1_sda3:
192                 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
193                 ret |= crisv32_pinmux_alloc(PORT_A, 6, 6, pinmux_fixed);
194                 hwprot.i2c1 = hwprot.i2c1_sda3 = regk_pinmux_yes;
195                 break;
196         default:
197                 ret = -EINVAL;
198                 break;
199         }
200
201         if (!ret) {
202                 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
203                 REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
204         } else
205                 memcpy(pins, saved, sizeof pins);
206
207   spin_unlock_irqrestore(&pinmux_lock, flags);
208
209   return ret;
210 }
211
212 void
213 crisv32_pinmux_set(int port)
214 {
215         int i;
216         int gpio_val = 0;
217         int iop_val = 0;
218         int pin = port * PORT_PINS;
219
220         for (i = 0; (i < PORT_PINS) && (pin < PINS); i++, pin++) {
221                 if (pins[pin] == pinmux_gpio)
222                         gpio_val |= (1 << i);
223                 else if (pins[pin] == pinmux_iop)
224                         iop_val |= (1 << i);
225         }
226
227         REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_gio_pa + 4 * port,
228                 gpio_val);
229         REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_iop_pa + 4 * port,
230                 iop_val);
231
232 #ifdef DEBUG
233        crisv32_pinmux_dump();
234 #endif
235 }
236
237 int
238 crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
239 {
240         int i;
241         unsigned long flags;
242
243         crisv32_pinmux_init();
244
245         if (port > PORTS)
246                 return -EINVAL;
247
248         spin_lock_irqsave(&pinmux_lock, flags);
249
250         for (i = first_pin; i <= last_pin; i++)
251                 pins[port * PORT_PINS + i] = pinmux_none;
252
253         crisv32_pinmux_set(port);
254         spin_unlock_irqrestore(&pinmux_lock, flags);
255
256         return 0;
257 }
258
259 int
260 crisv32_pinmux_dealloc_fixed(enum fixed_function function)
261 {
262         int ret = -EINVAL;
263         char saved[sizeof pins];
264         unsigned long flags;
265
266         spin_lock_irqsave(&pinmux_lock, flags);
267
268         /* Save internal data for recovery */
269         memcpy(saved, pins, sizeof pins);
270
271         crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
272
273         reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
274
275         switch (function) {
276         case pinmux_eth:
277                 ret = crisv32_pinmux_dealloc(PORT_B, 8, 23);
278                 ret |= crisv32_pinmux_dealloc(PORT_B, 24, 25);
279                 ret |= crisv32_pinmux_dealloc(PORT_B, 0, 7);
280                 hwprot.eth = hwprot.eth_mdio = hwprot.geth = regk_pinmux_no;
281                 break;
282         case pinmux_tg_cmos:
283                 ret = crisv32_pinmux_dealloc(PORT_B, 27, 29);
284                 hwprot.tg_clk = regk_pinmux_no;
285                 break;
286         case pinmux_tg_ccd:
287                 ret = crisv32_pinmux_dealloc(PORT_B, 27, 31);
288                 ret |= crisv32_pinmux_dealloc(PORT_C, 0, 15);
289                 hwprot.tg = hwprot.tg_clk = regk_pinmux_no;
290                 break;
291         case pinmux_vout:
292                 ret = crisv32_pinmux_dealloc(PORT_A, 8, 18);
293                 hwprot.vout = hwprot.vout_sync = regk_pinmux_no;
294                 break;
295         case pinmux_ser1:
296                 ret = crisv32_pinmux_dealloc(PORT_A, 24, 25);
297                 hwprot.ser1 = regk_pinmux_no;
298                 break;
299         case pinmux_ser2:
300                 ret = crisv32_pinmux_dealloc(PORT_A, 26, 27);
301                 hwprot.ser2 = regk_pinmux_no;
302                 break;
303         case pinmux_ser3:
304                 ret = crisv32_pinmux_dealloc(PORT_A, 28, 29);
305                 hwprot.ser3 = regk_pinmux_no;
306                 break;
307         case pinmux_ser4:
308                 ret = crisv32_pinmux_dealloc(PORT_A, 30, 31);
309                 hwprot.ser4 = regk_pinmux_no;
310                 break;
311         case pinmux_sser:
312                 ret = crisv32_pinmux_dealloc(PORT_A, 19, 23);
313                 hwprot.sser = regk_pinmux_no;
314                 break;
315         case pinmux_pwm0:
316                 ret = crisv32_pinmux_dealloc(PORT_A, 30, 30);
317                 hwprot.pwm0 = regk_pinmux_no;
318                 break;
319         case pinmux_pwm1:
320                 ret = crisv32_pinmux_dealloc(PORT_A, 31, 31);
321                 hwprot.pwm1 = regk_pinmux_no;
322                 break;
323         case pinmux_pwm2:
324                 ret = crisv32_pinmux_dealloc(PORT_B, 26, 26);
325                 hwprot.pwm2 = regk_pinmux_no;
326                 break;
327         case pinmux_i2c0:
328                 ret = crisv32_pinmux_dealloc(PORT_A, 0, 1);
329                 hwprot.i2c0 = regk_pinmux_no;
330                 break;
331         case pinmux_i2c1:
332                 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
333                 hwprot.i2c1 = regk_pinmux_no;
334                 break;
335         case pinmux_i2c1_3wire:
336                 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
337                 ret |= crisv32_pinmux_dealloc(PORT_A, 7, 7);
338                 hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_no;
339                 break;
340         case pinmux_i2c1_sda1:
341                 ret = crisv32_pinmux_dealloc(PORT_A, 2, 4);
342                 hwprot.i2c1_sda1 = regk_pinmux_no;
343                 break;
344         case pinmux_i2c1_sda2:
345                 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
346                 ret |= crisv32_pinmux_dealloc(PORT_A, 5, 5);
347                 hwprot.i2c1_sda2 = regk_pinmux_no;
348                 break;
349         case pinmux_i2c1_sda3:
350                 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
351                 ret |= crisv32_pinmux_dealloc(PORT_A, 6, 6);
352                 hwprot.i2c1_sda3 = regk_pinmux_no;
353                 break;
354         default:
355                 ret = -EINVAL;
356                 break;
357         }
358
359         if (!ret)
360                 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
361         else
362                 memcpy(pins, saved, sizeof pins);
363
364   spin_unlock_irqrestore(&pinmux_lock, flags);
365
366   return ret;
367 }
368
369 void
370 crisv32_pinmux_dump(void)
371 {
372         int i, j;
373         int pin = 0;
374
375         crisv32_pinmux_init();
376
377         for (i = 0; i < PORTS; i++) {
378                 pin++;
379                 printk(KERN_DEBUG "Port %c\n", 'A'+i);
380                 for (j = 0; (j < PORT_PINS) && (pin < PINS); j++, pin++)
381                         printk(KERN_DEBUG
382                                 "  Pin %d = %d\n", j, pins[i * PORT_PINS + j]);
383         }
384 }
385
386 __initcall(crisv32_pinmux_init);