1
2
3
4
5
6
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
26static char pins[PINS];
27static DEFINE_SPINLOCK(pinmux_lock);
28
29static void crisv32_pinmux_set(int port);
30
31int
32crisv32_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
47int
48crisv32_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
82int
83crisv32_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
94 memcpy(saved, pins, sizeof pins);
95
96 crisv32_pinmux_init();
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
213void
214crisv32_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
238int
239crisv32_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
260int
261crisv32_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
271 memcpy(saved, pins, sizeof pins);
272
273 crisv32_pinmux_init();
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
371void
372crisv32_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);
389