diff options
author | Jesper Nilsson <jesper.nilsson@axis.com> | 2008-01-29 05:27:19 -0500 |
---|---|---|
committer | Jesper Nilsson <jesper.nilsson@axis.com> | 2008-02-08 05:06:32 -0500 |
commit | b1220e2e7f03a0e86078c82819e802c25047638d (patch) | |
tree | da1280d7199cf06d22939ac92da51f4664dcc372 /arch/cris | |
parent | 5f526d1467383fbd7d64b4f7de85b2889838e454 (diff) |
CRIS v10: Update kernel/io_interface_mux.c
Fixed a bug where two interfaces using pins in the same pin group could
not be allocated at the same time even if there where no pin collisions.
Change all restore and returns into goto exit pattern.
Also, remove useless CVS id and correct chapter reference for ETRAX100LX
Designer's Reference in comment.
Diffstat (limited to 'arch/cris')
-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; |