diff options
-rw-r--r-- | arch/cris/arch-v10/kernel/io_interface_mux.c | 515 |
1 files changed, 408 insertions, 107 deletions
diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c index f3b327d4ed9c..add98e0941b5 100644 --- a/arch/cris/arch-v10/kernel/io_interface_mux.c +++ b/arch/cris/arch-v10/kernel/io_interface_mux.c | |||
@@ -1,10 +1,9 @@ | |||
1 | /* IO interface mux allocator for ETRAX100LX. | 1 | /* IO interface mux allocator for ETRAX100LX. |
2 | * Copyright 2004, Axis Communications AB | 2 | * Copyright 2004-2007, Axis Communications AB |
3 | * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $ | ||
4 | */ | 3 | */ |
5 | 4 | ||
6 | 5 | ||
7 | /* C.f. ETRAX100LX Designer's Reference 20.9 */ | 6 | /* C.f. ETRAX100LX Designer's Reference chapter 19.9 */ |
8 | 7 | ||
9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
10 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
@@ -45,17 +44,39 @@ struct watcher | |||
45 | struct if_group | 44 | struct if_group |
46 | { | 45 | { |
47 | enum io_if_group group; | 46 | enum io_if_group group; |
48 | unsigned char used; | 47 | /* name - the name of the group 'A' to 'F' */ |
49 | enum cris_io_interface owner; | 48 | char *name; |
49 | /* used - a bit mask of all pins in the group in the order listed | ||
50 | * in the tables in 19.9.1 to 19.9.6. Note that no | ||
51 | * distinction is made between in, out and in/out pins. */ | ||
52 | unsigned int used; | ||
50 | }; | 53 | }; |
51 | 54 | ||
52 | 55 | ||
53 | struct interface | 56 | struct interface |
54 | { | 57 | { |
55 | enum cris_io_interface ioif; | 58 | enum cris_io_interface ioif; |
59 | /* name - the name of the interface */ | ||
60 | char *name; | ||
61 | /* groups - OR'ed together io_if_group flags describing what pin groups | ||
62 | * the interface uses pins in. */ | ||
56 | unsigned char groups; | 63 | unsigned char groups; |
64 | /* used - set when the interface is allocated. */ | ||
57 | unsigned char used; | 65 | unsigned char used; |
58 | char *owner; | 66 | char *owner; |
67 | /* group_a through group_f - bit masks describing what pins in the | ||
68 | * pin groups the interface uses. */ | ||
69 | unsigned int group_a; | ||
70 | unsigned int group_b; | ||
71 | unsigned int group_c; | ||
72 | unsigned int group_d; | ||
73 | unsigned int group_e; | ||
74 | unsigned int group_f; | ||
75 | |||
76 | /* gpio_g_in, gpio_g_out, gpio_b - bit masks telling what pins in the | ||
77 | * GPIO ports the interface uses. This could be reconstucted using | ||
78 | * the group_X masks and a table of what pins the GPIO ports use, | ||
79 | * but that would be messy. */ | ||
59 | unsigned int gpio_g_in; | 80 | unsigned int gpio_g_in; |
60 | unsigned int gpio_g_out; | 81 | unsigned int gpio_g_out; |
61 | unsigned char gpio_b; | 82 | unsigned char gpio_b; |
@@ -64,26 +85,32 @@ struct interface | |||
64 | static struct if_group if_groups[6] = { | 85 | static struct if_group if_groups[6] = { |
65 | { | 86 | { |
66 | .group = group_a, | 87 | .group = group_a, |
88 | .name = "A", | ||
67 | .used = 0, | 89 | .used = 0, |
68 | }, | 90 | }, |
69 | { | 91 | { |
70 | .group = group_b, | 92 | .group = group_b, |
93 | .name = "B", | ||
71 | .used = 0, | 94 | .used = 0, |
72 | }, | 95 | }, |
73 | { | 96 | { |
74 | .group = group_c, | 97 | .group = group_c, |
98 | .name = "C", | ||
75 | .used = 0, | 99 | .used = 0, |
76 | }, | 100 | }, |
77 | { | 101 | { |
78 | .group = group_d, | 102 | .group = group_d, |
103 | .name = "D", | ||
79 | .used = 0, | 104 | .used = 0, |
80 | }, | 105 | }, |
81 | { | 106 | { |
82 | .group = group_e, | 107 | .group = group_e, |
108 | .name = "E", | ||
83 | .used = 0, | 109 | .used = 0, |
84 | }, | 110 | }, |
85 | { | 111 | { |
86 | .group = group_f, | 112 | .group = group_f, |
113 | .name = "F", | ||
87 | .used = 0, | 114 | .used = 0, |
88 | } | 115 | } |
89 | }; | 116 | }; |
@@ -94,14 +121,32 @@ static struct interface interfaces[] = { | |||
94 | /* Begin Non-multiplexed interfaces */ | 121 | /* Begin Non-multiplexed interfaces */ |
95 | { | 122 | { |
96 | .ioif = if_eth, | 123 | .ioif = if_eth, |
124 | .name = "ethernet", | ||
97 | .groups = 0, | 125 | .groups = 0, |
126 | |||
127 | .group_a = 0, | ||
128 | .group_b = 0, | ||
129 | .group_c = 0, | ||
130 | .group_d = 0, | ||
131 | .group_e = 0, | ||
132 | .group_f = 0, | ||
133 | |||
98 | .gpio_g_in = 0, | 134 | .gpio_g_in = 0, |
99 | .gpio_g_out = 0, | 135 | .gpio_g_out = 0, |
100 | .gpio_b = 0 | 136 | .gpio_b = 0 |
101 | }, | 137 | }, |
102 | { | 138 | { |
103 | .ioif = if_serial_0, | 139 | .ioif = if_serial_0, |
140 | .name = "serial_0", | ||
104 | .groups = 0, | 141 | .groups = 0, |
142 | |||
143 | .group_a = 0, | ||
144 | .group_b = 0, | ||
145 | .group_c = 0, | ||
146 | .group_d = 0, | ||
147 | .group_e = 0, | ||
148 | .group_f = 0, | ||
149 | |||
105 | .gpio_g_in = 0, | 150 | .gpio_g_in = 0, |
106 | .gpio_g_out = 0, | 151 | .gpio_g_out = 0, |
107 | .gpio_b = 0 | 152 | .gpio_b = 0 |
@@ -109,172 +154,385 @@ static struct interface interfaces[] = { | |||
109 | /* End Non-multiplexed interfaces */ | 154 | /* End Non-multiplexed interfaces */ |
110 | { | 155 | { |
111 | .ioif = if_serial_1, | 156 | .ioif = if_serial_1, |
157 | .name = "serial_1", | ||
112 | .groups = group_e, | 158 | .groups = group_e, |
159 | |||
160 | .group_a = 0, | ||
161 | .group_b = 0, | ||
162 | .group_c = 0, | ||
163 | .group_d = 0, | ||
164 | .group_e = 0x0f, | ||
165 | .group_f = 0, | ||
166 | |||
113 | .gpio_g_in = 0x00000000, | 167 | .gpio_g_in = 0x00000000, |
114 | .gpio_g_out = 0x00000000, | 168 | .gpio_g_out = 0x00000000, |
115 | .gpio_b = 0x00 | 169 | .gpio_b = 0x00 |
116 | }, | 170 | }, |
117 | { | 171 | { |
118 | .ioif = if_serial_2, | 172 | .ioif = if_serial_2, |
173 | .name = "serial_2", | ||
119 | .groups = group_b, | 174 | .groups = group_b, |
175 | |||
176 | .group_a = 0, | ||
177 | .group_b = 0x0f, | ||
178 | .group_c = 0, | ||
179 | .group_d = 0, | ||
180 | .group_e = 0, | ||
181 | .group_f = 0, | ||
182 | |||
120 | .gpio_g_in = 0x000000c0, | 183 | .gpio_g_in = 0x000000c0, |
121 | .gpio_g_out = 0x000000c0, | 184 | .gpio_g_out = 0x000000c0, |
122 | .gpio_b = 0x00 | 185 | .gpio_b = 0x00 |
123 | }, | 186 | }, |
124 | { | 187 | { |
125 | .ioif = if_serial_3, | 188 | .ioif = if_serial_3, |
189 | .name = "serial_3", | ||
126 | .groups = group_c, | 190 | .groups = group_c, |
191 | |||
192 | .group_a = 0, | ||
193 | .group_b = 0, | ||
194 | .group_c = 0x0f, | ||
195 | .group_d = 0, | ||
196 | .group_e = 0, | ||
197 | .group_f = 0, | ||
198 | |||
127 | .gpio_g_in = 0xc0000000, | 199 | .gpio_g_in = 0xc0000000, |
128 | .gpio_g_out = 0xc0000000, | 200 | .gpio_g_out = 0xc0000000, |
129 | .gpio_b = 0x00 | 201 | .gpio_b = 0x00 |
130 | }, | 202 | }, |
131 | { | 203 | { |
132 | .ioif = if_sync_serial_1, | 204 | .ioif = if_sync_serial_1, |
133 | .groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3 | 205 | .name = "sync_serial_1", |
134 | can be used simultaneously */ | 206 | .groups = group_e | group_f, |
207 | |||
208 | .group_a = 0, | ||
209 | .group_b = 0, | ||
210 | .group_c = 0, | ||
211 | .group_d = 0, | ||
212 | .group_e = 0x0f, | ||
213 | .group_f = 0x10, | ||
214 | |||
135 | .gpio_g_in = 0x00000000, | 215 | .gpio_g_in = 0x00000000, |
136 | .gpio_g_out = 0x00000000, | 216 | .gpio_g_out = 0x00000000, |
137 | .gpio_b = 0x10 | 217 | .gpio_b = 0x10 |
138 | }, | 218 | }, |
139 | { | 219 | { |
140 | .ioif = if_sync_serial_3, | 220 | .ioif = if_sync_serial_3, |
221 | .name = "sync_serial_3", | ||
141 | .groups = group_c | group_f, | 222 | .groups = group_c | group_f, |
223 | |||
224 | .group_a = 0, | ||
225 | .group_b = 0, | ||
226 | .group_c = 0x0f, | ||
227 | .group_d = 0, | ||
228 | .group_e = 0, | ||
229 | .group_f = 0x80, | ||
230 | |||
142 | .gpio_g_in = 0xc0000000, | 231 | .gpio_g_in = 0xc0000000, |
143 | .gpio_g_out = 0xc0000000, | 232 | .gpio_g_out = 0xc0000000, |
144 | .gpio_b = 0x80 | 233 | .gpio_b = 0x80 |
145 | }, | 234 | }, |
146 | { | 235 | { |
147 | .ioif = if_shared_ram, | 236 | .ioif = if_shared_ram, |
237 | .name = "shared_ram", | ||
148 | .groups = group_a, | 238 | .groups = group_a, |
239 | |||
240 | .group_a = 0x7f8ff, | ||
241 | .group_b = 0, | ||
242 | .group_c = 0, | ||
243 | .group_d = 0, | ||
244 | .group_e = 0, | ||
245 | .group_f = 0, | ||
246 | |||
149 | .gpio_g_in = 0x0000ff3e, | 247 | .gpio_g_in = 0x0000ff3e, |
150 | .gpio_g_out = 0x0000ff38, | 248 | .gpio_g_out = 0x0000ff38, |
151 | .gpio_b = 0x00 | 249 | .gpio_b = 0x00 |
152 | }, | 250 | }, |
153 | { | 251 | { |
154 | .ioif = if_shared_ram_w, | 252 | .ioif = if_shared_ram_w, |
253 | .name = "shared_ram_w", | ||
155 | .groups = group_a | group_d, | 254 | .groups = group_a | group_d, |
255 | |||
256 | .group_a = 0x7f8ff, | ||
257 | .group_b = 0, | ||
258 | .group_c = 0, | ||
259 | .group_d = 0xff, | ||
260 | .group_e = 0, | ||
261 | .group_f = 0, | ||
262 | |||
156 | .gpio_g_in = 0x00ffff3e, | 263 | .gpio_g_in = 0x00ffff3e, |
157 | .gpio_g_out = 0x00ffff38, | 264 | .gpio_g_out = 0x00ffff38, |
158 | .gpio_b = 0x00 | 265 | .gpio_b = 0x00 |
159 | }, | 266 | }, |
160 | { | 267 | { |
161 | .ioif = if_par_0, | 268 | .ioif = if_par_0, |
269 | .name = "par_0", | ||
162 | .groups = group_a, | 270 | .groups = group_a, |
271 | |||
272 | .group_a = 0x7fbff, | ||
273 | .group_b = 0, | ||
274 | .group_c = 0, | ||
275 | .group_d = 0, | ||
276 | .group_e = 0, | ||
277 | .group_f = 0, | ||
278 | |||
163 | .gpio_g_in = 0x0000ff3e, | 279 | .gpio_g_in = 0x0000ff3e, |
164 | .gpio_g_out = 0x0000ff3e, | 280 | .gpio_g_out = 0x0000ff3e, |
165 | .gpio_b = 0x00 | 281 | .gpio_b = 0x00 |
166 | }, | 282 | }, |
167 | { | 283 | { |
168 | .ioif = if_par_1, | 284 | .ioif = if_par_1, |
285 | .name = "par_1", | ||
169 | .groups = group_d, | 286 | .groups = group_d, |
287 | |||
288 | .group_a = 0, | ||
289 | .group_b = 0, | ||
290 | .group_c = 0, | ||
291 | .group_d = 0x7feff, | ||
292 | .group_e = 0, | ||
293 | .group_f = 0, | ||
294 | |||
170 | .gpio_g_in = 0x3eff0000, | 295 | .gpio_g_in = 0x3eff0000, |
171 | .gpio_g_out = 0x3eff0000, | 296 | .gpio_g_out = 0x3eff0000, |
172 | .gpio_b = 0x00 | 297 | .gpio_b = 0x00 |
173 | }, | 298 | }, |
174 | { | 299 | { |
175 | .ioif = if_par_w, | 300 | .ioif = if_par_w, |
301 | .name = "par_w", | ||
176 | .groups = group_a | group_d, | 302 | .groups = group_a | group_d, |
303 | |||
304 | .group_a = 0x7fbff, | ||
305 | .group_b = 0, | ||
306 | .group_c = 0, | ||
307 | .group_d = 0xff, | ||
308 | .group_e = 0, | ||
309 | .group_f = 0, | ||
310 | |||
177 | .gpio_g_in = 0x00ffff3e, | 311 | .gpio_g_in = 0x00ffff3e, |
178 | .gpio_g_out = 0x00ffff3e, | 312 | .gpio_g_out = 0x00ffff3e, |
179 | .gpio_b = 0x00 | 313 | .gpio_b = 0x00 |
180 | }, | 314 | }, |
181 | { | 315 | { |
182 | .ioif = if_scsi8_0, | 316 | .ioif = if_scsi8_0, |
183 | .groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1 | 317 | .name = "scsi8_0", |
184 | can be used simultaneously */ | 318 | .groups = group_a | group_b | group_f, |
319 | |||
320 | .group_a = 0x7ffff, | ||
321 | .group_b = 0x0f, | ||
322 | .group_c = 0, | ||
323 | .group_d = 0, | ||
324 | .group_e = 0, | ||
325 | .group_f = 0x10, | ||
326 | |||
185 | .gpio_g_in = 0x0000ffff, | 327 | .gpio_g_in = 0x0000ffff, |
186 | .gpio_g_out = 0x0000ffff, | 328 | .gpio_g_out = 0x0000ffff, |
187 | .gpio_b = 0x10 | 329 | .gpio_b = 0x10 |
188 | }, | 330 | }, |
189 | { | 331 | { |
190 | .ioif = if_scsi8_1, | 332 | .ioif = if_scsi8_1, |
191 | .groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1 | 333 | .name = "scsi8_1", |
192 | can be used simultaneously */ | 334 | .groups = group_c | group_d | group_f, |
335 | |||
336 | .group_a = 0, | ||
337 | .group_b = 0, | ||
338 | .group_c = 0x0f, | ||
339 | .group_d = 0x7ffff, | ||
340 | .group_e = 0, | ||
341 | .group_f = 0x80, | ||
342 | |||
193 | .gpio_g_in = 0xffff0000, | 343 | .gpio_g_in = 0xffff0000, |
194 | .gpio_g_out = 0xffff0000, | 344 | .gpio_g_out = 0xffff0000, |
195 | .gpio_b = 0x80 | 345 | .gpio_b = 0x80 |
196 | }, | 346 | }, |
197 | { | 347 | { |
198 | .ioif = if_scsi_w, | 348 | .ioif = if_scsi_w, |
349 | .name = "scsi_w", | ||
199 | .groups = group_a | group_b | group_d | group_f, | 350 | .groups = group_a | group_b | group_d | group_f, |
351 | |||
352 | .group_a = 0x7ffff, | ||
353 | .group_b = 0x0f, | ||
354 | .group_c = 0, | ||
355 | .group_d = 0x601ff, | ||
356 | .group_e = 0, | ||
357 | .group_f = 0x90, | ||
358 | |||
200 | .gpio_g_in = 0x01ffffff, | 359 | .gpio_g_in = 0x01ffffff, |
201 | .gpio_g_out = 0x07ffffff, | 360 | .gpio_g_out = 0x07ffffff, |
202 | .gpio_b = 0x80 | 361 | .gpio_b = 0x80 |
203 | }, | 362 | }, |
204 | { | 363 | { |
205 | .ioif = if_ata, | 364 | .ioif = if_ata, |
365 | .name = "ata", | ||
206 | .groups = group_a | group_b | group_c | group_d, | 366 | .groups = group_a | group_b | group_c | group_d, |
367 | |||
368 | .group_a = 0x7ffff, | ||
369 | .group_b = 0x0f, | ||
370 | .group_c = 0x0f, | ||
371 | .group_d = 0x7cfff, | ||
372 | .group_e = 0, | ||
373 | .group_f = 0, | ||
374 | |||
207 | .gpio_g_in = 0xf9ffffff, | 375 | .gpio_g_in = 0xf9ffffff, |
208 | .gpio_g_out = 0xffffffff, | 376 | .gpio_g_out = 0xffffffff, |
209 | .gpio_b = 0x80 | 377 | .gpio_b = 0x80 |
210 | }, | 378 | }, |
211 | { | 379 | { |
212 | .ioif = if_csp, | 380 | .ioif = if_csp, |
213 | .groups = group_f, /* if_csp and if_i2c can be used simultaneously */ | 381 | .name = "csp", |
382 | .groups = group_f, | ||
383 | |||
384 | .group_a = 0, | ||
385 | .group_b = 0, | ||
386 | .group_c = 0, | ||
387 | .group_d = 0, | ||
388 | .group_e = 0, | ||
389 | .group_f = 0xfc, | ||
390 | |||
214 | .gpio_g_in = 0x00000000, | 391 | .gpio_g_in = 0x00000000, |
215 | .gpio_g_out = 0x00000000, | 392 | .gpio_g_out = 0x00000000, |
216 | .gpio_b = 0xfc | 393 | .gpio_b = 0xfc |
217 | }, | 394 | }, |
218 | { | 395 | { |
219 | .ioif = if_i2c, | 396 | .ioif = if_i2c, |
220 | .groups = group_f, /* if_csp and if_i2c can be used simultaneously */ | 397 | .name = "i2c", |
398 | .groups = group_f, | ||
399 | |||
400 | .group_a = 0, | ||
401 | .group_b = 0, | ||
402 | .group_c = 0, | ||
403 | .group_d = 0, | ||
404 | .group_e = 0, | ||
405 | .group_f = 0x03, | ||
406 | |||
221 | .gpio_g_in = 0x00000000, | 407 | .gpio_g_in = 0x00000000, |
222 | .gpio_g_out = 0x00000000, | 408 | .gpio_g_out = 0x00000000, |
223 | .gpio_b = 0x03 | 409 | .gpio_b = 0x03 |
224 | }, | 410 | }, |
225 | { | 411 | { |
226 | .ioif = if_usb_1, | 412 | .ioif = if_usb_1, |
413 | .name = "usb_1", | ||
227 | .groups = group_e | group_f, | 414 | .groups = group_e | group_f, |
415 | |||
416 | .group_a = 0, | ||
417 | .group_b = 0, | ||
418 | .group_c = 0, | ||
419 | .group_d = 0, | ||
420 | .group_e = 0x0f, | ||
421 | .group_f = 0x2c, | ||
422 | |||
228 | .gpio_g_in = 0x00000000, | 423 | .gpio_g_in = 0x00000000, |
229 | .gpio_g_out = 0x00000000, | 424 | .gpio_g_out = 0x00000000, |
230 | .gpio_b = 0x2c | 425 | .gpio_b = 0x2c |
231 | }, | 426 | }, |
232 | { | 427 | { |
233 | .ioif = if_usb_2, | 428 | .ioif = if_usb_2, |
429 | .name = "usb_2", | ||
234 | .groups = group_d, | 430 | .groups = group_d, |
235 | .gpio_g_in = 0x0e000000, | 431 | |
236 | .gpio_g_out = 0x3c000000, | 432 | .group_a = 0, |
433 | .group_b = 0, | ||
434 | .group_c = 0, | ||
435 | .group_d = 0, | ||
436 | .group_e = 0x33e00, | ||
437 | .group_f = 0, | ||
438 | |||
439 | .gpio_g_in = 0x3e000000, | ||
440 | .gpio_g_out = 0x0c000000, | ||
237 | .gpio_b = 0x00 | 441 | .gpio_b = 0x00 |
238 | }, | 442 | }, |
239 | /* GPIO pins */ | 443 | /* GPIO pins */ |
240 | { | 444 | { |
241 | .ioif = if_gpio_grp_a, | 445 | .ioif = if_gpio_grp_a, |
446 | .name = "gpio_a", | ||
242 | .groups = group_a, | 447 | .groups = group_a, |
448 | |||
449 | .group_a = 0, | ||
450 | .group_b = 0, | ||
451 | .group_c = 0, | ||
452 | .group_d = 0, | ||
453 | .group_e = 0, | ||
454 | .group_f = 0, | ||
455 | |||
243 | .gpio_g_in = 0x0000ff3f, | 456 | .gpio_g_in = 0x0000ff3f, |
244 | .gpio_g_out = 0x0000ff3f, | 457 | .gpio_g_out = 0x0000ff3f, |
245 | .gpio_b = 0x00 | 458 | .gpio_b = 0x00 |
246 | }, | 459 | }, |
247 | { | 460 | { |
248 | .ioif = if_gpio_grp_b, | 461 | .ioif = if_gpio_grp_b, |
462 | .name = "gpio_b", | ||
249 | .groups = group_b, | 463 | .groups = group_b, |
464 | |||
465 | .group_a = 0, | ||
466 | .group_b = 0, | ||
467 | .group_c = 0, | ||
468 | .group_d = 0, | ||
469 | .group_e = 0, | ||
470 | .group_f = 0, | ||
471 | |||
250 | .gpio_g_in = 0x000000c0, | 472 | .gpio_g_in = 0x000000c0, |
251 | .gpio_g_out = 0x000000c0, | 473 | .gpio_g_out = 0x000000c0, |
252 | .gpio_b = 0x00 | 474 | .gpio_b = 0x00 |
253 | }, | 475 | }, |
254 | { | 476 | { |
255 | .ioif = if_gpio_grp_c, | 477 | .ioif = if_gpio_grp_c, |
478 | .name = "gpio_c", | ||
256 | .groups = group_c, | 479 | .groups = group_c, |
480 | |||
481 | .group_a = 0, | ||
482 | .group_b = 0, | ||
483 | .group_c = 0, | ||
484 | .group_d = 0, | ||
485 | .group_e = 0, | ||
486 | .group_f = 0, | ||
487 | |||
257 | .gpio_g_in = 0xc0000000, | 488 | .gpio_g_in = 0xc0000000, |
258 | .gpio_g_out = 0xc0000000, | 489 | .gpio_g_out = 0xc0000000, |
259 | .gpio_b = 0x00 | 490 | .gpio_b = 0x00 |
260 | }, | 491 | }, |
261 | { | 492 | { |
262 | .ioif = if_gpio_grp_d, | 493 | .ioif = if_gpio_grp_d, |
494 | .name = "gpio_d", | ||
263 | .groups = group_d, | 495 | .groups = group_d, |
496 | |||
497 | .group_a = 0, | ||
498 | .group_b = 0, | ||
499 | .group_c = 0, | ||
500 | .group_d = 0, | ||
501 | .group_e = 0, | ||
502 | .group_f = 0, | ||
503 | |||
264 | .gpio_g_in = 0x3fff0000, | 504 | .gpio_g_in = 0x3fff0000, |
265 | .gpio_g_out = 0x3fff0000, | 505 | .gpio_g_out = 0x3fff0000, |
266 | .gpio_b = 0x00 | 506 | .gpio_b = 0x00 |
267 | }, | 507 | }, |
268 | { | 508 | { |
269 | .ioif = if_gpio_grp_e, | 509 | .ioif = if_gpio_grp_e, |
510 | .name = "gpio_e", | ||
270 | .groups = group_e, | 511 | .groups = group_e, |
512 | |||
513 | .group_a = 0, | ||
514 | .group_b = 0, | ||
515 | .group_c = 0, | ||
516 | .group_d = 0, | ||
517 | .group_e = 0, | ||
518 | .group_f = 0, | ||
519 | |||
271 | .gpio_g_in = 0x00000000, | 520 | .gpio_g_in = 0x00000000, |
272 | .gpio_g_out = 0x00000000, | 521 | .gpio_g_out = 0x00000000, |
273 | .gpio_b = 0x00 | 522 | .gpio_b = 0x00 |
274 | }, | 523 | }, |
275 | { | 524 | { |
276 | .ioif = if_gpio_grp_f, | 525 | .ioif = if_gpio_grp_f, |
526 | .name = "gpio_f", | ||
277 | .groups = group_f, | 527 | .groups = group_f, |
528 | |||
529 | .group_a = 0, | ||
530 | .group_b = 0, | ||
531 | .group_c = 0, | ||
532 | .group_d = 0, | ||
533 | .group_e = 0, | ||
534 | .group_f = 0, | ||
535 | |||
278 | .gpio_g_in = 0x00000000, | 536 | .gpio_g_in = 0x00000000, |
279 | .gpio_g_out = 0x00000000, | 537 | .gpio_g_out = 0x00000000, |
280 | .gpio_b = 0xff | 538 | .gpio_b = 0xff |
@@ -284,11 +542,13 @@ static struct interface interfaces[] = { | |||
284 | 542 | ||
285 | static struct watcher *watchers = NULL; | 543 | static struct watcher *watchers = NULL; |
286 | 544 | ||
545 | /* The pins that are free to use in the GPIO ports. */ | ||
287 | static unsigned int gpio_in_pins = 0xffffffff; | 546 | static unsigned int gpio_in_pins = 0xffffffff; |
288 | static unsigned int gpio_out_pins = 0xffffffff; | 547 | static unsigned int gpio_out_pins = 0xffffffff; |
289 | static unsigned char gpio_pb_pins = 0xff; | 548 | static unsigned char gpio_pb_pins = 0xff; |
290 | static unsigned char gpio_pa_pins = 0xff; | 549 | static unsigned char gpio_pa_pins = 0xff; |
291 | 550 | ||
551 | /* Identifiers for the owners of the GPIO pins. */ | ||
292 | static enum cris_io_interface gpio_pa_owners[8]; | 552 | static enum cris_io_interface gpio_pa_owners[8]; |
293 | static enum cris_io_interface gpio_pb_owners[8]; | 553 | static enum cris_io_interface gpio_pb_owners[8]; |
294 | static enum cris_io_interface gpio_pg_owners[32]; | 554 | static enum cris_io_interface gpio_pg_owners[32]; |
@@ -338,13 +598,15 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id | |||
338 | struct if_group *grp; | 598 | struct if_group *grp; |
339 | unsigned char group_set; | 599 | unsigned char group_set; |
340 | unsigned long flags; | 600 | unsigned long flags; |
601 | int res = 0; | ||
341 | 602 | ||
342 | (void)cris_io_interface_init(); | 603 | (void)cris_io_interface_init(); |
343 | 604 | ||
344 | DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id)); | 605 | DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id)); |
345 | 606 | ||
346 | if ((ioif >= if_max_interfaces) || (ioif < 0)) { | 607 | if ((ioif >= if_max_interfaces) || (ioif < 0)) { |
347 | printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n", | 608 | printk(KERN_CRIT "cris_request_io_interface: Bad interface " |
609 | "%u submitted for %s\n", | ||
348 | ioif, | 610 | ioif, |
349 | device_id); | 611 | device_id); |
350 | return -EINVAL; | 612 | return -EINVAL; |
@@ -353,59 +615,69 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id | |||
353 | local_irq_save(flags); | 615 | local_irq_save(flags); |
354 | 616 | ||
355 | if (interfaces[ioif].used) { | 617 | if (interfaces[ioif].used) { |
356 | local_irq_restore(flags); | 618 | printk(KERN_CRIT "cris_io_interface: Cannot allocate interface " |
357 | printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n", | 619 | "%s for %s, in use by %s\n", |
620 | interfaces[ioif].name, | ||
358 | device_id, | 621 | device_id, |
359 | interfaces[ioif].owner); | 622 | interfaces[ioif].owner); |
360 | return -EBUSY; | 623 | res = -EBUSY; |
624 | goto exit; | ||
361 | } | 625 | } |
362 | 626 | ||
363 | /* Check that all required groups are free before allocating, */ | 627 | /* Check that all required pins in the used groups are free |
628 | * before allocating. */ | ||
364 | group_set = interfaces[ioif].groups; | 629 | group_set = interfaces[ioif].groups; |
365 | while (NULL != (grp = get_group(group_set))) { | 630 | while (NULL != (grp = get_group(group_set))) { |
366 | if (grp->used) { | 631 | unsigned int if_group_use = 0; |
367 | if (grp->group == group_f) { | 632 | |
368 | if ((if_sync_serial_1 == ioif) || | 633 | switch (grp->group) { |
369 | (if_sync_serial_3 == ioif)) { | 634 | case group_a: |
370 | if ((grp->owner != if_sync_serial_1) && | 635 | if_group_use = interfaces[ioif].group_a; |
371 | (grp->owner != if_sync_serial_3)) { | 636 | break; |
372 | local_irq_restore(flags); | 637 | case group_b: |
373 | return -EBUSY; | 638 | if_group_use = interfaces[ioif].group_b; |
374 | } | 639 | break; |
375 | } else if ((if_scsi8_0 == ioif) || | 640 | case group_c: |
376 | (if_scsi8_1 == ioif)) { | 641 | if_group_use = interfaces[ioif].group_c; |
377 | if ((grp->owner != if_scsi8_0) && | 642 | break; |
378 | (grp->owner != if_scsi8_1)) { | 643 | case group_d: |
379 | local_irq_restore(flags); | 644 | if_group_use = interfaces[ioif].group_d; |
380 | return -EBUSY; | 645 | break; |
381 | } | 646 | case group_e: |
382 | } | 647 | if_group_use = interfaces[ioif].group_e; |
383 | } else { | 648 | break; |
384 | local_irq_restore(flags); | 649 | case group_f: |
385 | return -EBUSY; | 650 | if_group_use = interfaces[ioif].group_f; |
386 | } | 651 | break; |
652 | default: | ||
653 | BUG_ON(1); | ||
387 | } | 654 | } |
655 | |||
656 | if (if_group_use & grp->used) { | ||
657 | printk(KERN_INFO "cris_request_io_interface: group " | ||
658 | "%s needed by %s not available\n", | ||
659 | grp->name, interfaces[ioif].name); | ||
660 | res = -EBUSY; | ||
661 | goto exit; | ||
662 | } | ||
663 | |||
388 | group_set = clear_group_from_set(group_set, grp); | 664 | group_set = clear_group_from_set(group_set, grp); |
389 | } | 665 | } |
390 | 666 | ||
391 | /* Are the required GPIO pins available too? */ | 667 | /* Are the required GPIO pins available too? */ |
392 | if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) || | 668 | if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != |
393 | ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) || | 669 | interfaces[ioif].gpio_g_in) || |
394 | ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) { | 670 | ((interfaces[ioif].gpio_g_out & gpio_out_pins) != |
395 | local_irq_restore(flags); | 671 | interfaces[ioif].gpio_g_out) || |
396 | printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n", | 672 | ((interfaces[ioif].gpio_b & gpio_pb_pins) != |
397 | ioif); | 673 | interfaces[ioif].gpio_b)) { |
398 | return -EBUSY; | 674 | printk(KERN_CRIT "cris_request_io_interface: Could not get " |
399 | } | 675 | "required pins for interface %u\n", ioif); |
400 | 676 | res = -EBUSY; | |
401 | /* All needed I/O pins and pin groups are free, allocate. */ | 677 | goto exit; |
402 | group_set = interfaces[ioif].groups; | ||
403 | while (NULL != (grp = get_group(group_set))) { | ||
404 | grp->used = 1; | ||
405 | grp->owner = ioif; | ||
406 | group_set = clear_group_from_set(group_set, grp); | ||
407 | } | 678 | } |
408 | 679 | ||
680 | /* Check which registers need to be reconfigured. */ | ||
409 | gens = genconfig_shadow; | 681 | gens = genconfig_shadow; |
410 | gens_ii = gen_config_ii_shadow; | 682 | gens_ii = gen_config_ii_shadow; |
411 | 683 | ||
@@ -495,9 +767,43 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id | |||
495 | set_gen_config = 0; | 767 | set_gen_config = 0; |
496 | break; | 768 | break; |
497 | default: | 769 | default: |
498 | panic("cris_request_io_interface: Bad interface %u submitted for %s\n", | 770 | printk(KERN_INFO "cris_request_io_interface: Bad interface " |
499 | ioif, | 771 | "%u submitted for %s\n", |
500 | device_id); | 772 | ioif, device_id); |
773 | res = -EBUSY; | ||
774 | goto exit; | ||
775 | } | ||
776 | |||
777 | /* All needed I/O pins and pin groups are free, allocate. */ | ||
778 | group_set = interfaces[ioif].groups; | ||
779 | while (NULL != (grp = get_group(group_set))) { | ||
780 | unsigned int if_group_use = 0; | ||
781 | |||
782 | switch (grp->group) { | ||
783 | case group_a: | ||
784 | if_group_use = interfaces[ioif].group_a; | ||
785 | break; | ||
786 | case group_b: | ||
787 | if_group_use = interfaces[ioif].group_b; | ||
788 | break; | ||
789 | case group_c: | ||
790 | if_group_use = interfaces[ioif].group_c; | ||
791 | break; | ||
792 | case group_d: | ||
793 | if_group_use = interfaces[ioif].group_d; | ||
794 | break; | ||
795 | case group_e: | ||
796 | if_group_use = interfaces[ioif].group_e; | ||
797 | break; | ||
798 | case group_f: | ||
799 | if_group_use = interfaces[ioif].group_f; | ||
800 | break; | ||
801 | default: | ||
802 | BUG_ON(1); | ||
803 | } | ||
804 | grp->used |= if_group_use; | ||
805 | |||
806 | group_set = clear_group_from_set(group_set, grp); | ||
501 | } | 807 | } |
502 | 808 | ||
503 | interfaces[ioif].used = 1; | 809 | interfaces[ioif].used = 1; |
@@ -516,25 +822,28 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id | |||
516 | *R_GEN_CONFIG_II = gen_config_ii_shadow; | 822 | *R_GEN_CONFIG_II = gen_config_ii_shadow; |
517 | } | 823 | } |
518 | 824 | ||
519 | DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | 825 | DBG(printk(KERN_DEBUG "GPIO pins: available before: " |
520 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | 826 | "g_in=0x%08x g_out=0x%08x pb=0x%02x\n", |
521 | DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | 827 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); |
522 | interfaces[ioif].gpio_g_in, | 828 | DBG(printk(KERN_DEBUG |
523 | interfaces[ioif].gpio_g_out, | 829 | "grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", |
524 | interfaces[ioif].gpio_b)); | 830 | interfaces[ioif].gpio_g_in, |
831 | interfaces[ioif].gpio_g_out, | ||
832 | interfaces[ioif].gpio_b)); | ||
525 | 833 | ||
526 | gpio_in_pins &= ~interfaces[ioif].gpio_g_in; | 834 | gpio_in_pins &= ~interfaces[ioif].gpio_g_in; |
527 | gpio_out_pins &= ~interfaces[ioif].gpio_g_out; | 835 | gpio_out_pins &= ~interfaces[ioif].gpio_g_out; |
528 | gpio_pb_pins &= ~interfaces[ioif].gpio_b; | 836 | gpio_pb_pins &= ~interfaces[ioif].gpio_b; |
529 | 837 | ||
530 | DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | 838 | DBG(printk(KERN_DEBUG "GPIO pins: available after: " |
531 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | 839 | "g_in=0x%08x g_out=0x%08x pb=0x%02x\n", |
840 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | ||
532 | 841 | ||
842 | exit: | ||
533 | local_irq_restore(flags); | 843 | local_irq_restore(flags); |
534 | 844 | if (res == 0) | |
535 | notify_watchers(); | 845 | notify_watchers(); |
536 | 846 | return res; | |
537 | return 0; | ||
538 | } | 847 | } |
539 | 848 | ||
540 | 849 | ||
@@ -560,43 +869,35 @@ void cris_free_io_interface(enum cris_io_interface ioif) | |||
560 | } | 869 | } |
561 | group_set = interfaces[ioif].groups; | 870 | group_set = interfaces[ioif].groups; |
562 | while (NULL != (grp = get_group(group_set))) { | 871 | while (NULL != (grp = get_group(group_set))) { |
563 | if (grp->group == group_f) { | 872 | unsigned int if_group_use = 0; |
564 | switch (ioif) | 873 | |
565 | { | 874 | switch (grp->group) { |
566 | case if_sync_serial_1: | 875 | case group_a: |
567 | if ((grp->owner == if_sync_serial_1) && | 876 | if_group_use = interfaces[ioif].group_a; |
568 | interfaces[if_sync_serial_3].used) { | 877 | break; |
569 | grp->owner = if_sync_serial_3; | 878 | case group_b: |
570 | } else | 879 | if_group_use = interfaces[ioif].group_b; |
571 | grp->used = 0; | 880 | break; |
572 | break; | 881 | case group_c: |
573 | case if_sync_serial_3: | 882 | if_group_use = interfaces[ioif].group_c; |
574 | if ((grp->owner == if_sync_serial_3) && | 883 | break; |
575 | interfaces[if_sync_serial_1].used) { | 884 | case group_d: |
576 | grp->owner = if_sync_serial_1; | 885 | if_group_use = interfaces[ioif].group_d; |
577 | } else | 886 | break; |
578 | grp->used = 0; | 887 | case group_e: |
579 | break; | 888 | if_group_use = interfaces[ioif].group_e; |
580 | case if_scsi8_0: | 889 | break; |
581 | if ((grp->owner == if_scsi8_0) && | 890 | case group_f: |
582 | interfaces[if_scsi8_1].used) { | 891 | if_group_use = interfaces[ioif].group_f; |
583 | grp->owner = if_scsi8_1; | 892 | break; |
584 | } else | 893 | default: |
585 | grp->used = 0; | 894 | BUG_ON(1); |
586 | break; | ||
587 | case if_scsi8_1: | ||
588 | if ((grp->owner == if_scsi8_1) && | ||
589 | interfaces[if_scsi8_0].used) { | ||
590 | grp->owner = if_scsi8_0; | ||
591 | } else | ||
592 | grp->used = 0; | ||
593 | break; | ||
594 | default: | ||
595 | grp->used = 0; | ||
596 | } | ||
597 | } else { | ||
598 | grp->used = 0; | ||
599 | } | 895 | } |
896 | |||
897 | if ((grp->used & if_group_use) != if_group_use) | ||
898 | BUG_ON(1); | ||
899 | grp->used = grp->used & ~if_group_use; | ||
900 | |||
600 | group_set = clear_group_from_set(group_set, grp); | 901 | group_set = clear_group_from_set(group_set, grp); |
601 | } | 902 | } |
602 | interfaces[ioif].used = 0; | 903 | interfaces[ioif].used = 0; |