• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/cris/arch-v10/kernel/
1/* IO interface mux allocator for ETRAX100LX.
2 * Copyright 2004-2007, Axis Communications AB
3 */
4
5
6/* C.f. ETRAX100LX Designer's Reference chapter 19.9 */
7
8#include <linux/kernel.h>
9#include <linux/slab.h>
10#include <linux/errno.h>
11#include <linux/module.h>
12#include <linux/init.h>
13
14#include <arch/svinto.h>
15#include <asm/io.h>
16#include <arch/io_interface_mux.h>
17
18
19#define DBG(s)
20
21/* Macro to access ETRAX 100 registers */
22#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
23					  IO_STATE_(reg##_, field##_, _##val)
24
25enum io_if_group {
26	group_a = (1<<0),
27	group_b = (1<<1),
28	group_c = (1<<2),
29	group_d = (1<<3),
30	group_e = (1<<4),
31	group_f = (1<<5)
32};
33
34struct watcher
35{
36	void (*notify)(const unsigned int gpio_in_available,
37		       const unsigned int gpio_out_available,
38		       const unsigned char pa_available,
39		       const unsigned char pb_available);
40	struct watcher *next;
41};
42
43
44struct if_group
45{
46	enum io_if_group        group;
47	/* name	- the name of the group 'A' to 'F' */
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;
53};
54
55
56struct interface
57{
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. */
63	unsigned char            groups;
64	/* used - set when the interface is allocated. */
65	unsigned char            used;
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. */
80	unsigned int             gpio_g_in;
81	unsigned int             gpio_g_out;
82	unsigned char            gpio_b;
83};
84
85static struct if_group if_groups[6] = {
86	{
87		.group = group_a,
88		.name = "A",
89		.used = 0,
90	},
91	{
92		.group = group_b,
93		.name = "B",
94		.used = 0,
95	},
96	{
97		.group = group_c,
98		.name = "C",
99		.used = 0,
100	},
101	{
102		.group = group_d,
103		.name = "D",
104		.used = 0,
105	},
106	{
107		.group = group_e,
108		.name = "E",
109		.used = 0,
110	},
111	{
112		.group = group_f,
113		.name = "F",
114		.used = 0,
115	}
116};
117
118/* The order in the array must match the order of enum
119 * cris_io_interface in io_interface_mux.h */
120static struct interface interfaces[] = {
121	/* Begin Non-multiplexed interfaces */
122	{
123		.ioif = if_eth,
124		.name = "ethernet",
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
134		.gpio_g_in = 0,
135		.gpio_g_out = 0,
136		.gpio_b = 0
137	},
138	{
139		.ioif = if_serial_0,
140		.name = "serial_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
150		.gpio_g_in = 0,
151		.gpio_g_out = 0,
152		.gpio_b = 0
153	},
154	/* End Non-multiplexed interfaces */
155	{
156		.ioif = if_serial_1,
157		.name = "serial_1",
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
167		.gpio_g_in =  0x00000000,
168		.gpio_g_out = 0x00000000,
169		.gpio_b = 0x00
170	},
171	{
172		.ioif = if_serial_2,
173		.name = "serial_2",
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
183		.gpio_g_in =  0x000000c0,
184		.gpio_g_out = 0x000000c0,
185		.gpio_b = 0x00
186	},
187	{
188		.ioif = if_serial_3,
189		.name = "serial_3",
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
199		.gpio_g_in =  0xc0000000,
200		.gpio_g_out = 0xc0000000,
201		.gpio_b = 0x00
202	},
203	{
204		.ioif = if_sync_serial_1,
205		.name = "sync_serial_1",
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
215		.gpio_g_in =  0x00000000,
216		.gpio_g_out = 0x00000000,
217		.gpio_b = 0x10
218	},
219	{
220		.ioif = if_sync_serial_3,
221		.name = "sync_serial_3",
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
231		.gpio_g_in =  0xc0000000,
232		.gpio_g_out = 0xc0000000,
233		.gpio_b = 0x80
234	},
235	{
236		.ioif = if_shared_ram,
237		.name = "shared_ram",
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
247		.gpio_g_in =  0x0000ff3e,
248		.gpio_g_out = 0x0000ff38,
249		.gpio_b = 0x00
250	},
251	{
252		.ioif = if_shared_ram_w,
253		.name = "shared_ram_w",
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
263		.gpio_g_in =  0x00ffff3e,
264		.gpio_g_out = 0x00ffff38,
265		.gpio_b = 0x00
266	},
267	{
268		.ioif = if_par_0,
269		.name = "par_0",
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
279		.gpio_g_in =  0x0000ff3e,
280		.gpio_g_out = 0x0000ff3e,
281		.gpio_b = 0x00
282	},
283	{
284		.ioif = if_par_1,
285		.name = "par_1",
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
295		.gpio_g_in =  0x3eff0000,
296		.gpio_g_out = 0x3eff0000,
297		.gpio_b = 0x00
298	},
299	{
300		.ioif = if_par_w,
301		.name = "par_w",
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
311		.gpio_g_in =  0x00ffff3e,
312		.gpio_g_out = 0x00ffff3e,
313		.gpio_b = 0x00
314	},
315	{
316		.ioif = if_scsi8_0,
317		.name = "scsi8_0",
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
327		.gpio_g_in =  0x0000ffff,
328		.gpio_g_out = 0x0000ffff,
329		.gpio_b = 0x10
330	},
331	{
332		.ioif = if_scsi8_1,
333		.name = "scsi8_1",
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
343		.gpio_g_in =  0xffff0000,
344		.gpio_g_out = 0xffff0000,
345		.gpio_b = 0x80
346	},
347	{
348		.ioif = if_scsi_w,
349		.name = "scsi_w",
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
359		.gpio_g_in =  0x01ffffff,
360		.gpio_g_out = 0x07ffffff,
361		.gpio_b = 0x80
362	},
363	{
364		.ioif = if_ata,
365		.name = "ata",
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
375		.gpio_g_in =  0xf9ffffff,
376		.gpio_g_out = 0xffffffff,
377		.gpio_b = 0x80
378	},
379	{
380		.ioif = if_csp,
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
391		.gpio_g_in =  0x00000000,
392		.gpio_g_out = 0x00000000,
393		.gpio_b = 0xfc
394	},
395	{
396		.ioif = if_i2c,
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
407		.gpio_g_in =  0x00000000,
408		.gpio_g_out = 0x00000000,
409		.gpio_b = 0x03
410	},
411	{
412		.ioif = if_usb_1,
413		.name = "usb_1",
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
423		.gpio_g_in =  0x00000000,
424		.gpio_g_out = 0x00000000,
425		.gpio_b = 0x2c
426	},
427	{
428		.ioif = if_usb_2,
429		.name = "usb_2",
430		.groups = group_d,
431
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,
441		.gpio_b = 0x00
442	},
443	/* GPIO pins */
444	{
445		.ioif = if_gpio_grp_a,
446		.name = "gpio_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
456		.gpio_g_in =  0x0000ff3f,
457		.gpio_g_out = 0x0000ff3f,
458		.gpio_b = 0x00
459	},
460	{
461		.ioif = if_gpio_grp_b,
462		.name = "gpio_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
472		.gpio_g_in =  0x000000c0,
473		.gpio_g_out = 0x000000c0,
474		.gpio_b = 0x00
475	},
476	{
477		.ioif = if_gpio_grp_c,
478		.name = "gpio_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
488		.gpio_g_in =  0xc0000000,
489		.gpio_g_out = 0xc0000000,
490		.gpio_b = 0x00
491	},
492	{
493		.ioif = if_gpio_grp_d,
494		.name = "gpio_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
504		.gpio_g_in =  0x3fff0000,
505		.gpio_g_out = 0x3fff0000,
506		.gpio_b = 0x00
507	},
508	{
509		.ioif = if_gpio_grp_e,
510		.name = "gpio_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
520		.gpio_g_in =  0x00000000,
521		.gpio_g_out = 0x00000000,
522		.gpio_b = 0x00
523	},
524	{
525		.ioif = if_gpio_grp_f,
526		.name = "gpio_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
536		.gpio_g_in =  0x00000000,
537		.gpio_g_out = 0x00000000,
538		.gpio_b = 0xff
539	}
540	/* Array end */
541};
542
543static struct watcher *watchers = NULL;
544
545/* The pins that are free to use in the GPIO ports. */
546static unsigned int gpio_in_pins =  0xffffffff;
547static unsigned int gpio_out_pins = 0xffffffff;
548static unsigned char gpio_pb_pins = 0xff;
549static unsigned char gpio_pa_pins = 0xff;
550
551/* Identifiers for the owners of the GPIO pins. */
552static enum cris_io_interface gpio_pa_owners[8];
553static enum cris_io_interface gpio_pb_owners[8];
554static enum cris_io_interface gpio_pg_owners[32];
555
556static int cris_io_interface_init(void);
557
558static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group)
559{
560	return (groups & ~group->group);
561}
562
563
564static struct if_group *get_group(const unsigned char groups)
565{
566	int i;
567	for (i = 0; i < ARRAY_SIZE(if_groups); i++) {
568		if (groups & if_groups[i].group) {
569			return &if_groups[i];
570		}
571	}
572	return NULL;
573}
574
575
576static void notify_watchers(void)
577{
578	struct watcher *w = watchers;
579
580	DBG(printk("io_interface_mux: notifying watchers\n"));
581
582	while (NULL != w) {
583		w->notify((const unsigned int)gpio_in_pins,
584			  (const unsigned int)gpio_out_pins,
585			  (const unsigned char)gpio_pa_pins,
586			  (const unsigned char)gpio_pb_pins);
587		w = w->next;
588	}
589}
590
591
592int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id)
593{
594	int set_gen_config = 0;
595	int set_gen_config_ii = 0;
596	unsigned long int gens;
597	unsigned long int gens_ii;
598	struct if_group *grp;
599	unsigned char group_set;
600	unsigned long flags;
601	int res = 0;
602
603	(void)cris_io_interface_init();
604
605	DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
606
607	if ((ioif >= if_max_interfaces) || (ioif < 0)) {
608		printk(KERN_CRIT "cris_request_io_interface: Bad interface "
609			"%u submitted for %s\n",
610		       ioif,
611		       device_id);
612		return -EINVAL;
613	}
614
615	local_irq_save(flags);
616
617	if (interfaces[ioif].used) {
618		printk(KERN_CRIT "cris_io_interface: Cannot allocate interface "
619			"%s for %s, in use by %s\n",
620		       interfaces[ioif].name,
621		       device_id,
622		       interfaces[ioif].owner);
623		res = -EBUSY;
624		goto exit;
625	}
626
627	/* Check that all required pins in the used groups are free
628	 * before allocating. */
629	group_set = interfaces[ioif].groups;
630	while (NULL != (grp = get_group(group_set))) {
631		unsigned int if_group_use = 0;
632
633		switch (grp->group) {
634		case group_a:
635			if_group_use = interfaces[ioif].group_a;
636			break;
637		case group_b:
638			if_group_use = interfaces[ioif].group_b;
639			break;
640		case group_c:
641			if_group_use = interfaces[ioif].group_c;
642			break;
643		case group_d:
644			if_group_use = interfaces[ioif].group_d;
645			break;
646		case group_e:
647			if_group_use = interfaces[ioif].group_e;
648			break;
649		case group_f:
650			if_group_use = interfaces[ioif].group_f;
651			break;
652		default:
653			BUG_ON(1);
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
664		group_set = clear_group_from_set(group_set, grp);
665	}
666
667	/* Are the required GPIO pins available too? */
668	if (((interfaces[ioif].gpio_g_in & gpio_in_pins) !=
669			interfaces[ioif].gpio_g_in) ||
670		((interfaces[ioif].gpio_g_out & gpio_out_pins) !=
671			interfaces[ioif].gpio_g_out) ||
672		((interfaces[ioif].gpio_b & gpio_pb_pins) !=
673			interfaces[ioif].gpio_b)) {
674		printk(KERN_CRIT "cris_request_io_interface: Could not get "
675			"required pins for interface %u\n", ioif);
676		res = -EBUSY;
677		goto exit;
678	}
679
680	/* Check which registers need to be reconfigured. */
681	gens = genconfig_shadow;
682	gens_ii = gen_config_ii_shadow;
683
684	set_gen_config = 1;
685	switch (ioif)
686	{
687	/* Begin Non-multiplexed interfaces */
688	case if_eth:
689		/* fall through */
690	case if_serial_0:
691		set_gen_config = 0;
692		break;
693	/* End Non-multiplexed interfaces */
694	case if_serial_1:
695		set_gen_config_ii = 1;
696		SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
697		break;
698	case if_serial_2:
699		SETS(gens, R_GEN_CONFIG, ser2, select);
700		break;
701	case if_serial_3:
702		SETS(gens, R_GEN_CONFIG, ser3, select);
703		set_gen_config_ii = 1;
704		SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
705		break;
706	case if_sync_serial_1:
707		set_gen_config_ii = 1;
708		SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
709		break;
710	case if_sync_serial_3:
711		SETS(gens, R_GEN_CONFIG, ser3, select);
712		set_gen_config_ii = 1;
713		SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
714		break;
715	case if_shared_ram:
716		SETS(gens, R_GEN_CONFIG, mio, select);
717		break;
718	case if_shared_ram_w:
719		SETS(gens, R_GEN_CONFIG, mio_w, select);
720		break;
721	case if_par_0:
722		SETS(gens, R_GEN_CONFIG, par0, select);
723		break;
724	case if_par_1:
725		SETS(gens, R_GEN_CONFIG, par1, select);
726		break;
727	case if_par_w:
728		SETS(gens, R_GEN_CONFIG, par0, select);
729		SETS(gens, R_GEN_CONFIG, par_w, select);
730		break;
731	case if_scsi8_0:
732		SETS(gens, R_GEN_CONFIG, scsi0, select);
733		break;
734	case if_scsi8_1:
735		SETS(gens, R_GEN_CONFIG, scsi1, select);
736		break;
737	case if_scsi_w:
738		SETS(gens, R_GEN_CONFIG, scsi0, select);
739		SETS(gens, R_GEN_CONFIG, scsi0w, select);
740		break;
741	case if_ata:
742		SETS(gens, R_GEN_CONFIG, ata, select);
743		break;
744	case if_csp:
745		/* fall through */
746	case if_i2c:
747		set_gen_config = 0;
748		break;
749	case if_usb_1:
750		SETS(gens, R_GEN_CONFIG, usb1, select);
751		break;
752	case if_usb_2:
753		SETS(gens, R_GEN_CONFIG, usb2, select);
754		break;
755	case if_gpio_grp_a:
756		/* GPIO groups are only accounted, don't do configuration changes. */
757		/* fall through */
758	case if_gpio_grp_b:
759		/* fall through */
760	case if_gpio_grp_c:
761		/* fall through */
762	case if_gpio_grp_d:
763		/* fall through */
764	case if_gpio_grp_e:
765		/* fall through */
766	case if_gpio_grp_f:
767		set_gen_config = 0;
768		break;
769	default:
770		printk(KERN_INFO "cris_request_io_interface: Bad interface "
771			"%u submitted for %s\n",
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);
807	}
808
809	interfaces[ioif].used = 1;
810	interfaces[ioif].owner = (char*)device_id;
811
812	if (set_gen_config) {
813		volatile int i;
814		genconfig_shadow = gens;
815		*R_GEN_CONFIG = genconfig_shadow;
816		/* Wait 12 cycles before doing any DMA command */
817		for(i = 6; i > 0; i--)
818			nop();
819	}
820	if (set_gen_config_ii) {
821		gen_config_ii_shadow = gens_ii;
822		*R_GEN_CONFIG_II = gen_config_ii_shadow;
823	}
824
825	DBG(printk(KERN_DEBUG "GPIO pins: available before: "
826		"g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
827		gpio_in_pins, gpio_out_pins, gpio_pb_pins));
828	DBG(printk(KERN_DEBUG
829		"grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
830		interfaces[ioif].gpio_g_in,
831		interfaces[ioif].gpio_g_out,
832		interfaces[ioif].gpio_b));
833
834	gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
835	gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
836	gpio_pb_pins &= ~interfaces[ioif].gpio_b;
837
838	DBG(printk(KERN_DEBUG "GPIO pins: available after: "
839		"g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
840		gpio_in_pins, gpio_out_pins, gpio_pb_pins));
841
842exit:
843	local_irq_restore(flags);
844	if (res == 0)
845		notify_watchers();
846	return res;
847}
848
849
850void cris_free_io_interface(enum cris_io_interface ioif)
851{
852	struct if_group *grp;
853	unsigned char group_set;
854	unsigned long flags;
855
856	(void)cris_io_interface_init();
857
858	if ((ioif >= if_max_interfaces) || (ioif < 0)) {
859		printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
860		       ioif);
861		return;
862	}
863	local_irq_save(flags);
864	if (!interfaces[ioif].used) {
865		printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
866		       ioif);
867		local_irq_restore(flags);
868		return;
869	}
870	group_set = interfaces[ioif].groups;
871	while (NULL != (grp = get_group(group_set))) {
872		unsigned int if_group_use = 0;
873
874		switch (grp->group) {
875		case group_a:
876			if_group_use = interfaces[ioif].group_a;
877			break;
878		case group_b:
879			if_group_use = interfaces[ioif].group_b;
880			break;
881		case group_c:
882			if_group_use = interfaces[ioif].group_c;
883			break;
884		case group_d:
885			if_group_use = interfaces[ioif].group_d;
886			break;
887		case group_e:
888			if_group_use = interfaces[ioif].group_e;
889			break;
890		case group_f:
891			if_group_use = interfaces[ioif].group_f;
892			break;
893		default:
894			BUG_ON(1);
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
901		group_set = clear_group_from_set(group_set, grp);
902	}
903	interfaces[ioif].used = 0;
904	interfaces[ioif].owner = NULL;
905
906	DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
907		   gpio_in_pins, gpio_out_pins, gpio_pb_pins));
908	DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
909		   interfaces[ioif].gpio_g_in,
910		   interfaces[ioif].gpio_g_out,
911		   interfaces[ioif].gpio_b));
912
913	gpio_in_pins |= interfaces[ioif].gpio_g_in;
914	gpio_out_pins |= interfaces[ioif].gpio_g_out;
915	gpio_pb_pins |= interfaces[ioif].gpio_b;
916
917	DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
918		   gpio_in_pins, gpio_out_pins, gpio_pb_pins));
919
920	local_irq_restore(flags);
921
922	notify_watchers();
923}
924
925/* Create a bitmask from bit 0 (inclusive) to bit stop_bit
926   (non-inclusive).  stop_bit == 0 returns 0x0 */
927static inline unsigned int create_mask(const unsigned stop_bit)
928{
929	/* Avoid overflow */
930	if (stop_bit >= 32) {
931		return 0xffffffff;
932	}
933	return (1<<stop_bit)-1;
934}
935
936
937/* port can be 'a', 'b' or 'g' */
938int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
939				    const char port,
940				    const unsigned start_bit,
941				    const unsigned stop_bit)
942{
943	unsigned int i;
944	unsigned int mask = 0;
945	unsigned int tmp_mask;
946	unsigned long int flags;
947	enum cris_io_interface *owners;
948
949	(void)cris_io_interface_init();
950
951	DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
952		   ioif, port, start_bit, stop_bit));
953
954	if (!((start_bit <= stop_bit) &&
955	      ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
956	       ((port == 'g') && (stop_bit < 32))))) {
957		return -EINVAL;
958	}
959
960	mask = create_mask(stop_bit + 1);
961	tmp_mask = create_mask(start_bit);
962	mask &= ~tmp_mask;
963
964	DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
965		   port, start_bit, stop_bit, mask));
966
967	local_irq_save(flags);
968
969	switch (port) {
970	case 'a':
971		if ((gpio_pa_pins & mask) != mask) {
972			local_irq_restore(flags);
973			return -EBUSY;
974		}
975		owners = gpio_pa_owners;
976		gpio_pa_pins &= ~mask;
977		break;
978	case 'b':
979		if ((gpio_pb_pins & mask) != mask) {
980			local_irq_restore(flags);
981			return -EBUSY;
982		}
983		owners = gpio_pb_owners;
984		gpio_pb_pins &= ~mask;
985		break;
986	case 'g':
987		if (((gpio_in_pins & mask) != mask) ||
988		    ((gpio_out_pins & mask) != mask)) {
989			local_irq_restore(flags);
990			return -EBUSY;
991		}
992		owners = gpio_pg_owners;
993		gpio_in_pins &= ~mask;
994		gpio_out_pins &= ~mask;
995		break;
996	default:
997		local_irq_restore(flags);
998		return -EINVAL;
999	}
1000
1001	for (i = start_bit; i <= stop_bit; i++) {
1002		owners[i] = ioif;
1003	}
1004	local_irq_restore(flags);
1005
1006	notify_watchers();
1007	return 0;
1008}
1009
1010
1011/* port can be 'a', 'b' or 'g' */
1012int cris_io_interface_free_pins(const enum cris_io_interface ioif,
1013                                const char port,
1014                                const unsigned start_bit,
1015                                const unsigned stop_bit)
1016{
1017	unsigned int i;
1018	unsigned int mask = 0;
1019	unsigned int tmp_mask;
1020	unsigned long int flags;
1021	enum cris_io_interface *owners;
1022
1023	(void)cris_io_interface_init();
1024
1025	if (!((start_bit <= stop_bit) &&
1026	      ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
1027	       ((port == 'g') && (stop_bit < 32))))) {
1028		return -EINVAL;
1029	}
1030
1031	mask = create_mask(stop_bit + 1);
1032	tmp_mask = create_mask(start_bit);
1033	mask &= ~tmp_mask;
1034
1035	DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
1036		   port, start_bit, stop_bit, mask));
1037
1038	local_irq_save(flags);
1039
1040	switch (port) {
1041	case 'a':
1042		if ((~gpio_pa_pins & mask) != mask) {
1043			local_irq_restore(flags);
1044			printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
1045		}
1046		owners = gpio_pa_owners;
1047		break;
1048	case 'b':
1049		if ((~gpio_pb_pins & mask) != mask) {
1050			local_irq_restore(flags);
1051			printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
1052		}
1053		owners = gpio_pb_owners;
1054		break;
1055	case 'g':
1056		if (((~gpio_in_pins & mask) != mask) ||
1057		    ((~gpio_out_pins & mask) != mask)) {
1058			local_irq_restore(flags);
1059			printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
1060		}
1061		owners = gpio_pg_owners;
1062		break;
1063	default:
1064		owners = NULL; /* Cannot happen. Shut up, gcc! */
1065	}
1066
1067	for (i = start_bit; i <= stop_bit; i++) {
1068		if (owners[i] != ioif) {
1069			printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
1070		}
1071	}
1072
1073	/* All was ok, change data. */
1074	switch (port) {
1075	case 'a':
1076		gpio_pa_pins |= mask;
1077		break;
1078	case 'b':
1079		gpio_pb_pins |= mask;
1080		break;
1081	case 'g':
1082		gpio_in_pins |= mask;
1083		gpio_out_pins |= mask;
1084		break;
1085	}
1086
1087	for (i = start_bit; i <= stop_bit; i++) {
1088		owners[i] = if_unclaimed;
1089	}
1090	local_irq_restore(flags);
1091	notify_watchers();
1092
1093        return 0;
1094}
1095
1096
1097int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
1098                                                      const unsigned int gpio_out_available,
1099                                                      const unsigned char pa_available,
1100                                                      const unsigned char pb_available))
1101{
1102	struct watcher *w;
1103
1104	(void)cris_io_interface_init();
1105
1106	if (NULL == notify) {
1107		return -EINVAL;
1108	}
1109	w = kmalloc(sizeof(*w), GFP_KERNEL);
1110	if (!w) {
1111		return -ENOMEM;
1112	}
1113	w->notify = notify;
1114	w->next = watchers;
1115	watchers = w;
1116
1117	w->notify((const unsigned int)gpio_in_pins,
1118		  (const unsigned int)gpio_out_pins,
1119		  (const unsigned char)gpio_pa_pins,
1120		  (const unsigned char)gpio_pb_pins);
1121
1122	return 0;
1123}
1124
1125void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
1126						     const unsigned int gpio_out_available,
1127                                                     const unsigned char pa_available,
1128						     const unsigned char pb_available))
1129{
1130	struct watcher *w = watchers, *prev = NULL;
1131
1132	(void)cris_io_interface_init();
1133
1134	while ((NULL != w) && (w->notify != notify)){
1135		prev = w;
1136		w = w->next;
1137	}
1138	if (NULL != w) {
1139		if (NULL != prev) {
1140			prev->next = w->next;
1141		} else {
1142			watchers = w->next;
1143		}
1144		kfree(w);
1145		return;
1146	}
1147	printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
1148}
1149
1150
1151static int cris_io_interface_init(void)
1152{
1153	static int first = 1;
1154	int i;
1155
1156	if (!first) {
1157		return 0;
1158	}
1159	first = 0;
1160
1161	for (i = 0; i<8; i++) {
1162		gpio_pa_owners[i] = if_unclaimed;
1163		gpio_pb_owners[i] = if_unclaimed;
1164		gpio_pg_owners[i] = if_unclaimed;
1165	}
1166	for (; i<32; i++) {
1167		gpio_pg_owners[i] = if_unclaimed;
1168	}
1169	return 0;
1170}
1171
1172
1173module_init(cris_io_interface_init);
1174
1175
1176EXPORT_SYMBOL(cris_request_io_interface);
1177EXPORT_SYMBOL(cris_free_io_interface);
1178EXPORT_SYMBOL(cris_io_interface_allocate_pins);
1179EXPORT_SYMBOL(cris_io_interface_free_pins);
1180EXPORT_SYMBOL(cris_io_interface_register_watcher);
1181EXPORT_SYMBOL(cris_io_interface_delete_watcher);
1182