Merge branches 'release' and 'ppc-workaround' into release
[linux-2.6] / arch / cris / arch-v10 / kernel / io_interface_mux.c
1 /* IO interface mux allocator for ETRAX100LX.
2  * Copyright 2004, Axis Communications AB
3  * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
4  */
5
6
7 /* C.f. ETRAX100LX Designer's Reference 20.9 */
8
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/errno.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14
15 #include <asm/arch/svinto.h>
16 #include <asm/io.h>
17 #include <asm/arch/io_interface_mux.h>
18
19
20 #define DBG(s)
21
22 /* Macro to access ETRAX 100 registers */
23 #define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
24                                           IO_STATE_(reg##_, field##_, _##val)
25
26 enum io_if_group {
27         group_a = (1<<0),
28         group_b = (1<<1),
29         group_c = (1<<2),
30         group_d = (1<<3),
31         group_e = (1<<4),
32         group_f = (1<<5)
33 };
34
35 struct watcher
36 {
37         void (*notify)(const unsigned int gpio_in_available,
38                        const unsigned int gpio_out_available,
39                        const unsigned char pa_available,
40                        const unsigned char pb_available);
41         struct watcher *next;
42 };
43
44
45 struct if_group
46 {
47         enum io_if_group        group;
48         unsigned char           used;
49         enum cris_io_interface  owner;
50 };
51
52
53 struct interface
54 {
55         enum cris_io_interface   ioif;
56         unsigned char            groups;
57         unsigned char            used;
58         char                    *owner;
59         unsigned int             gpio_g_in;
60         unsigned int             gpio_g_out;
61         unsigned char            gpio_b;
62 };
63
64 static struct if_group if_groups[6] = {
65         {
66                 .group = group_a,
67                 .used = 0,
68         },
69         {
70                 .group = group_b,
71                 .used = 0,
72         },
73         {
74                 .group = group_c,
75                 .used = 0,
76         },
77         {
78                 .group = group_d,
79                 .used = 0,
80         },
81         {
82                 .group = group_e,
83                 .used = 0,
84         },
85         {
86                 .group = group_f,
87                 .used = 0,
88         }
89 };
90
91 /* The order in the array must match the order of enum
92  * cris_io_interface in io_interface_mux.h */
93 static struct interface interfaces[] = {
94         /* Begin Non-multiplexed interfaces */
95         {
96                 .ioif = if_eth,
97                 .groups = 0,
98                 .gpio_g_in = 0,
99                 .gpio_g_out = 0,
100                 .gpio_b = 0
101         },
102         {
103                 .ioif = if_serial_0,
104                 .groups = 0,
105                 .gpio_g_in = 0,
106                 .gpio_g_out = 0,
107                 .gpio_b = 0
108         },
109         /* End Non-multiplexed interfaces */
110         {
111                 .ioif = if_serial_1,
112                 .groups = group_e,
113                 .gpio_g_in =  0x00000000,
114                 .gpio_g_out = 0x00000000,
115                 .gpio_b = 0x00
116         },
117         {
118                 .ioif = if_serial_2,
119                 .groups = group_b,
120                 .gpio_g_in =  0x000000c0,
121                 .gpio_g_out = 0x000000c0,
122                 .gpio_b = 0x00
123         },
124         {
125                 .ioif = if_serial_3,
126                 .groups = group_c,
127                 .gpio_g_in =  0xc0000000,
128                 .gpio_g_out = 0xc0000000,
129                 .gpio_b = 0x00
130         },
131         {
132                 .ioif = if_sync_serial_1,
133                 .groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
134                                                can be used simultaneously */
135                 .gpio_g_in =  0x00000000,
136                 .gpio_g_out = 0x00000000,
137                 .gpio_b = 0x10
138         },
139         {
140                 .ioif = if_sync_serial_3,
141                 .groups = group_c | group_f,
142                 .gpio_g_in =  0xc0000000,
143                 .gpio_g_out = 0xc0000000,
144                 .gpio_b = 0x80
145         },
146         {
147                 .ioif = if_shared_ram,
148                 .groups = group_a,
149                 .gpio_g_in =  0x0000ff3e,
150                 .gpio_g_out = 0x0000ff38,
151                 .gpio_b = 0x00
152         },
153         {
154                 .ioif = if_shared_ram_w,
155                 .groups = group_a | group_d,
156                 .gpio_g_in =  0x00ffff3e,
157                 .gpio_g_out = 0x00ffff38,
158                 .gpio_b = 0x00
159         },
160         {
161                 .ioif = if_par_0,
162                 .groups = group_a,
163                 .gpio_g_in =  0x0000ff3e,
164                 .gpio_g_out = 0x0000ff3e,
165                 .gpio_b = 0x00
166         },
167         {
168                 .ioif = if_par_1,
169                 .groups = group_d,
170                 .gpio_g_in =  0x3eff0000,
171                 .gpio_g_out = 0x3eff0000,
172                 .gpio_b = 0x00
173         },
174         {
175                 .ioif = if_par_w,
176                 .groups = group_a | group_d,
177                 .gpio_g_in =  0x00ffff3e,
178                 .gpio_g_out = 0x00ffff3e,
179                 .gpio_b = 0x00
180         },
181         {
182                 .ioif = if_scsi8_0,
183                 .groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
184                                                           can be used simultaneously */
185                 .gpio_g_in =  0x0000ffff,
186                 .gpio_g_out = 0x0000ffff,
187                 .gpio_b = 0x10
188         },
189         {
190                 .ioif = if_scsi8_1,
191                 .groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
192                                                           can be used simultaneously */
193                 .gpio_g_in =  0xffff0000,
194                 .gpio_g_out = 0xffff0000,
195                 .gpio_b = 0x80
196         },
197         {
198                 .ioif = if_scsi_w,
199                 .groups = group_a | group_b | group_d | group_f,
200                 .gpio_g_in =  0x01ffffff,
201                 .gpio_g_out = 0x07ffffff,
202                 .gpio_b = 0x80
203         },
204         {
205                 .ioif = if_ata,
206                 .groups = group_a | group_b | group_c | group_d,
207                 .gpio_g_in =  0xf9ffffff,
208                 .gpio_g_out = 0xffffffff,
209                 .gpio_b = 0x80
210         },
211         {
212                 .ioif = if_csp,
213                 .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
214                 .gpio_g_in =  0x00000000,
215                 .gpio_g_out = 0x00000000,
216                 .gpio_b = 0xfc
217         },
218         {
219                 .ioif = if_i2c,
220                 .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
221                 .gpio_g_in =  0x00000000,
222                 .gpio_g_out = 0x00000000,
223                 .gpio_b = 0x03
224         },
225         {
226                 .ioif = if_usb_1,
227                 .groups = group_e | group_f,
228                 .gpio_g_in =  0x00000000,
229                 .gpio_g_out = 0x00000000,
230                 .gpio_b = 0x2c
231         },
232         {
233                 .ioif = if_usb_2,
234                 .groups = group_d,
235                 .gpio_g_in =  0x0e000000,
236                 .gpio_g_out = 0x3c000000,
237                 .gpio_b = 0x00
238         },
239         /* GPIO pins */
240         {
241                 .ioif = if_gpio_grp_a,
242                 .groups = group_a,
243                 .gpio_g_in =  0x0000ff3f,
244                 .gpio_g_out = 0x0000ff3f,
245                 .gpio_b = 0x00
246         },
247         {
248                 .ioif = if_gpio_grp_b,
249                 .groups = group_b,
250                 .gpio_g_in =  0x000000c0,
251                 .gpio_g_out = 0x000000c0,
252                 .gpio_b = 0x00
253         },
254         {
255                 .ioif = if_gpio_grp_c,
256                 .groups = group_c,
257                 .gpio_g_in =  0xc0000000,
258                 .gpio_g_out = 0xc0000000,
259                 .gpio_b = 0x00
260         },
261         {
262                 .ioif = if_gpio_grp_d,
263                 .groups = group_d,
264                 .gpio_g_in =  0x3fff0000,
265                 .gpio_g_out = 0x3fff0000,
266                 .gpio_b = 0x00
267         },
268         {
269                 .ioif = if_gpio_grp_e,
270                 .groups = group_e,
271                 .gpio_g_in =  0x00000000,
272                 .gpio_g_out = 0x00000000,
273                 .gpio_b = 0x00
274         },
275         {
276                 .ioif = if_gpio_grp_f,
277                 .groups = group_f,
278                 .gpio_g_in =  0x00000000,
279                 .gpio_g_out = 0x00000000,
280                 .gpio_b = 0xff
281         }
282         /* Array end */
283 };
284
285 static struct watcher *watchers = NULL;
286
287 static unsigned int gpio_in_pins =  0xffffffff;
288 static unsigned int gpio_out_pins = 0xffffffff;
289 static unsigned char gpio_pb_pins = 0xff;
290 static unsigned char gpio_pa_pins = 0xff;
291
292 static enum cris_io_interface gpio_pa_owners[8];
293 static enum cris_io_interface gpio_pb_owners[8];
294 static enum cris_io_interface gpio_pg_owners[32];
295
296 static int cris_io_interface_init(void);
297
298 static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group)
299 {
300         return (groups & ~group->group);
301 }
302
303
304 static struct if_group *get_group(const unsigned char groups)
305 {
306         int i;
307         for (i = 0; i < ARRAY_SIZE(if_groups); i++) {
308                 if (groups & if_groups[i].group) {
309                         return &if_groups[i];
310                 }
311         }
312         return NULL;
313 }
314
315
316 static void notify_watchers(void)
317 {
318         struct watcher *w = watchers;
319
320         DBG(printk("io_interface_mux: notifying watchers\n"));
321
322         while (NULL != w) {
323                 w->notify((const unsigned int)gpio_in_pins,
324                           (const unsigned int)gpio_out_pins,
325                           (const unsigned char)gpio_pa_pins,
326                           (const unsigned char)gpio_pb_pins);
327                 w = w->next;
328         }
329 }
330
331
332 int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id)
333 {
334         int set_gen_config = 0;
335         int set_gen_config_ii = 0;
336         unsigned long int gens;
337         unsigned long int gens_ii;
338         struct if_group *grp;
339         unsigned char group_set;
340         unsigned long flags;
341
342         (void)cris_io_interface_init();
343
344         DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
345
346         if ((ioif >= if_max_interfaces) || (ioif < 0)) {
347                 printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
348                        ioif,
349                        device_id);
350                 return -EINVAL;
351         }
352
353         local_irq_save(flags);
354
355         if (interfaces[ioif].used) {
356                 local_irq_restore(flags);
357                 printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
358                        device_id,
359                        interfaces[ioif].owner);
360                 return -EBUSY;
361         }
362
363         /* Check that all required groups are free before allocating, */
364         group_set = interfaces[ioif].groups;
365         while (NULL != (grp = get_group(group_set))) {
366                 if (grp->used) {
367                         if (grp->group == group_f) {
368                                 if ((if_sync_serial_1 ==  ioif) ||
369                                     (if_sync_serial_3 ==  ioif)) {
370                                         if ((grp->owner != if_sync_serial_1) &&
371                                             (grp->owner != if_sync_serial_3)) {
372                                                 local_irq_restore(flags);
373                                                 return -EBUSY;
374                                         }
375                                 } else if ((if_scsi8_0 == ioif) ||
376                                            (if_scsi8_1 == ioif)) {
377                                         if ((grp->owner != if_scsi8_0) &&
378                                             (grp->owner != if_scsi8_1)) {
379                                                 local_irq_restore(flags);
380                                                 return -EBUSY;
381                                         }
382                                 }
383                         } else {
384                                 local_irq_restore(flags);
385                                 return -EBUSY;
386                         }
387                 }
388                 group_set = clear_group_from_set(group_set, grp);
389         }
390
391         /* Are the required GPIO pins available too? */
392         if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
393             ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
394             ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
395                 local_irq_restore(flags);
396                 printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
397                        ioif);
398                 return -EBUSY;
399         }
400
401         /* All needed I/O pins and pin groups are free, allocate. */
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         }
408
409         gens = genconfig_shadow;
410         gens_ii = gen_config_ii_shadow;
411
412         set_gen_config = 1;
413         switch (ioif)
414         {
415         /* Begin Non-multiplexed interfaces */
416         case if_eth:
417                 /* fall through */
418         case if_serial_0:
419                 set_gen_config = 0;
420                 break;
421         /* End Non-multiplexed interfaces */
422         case if_serial_1:
423                 set_gen_config_ii = 1;
424                 SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
425                 break;
426         case if_serial_2:
427                 SETS(gens, R_GEN_CONFIG, ser2, select);
428                 break;
429         case if_serial_3:
430                 SETS(gens, R_GEN_CONFIG, ser3, select);
431                 set_gen_config_ii = 1;
432                 SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
433                 break;
434         case if_sync_serial_1:
435                 set_gen_config_ii = 1;
436                 SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
437                 break;
438         case if_sync_serial_3:
439                 SETS(gens, R_GEN_CONFIG, ser3, select);
440                 set_gen_config_ii = 1;
441                 SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
442                 break;
443         case if_shared_ram:
444                 SETS(gens, R_GEN_CONFIG, mio, select);
445                 break;
446         case if_shared_ram_w:
447                 SETS(gens, R_GEN_CONFIG, mio_w, select);
448                 break;
449         case if_par_0:
450                 SETS(gens, R_GEN_CONFIG, par0, select);
451                 break;
452         case if_par_1:
453                 SETS(gens, R_GEN_CONFIG, par1, select);
454                 break;
455         case if_par_w:
456                 SETS(gens, R_GEN_CONFIG, par0, select);
457                 SETS(gens, R_GEN_CONFIG, par_w, select);
458                 break;
459         case if_scsi8_0:
460                 SETS(gens, R_GEN_CONFIG, scsi0, select);
461                 break;
462         case if_scsi8_1:
463                 SETS(gens, R_GEN_CONFIG, scsi1, select);
464                 break;
465         case if_scsi_w:
466                 SETS(gens, R_GEN_CONFIG, scsi0, select);
467                 SETS(gens, R_GEN_CONFIG, scsi0w, select);
468                 break;
469         case if_ata:
470                 SETS(gens, R_GEN_CONFIG, ata, select);
471                 break;
472         case if_csp:
473                 /* fall through */
474         case if_i2c:
475                 set_gen_config = 0;
476                 break;
477         case if_usb_1:
478                 SETS(gens, R_GEN_CONFIG, usb1, select);
479                 break;
480         case if_usb_2:
481                 SETS(gens, R_GEN_CONFIG, usb2, select);
482                 break;
483         case if_gpio_grp_a:
484                 /* GPIO groups are only accounted, don't do configuration changes. */
485                 /* fall through */
486         case if_gpio_grp_b:
487                 /* fall through */
488         case if_gpio_grp_c:
489                 /* fall through */
490         case if_gpio_grp_d:
491                 /* fall through */
492         case if_gpio_grp_e:
493                 /* fall through */
494         case if_gpio_grp_f:
495                 set_gen_config = 0;
496                 break;
497         default:
498                 panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
499                       ioif,
500                       device_id);
501         }
502
503         interfaces[ioif].used = 1;
504         interfaces[ioif].owner = (char*)device_id;
505
506         if (set_gen_config) {
507                 volatile int i;
508                 genconfig_shadow = gens;
509                 *R_GEN_CONFIG = genconfig_shadow;
510                 /* Wait 12 cycles before doing any DMA command */
511                 for(i = 6; i > 0; i--)
512                         nop();
513         }
514         if (set_gen_config_ii) {
515                 gen_config_ii_shadow = gens_ii;
516                 *R_GEN_CONFIG_II = gen_config_ii_shadow;
517         }
518
519         DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
520                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
521         DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
522                    interfaces[ioif].gpio_g_in,
523                    interfaces[ioif].gpio_g_out,
524                    interfaces[ioif].gpio_b));
525
526         gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
527         gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
528         gpio_pb_pins &= ~interfaces[ioif].gpio_b;
529
530         DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
531                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
532
533         local_irq_restore(flags);
534
535         notify_watchers();
536
537         return 0;
538 }
539
540
541 void cris_free_io_interface(enum cris_io_interface ioif)
542 {
543         struct if_group *grp;
544         unsigned char group_set;
545         unsigned long flags;
546
547         (void)cris_io_interface_init();
548
549         if ((ioif >= if_max_interfaces) || (ioif < 0)) {
550                 printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
551                        ioif);
552                 return;
553         }
554         local_irq_save(flags);
555         if (!interfaces[ioif].used) {
556                 printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
557                        ioif);
558                 local_irq_restore(flags);
559                 return;
560         }
561         group_set = interfaces[ioif].groups;
562         while (NULL != (grp = get_group(group_set))) {
563                 if (grp->group == group_f) {
564                         switch (ioif)
565                         {
566                         case if_sync_serial_1:
567                                 if ((grp->owner == if_sync_serial_1) &&
568                                     interfaces[if_sync_serial_3].used) {
569                                         grp->owner = if_sync_serial_3;
570                                 } else
571                                         grp->used = 0;
572                                 break;
573                         case if_sync_serial_3:
574                                 if ((grp->owner == if_sync_serial_3) &&
575                                     interfaces[if_sync_serial_1].used) {
576                                         grp->owner = if_sync_serial_1;
577                                 } else
578                                         grp->used = 0;
579                                 break;
580                         case if_scsi8_0:
581                                 if ((grp->owner == if_scsi8_0) &&
582                                     interfaces[if_scsi8_1].used) {
583                                         grp->owner = if_scsi8_1;
584                                 } else
585                                         grp->used = 0;
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                 }
600                 group_set = clear_group_from_set(group_set, grp);
601         }
602         interfaces[ioif].used = 0;
603         interfaces[ioif].owner = NULL;
604
605         DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
606                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
607         DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
608                    interfaces[ioif].gpio_g_in,
609                    interfaces[ioif].gpio_g_out,
610                    interfaces[ioif].gpio_b));
611
612         gpio_in_pins |= interfaces[ioif].gpio_g_in;
613         gpio_out_pins |= interfaces[ioif].gpio_g_out;
614         gpio_pb_pins |= interfaces[ioif].gpio_b;
615
616         DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
617                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
618
619         local_irq_restore(flags);
620
621         notify_watchers();
622 }
623
624 /* Create a bitmask from bit 0 (inclusive) to bit stop_bit
625    (non-inclusive).  stop_bit == 0 returns 0x0 */
626 static inline unsigned int create_mask(const unsigned stop_bit)
627 {
628         /* Avoid overflow */
629         if (stop_bit >= 32) {
630                 return 0xffffffff;
631         }
632         return (1<<stop_bit)-1;
633 }
634
635
636 /* port can be 'a', 'b' or 'g' */
637 int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
638                                     const char port,
639                                     const unsigned start_bit,
640                                     const unsigned stop_bit)
641 {
642         unsigned int i;
643         unsigned int mask = 0;
644         unsigned int tmp_mask;
645         unsigned long int flags;
646         enum cris_io_interface *owners;
647
648         (void)cris_io_interface_init();
649
650         DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
651                    ioif, port, start_bit, stop_bit));
652
653         if (!((start_bit <= stop_bit) &&
654               ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
655                ((port == 'g') && (stop_bit < 32))))) {
656                 return -EINVAL;
657         }
658
659         mask = create_mask(stop_bit + 1);
660         tmp_mask = create_mask(start_bit);
661         mask &= ~tmp_mask;
662
663         DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
664                    port, start_bit, stop_bit, mask));
665
666         local_irq_save(flags);
667
668         switch (port) {
669         case 'a':
670                 if ((gpio_pa_pins & mask) != mask) {
671                         local_irq_restore(flags);
672                         return -EBUSY;
673                 }
674                 owners = gpio_pa_owners;
675                 gpio_pa_pins &= ~mask;
676                 break;
677         case 'b':
678                 if ((gpio_pb_pins & mask) != mask) {
679                         local_irq_restore(flags);
680                         return -EBUSY;
681                 }
682                 owners = gpio_pb_owners;
683                 gpio_pb_pins &= ~mask;
684                 break;
685         case 'g':
686                 if (((gpio_in_pins & mask) != mask) ||
687                     ((gpio_out_pins & mask) != mask)) {
688                         local_irq_restore(flags);
689                         return -EBUSY;
690                 }
691                 owners = gpio_pg_owners;
692                 gpio_in_pins &= ~mask;
693                 gpio_out_pins &= ~mask;
694                 break;
695         default:
696                 local_irq_restore(flags);
697                 return -EINVAL;
698         }
699
700         for (i = start_bit; i <= stop_bit; i++) {
701                 owners[i] = ioif;
702         }
703         local_irq_restore(flags);
704
705         notify_watchers();
706         return 0;
707 }
708
709
710 /* port can be 'a', 'b' or 'g' */
711 int cris_io_interface_free_pins(const enum cris_io_interface ioif,
712                                 const char port,
713                                 const unsigned start_bit,
714                                 const unsigned stop_bit)
715 {
716         unsigned int i;
717         unsigned int mask = 0;
718         unsigned int tmp_mask;
719         unsigned long int flags;
720         enum cris_io_interface *owners;
721
722         (void)cris_io_interface_init();
723
724         if (!((start_bit <= stop_bit) &&
725               ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
726                ((port == 'g') && (stop_bit < 32))))) {
727                 return -EINVAL;
728         }
729
730         mask = create_mask(stop_bit + 1);
731         tmp_mask = create_mask(start_bit);
732         mask &= ~tmp_mask;
733
734         DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
735                    port, start_bit, stop_bit, mask));
736
737         local_irq_save(flags);
738
739         switch (port) {
740         case 'a':
741                 if ((~gpio_pa_pins & mask) != mask) {
742                         local_irq_restore(flags);
743                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
744                 }
745                 owners = gpio_pa_owners;
746                 break;
747         case 'b':
748                 if ((~gpio_pb_pins & mask) != mask) {
749                         local_irq_restore(flags);
750                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
751                 }
752                 owners = gpio_pb_owners;
753                 break;
754         case 'g':
755                 if (((~gpio_in_pins & mask) != mask) ||
756                     ((~gpio_out_pins & mask) != mask)) {
757                         local_irq_restore(flags);
758                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
759                 }
760                 owners = gpio_pg_owners;
761                 break;
762         default:
763                 owners = NULL; /* Cannot happen. Shut up, gcc! */
764         }
765
766         for (i = start_bit; i <= stop_bit; i++) {
767                 if (owners[i] != ioif) {
768                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
769                 }
770         }
771
772         /* All was ok, change data. */
773         switch (port) {
774         case 'a':
775                 gpio_pa_pins |= mask;
776                 break;
777         case 'b':
778                 gpio_pb_pins |= mask;
779                 break;
780         case 'g':
781                 gpio_in_pins |= mask;
782                 gpio_out_pins |= mask;
783                 break;
784         }
785
786         for (i = start_bit; i <= stop_bit; i++) {
787                 owners[i] = if_unclaimed;
788         }
789         local_irq_restore(flags);
790         notify_watchers();
791
792         return 0;
793 }
794
795
796 int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
797                                                       const unsigned int gpio_out_available,
798                                                       const unsigned char pa_available,
799                                                       const unsigned char pb_available))
800 {
801         struct watcher *w;
802
803         (void)cris_io_interface_init();
804
805         if (NULL == notify) {
806                 return -EINVAL;
807         }
808         w = kmalloc(sizeof(*w), GFP_KERNEL);
809         if (!w) {
810                 return -ENOMEM;
811         }
812         w->notify = notify;
813         w->next = watchers;
814         watchers = w;
815
816         w->notify((const unsigned int)gpio_in_pins,
817                   (const unsigned int)gpio_out_pins,
818                   (const unsigned char)gpio_pa_pins,
819                   (const unsigned char)gpio_pb_pins);
820
821         return 0;
822 }
823
824 void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
825                                                      const unsigned int gpio_out_available,
826                                                      const unsigned char pa_available,
827                                                      const unsigned char pb_available))
828 {
829         struct watcher *w = watchers, *prev = NULL;
830
831         (void)cris_io_interface_init();
832
833         while ((NULL != w) && (w->notify != notify)){
834                 prev = w;
835                 w = w->next;
836         }
837         if (NULL != w) {
838                 if (NULL != prev) {
839                         prev->next = w->next;
840                 } else {
841                         watchers = w->next;
842                 }
843                 kfree(w);
844                 return;
845         }
846         printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
847 }
848
849
850 static int cris_io_interface_init(void)
851 {
852         static int first = 1;
853         int i;
854
855         if (!first) {
856                 return 0;
857         }
858         first = 0;
859
860         for (i = 0; i<8; i++) {
861                 gpio_pa_owners[i] = if_unclaimed;
862                 gpio_pb_owners[i] = if_unclaimed;
863                 gpio_pg_owners[i] = if_unclaimed;
864         }
865         for (; i<32; i++) {
866                 gpio_pg_owners[i] = if_unclaimed;
867         }
868         return 0;
869 }
870
871
872 module_init(cris_io_interface_init);
873
874
875 EXPORT_SYMBOL(cris_request_io_interface);
876 EXPORT_SYMBOL(cris_free_io_interface);
877 EXPORT_SYMBOL(cris_io_interface_allocate_pins);
878 EXPORT_SYMBOL(cris_io_interface_free_pins);
879 EXPORT_SYMBOL(cris_io_interface_register_watcher);
880 EXPORT_SYMBOL(cris_io_interface_delete_watcher);