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