aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v32/mach-a3/pinmux.c
diff options
context:
space:
mode:
authorJesper Nilsson <jespern@stork.se.axis.com>2007-11-29 11:11:23 -0500
committerJesper Nilsson <jesper.nilsson@axis.com>2008-02-08 05:06:23 -0500
commit035e111f9a9b29843bc899f03d56f19d94bebb53 (patch)
treecb46b3c0eb6d9f2cc915522153454d3acaa7fcda /arch/cris/arch-v32/mach-a3/pinmux.c
parent6107c61fd3e6b47106b078db1726ad814564efef (diff)
CRIS v32: Add new machine dependent files for Etrax-FS and Artpec-3.
The two chips are somewhat different, and needs different handling. Adds handing of the dma, dram initialization, hardware settings, io, memory arbiter and pinmux Also moves the dma, dram initialization and io from CRIS v32 common files.
Diffstat (limited to 'arch/cris/arch-v32/mach-a3/pinmux.c')
-rw-r--r--arch/cris/arch-v32/mach-a3/pinmux.c386
1 files changed, 386 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c
new file mode 100644
index 000000000000..0a28c9bedfb7
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/pinmux.c
@@ -0,0 +1,386 @@
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
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
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
212void
213crisv32_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
237int
238crisv32_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
259int
260crisv32_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
369void
370crisv32_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);