1 /* $Id: gpio.c,v 1.8 2003/07/04 08:27:37 starvik Exp $
3 * Etrax general port I/O device
5 * Copyright (c) 1999, 2000, 2001, 2002 Axis Communications AB
7 * Authors: Bjorn Wesen (initial version)
8 * Ola Knutsson (LED handling)
9 * Johan Adolfsson (read/set directions, write, port G)
12 * Revision 1.8 2003/07/04 08:27:37 starvik
13 * Merge of Linux 2.5.74
15 * Revision 1.7 2003/01/10 07:44:07 starvik
16 * init_ioremap is now called by kernel before drivers are initialized
18 * Revision 1.6 2002/12/11 13:13:57 starvik
19 * Added arch/ to v10 specific includes
20 * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
22 * Revision 1.5 2002/11/20 11:56:11 starvik
23 * Merge of Linux 2.5.48
25 * Revision 1.4 2002/11/18 10:10:05 starvik
26 * Linux 2.5 port of latest gpio.c from Linux 2.4
28 * Revision 1.20 2002/10/16 21:16:24 johana
29 * Added support for PA high level interrupt.
30 * That gives 2ms response time with iodtest for high levels and 2-12 ms
31 * response time on low levels if the check is not made in
32 * process.c:cpu_idle() as well.
34 * Revision 1.19 2002/10/14 18:27:33 johana
35 * Implemented alarm handling so select() now works.
36 * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
38 * Otherwise I get 15-18 ms (same as doing the poll in userspace -
40 * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
42 * TODO? Perhaps call request_irq()/free_irq() only when needed?
43 * Increased version to 2.5
45 * Revision 1.18 2002/10/11 15:02:00 johana
46 * Mask inverted 8 bit value in setget_input().
48 * Revision 1.17 2002/06/17 15:53:01 johana
49 * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
50 * that take a pointer as argument and thus can handle 32 bit ports (G)
52 * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
53 * (especially if Port G bit 31 is used)
55 * Revision 1.16 2002/06/17 09:59:51 johana
56 * Returning 32 bit values in the ioctl return value doesn't work if bit
57 * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
58 * A new set of ioctl's will be added.
60 * Revision 1.15 2002/05/06 13:19:13 johana
61 * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
63 * Revision 1.14 2002/04/12 12:01:53 johana
64 * Use global r_port_g_data_shadow.
65 * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
67 * Revision 1.13 2002/04/10 12:03:55 johana
68 * Added support for port G /dev/gpiog (minor 3).
69 * Changed indentation on switch cases.
70 * Fixed other spaces to tabs.
72 * Revision 1.12 2001/11/12 19:42:15 pkj
73 * * Corrected return values from gpio_leds_ioctl().
74 * * Fixed compiler warnings.
76 * Revision 1.11 2001/10/30 14:39:12 johana
77 * Added D() around gpio_write printk.
79 * Revision 1.10 2001/10/25 10:24:42 johana
80 * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
81 * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
82 * from ~60 seconds to 4 seconds).
83 * Added save_flags/cli/restore_flags in ioctl.
85 * Revision 1.9 2001/05/04 14:16:07 matsfg
86 * Corrected spelling error
88 * Revision 1.8 2001/04/27 13:55:26 matsfg
90 * Turns off all LEDS on init.
91 * Added support for shutdown and powerbutton.
93 * Revision 1.7 2001/04/04 13:30:08 matsfg
94 * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
96 * Revision 1.6 2001/03/26 16:03:06 bjornw
97 * Needs linux/config.h
99 * Revision 1.5 2001/03/26 14:22:03 bjornw
100 * Namechange of some config options
102 * Revision 1.4 2001/02/27 13:52:48 bjornw
105 * Revision 1.3 2001/01/24 15:06:48 bjornw
106 * gpio_wq correct type
108 * Revision 1.2 2001/01/18 16:07:30 bjornw
111 * Revision 1.1 2001/01/18 15:55:16 bjornw
112 * Verbatim copy of etraxgpio.c from elinux 2.0 added
117 #include <linux/config.h>
119 #include <linux/module.h>
120 #include <linux/sched.h>
121 #include <linux/slab.h>
122 #include <linux/ioport.h>
123 #include <linux/errno.h>
124 #include <linux/kernel.h>
125 #include <linux/fs.h>
126 #include <linux/string.h>
127 #include <linux/poll.h>
128 #include <linux/init.h>
129 #include <linux/interrupt.h>
131 #include <asm/etraxgpio.h>
132 #include <asm/arch/svinto.h>
134 #include <asm/system.h>
137 #define GPIO_MAJOR 120 /* experimental MAJOR number */
143 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
148 static char gpio_name[] = "etrax gpio";
151 static wait_queue_head_t *gpio_wq;
154 static int gpio_ioctl(struct inode *inode, struct file *file,
155 unsigned int cmd, unsigned long arg);
156 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
158 static int gpio_open(struct inode *inode, struct file *filp);
159 static int gpio_release(struct inode *inode, struct file *filp);
160 static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
162 /* private data per open() of this driver */
164 struct gpio_private {
165 struct gpio_private *next;
166 /* These fields are for PA and PB only */
167 volatile unsigned char *port, *shadow;
168 volatile unsigned char *dir, *dir_shadow;
169 unsigned char changeable_dir;
170 unsigned char changeable_bits;
171 unsigned char clk_mask;
172 unsigned char data_mask;
173 unsigned char write_msb;
174 unsigned char pad1, pad2, pad3;
175 /* These fields are generic */
176 unsigned long highalarm, lowalarm;
177 wait_queue_head_t alarm_wq;
181 /* linked list of alarms to check for */
183 static struct gpio_private *alarmlist = 0;
185 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
187 /* Port A and B use 8 bit access, but Port G is 32 bit */
188 #define NUM_PORTS (GPIO_MINOR_B+1)
190 static volatile unsigned char *ports[NUM_PORTS] = {
194 static volatile unsigned char *shads[NUM_PORTS] = {
195 &port_pa_data_shadow,
199 /* What direction bits that are user changeable 1=changeable*/
200 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
201 #define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
203 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
204 #define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
207 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
208 #define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
210 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
211 #define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
215 static unsigned char changeable_dir[NUM_PORTS] = {
216 CONFIG_ETRAX_PA_CHANGEABLE_DIR,
217 CONFIG_ETRAX_PB_CHANGEABLE_DIR
219 static unsigned char changeable_bits[NUM_PORTS] = {
220 CONFIG_ETRAX_PA_CHANGEABLE_BITS,
221 CONFIG_ETRAX_PB_CHANGEABLE_BITS
224 static volatile unsigned char *dir[NUM_PORTS] = {
229 static volatile unsigned char *dir_shadow[NUM_PORTS] = {
234 /* Port G is 32 bit, handle it special, some bits are both inputs
235 and outputs at the same time, only some of the bits can change direction
236 and some of them in groups of 8 bit. */
237 static unsigned long changeable_dir_g;
238 static unsigned long dir_g_in_bits;
239 static unsigned long dir_g_out_bits;
240 static unsigned long dir_g_shadow; /* 1=output */
242 #define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
247 gpio_poll(struct file *file,
250 unsigned int mask = 0;
251 struct gpio_private *priv = (struct gpio_private *)file->private_data;
253 poll_wait(file, &priv->alarm_wq, wait);
254 if (priv->minor == GPIO_MINOR_A) {
256 data = *R_PORT_PA_DATA;
257 /* PA has support for high level interrupt -
258 * lets activate for those low and with highalarm set
260 tmp = ~data & priv->highalarm & 0xFF;
261 *R_IRQ_MASK1_SET = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
262 } else if (priv->minor == GPIO_MINOR_B)
263 data = *R_PORT_PB_DATA;
264 else if (priv->minor == GPIO_MINOR_G)
265 data = *R_PORT_G_DATA;
269 if ((data & priv->highalarm) ||
270 (~data & priv->lowalarm)) {
271 mask = POLLIN|POLLRDNORM;
274 DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
278 int etrax_gpio_wake_up_check(void)
280 struct gpio_private *priv = alarmlist;
281 unsigned long data = 0;
284 if (USE_PORTS(priv)) {
286 } else if (priv->minor == GPIO_MINOR_G) {
287 data = *R_PORT_G_DATA;
289 if ((data & priv->highalarm) ||
290 (~data & priv->lowalarm)) {
291 DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
292 wake_up_interruptible(&priv->alarm_wq);
301 gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
303 if (gpio_some_alarms) {
304 etrax_gpio_wake_up_check();
311 gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
314 /* Find what PA interrupts are active */
315 tmp = (*R_IRQ_READ1 >> R_IRQ_READ1__pa0__BITNR) & 0xFF;
317 /* NOTE: Maybe we need to be more careful here if some other
318 * driver uses PA interrupt as well?
320 *R_IRQ_MASK1_CLR = (tmp << R_IRQ_MASK1_CLR__pa0__BITNR);
321 if (gpio_some_alarms) {
322 return IRQ_RETVAL(etrax_gpio_wake_up_check());
328 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
331 struct gpio_private *priv = (struct gpio_private *)file->private_data;
332 unsigned char data, clk_mask, data_mask, write_msb;
334 ssize_t retval = count;
335 if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
339 if (verify_area(VERIFY_READ, buf, count)) {
342 clk_mask = priv->clk_mask;
343 data_mask = priv->data_mask;
344 /* It must have been configured using the IO_CFG_WRITE_MODE */
345 /* Perhaps a better error code? */
346 if (clk_mask == 0 || data_mask == 0) {
349 write_msb = priv->write_msb;
350 D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
354 if (priv->write_msb) {
355 for (i = 7; i >= 0;i--) {
356 local_irq_save(flags); local_irq_disable();
357 *priv->port = *priv->shadow &= ~clk_mask;
359 *priv->port = *priv->shadow |= data_mask;
361 *priv->port = *priv->shadow &= ~data_mask;
362 /* For FPGA: min 5.0ns (DCC) before CCLK high */
363 *priv->port = *priv->shadow |= clk_mask;
364 local_irq_restore(flags);
367 for (i = 0; i <= 7;i++) {
368 local_irq_save(flags); local_irq_disable();
369 *priv->port = *priv->shadow &= ~clk_mask;
371 *priv->port = *priv->shadow |= data_mask;
373 *priv->port = *priv->shadow &= ~data_mask;
374 /* For FPGA: min 5.0ns (DCC) before CCLK high */
375 *priv->port = *priv->shadow |= clk_mask;
376 local_irq_restore(flags);
386 gpio_open(struct inode *inode, struct file *filp)
388 struct gpio_private *priv;
389 int p = iminor(inode);
391 if (p > GPIO_MINOR_LAST)
394 priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
402 /* initialize the io/alarm struct and link it into our alarmlist */
404 priv->next = alarmlist;
406 if (USE_PORTS(priv)) { /* A and B */
407 priv->port = ports[p];
408 priv->shadow = shads[p];
410 priv->dir_shadow = dir_shadow[p];
411 priv->changeable_dir = changeable_dir[p];
412 priv->changeable_bits = changeable_bits[p];
417 priv->dir_shadow = NULL;
418 priv->changeable_dir = 0;
419 priv->changeable_bits = 0;
426 init_waitqueue_head(&priv->alarm_wq);
428 filp->private_data = (void *)priv;
434 gpio_release(struct inode *inode, struct file *filp)
436 struct gpio_private *p = alarmlist;
437 struct gpio_private *todel = (struct gpio_private *)filp->private_data;
439 /* unlink from alarmlist and free the private structure */
442 alarmlist = todel->next;
444 while (p->next != todel)
446 p->next = todel->next;
450 /* Check if there are still any alarms set */
453 if (p->highalarm | p->lowalarm) {
454 gpio_some_alarms = 1;
459 gpio_some_alarms = 0;
464 /* Main device API. ioctl's to read/set/clear bits, as well as to
465 * set alarms to wait for using a subsequent select().
468 unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
470 /* Set direction 0=unchanged 1=input,
471 * return mask with 1=input
474 if (USE_PORTS(priv)) {
475 local_irq_save(flags); local_irq_disable();
476 *priv->dir = *priv->dir_shadow &=
477 ~((unsigned char)arg & priv->changeable_dir);
478 local_irq_restore(flags);
479 return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
480 } else if (priv->minor == GPIO_MINOR_G) {
481 /* We must fiddle with R_GEN_CONFIG to change dir */
482 if (((arg & dir_g_in_bits) != arg) &&
483 (arg & changeable_dir_g)) {
484 arg &= changeable_dir_g;
485 /* Clear bits in genconfig to set to input */
487 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
488 dir_g_in_bits |= (1<<0);
489 dir_g_out_bits &= ~(1<<0);
491 if ((arg & 0x0000FF00) == 0x0000FF00) {
492 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
493 dir_g_in_bits |= 0x0000FF00;
494 dir_g_out_bits &= ~0x0000FF00;
496 if ((arg & 0x00FF0000) == 0x00FF0000) {
497 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
498 dir_g_in_bits |= 0x00FF0000;
499 dir_g_out_bits &= ~0x00FF0000;
502 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
503 dir_g_in_bits |= (1<<24);
504 dir_g_out_bits &= ~(1<<24);
506 printk("gpio: SETINPUT on port G set "
507 "genconfig to 0x%08lX "
509 "out_bits: 0x%08lX\n",
510 (unsigned long)genconfig_shadow,
511 dir_g_in_bits, dir_g_out_bits);
512 *R_GEN_CONFIG = genconfig_shadow;
513 /* Must be a >120 ns delay before writing this again */
516 return dir_g_in_bits;
521 unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
524 if (USE_PORTS(priv)) {
525 local_irq_save(flags); local_irq_disable();
526 *priv->dir = *priv->dir_shadow |=
527 ((unsigned char)arg & priv->changeable_dir);
528 local_irq_restore(flags);
529 return *priv->dir_shadow;
530 } else if (priv->minor == GPIO_MINOR_G) {
531 /* We must fiddle with R_GEN_CONFIG to change dir */
532 if (((arg & dir_g_out_bits) != arg) &&
533 (arg & changeable_dir_g)) {
534 /* Set bits in genconfig to set to output */
536 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
537 dir_g_out_bits |= (1<<0);
538 dir_g_in_bits &= ~(1<<0);
540 if ((arg & 0x0000FF00) == 0x0000FF00) {
541 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
542 dir_g_out_bits |= 0x0000FF00;
543 dir_g_in_bits &= ~0x0000FF00;
545 if ((arg & 0x00FF0000) == 0x00FF0000) {
546 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
547 dir_g_out_bits |= 0x00FF0000;
548 dir_g_in_bits &= ~0x00FF0000;
551 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
552 dir_g_out_bits |= (1<<24);
553 dir_g_in_bits &= ~(1<<24);
555 printk("gpio: SETOUTPUT on port G set "
556 "genconfig to 0x%08lX "
558 "out_bits: 0x%08lX\n",
559 (unsigned long)genconfig_shadow,
560 dir_g_in_bits, dir_g_out_bits);
561 *R_GEN_CONFIG = genconfig_shadow;
562 /* Must be a >120 ns delay before writing this again */
564 return dir_g_out_bits & 0x7FFFFFFF;
567 } /* setget_output */
570 gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
573 gpio_ioctl(struct inode *inode, struct file *file,
574 unsigned int cmd, unsigned long arg)
578 struct gpio_private *priv = (struct gpio_private *)file->private_data;
579 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
583 switch (_IOC_NR(cmd)) {
584 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
586 if (USE_PORTS(priv)) {
588 } else if (priv->minor == GPIO_MINOR_G) {
589 return (*R_PORT_G_DATA) & 0x7FFFFFFF;
593 local_irq_save(flags); local_irq_disable();
594 // set changeable bits with a 1 in arg
595 if (USE_PORTS(priv)) {
596 *priv->port = *priv->shadow |=
597 ((unsigned char)arg & priv->changeable_bits);
598 } else if (priv->minor == GPIO_MINOR_G) {
599 *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
601 local_irq_restore(flags);
604 local_irq_save(flags); local_irq_disable();
605 // clear changeable bits with a 1 in arg
606 if (USE_PORTS(priv)) {
607 *priv->port = *priv->shadow &=
608 ~((unsigned char)arg & priv->changeable_bits);
609 } else if (priv->minor == GPIO_MINOR_G) {
610 *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
612 local_irq_restore(flags);
615 // set alarm when bits with 1 in arg go high
616 priv->highalarm |= arg;
617 gpio_some_alarms = 1;
620 // set alarm when bits with 1 in arg go low
621 priv->lowalarm |= arg;
622 gpio_some_alarms = 1;
625 // clear alarm for bits with 1 in arg
626 priv->highalarm &= ~arg;
627 priv->lowalarm &= ~arg;
629 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
630 /* Read direction 0=input 1=output */
631 if (USE_PORTS(priv)) {
632 return *priv->dir_shadow;
633 } else if (priv->minor == GPIO_MINOR_G) {
634 /* Note: Some bits are both in and out,
635 * Those that are dual is set here as well.
637 return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
639 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
640 /* Set direction 0=unchanged 1=input,
641 * return mask with 1=input
643 return setget_input(priv, arg) & 0x7FFFFFFF;
645 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
646 /* Set direction 0=unchanged 1=output,
647 * return mask with 1=output
649 return setget_output(priv, arg) & 0x7FFFFFFF;
655 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
656 return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
661 case IO_CFG_WRITE_MODE:
662 priv->clk_mask = arg & 0xFF;
663 priv->data_mask = (arg >> 8) & 0xFF;
664 priv->write_msb = (arg >> 16) & 0x01;
665 /* Check if we're allowed to change the bits and
666 * the direction is correct
668 if (!((priv->clk_mask & priv->changeable_bits) &&
669 (priv->data_mask & priv->changeable_bits) &&
670 (priv->clk_mask & *priv->dir_shadow) &&
671 (priv->data_mask & *priv->dir_shadow)))
679 /* *arg is result of reading the input pins */
680 if (USE_PORTS(priv)) {
682 } else if (priv->minor == GPIO_MINOR_G) {
683 val = *R_PORT_G_DATA;
685 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
689 case IO_READ_OUTBITS:
690 /* *arg is result of reading the output shadow */
691 if (USE_PORTS(priv)) {
693 } else if (priv->minor == GPIO_MINOR_G) {
694 val = port_g_data_shadow;
696 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
699 case IO_SETGET_INPUT:
700 /* bits set in *arg is set to input,
701 * *arg updated with current input pins.
703 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
705 val = setget_input(priv, val);
706 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
709 case IO_SETGET_OUTPUT:
710 /* bits set in *arg is set to output,
711 * *arg updated with current output pins.
713 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
715 val = setget_output(priv, val);
716 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
720 if (priv->minor == GPIO_MINOR_LEDS)
721 return gpio_leds_ioctl(cmd, arg);
730 gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
735 switch (_IOC_NR(cmd)) {
736 case IO_LEDACTIVE_SET:
737 green = ((unsigned char) arg) & 1;
738 red = (((unsigned char) arg) >> 1) & 1;
739 LED_ACTIVE_SET_G(green);
740 LED_ACTIVE_SET_R(red);
758 struct file_operations gpio_fops = {
759 .owner = THIS_MODULE,
764 .release = gpio_release,
768 static void __init gpio_init_port_g(void)
770 #define GROUPA (0x0000FF3F)
771 #define GROUPB (1<<6 | 1<<7)
772 #define GROUPC (1<<30 | 1<<31)
773 #define GROUPD (0x3FFF0000)
774 #define GROUPD_LOW (0x00FF0000)
775 unsigned long used_in_bits = 0;
776 unsigned long used_out_bits = 0;
777 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
778 used_in_bits |= GROUPA | GROUPB | 0 | 0;
779 used_out_bits |= GROUPA | GROUPB | 0 | 0;
781 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
782 used_in_bits |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
783 used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
786 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
787 used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
788 used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
790 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
791 used_in_bits |= 0 | GROUPB | 0 | 0;
792 used_out_bits |= 0 | GROUPB | 0 | 0;
794 /* mio same as shared RAM ? */
795 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
796 used_in_bits |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
797 used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
799 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
800 used_in_bits |= 0 | 0 | GROUPC | GROUPD;
801 used_out_bits |= 0 | 0 | GROUPC | GROUPD;
803 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
804 used_in_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
805 used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
808 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
809 used_in_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
810 used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
812 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
813 used_in_bits |= 0 | 0 | GROUPC | 0;
814 used_out_bits |= 0 | 0 | GROUPC | 0;
816 /* mio same as shared RAM-W? */
817 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
818 used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
819 used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
821 /* TODO: USB p2, parw, sync ser3? */
823 /* Initialise the dir_g_shadow etc. depending on genconfig */
824 /* 0=input 1=output */
825 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out))
826 dir_g_shadow |= (1 << 0);
827 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
828 dir_g_shadow |= 0x0000FF00;
829 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))
830 dir_g_shadow |= 0x00FF0000;
831 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
832 dir_g_shadow |= (1 << 24);
834 dir_g_in_bits = ~used_in_bits;
835 dir_g_out_bits = ~used_out_bits;
837 changeable_dir_g = 0x01FFFF01; /* all that can change dir */
838 changeable_dir_g &= dir_g_out_bits;
839 changeable_dir_g &= dir_g_in_bits;
840 /* Correct the bits that can change direction */
841 dir_g_out_bits &= ~changeable_dir_g;
842 dir_g_out_bits |= dir_g_shadow;
843 dir_g_in_bits &= ~changeable_dir_g;
844 dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
847 printk("GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
848 dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
849 printk("GPIO port G: dir: %08lX changeable: %08lX\n",
850 dir_g_shadow, changeable_dir_g);
853 /* main driver initialization routine, called from mem.c */
859 #if defined (CONFIG_ETRAX_CSP0_LEDS)
863 /* do the formalities */
865 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
867 printk(KERN_ERR "gpio: couldn't get a major number.\n");
872 #if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
878 #if defined (CONFIG_ETRAX_CSP0_LEDS)
879 for (i = 0; i < 32; i++) {
886 printk("ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
887 /* We call etrax_gpio_wake_up_check() from timer interrupt and
888 * from cpu_idle() in kernel/process.c
889 * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
892 if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
893 SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) {
894 printk("err: timer0 irq for gpio\n");
896 if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
897 SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) {
898 printk("err: PA irq for gpio\n");
905 /* this makes sure that gpio_init is called during kernel boot */
907 module_init(gpio_init);