1 /* $Id: gpio.c,v 1.11 2004/05/14 07:58:03 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.11 2004/05/14 07:58:03 starvik
13 * Merge of changes from 2.4
15 * Revision 1.9 2003/09/11 07:29:48 starvik
16 * Merge of Linux 2.6.0-test5
18 * Revision 1.8 2003/07/04 08:27:37 starvik
19 * Merge of Linux 2.5.74
21 * Revision 1.7 2003/01/10 07:44:07 starvik
22 * init_ioremap is now called by kernel before drivers are initialized
24 * Revision 1.6 2002/12/11 13:13:57 starvik
25 * Added arch/ to v10 specific includes
26 * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
28 * Revision 1.5 2002/11/20 11:56:11 starvik
29 * Merge of Linux 2.5.48
31 * Revision 1.4 2002/11/18 10:10:05 starvik
32 * Linux 2.5 port of latest gpio.c from Linux 2.4
34 * Revision 1.20 2002/10/16 21:16:24 johana
35 * Added support for PA high level interrupt.
36 * That gives 2ms response time with iodtest for high levels and 2-12 ms
37 * response time on low levels if the check is not made in
38 * process.c:cpu_idle() as well.
40 * Revision 1.19 2002/10/14 18:27:33 johana
41 * Implemented alarm handling so select() now works.
42 * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
44 * Otherwise I get 15-18 ms (same as doing the poll in userspace -
46 * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
48 * TODO? Perhaps call request_irq()/free_irq() only when needed?
49 * Increased version to 2.5
51 * Revision 1.18 2002/10/11 15:02:00 johana
52 * Mask inverted 8 bit value in setget_input().
54 * Revision 1.17 2002/06/17 15:53:01 johana
55 * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
56 * that take a pointer as argument and thus can handle 32 bit ports (G)
58 * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
59 * (especially if Port G bit 31 is used)
61 * Revision 1.16 2002/06/17 09:59:51 johana
62 * Returning 32 bit values in the ioctl return value doesn't work if bit
63 * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
64 * A new set of ioctl's will be added.
66 * Revision 1.15 2002/05/06 13:19:13 johana
67 * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
69 * Revision 1.14 2002/04/12 12:01:53 johana
70 * Use global r_port_g_data_shadow.
71 * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
73 * Revision 1.13 2002/04/10 12:03:55 johana
74 * Added support for port G /dev/gpiog (minor 3).
75 * Changed indentation on switch cases.
76 * Fixed other spaces to tabs.
78 * Revision 1.12 2001/11/12 19:42:15 pkj
79 * * Corrected return values from gpio_leds_ioctl().
80 * * Fixed compiler warnings.
82 * Revision 1.11 2001/10/30 14:39:12 johana
83 * Added D() around gpio_write printk.
85 * Revision 1.10 2001/10/25 10:24:42 johana
86 * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
87 * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
88 * from ~60 seconds to 4 seconds).
89 * Added save_flags/cli/restore_flags in ioctl.
91 * Revision 1.9 2001/05/04 14:16:07 matsfg
92 * Corrected spelling error
94 * Revision 1.8 2001/04/27 13:55:26 matsfg
96 * Turns off all LEDS on init.
97 * Added support for shutdown and powerbutton.
99 * Revision 1.7 2001/04/04 13:30:08 matsfg
100 * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
102 * Revision 1.6 2001/03/26 16:03:06 bjornw
103 * Needs linux/config.h
105 * Revision 1.5 2001/03/26 14:22:03 bjornw
106 * Namechange of some config options
108 * Revision 1.4 2001/02/27 13:52:48 bjornw
111 * Revision 1.3 2001/01/24 15:06:48 bjornw
112 * gpio_wq correct type
114 * Revision 1.2 2001/01/18 16:07:30 bjornw
117 * Revision 1.1 2001/01/18 15:55:16 bjornw
118 * Verbatim copy of etraxgpio.c from elinux 2.0 added
123 #include <linux/config.h>
125 #include <linux/module.h>
126 #include <linux/sched.h>
127 #include <linux/slab.h>
128 #include <linux/ioport.h>
129 #include <linux/errno.h>
130 #include <linux/kernel.h>
131 #include <linux/fs.h>
132 #include <linux/string.h>
133 #include <linux/poll.h>
134 #include <linux/init.h>
135 #include <linux/interrupt.h>
137 #include <asm/etraxgpio.h>
138 #include <asm/arch/svinto.h>
140 #include <asm/system.h>
143 #define GPIO_MAJOR 120 /* experimental MAJOR number */
149 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
154 static char gpio_name[] = "etrax gpio";
157 static wait_queue_head_t *gpio_wq;
160 static int gpio_ioctl(struct inode *inode, struct file *file,
161 unsigned int cmd, unsigned long arg);
162 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
164 static int gpio_open(struct inode *inode, struct file *filp);
165 static int gpio_release(struct inode *inode, struct file *filp);
166 static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
168 /* private data per open() of this driver */
170 struct gpio_private {
171 struct gpio_private *next;
172 /* These fields are for PA and PB only */
173 volatile unsigned char *port, *shadow;
174 volatile unsigned char *dir, *dir_shadow;
175 unsigned char changeable_dir;
176 unsigned char changeable_bits;
177 unsigned char clk_mask;
178 unsigned char data_mask;
179 unsigned char write_msb;
180 unsigned char pad1, pad2, pad3;
181 /* These fields are generic */
182 unsigned long highalarm, lowalarm;
183 wait_queue_head_t alarm_wq;
187 /* linked list of alarms to check for */
189 static struct gpio_private *alarmlist = 0;
191 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
192 static unsigned long gpio_pa_irq_enabled_mask = 0;
194 /* Port A and B use 8 bit access, but Port G is 32 bit */
195 #define NUM_PORTS (GPIO_MINOR_B+1)
197 static volatile unsigned char *ports[NUM_PORTS] = {
201 static volatile unsigned char *shads[NUM_PORTS] = {
202 &port_pa_data_shadow,
206 /* What direction bits that are user changeable 1=changeable*/
207 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
208 #define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
210 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
211 #define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
214 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
215 #define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
217 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
218 #define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
222 static unsigned char changeable_dir[NUM_PORTS] = {
223 CONFIG_ETRAX_PA_CHANGEABLE_DIR,
224 CONFIG_ETRAX_PB_CHANGEABLE_DIR
226 static unsigned char changeable_bits[NUM_PORTS] = {
227 CONFIG_ETRAX_PA_CHANGEABLE_BITS,
228 CONFIG_ETRAX_PB_CHANGEABLE_BITS
231 static volatile unsigned char *dir[NUM_PORTS] = {
236 static volatile unsigned char *dir_shadow[NUM_PORTS] = {
241 /* Port G is 32 bit, handle it special, some bits are both inputs
242 and outputs at the same time, only some of the bits can change direction
243 and some of them in groups of 8 bit. */
244 static unsigned long changeable_dir_g;
245 static unsigned long dir_g_in_bits;
246 static unsigned long dir_g_out_bits;
247 static unsigned long dir_g_shadow; /* 1=output */
249 #define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
254 gpio_poll(struct file *file,
257 unsigned int mask = 0;
258 struct gpio_private *priv = (struct gpio_private *)file->private_data;
260 poll_wait(file, &priv->alarm_wq, wait);
261 if (priv->minor == GPIO_MINOR_A) {
264 data = *R_PORT_PA_DATA;
265 /* PA has support for high level interrupt -
266 * lets activate for those low and with highalarm set
268 tmp = ~data & priv->highalarm & 0xFF;
269 tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
270 save_flags(flags); cli();
271 gpio_pa_irq_enabled_mask |= tmp;
272 *R_IRQ_MASK1_SET = tmp;
273 restore_flags(flags);
275 } else if (priv->minor == GPIO_MINOR_B)
276 data = *R_PORT_PB_DATA;
277 else if (priv->minor == GPIO_MINOR_G)
278 data = *R_PORT_G_DATA;
282 if ((data & priv->highalarm) ||
283 (~data & priv->lowalarm)) {
284 mask = POLLIN|POLLRDNORM;
287 DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
291 int etrax_gpio_wake_up_check(void)
293 struct gpio_private *priv = alarmlist;
294 unsigned long data = 0;
297 if (USE_PORTS(priv)) {
299 } else if (priv->minor == GPIO_MINOR_G) {
300 data = *R_PORT_G_DATA;
302 if ((data & priv->highalarm) ||
303 (~data & priv->lowalarm)) {
304 DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
305 wake_up_interruptible(&priv->alarm_wq);
314 gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
316 if (gpio_some_alarms) {
317 etrax_gpio_wake_up_check();
324 gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
327 /* Find what PA interrupts are active */
328 tmp = (*R_IRQ_READ1);
330 /* Find those that we have enabled */
331 tmp &= gpio_pa_irq_enabled_mask;
334 *R_IRQ_MASK1_CLR = tmp;
335 gpio_pa_irq_enabled_mask &= ~tmp;
337 if (gpio_some_alarms) {
338 return IRQ_RETVAL(etrax_gpio_wake_up_check());
344 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
347 struct gpio_private *priv = (struct gpio_private *)file->private_data;
348 unsigned char data, clk_mask, data_mask, write_msb;
350 ssize_t retval = count;
351 if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
355 if (verify_area(VERIFY_READ, buf, count)) {
358 clk_mask = priv->clk_mask;
359 data_mask = priv->data_mask;
360 /* It must have been configured using the IO_CFG_WRITE_MODE */
361 /* Perhaps a better error code? */
362 if (clk_mask == 0 || data_mask == 0) {
365 write_msb = priv->write_msb;
366 D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
370 if (priv->write_msb) {
371 for (i = 7; i >= 0;i--) {
372 local_irq_save(flags); local_irq_disable();
373 *priv->port = *priv->shadow &= ~clk_mask;
375 *priv->port = *priv->shadow |= data_mask;
377 *priv->port = *priv->shadow &= ~data_mask;
378 /* For FPGA: min 5.0ns (DCC) before CCLK high */
379 *priv->port = *priv->shadow |= clk_mask;
380 local_irq_restore(flags);
383 for (i = 0; i <= 7;i++) {
384 local_irq_save(flags); local_irq_disable();
385 *priv->port = *priv->shadow &= ~clk_mask;
387 *priv->port = *priv->shadow |= data_mask;
389 *priv->port = *priv->shadow &= ~data_mask;
390 /* For FPGA: min 5.0ns (DCC) before CCLK high */
391 *priv->port = *priv->shadow |= clk_mask;
392 local_irq_restore(flags);
402 gpio_open(struct inode *inode, struct file *filp)
404 struct gpio_private *priv;
405 int p = MINOR(inode->i_rdev);
407 if (p > GPIO_MINOR_LAST)
410 priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
418 /* initialize the io/alarm struct and link it into our alarmlist */
420 priv->next = alarmlist;
422 if (USE_PORTS(priv)) { /* A and B */
423 priv->port = ports[p];
424 priv->shadow = shads[p];
426 priv->dir_shadow = dir_shadow[p];
427 priv->changeable_dir = changeable_dir[p];
428 priv->changeable_bits = changeable_bits[p];
433 priv->dir_shadow = NULL;
434 priv->changeable_dir = 0;
435 priv->changeable_bits = 0;
442 init_waitqueue_head(&priv->alarm_wq);
444 filp->private_data = (void *)priv;
450 gpio_release(struct inode *inode, struct file *filp)
452 struct gpio_private *p = alarmlist;
453 struct gpio_private *todel = (struct gpio_private *)filp->private_data;
455 /* unlink from alarmlist and free the private structure */
458 alarmlist = todel->next;
460 while (p->next != todel)
462 p->next = todel->next;
466 /* Check if there are still any alarms set */
469 if (p->highalarm | p->lowalarm) {
470 gpio_some_alarms = 1;
475 gpio_some_alarms = 0;
480 /* Main device API. ioctl's to read/set/clear bits, as well as to
481 * set alarms to wait for using a subsequent select().
484 unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
486 /* Set direction 0=unchanged 1=input,
487 * return mask with 1=input
490 if (USE_PORTS(priv)) {
491 local_irq_save(flags); local_irq_disable();
492 *priv->dir = *priv->dir_shadow &=
493 ~((unsigned char)arg & priv->changeable_dir);
494 local_irq_restore(flags);
495 return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
496 } else if (priv->minor == GPIO_MINOR_G) {
497 /* We must fiddle with R_GEN_CONFIG to change dir */
498 save_flags(flags); cli();
499 if (((arg & dir_g_in_bits) != arg) &&
500 (arg & changeable_dir_g)) {
501 arg &= changeable_dir_g;
502 /* Clear bits in genconfig to set to input */
504 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
505 dir_g_in_bits |= (1<<0);
506 dir_g_out_bits &= ~(1<<0);
508 if ((arg & 0x0000FF00) == 0x0000FF00) {
509 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
510 dir_g_in_bits |= 0x0000FF00;
511 dir_g_out_bits &= ~0x0000FF00;
513 if ((arg & 0x00FF0000) == 0x00FF0000) {
514 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
515 dir_g_in_bits |= 0x00FF0000;
516 dir_g_out_bits &= ~0x00FF0000;
519 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
520 dir_g_in_bits |= (1<<24);
521 dir_g_out_bits &= ~(1<<24);
523 D(printk(KERN_INFO "gpio: SETINPUT on port G set "
524 "genconfig to 0x%08lX "
526 "out_bits: 0x%08lX\n",
527 (unsigned long)genconfig_shadow,
528 dir_g_in_bits, dir_g_out_bits));
529 *R_GEN_CONFIG = genconfig_shadow;
530 /* Must be a >120 ns delay before writing this again */
533 restore_flags(flags);
534 return dir_g_in_bits;
539 unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
542 if (USE_PORTS(priv)) {
543 local_irq_save(flags); local_irq_disable();
544 *priv->dir = *priv->dir_shadow |=
545 ((unsigned char)arg & priv->changeable_dir);
546 local_irq_restore(flags);
547 return *priv->dir_shadow;
548 } else if (priv->minor == GPIO_MINOR_G) {
549 /* We must fiddle with R_GEN_CONFIG to change dir */
550 save_flags(flags); cli();
551 if (((arg & dir_g_out_bits) != arg) &&
552 (arg & changeable_dir_g)) {
553 /* Set bits in genconfig to set to output */
555 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
556 dir_g_out_bits |= (1<<0);
557 dir_g_in_bits &= ~(1<<0);
559 if ((arg & 0x0000FF00) == 0x0000FF00) {
560 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
561 dir_g_out_bits |= 0x0000FF00;
562 dir_g_in_bits &= ~0x0000FF00;
564 if ((arg & 0x00FF0000) == 0x00FF0000) {
565 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
566 dir_g_out_bits |= 0x00FF0000;
567 dir_g_in_bits &= ~0x00FF0000;
570 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
571 dir_g_out_bits |= (1<<24);
572 dir_g_in_bits &= ~(1<<24);
574 D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
575 "genconfig to 0x%08lX "
577 "out_bits: 0x%08lX\n",
578 (unsigned long)genconfig_shadow,
579 dir_g_in_bits, dir_g_out_bits));
580 *R_GEN_CONFIG = genconfig_shadow;
581 /* Must be a >120 ns delay before writing this again */
583 restore_flags(flags);
584 return dir_g_out_bits & 0x7FFFFFFF;
587 } /* setget_output */
590 gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
593 gpio_ioctl(struct inode *inode, struct file *file,
594 unsigned int cmd, unsigned long arg)
598 struct gpio_private *priv = (struct gpio_private *)file->private_data;
599 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
603 switch (_IOC_NR(cmd)) {
604 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
606 if (USE_PORTS(priv)) {
608 } else if (priv->minor == GPIO_MINOR_G) {
609 return (*R_PORT_G_DATA) & 0x7FFFFFFF;
613 local_irq_save(flags); local_irq_disable();
614 // set changeable bits with a 1 in arg
615 if (USE_PORTS(priv)) {
616 *priv->port = *priv->shadow |=
617 ((unsigned char)arg & priv->changeable_bits);
618 } else if (priv->minor == GPIO_MINOR_G) {
619 *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
621 local_irq_restore(flags);
624 local_irq_save(flags); local_irq_disable();
625 // clear changeable bits with a 1 in arg
626 if (USE_PORTS(priv)) {
627 *priv->port = *priv->shadow &=
628 ~((unsigned char)arg & priv->changeable_bits);
629 } else if (priv->minor == GPIO_MINOR_G) {
630 *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
632 local_irq_restore(flags);
635 // set alarm when bits with 1 in arg go high
636 priv->highalarm |= arg;
637 gpio_some_alarms = 1;
640 // set alarm when bits with 1 in arg go low
641 priv->lowalarm |= arg;
642 gpio_some_alarms = 1;
645 // clear alarm for bits with 1 in arg
646 priv->highalarm &= ~arg;
647 priv->lowalarm &= ~arg;
649 /* Must update gpio_some_alarms */
650 struct gpio_private *p = alarmlist;
654 if (p->highalarm | p->lowalarm) {
660 gpio_some_alarms = some_alarms;
663 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
664 /* Read direction 0=input 1=output */
665 if (USE_PORTS(priv)) {
666 return *priv->dir_shadow;
667 } else if (priv->minor == GPIO_MINOR_G) {
668 /* Note: Some bits are both in and out,
669 * Those that are dual is set here as well.
671 return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
673 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
674 /* Set direction 0=unchanged 1=input,
675 * return mask with 1=input
677 return setget_input(priv, arg) & 0x7FFFFFFF;
679 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
680 /* Set direction 0=unchanged 1=output,
681 * return mask with 1=output
683 return setget_output(priv, arg) & 0x7FFFFFFF;
689 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
690 return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
695 case IO_CFG_WRITE_MODE:
696 priv->clk_mask = arg & 0xFF;
697 priv->data_mask = (arg >> 8) & 0xFF;
698 priv->write_msb = (arg >> 16) & 0x01;
699 /* Check if we're allowed to change the bits and
700 * the direction is correct
702 if (!((priv->clk_mask & priv->changeable_bits) &&
703 (priv->data_mask & priv->changeable_bits) &&
704 (priv->clk_mask & *priv->dir_shadow) &&
705 (priv->data_mask & *priv->dir_shadow)))
713 /* *arg is result of reading the input pins */
714 if (USE_PORTS(priv)) {
716 } else if (priv->minor == GPIO_MINOR_G) {
717 val = *R_PORT_G_DATA;
719 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
723 case IO_READ_OUTBITS:
724 /* *arg is result of reading the output shadow */
725 if (USE_PORTS(priv)) {
727 } else if (priv->minor == GPIO_MINOR_G) {
728 val = port_g_data_shadow;
730 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
733 case IO_SETGET_INPUT:
734 /* bits set in *arg is set to input,
735 * *arg updated with current input pins.
737 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
739 val = setget_input(priv, val);
740 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
743 case IO_SETGET_OUTPUT:
744 /* bits set in *arg is set to output,
745 * *arg updated with current output pins.
747 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
749 val = setget_output(priv, val);
750 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
754 if (priv->minor == GPIO_MINOR_LEDS)
755 return gpio_leds_ioctl(cmd, arg);
764 gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
769 switch (_IOC_NR(cmd)) {
770 case IO_LEDACTIVE_SET:
771 green = ((unsigned char) arg) & 1;
772 red = (((unsigned char) arg) >> 1) & 1;
773 LED_ACTIVE_SET_G(green);
774 LED_ACTIVE_SET_R(red);
792 struct file_operations gpio_fops = {
793 .owner = THIS_MODULE,
798 .release = gpio_release,
802 static void __init gpio_init_port_g(void)
804 #define GROUPA (0x0000FF3F)
805 #define GROUPB (1<<6 | 1<<7)
806 #define GROUPC (1<<30 | 1<<31)
807 #define GROUPD (0x3FFF0000)
808 #define GROUPD_LOW (0x00FF0000)
809 unsigned long used_in_bits = 0;
810 unsigned long used_out_bits = 0;
811 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
812 used_in_bits |= GROUPA | GROUPB | 0 | 0;
813 used_out_bits |= GROUPA | GROUPB | 0 | 0;
815 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
816 used_in_bits |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
817 used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
820 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
821 used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
822 used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
824 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
825 used_in_bits |= 0 | GROUPB | 0 | 0;
826 used_out_bits |= 0 | GROUPB | 0 | 0;
828 /* mio same as shared RAM ? */
829 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
830 used_in_bits |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
831 used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
833 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
834 used_in_bits |= 0 | 0 | GROUPC | GROUPD;
835 used_out_bits |= 0 | 0 | GROUPC | GROUPD;
837 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
838 used_in_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
839 used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
842 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
843 used_in_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
844 used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
846 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
847 used_in_bits |= 0 | 0 | GROUPC | 0;
848 used_out_bits |= 0 | 0 | GROUPC | 0;
850 /* mio same as shared RAM-W? */
851 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
852 used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
853 used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
855 /* TODO: USB p2, parw, sync ser3? */
857 /* Initialise the dir_g_shadow etc. depending on genconfig */
858 /* 0=input 1=output */
859 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out))
860 dir_g_shadow |= (1 << 0);
861 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
862 dir_g_shadow |= 0x0000FF00;
863 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))
864 dir_g_shadow |= 0x00FF0000;
865 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
866 dir_g_shadow |= (1 << 24);
868 dir_g_in_bits = ~used_in_bits;
869 dir_g_out_bits = ~used_out_bits;
871 changeable_dir_g = 0x01FFFF01; /* all that can change dir */
872 changeable_dir_g &= dir_g_out_bits;
873 changeable_dir_g &= dir_g_in_bits;
874 /* Correct the bits that can change direction */
875 dir_g_out_bits &= ~changeable_dir_g;
876 dir_g_out_bits |= dir_g_shadow;
877 dir_g_in_bits &= ~changeable_dir_g;
878 dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
881 printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
882 dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
883 printk(KERN_INFO "GPIO port G: dir: %08lX changeable: %08lX\n",
884 dir_g_shadow, changeable_dir_g);
887 /* main driver initialization routine, called from mem.c */
893 #if defined (CONFIG_ETRAX_CSP0_LEDS)
897 /* do the formalities */
899 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
901 printk(KERN_ERR "gpio: couldn't get a major number.\n");
906 #if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
912 #if defined (CONFIG_ETRAX_CSP0_LEDS)
913 for (i = 0; i < 32; i++) {
920 printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
921 /* We call etrax_gpio_wake_up_check() from timer interrupt and
922 * from cpu_idle() in kernel/process.c
923 * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
926 if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
927 SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) {
928 printk(KERN_CRIT "err: timer0 irq for gpio\n");
930 if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
931 SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) {
932 printk(KERN_CRIT "err: PA irq for gpio\n");
939 /* this makes sure that gpio_init is called during kernel boot */
941 module_init(gpio_init);