3a9114e89edfcc1f2ef6e87b8e7c7bc6ca1fd35d
[linux-2.6.git] / 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                 printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
396                        ioif);
397                 return -EBUSY;
398         }
399
400         /* All needed I/O pins and pin groups are free, allocate. */
401         group_set = interfaces[ioif].groups;
402         while (NULL != (grp = get_group(group_set))) {
403                 grp->used = 1;
404                 grp->owner = ioif;
405                 group_set = clear_group_from_set(group_set, grp);
406         }
407
408         gens = genconfig_shadow;
409         gens_ii = gen_config_ii_shadow;
410
411         set_gen_config = 1;
412         switch (ioif)
413         {
414         /* Begin Non-multiplexed interfaces */
415         case if_eth:
416                 /* fall through */
417         case if_serial_0:
418                 set_gen_config = 0;
419                 break;
420         /* End Non-multiplexed interfaces */
421         case if_serial_1:
422                 set_gen_config_ii = 1;
423                 SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
424                 break;
425         case if_serial_2:
426                 SETS(gens, R_GEN_CONFIG, ser2, select);
427                 break;
428         case if_serial_3:
429                 SETS(gens, R_GEN_CONFIG, ser3, select);
430                 set_gen_config_ii = 1;
431                 SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
432                 break;
433         case if_sync_serial_1:
434                 set_gen_config_ii = 1;
435                 SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
436                 break;
437         case if_sync_serial_3:
438                 SETS(gens, R_GEN_CONFIG, ser3, select);
439                 set_gen_config_ii = 1;
440                 SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
441                 break;
442         case if_shared_ram:
443                 SETS(gens, R_GEN_CONFIG, mio, select);
444                 break;
445         case if_shared_ram_w:
446                 SETS(gens, R_GEN_CONFIG, mio_w, select);
447                 break;
448         case if_par_0:
449                 SETS(gens, R_GEN_CONFIG, par0, select);
450                 break;
451         case if_par_1:
452                 SETS(gens, R_GEN_CONFIG, par1, select);
453                 break;
454         case if_par_w:
455                 SETS(gens, R_GEN_CONFIG, par0, select);
456                 SETS(gens, R_GEN_CONFIG, par_w, select);
457                 break;
458         case if_scsi8_0:
459                 SETS(gens, R_GEN_CONFIG, scsi0, select);
460                 break;
461         case if_scsi8_1:
462                 SETS(gens, R_GEN_CONFIG, scsi1, select);
463                 break;
464         case if_scsi_w:
465                 SETS(gens, R_GEN_CONFIG, scsi0, select);
466                 SETS(gens, R_GEN_CONFIG, scsi0w, select);
467                 break;
468         case if_ata:
469                 SETS(gens, R_GEN_CONFIG, ata, select);
470                 break;
471         case if_csp:
472                 /* fall through */
473         case if_i2c:
474                 set_gen_config = 0;
475                 break;
476         case if_usb_1:
477                 SETS(gens, R_GEN_CONFIG, usb1, select);
478                 break;
479         case if_usb_2:
480                 SETS(gens, R_GEN_CONFIG, usb2, select);
481                 break;
482         case if_gpio_grp_a:
483                 /* GPIO groups are only accounted, don't do configuration changes. */
484                 /* fall through */
485         case if_gpio_grp_b:
486                 /* fall through */
487         case if_gpio_grp_c:
488                 /* fall through */
489         case if_gpio_grp_d:
490                 /* fall through */
491         case if_gpio_grp_e:
492                 /* fall through */
493         case if_gpio_grp_f:
494                 set_gen_config = 0;
495                 break;
496         default:
497                 panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
498                       ioif,
499                       device_id);
500         }
501
502         interfaces[ioif].used = 1;
503         interfaces[ioif].owner = (char*)device_id;
504
505         if (set_gen_config) {
506                 volatile int i;
507                 genconfig_shadow = gens;
508                 *R_GEN_CONFIG = genconfig_shadow;
509                 /* Wait 12 cycles before doing any DMA command */
510                 for(i = 6; i > 0; i--)
511                         nop();
512         }
513         if (set_gen_config_ii) {
514                 gen_config_ii_shadow = gens_ii;
515                 *R_GEN_CONFIG_II = gen_config_ii_shadow;
516         }
517
518         DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
519                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
520         DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
521                    interfaces[ioif].gpio_g_in,
522                    interfaces[ioif].gpio_g_out,
523                    interfaces[ioif].gpio_b));
524
525         gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
526         gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
527         gpio_pb_pins &= ~interfaces[ioif].gpio_b;
528
529         DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
530                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
531
532         local_irq_restore(flags);
533
534         notify_watchers();
535
536         return 0;
537 }
538
539
540 void cris_free_io_interface(enum cris_io_interface ioif)
541 {
542         struct if_group *grp;
543         unsigned char group_set;
544         unsigned long flags;
545
546         (void)cris_io_interface_init();
547
548         if ((ioif >= if_max_interfaces) || (ioif < 0)) {
549                 printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
550                        ioif);
551                 return;
552         }
553         local_irq_save(flags);
554         if (!interfaces[ioif].used) {
555                 printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
556                        ioif);
557                 local_irq_restore(flags);
558                 return;
559         }
560         group_set = interfaces[ioif].groups;
561         while (NULL != (grp = get_group(group_set))) {
562                 if (grp->group == group_f) {
563                         switch (ioif)
564                         {
565                         case if_sync_serial_1:
566                                 if ((grp->owner == if_sync_serial_1) &&
567                                     interfaces[if_sync_serial_3].used) {
568                                         grp->owner = if_sync_serial_3;
569                                 } else
570                                         grp->used = 0;
571                                 break;
572                         case if_sync_serial_3:
573                                 if ((grp->owner == if_sync_serial_3) &&
574                                     interfaces[if_sync_serial_1].used) {
575                                         grp->owner = if_sync_serial_1;
576                                 } else
577                                         grp->used = 0;
578                                 break;
579                         case if_scsi8_0:
580                                 if ((grp->owner == if_scsi8_0) &&
581                                     interfaces[if_scsi8_1].used) {
582                                         grp->owner = if_scsi8_1;
583                                 } else
584                                         grp->used = 0;
585                                 break;
586                         case if_scsi8_1:
587                                 if ((grp->owner == if_scsi8_1) &&
588                                     interfaces[if_scsi8_0].used) {
589                                         grp->owner = if_scsi8_0;
590                                 } else
591                                         grp->used = 0;
592                                 break;
593                         default:
594                                 grp->used = 0;
595                         }
596                 } else {
597                         grp->used = 0;
598                 }
599                 group_set = clear_group_from_set(group_set, grp);
600         }
601         interfaces[ioif].used = 0;
602         interfaces[ioif].owner = NULL;
603
604         DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
605                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
606         DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
607                    interfaces[ioif].gpio_g_in,
608                    interfaces[ioif].gpio_g_out,
609                    interfaces[ioif].gpio_b));
610
611         gpio_in_pins |= interfaces[ioif].gpio_g_in;
612         gpio_out_pins |= interfaces[ioif].gpio_g_out;
613         gpio_pb_pins |= interfaces[ioif].gpio_b;
614
615         DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
616                    gpio_in_pins, gpio_out_pins, gpio_pb_pins));
617
618         local_irq_restore(flags);
619
620         notify_watchers();
621 }
622
623 /* Create a bitmask from bit 0 (inclusive) to bit stop_bit
624    (non-inclusive).  stop_bit == 0 returns 0x0 */
625 static inline unsigned int create_mask(const unsigned stop_bit)
626 {
627         /* Avoid overflow */
628         if (stop_bit >= 32) {
629                 return 0xffffffff;
630         }
631         return (1<<stop_bit)-1;
632 }
633
634
635 /* port can be 'a', 'b' or 'g' */
636 int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
637                                     const char port,
638                                     const unsigned start_bit,
639                                     const unsigned stop_bit)
640 {
641         unsigned int i;
642         unsigned int mask = 0;
643         unsigned int tmp_mask;
644         unsigned long int flags;
645         enum cris_io_interface *owners;
646
647         (void)cris_io_interface_init();
648
649         DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
650                    ioif, port, start_bit, stop_bit));
651
652         if (!((start_bit <= stop_bit) &&
653               ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
654                ((port == 'g') && (stop_bit < 32))))) {
655                 return -EINVAL;
656         }
657
658         mask = create_mask(stop_bit + 1);
659         tmp_mask = create_mask(start_bit);
660         mask &= ~tmp_mask;
661
662         DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
663                    port, start_bit, stop_bit, mask));
664
665         local_irq_save(flags);
666
667         switch (port) {
668         case 'a':
669                 if ((gpio_pa_pins & mask) != mask) {
670                         local_irq_restore(flags);
671                         return -EBUSY;
672                 }
673                 owners = gpio_pa_owners;
674                 gpio_pa_pins &= ~mask;
675                 break;
676         case 'b':
677                 if ((gpio_pb_pins & mask) != mask) {
678                         local_irq_restore(flags);
679                         return -EBUSY;
680                 }
681                 owners = gpio_pb_owners;
682                 gpio_pb_pins &= ~mask;
683                 break;
684         case 'g':
685                 if (((gpio_in_pins & mask) != mask) ||
686                     ((gpio_out_pins & mask) != mask)) {
687                         local_irq_restore(flags);
688                         return -EBUSY;
689                 }
690                 owners = gpio_pg_owners;
691                 gpio_in_pins &= ~mask;
692                 gpio_out_pins &= ~mask;
693                 break;
694         default:
695                 local_irq_restore(flags);
696                 return -EINVAL;
697         }
698
699         for (i = start_bit; i <= stop_bit; i++) {
700                 owners[i] = ioif;
701         }
702         local_irq_restore(flags);
703
704         notify_watchers();
705         return 0;
706 }
707
708
709 /* port can be 'a', 'b' or 'g' */
710 int cris_io_interface_free_pins(const enum cris_io_interface ioif,
711                                 const char port,
712                                 const unsigned start_bit,
713                                 const unsigned stop_bit)
714 {
715         unsigned int i;
716         unsigned int mask = 0;
717         unsigned int tmp_mask;
718         unsigned long int flags;
719         enum cris_io_interface *owners;
720
721         (void)cris_io_interface_init();
722
723         if (!((start_bit <= stop_bit) &&
724               ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
725                ((port == 'g') && (stop_bit < 32))))) {
726                 return -EINVAL;
727         }
728
729         mask = create_mask(stop_bit + 1);
730         tmp_mask = create_mask(start_bit);
731         mask &= ~tmp_mask;
732
733         DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
734                    port, start_bit, stop_bit, mask));
735
736         local_irq_save(flags);
737
738         switch (port) {
739         case 'a':
740                 if ((~gpio_pa_pins & mask) != mask) {
741                         local_irq_restore(flags);
742                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
743                 }
744                 owners = gpio_pa_owners;
745                 break;
746         case 'b':
747                 if ((~gpio_pb_pins & mask) != mask) {
748                         local_irq_restore(flags);
749                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
750                 }
751                 owners = gpio_pb_owners;
752                 break;
753         case 'g':
754                 if (((~gpio_in_pins & mask) != mask) ||
755                     ((~gpio_out_pins & mask) != mask)) {
756                         local_irq_restore(flags);
757                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
758                 }
759                 owners = gpio_pg_owners;
760                 break;
761         default:
762                 owners = NULL; /* Cannot happen. Shut up, gcc! */
763         }
764
765         for (i = start_bit; i <= stop_bit; i++) {
766                 if (owners[i] != ioif) {
767                         printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
768                 }
769         }
770
771         /* All was ok, change data. */
772         switch (port) {
773         case 'a':
774                 gpio_pa_pins |= mask;
775                 break;
776         case 'b':
777                 gpio_pb_pins |= mask;
778                 break;
779         case 'g':
780                 gpio_in_pins |= mask;
781                 gpio_out_pins |= mask;
782                 break;
783         }
784
785         for (i = start_bit; i <= stop_bit; i++) {
786                 owners[i] = if_unclaimed;
787         }
788         local_irq_restore(flags);
789         notify_watchers();
790
791         return 0;
792 }
793
794
795 int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
796                                                       const unsigned int gpio_out_available,
797                                                       const unsigned char pa_available,
798                                                       const unsigned char pb_available))
799 {
800         struct watcher *w;
801
802         (void)cris_io_interface_init();
803
804         if (NULL == notify) {
805                 return -EINVAL;
806         }
807         w = kmalloc(sizeof(*w), GFP_KERNEL);
808         if (!w) {
809                 return -ENOMEM;
810         }
811         w->notify = notify;
812         w->next = watchers;
813         watchers = w;
814
815         w->notify((const unsigned int)gpio_in_pins,
816                   (const unsigned int)gpio_out_pins,
817                   (const unsigned char)gpio_pa_pins,
818                   (const unsigned char)gpio_pb_pins);
819
820         return 0;
821 }
822
823 void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
824                                                      const unsigned int gpio_out_available,
825                                                      const unsigned char pa_available,
826                                                      const unsigned char pb_available))
827 {
828         struct watcher *w = watchers, *prev = NULL;
829
830         (void)cris_io_interface_init();
831
832         while ((NULL != w) && (w->notify != notify)){
833                 prev = w;
834                 w = w->next;
835         }
836         if (NULL != w) {
837                 if (NULL != prev) {
838                         prev->next = w->next;
839                 } else {
840                         watchers = w->next;
841                 }
842                 kfree(w);
843                 return;
844         }
845         printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
846 }
847
848
849 static int cris_io_interface_init(void)
850 {
851         static int first = 1;
852         int i;
853
854         if (!first) {
855                 return 0;
856         }
857         first = 0;
858
859         for (i = 0; i<8; i++) {
860                 gpio_pa_owners[i] = if_unclaimed;
861                 gpio_pb_owners[i] = if_unclaimed;
862                 gpio_pg_owners[i] = if_unclaimed;
863         }
864         for (; i<32; i++) {
865                 gpio_pg_owners[i] = if_unclaimed;
866         }
867         return 0;
868 }
869
870
871 module_init(cris_io_interface_init);
872
873
874 EXPORT_SYMBOL(cris_request_io_interface);
875 EXPORT_SYMBOL(cris_free_io_interface);
876 EXPORT_SYMBOL(cris_io_interface_allocate_pins);
877 EXPORT_SYMBOL(cris_io_interface_free_pins);
878 EXPORT_SYMBOL(cris_io_interface_register_watcher);
879 EXPORT_SYMBOL(cris_io_interface_delete_watcher);