aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v32/mach-fs/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-fs/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-fs/pinmux.c')
-rw-r--r--arch/cris/arch-v32/mach-fs/pinmux.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/mach-fs/pinmux.c b/arch/cris/arch-v32/mach-fs/pinmux.c
new file mode 100644
index 000000000000..d722ad9ae626
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/pinmux.c
@@ -0,0 +1,309 @@
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
24static char pins[PORTS][PORT_PINS];
25static DEFINE_SPINLOCK(pinmux_lock);
26
27static void crisv32_pinmux_set(int port);
28
29int 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
49int
50crisv32_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)
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
84int 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
168void 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
191int 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)
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
212int 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
296void 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);