allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / cris / arch-v10 / drivers / gpio.c
blobf389ed6998fe4f92ec9fc28b95ce2cc8cbd65e34
1 /* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 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)
11 * $Log: gpio.c,v $
12 * Revision 1.17 2005/06/19 17:06:46 starvik
13 * Merge of Linux 2.6.12.
15 * Revision 1.16 2005/03/07 13:02:29 starvik
16 * Protect driver global states with spinlock
18 * Revision 1.15 2005/01/05 06:08:55 starvik
19 * No need to do local_irq_disable after local_irq_save.
21 * Revision 1.14 2004/12/13 12:21:52 starvik
22 * Added I/O and DMA allocators from Linux 2.4
24 * Revision 1.12 2004/08/24 07:19:59 starvik
25 * Whitespace cleanup
27 * Revision 1.11 2004/05/14 07:58:03 starvik
28 * Merge of changes from 2.4
30 * Revision 1.9 2003/09/11 07:29:48 starvik
31 * Merge of Linux 2.6.0-test5
33 * Revision 1.8 2003/07/04 08:27:37 starvik
34 * Merge of Linux 2.5.74
36 * Revision 1.7 2003/01/10 07:44:07 starvik
37 * init_ioremap is now called by kernel before drivers are initialized
39 * Revision 1.6 2002/12/11 13:13:57 starvik
40 * Added arch/ to v10 specific includes
41 * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
43 * Revision 1.5 2002/11/20 11:56:11 starvik
44 * Merge of Linux 2.5.48
46 * Revision 1.4 2002/11/18 10:10:05 starvik
47 * Linux 2.5 port of latest gpio.c from Linux 2.4
49 * Revision 1.20 2002/10/16 21:16:24 johana
50 * Added support for PA high level interrupt.
51 * That gives 2ms response time with iodtest for high levels and 2-12 ms
52 * response time on low levels if the check is not made in
53 * process.c:cpu_idle() as well.
55 * Revision 1.19 2002/10/14 18:27:33 johana
56 * Implemented alarm handling so select() now works.
57 * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
58 * cpu_idle().
59 * Otherwise I get 15-18 ms (same as doing the poll in userspace -
60 * but less overhead).
61 * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
62 * is in 2.4) as well?
63 * TODO? Perhaps call request_irq()/free_irq() only when needed?
64 * Increased version to 2.5
66 * Revision 1.18 2002/10/11 15:02:00 johana
67 * Mask inverted 8 bit value in setget_input().
69 * Revision 1.17 2002/06/17 15:53:01 johana
70 * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
71 * that take a pointer as argument and thus can handle 32 bit ports (G)
72 * correctly.
73 * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
74 * (especially if Port G bit 31 is used)
76 * Revision 1.16 2002/06/17 09:59:51 johana
77 * Returning 32 bit values in the ioctl return value doesn't work if bit
78 * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
79 * A new set of ioctl's will be added.
81 * Revision 1.15 2002/05/06 13:19:13 johana
82 * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
84 * Revision 1.14 2002/04/12 12:01:53 johana
85 * Use global r_port_g_data_shadow.
86 * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
88 * Revision 1.13 2002/04/10 12:03:55 johana
89 * Added support for port G /dev/gpiog (minor 3).
90 * Changed indentation on switch cases.
91 * Fixed other spaces to tabs.
93 * Revision 1.12 2001/11/12 19:42:15 pkj
94 * * Corrected return values from gpio_leds_ioctl().
95 * * Fixed compiler warnings.
97 * Revision 1.11 2001/10/30 14:39:12 johana
98 * Added D() around gpio_write printk.
100 * Revision 1.10 2001/10/25 10:24:42 johana
101 * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
102 * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
103 * from ~60 seconds to 4 seconds).
104 * Added save_flags/cli/restore_flags in ioctl.
106 * Revision 1.9 2001/05/04 14:16:07 matsfg
107 * Corrected spelling error
109 * Revision 1.8 2001/04/27 13:55:26 matsfg
110 * Moved initioremap.
111 * Turns off all LEDS on init.
112 * Added support for shutdown and powerbutton.
114 * Revision 1.7 2001/04/04 13:30:08 matsfg
115 * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
117 * Revision 1.6 2001/03/26 16:03:06 bjornw
118 * Needs linux/config.h
120 * Revision 1.5 2001/03/26 14:22:03 bjornw
121 * Namechange of some config options
123 * Revision 1.4 2001/02/27 13:52:48 bjornw
124 * malloc.h -> slab.h
126 * Revision 1.3 2001/01/24 15:06:48 bjornw
127 * gpio_wq correct type
129 * Revision 1.2 2001/01/18 16:07:30 bjornw
130 * 2.4 port
132 * Revision 1.1 2001/01/18 15:55:16 bjornw
133 * Verbatim copy of etraxgpio.c from elinux 2.0 added
139 #include <linux/module.h>
140 #include <linux/sched.h>
141 #include <linux/slab.h>
142 #include <linux/ioport.h>
143 #include <linux/errno.h>
144 #include <linux/kernel.h>
145 #include <linux/fs.h>
146 #include <linux/string.h>
147 #include <linux/poll.h>
148 #include <linux/init.h>
149 #include <linux/interrupt.h>
151 #include <asm/etraxgpio.h>
152 #include <asm/arch/svinto.h>
153 #include <asm/io.h>
154 #include <asm/system.h>
155 #include <asm/irq.h>
156 #include <asm/arch/io_interface_mux.h>
158 #define GPIO_MAJOR 120 /* experimental MAJOR number */
160 #define D(x)
162 #if 0
163 static int dp_cnt;
164 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
165 #else
166 #define DP(x)
167 #endif
169 static char gpio_name[] = "etrax gpio";
171 #if 0
172 static wait_queue_head_t *gpio_wq;
173 #endif
175 static int gpio_ioctl(struct inode *inode, struct file *file,
176 unsigned int cmd, unsigned long arg);
177 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
178 loff_t *off);
179 static int gpio_open(struct inode *inode, struct file *filp);
180 static int gpio_release(struct inode *inode, struct file *filp);
181 static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
183 /* private data per open() of this driver */
185 struct gpio_private {
186 struct gpio_private *next;
187 /* These fields are for PA and PB only */
188 volatile unsigned char *port, *shadow;
189 volatile unsigned char *dir, *dir_shadow;
190 unsigned char changeable_dir;
191 unsigned char changeable_bits;
192 unsigned char clk_mask;
193 unsigned char data_mask;
194 unsigned char write_msb;
195 unsigned char pad1, pad2, pad3;
196 /* These fields are generic */
197 unsigned long highalarm, lowalarm;
198 wait_queue_head_t alarm_wq;
199 int minor;
202 /* linked list of alarms to check for */
204 static struct gpio_private *alarmlist = 0;
206 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
207 static unsigned long gpio_pa_irq_enabled_mask = 0;
209 static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */
211 /* Port A and B use 8 bit access, but Port G is 32 bit */
212 #define NUM_PORTS (GPIO_MINOR_B+1)
214 static volatile unsigned char *ports[NUM_PORTS] = {
215 R_PORT_PA_DATA,
216 R_PORT_PB_DATA,
218 static volatile unsigned char *shads[NUM_PORTS] = {
219 &port_pa_data_shadow,
220 &port_pb_data_shadow
223 /* What direction bits that are user changeable 1=changeable*/
224 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
225 #define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
226 #endif
227 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
228 #define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
229 #endif
231 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
232 #define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
233 #endif
234 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
235 #define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
236 #endif
239 static unsigned char changeable_dir[NUM_PORTS] = {
240 CONFIG_ETRAX_PA_CHANGEABLE_DIR,
241 CONFIG_ETRAX_PB_CHANGEABLE_DIR
243 static unsigned char changeable_bits[NUM_PORTS] = {
244 CONFIG_ETRAX_PA_CHANGEABLE_BITS,
245 CONFIG_ETRAX_PB_CHANGEABLE_BITS
248 static volatile unsigned char *dir[NUM_PORTS] = {
249 R_PORT_PA_DIR,
250 R_PORT_PB_DIR
253 static volatile unsigned char *dir_shadow[NUM_PORTS] = {
254 &port_pa_dir_shadow,
255 &port_pb_dir_shadow
258 /* All bits in port g that can change dir. */
259 static const unsigned long int changeable_dir_g_mask = 0x01FFFF01;
261 /* Port G is 32 bit, handle it special, some bits are both inputs
262 and outputs at the same time, only some of the bits can change direction
263 and some of them in groups of 8 bit. */
264 static unsigned long changeable_dir_g;
265 static unsigned long dir_g_in_bits;
266 static unsigned long dir_g_out_bits;
267 static unsigned long dir_g_shadow; /* 1=output */
269 #define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
273 static unsigned int
274 gpio_poll(struct file *file,
275 poll_table *wait)
277 unsigned int mask = 0;
278 struct gpio_private *priv = (struct gpio_private *)file->private_data;
279 unsigned long data;
280 spin_lock(&gpio_lock);
281 poll_wait(file, &priv->alarm_wq, wait);
282 if (priv->minor == GPIO_MINOR_A) {
283 unsigned long flags;
284 unsigned long tmp;
285 data = *R_PORT_PA_DATA;
286 /* PA has support for high level interrupt -
287 * lets activate for those low and with highalarm set
289 tmp = ~data & priv->highalarm & 0xFF;
290 tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
291 local_irq_save(flags);
292 gpio_pa_irq_enabled_mask |= tmp;
293 *R_IRQ_MASK1_SET = tmp;
294 local_irq_restore(flags);
296 } else if (priv->minor == GPIO_MINOR_B)
297 data = *R_PORT_PB_DATA;
298 else if (priv->minor == GPIO_MINOR_G)
299 data = *R_PORT_G_DATA;
300 else
301 return 0;
303 if ((data & priv->highalarm) ||
304 (~data & priv->lowalarm)) {
305 mask = POLLIN|POLLRDNORM;
308 spin_unlock(&gpio_lock);
310 DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
312 return mask;
315 int etrax_gpio_wake_up_check(void)
317 struct gpio_private *priv = alarmlist;
318 unsigned long data = 0;
319 int ret = 0;
320 spin_lock(&gpio_lock);
321 while (priv) {
322 if (USE_PORTS(priv)) {
323 data = *priv->port;
324 } else if (priv->minor == GPIO_MINOR_G) {
325 data = *R_PORT_G_DATA;
327 if ((data & priv->highalarm) ||
328 (~data & priv->lowalarm)) {
329 DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
330 wake_up_interruptible(&priv->alarm_wq);
331 ret = 1;
333 priv = priv->next;
335 spin_unlock(&gpio_lock);
336 return ret;
339 static irqreturn_t
340 gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
342 if (gpio_some_alarms) {
343 etrax_gpio_wake_up_check();
344 return IRQ_HANDLED;
346 return IRQ_NONE;
349 static irqreturn_t
350 gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
352 unsigned long tmp;
353 spin_lock(&gpio_lock);
354 /* Find what PA interrupts are active */
355 tmp = (*R_IRQ_READ1);
357 /* Find those that we have enabled */
358 tmp &= gpio_pa_irq_enabled_mask;
360 /* Clear them.. */
361 *R_IRQ_MASK1_CLR = tmp;
362 gpio_pa_irq_enabled_mask &= ~tmp;
364 spin_unlock(&gpio_lock);
366 if (gpio_some_alarms) {
367 return IRQ_RETVAL(etrax_gpio_wake_up_check());
369 return IRQ_NONE;
373 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
374 loff_t *off)
376 struct gpio_private *priv = (struct gpio_private *)file->private_data;
377 unsigned char data, clk_mask, data_mask, write_msb;
378 unsigned long flags;
380 spin_lock(&gpio_lock);
382 ssize_t retval = count;
383 if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
384 return -EFAULT;
387 if (!access_ok(VERIFY_READ, buf, count)) {
388 return -EFAULT;
390 clk_mask = priv->clk_mask;
391 data_mask = priv->data_mask;
392 /* It must have been configured using the IO_CFG_WRITE_MODE */
393 /* Perhaps a better error code? */
394 if (clk_mask == 0 || data_mask == 0) {
395 return -EPERM;
397 write_msb = priv->write_msb;
398 D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
399 while (count--) {
400 int i;
401 data = *buf++;
402 if (priv->write_msb) {
403 for (i = 7; i >= 0;i--) {
404 local_irq_save(flags);
405 *priv->port = *priv->shadow &= ~clk_mask;
406 if (data & 1<<i)
407 *priv->port = *priv->shadow |= data_mask;
408 else
409 *priv->port = *priv->shadow &= ~data_mask;
410 /* For FPGA: min 5.0ns (DCC) before CCLK high */
411 *priv->port = *priv->shadow |= clk_mask;
412 local_irq_restore(flags);
414 } else {
415 for (i = 0; i <= 7;i++) {
416 local_irq_save(flags);
417 *priv->port = *priv->shadow &= ~clk_mask;
418 if (data & 1<<i)
419 *priv->port = *priv->shadow |= data_mask;
420 else
421 *priv->port = *priv->shadow &= ~data_mask;
422 /* For FPGA: min 5.0ns (DCC) before CCLK high */
423 *priv->port = *priv->shadow |= clk_mask;
424 local_irq_restore(flags);
428 spin_unlock(&gpio_lock);
429 return retval;
434 static int
435 gpio_open(struct inode *inode, struct file *filp)
437 struct gpio_private *priv;
438 int p = iminor(inode);
440 if (p > GPIO_MINOR_LAST)
441 return -EINVAL;
443 priv = kmalloc(sizeof(struct gpio_private),
444 GFP_KERNEL);
446 if (!priv)
447 return -ENOMEM;
449 priv->minor = p;
451 /* initialize the io/alarm struct and link it into our alarmlist */
453 priv->next = alarmlist;
454 alarmlist = priv;
455 if (USE_PORTS(priv)) { /* A and B */
456 priv->port = ports[p];
457 priv->shadow = shads[p];
458 priv->dir = dir[p];
459 priv->dir_shadow = dir_shadow[p];
460 priv->changeable_dir = changeable_dir[p];
461 priv->changeable_bits = changeable_bits[p];
462 } else {
463 priv->port = NULL;
464 priv->shadow = NULL;
465 priv->dir = NULL;
466 priv->dir_shadow = NULL;
467 priv->changeable_dir = 0;
468 priv->changeable_bits = 0;
471 priv->highalarm = 0;
472 priv->lowalarm = 0;
473 priv->clk_mask = 0;
474 priv->data_mask = 0;
475 init_waitqueue_head(&priv->alarm_wq);
477 filp->private_data = (void *)priv;
479 return 0;
482 static int
483 gpio_release(struct inode *inode, struct file *filp)
485 struct gpio_private *p;
486 struct gpio_private *todel;
488 spin_lock(&gpio_lock);
490 p = alarmlist;
491 todel = (struct gpio_private *)filp->private_data;
493 /* unlink from alarmlist and free the private structure */
495 if (p == todel) {
496 alarmlist = todel->next;
497 } else {
498 while (p->next != todel)
499 p = p->next;
500 p->next = todel->next;
503 kfree(todel);
504 /* Check if there are still any alarms set */
505 p = alarmlist;
506 while (p) {
507 if (p->highalarm | p->lowalarm) {
508 gpio_some_alarms = 1;
509 return 0;
511 p = p->next;
513 gpio_some_alarms = 0;
514 spin_unlock(&gpio_lock);
515 return 0;
518 /* Main device API. ioctl's to read/set/clear bits, as well as to
519 * set alarms to wait for using a subsequent select().
522 unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
524 /* Set direction 0=unchanged 1=input,
525 * return mask with 1=input
527 unsigned long flags;
528 if (USE_PORTS(priv)) {
529 local_irq_save(flags);
530 *priv->dir = *priv->dir_shadow &=
531 ~((unsigned char)arg & priv->changeable_dir);
532 local_irq_restore(flags);
533 return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
534 } else if (priv->minor == GPIO_MINOR_G) {
535 /* We must fiddle with R_GEN_CONFIG to change dir */
536 local_irq_save(flags);
537 if (((arg & dir_g_in_bits) != arg) &&
538 (arg & changeable_dir_g)) {
539 arg &= changeable_dir_g;
540 /* Clear bits in genconfig to set to input */
541 if (arg & (1<<0)) {
542 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
543 dir_g_in_bits |= (1<<0);
544 dir_g_out_bits &= ~(1<<0);
546 if ((arg & 0x0000FF00) == 0x0000FF00) {
547 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
548 dir_g_in_bits |= 0x0000FF00;
549 dir_g_out_bits &= ~0x0000FF00;
551 if ((arg & 0x00FF0000) == 0x00FF0000) {
552 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
553 dir_g_in_bits |= 0x00FF0000;
554 dir_g_out_bits &= ~0x00FF0000;
556 if (arg & (1<<24)) {
557 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
558 dir_g_in_bits |= (1<<24);
559 dir_g_out_bits &= ~(1<<24);
561 D(printk(KERN_INFO "gpio: SETINPUT on port G set "
562 "genconfig to 0x%08lX "
563 "in_bits: 0x%08lX "
564 "out_bits: 0x%08lX\n",
565 (unsigned long)genconfig_shadow,
566 dir_g_in_bits, dir_g_out_bits));
567 *R_GEN_CONFIG = genconfig_shadow;
568 /* Must be a >120 ns delay before writing this again */
571 local_irq_restore(flags);
572 return dir_g_in_bits;
574 return 0;
575 } /* setget_input */
577 unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
579 unsigned long flags;
580 if (USE_PORTS(priv)) {
581 local_irq_save(flags);
582 *priv->dir = *priv->dir_shadow |=
583 ((unsigned char)arg & priv->changeable_dir);
584 local_irq_restore(flags);
585 return *priv->dir_shadow;
586 } else if (priv->minor == GPIO_MINOR_G) {
587 /* We must fiddle with R_GEN_CONFIG to change dir */
588 local_irq_save(flags);
589 if (((arg & dir_g_out_bits) != arg) &&
590 (arg & changeable_dir_g)) {
591 /* Set bits in genconfig to set to output */
592 if (arg & (1<<0)) {
593 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
594 dir_g_out_bits |= (1<<0);
595 dir_g_in_bits &= ~(1<<0);
597 if ((arg & 0x0000FF00) == 0x0000FF00) {
598 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
599 dir_g_out_bits |= 0x0000FF00;
600 dir_g_in_bits &= ~0x0000FF00;
602 if ((arg & 0x00FF0000) == 0x00FF0000) {
603 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
604 dir_g_out_bits |= 0x00FF0000;
605 dir_g_in_bits &= ~0x00FF0000;
607 if (arg & (1<<24)) {
608 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
609 dir_g_out_bits |= (1<<24);
610 dir_g_in_bits &= ~(1<<24);
612 D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
613 "genconfig to 0x%08lX "
614 "in_bits: 0x%08lX "
615 "out_bits: 0x%08lX\n",
616 (unsigned long)genconfig_shadow,
617 dir_g_in_bits, dir_g_out_bits));
618 *R_GEN_CONFIG = genconfig_shadow;
619 /* Must be a >120 ns delay before writing this again */
621 local_irq_restore(flags);
622 return dir_g_out_bits & 0x7FFFFFFF;
624 return 0;
625 } /* setget_output */
627 static int
628 gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
630 static int
631 gpio_ioctl(struct inode *inode, struct file *file,
632 unsigned int cmd, unsigned long arg)
634 unsigned long flags;
635 unsigned long val;
636 int ret = 0;
638 struct gpio_private *priv = (struct gpio_private *)file->private_data;
639 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
640 return -EINVAL;
643 spin_lock(&gpio_lock);
645 switch (_IOC_NR(cmd)) {
646 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
647 // read the port
648 if (USE_PORTS(priv)) {
649 ret = *priv->port;
650 } else if (priv->minor == GPIO_MINOR_G) {
651 ret = (*R_PORT_G_DATA) & 0x7FFFFFFF;
653 break;
654 case IO_SETBITS:
655 local_irq_save(flags);
656 // set changeable bits with a 1 in arg
657 if (USE_PORTS(priv)) {
658 *priv->port = *priv->shadow |=
659 ((unsigned char)arg & priv->changeable_bits);
660 } else if (priv->minor == GPIO_MINOR_G) {
661 *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
663 local_irq_restore(flags);
664 break;
665 case IO_CLRBITS:
666 local_irq_save(flags);
667 // clear changeable bits with a 1 in arg
668 if (USE_PORTS(priv)) {
669 *priv->port = *priv->shadow &=
670 ~((unsigned char)arg & priv->changeable_bits);
671 } else if (priv->minor == GPIO_MINOR_G) {
672 *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
674 local_irq_restore(flags);
675 break;
676 case IO_HIGHALARM:
677 // set alarm when bits with 1 in arg go high
678 priv->highalarm |= arg;
679 gpio_some_alarms = 1;
680 break;
681 case IO_LOWALARM:
682 // set alarm when bits with 1 in arg go low
683 priv->lowalarm |= arg;
684 gpio_some_alarms = 1;
685 break;
686 case IO_CLRALARM:
687 // clear alarm for bits with 1 in arg
688 priv->highalarm &= ~arg;
689 priv->lowalarm &= ~arg;
691 /* Must update gpio_some_alarms */
692 struct gpio_private *p = alarmlist;
693 int some_alarms;
694 some_alarms = 0;
695 while (p) {
696 if (p->highalarm | p->lowalarm) {
697 some_alarms = 1;
698 break;
700 p = p->next;
702 gpio_some_alarms = some_alarms;
704 break;
705 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
706 /* Read direction 0=input 1=output */
707 if (USE_PORTS(priv)) {
708 ret = *priv->dir_shadow;
709 } else if (priv->minor == GPIO_MINOR_G) {
710 /* Note: Some bits are both in and out,
711 * Those that are dual is set here as well.
713 ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
715 break;
716 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
717 /* Set direction 0=unchanged 1=input,
718 * return mask with 1=input
720 ret = setget_input(priv, arg) & 0x7FFFFFFF;
721 break;
722 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
723 /* Set direction 0=unchanged 1=output,
724 * return mask with 1=output
726 ret = setget_output(priv, arg) & 0x7FFFFFFF;
727 break;
728 case IO_SHUTDOWN:
729 SOFT_SHUTDOWN();
730 break;
731 case IO_GET_PWR_BT:
732 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
733 ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
734 #else
735 ret = 0;
736 #endif
737 break;
738 case IO_CFG_WRITE_MODE:
739 priv->clk_mask = arg & 0xFF;
740 priv->data_mask = (arg >> 8) & 0xFF;
741 priv->write_msb = (arg >> 16) & 0x01;
742 /* Check if we're allowed to change the bits and
743 * the direction is correct
745 if (!((priv->clk_mask & priv->changeable_bits) &&
746 (priv->data_mask & priv->changeable_bits) &&
747 (priv->clk_mask & *priv->dir_shadow) &&
748 (priv->data_mask & *priv->dir_shadow)))
750 priv->clk_mask = 0;
751 priv->data_mask = 0;
752 ret = -EPERM;
754 break;
755 case IO_READ_INBITS:
756 /* *arg is result of reading the input pins */
757 if (USE_PORTS(priv)) {
758 val = *priv->port;
759 } else if (priv->minor == GPIO_MINOR_G) {
760 val = *R_PORT_G_DATA;
762 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
763 ret = -EFAULT;
764 break;
765 case IO_READ_OUTBITS:
766 /* *arg is result of reading the output shadow */
767 if (USE_PORTS(priv)) {
768 val = *priv->shadow;
769 } else if (priv->minor == GPIO_MINOR_G) {
770 val = port_g_data_shadow;
772 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
773 ret = -EFAULT;
774 break;
775 case IO_SETGET_INPUT:
776 /* bits set in *arg is set to input,
777 * *arg updated with current input pins.
779 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
781 ret = -EFAULT;
782 break;
784 val = setget_input(priv, val);
785 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
786 ret = -EFAULT;
787 break;
788 case IO_SETGET_OUTPUT:
789 /* bits set in *arg is set to output,
790 * *arg updated with current output pins.
792 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
794 ret = -EFAULT;
795 break;
797 val = setget_output(priv, val);
798 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
799 ret = -EFAULT;
800 break;
801 default:
802 if (priv->minor == GPIO_MINOR_LEDS)
803 ret = gpio_leds_ioctl(cmd, arg);
804 else
805 ret = -EINVAL;
806 } /* switch */
808 spin_unlock(&gpio_lock);
809 return ret;
812 static int
813 gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
815 unsigned char green;
816 unsigned char red;
818 switch (_IOC_NR(cmd)) {
819 case IO_LEDACTIVE_SET:
820 green = ((unsigned char) arg) & 1;
821 red = (((unsigned char) arg) >> 1) & 1;
822 LED_ACTIVE_SET_G(green);
823 LED_ACTIVE_SET_R(red);
824 break;
826 case IO_LED_SETBIT:
827 LED_BIT_SET(arg);
828 break;
830 case IO_LED_CLRBIT:
831 LED_BIT_CLR(arg);
832 break;
834 default:
835 return -EINVAL;
836 } /* switch */
838 return 0;
841 const struct file_operations gpio_fops = {
842 .owner = THIS_MODULE,
843 .poll = gpio_poll,
844 .ioctl = gpio_ioctl,
845 .write = gpio_write,
846 .open = gpio_open,
847 .release = gpio_release,
851 void ioif_watcher(const unsigned int gpio_in_available,
852 const unsigned int gpio_out_available,
853 const unsigned char pa_available,
854 const unsigned char pb_available)
856 unsigned long int flags;
857 D(printk("gpio.c: ioif_watcher called\n"));
858 D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n",
859 gpio_in_available, gpio_out_available, pa_available, pb_available));
861 spin_lock_irqsave(&gpio_lock, flags);
863 dir_g_in_bits = gpio_in_available;
864 dir_g_out_bits = gpio_out_available;
866 /* Initialise the dir_g_shadow etc. depending on genconfig */
867 /* 0=input 1=output */
868 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out))
869 dir_g_shadow |= (1 << 0);
870 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
871 dir_g_shadow |= 0x0000FF00;
872 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))
873 dir_g_shadow |= 0x00FF0000;
874 if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
875 dir_g_shadow |= (1 << 24);
877 changeable_dir_g = changeable_dir_g_mask;
878 changeable_dir_g &= dir_g_out_bits;
879 changeable_dir_g &= dir_g_in_bits;
880 /* Correct the bits that can change direction */
881 dir_g_out_bits &= ~changeable_dir_g;
882 dir_g_out_bits |= dir_g_shadow;
883 dir_g_in_bits &= ~changeable_dir_g;
884 dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
886 spin_unlock_irqrestore(&gpio_lock, flags);
888 printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
889 dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
890 printk(KERN_INFO "GPIO port G: dir: %08lX changeable: %08lX\n",
891 dir_g_shadow, changeable_dir_g);
894 /* main driver initialization routine, called from mem.c */
896 static __init int
897 gpio_init(void)
899 int res;
900 #if defined (CONFIG_ETRAX_CSP0_LEDS)
901 int i;
902 #endif
903 printk("gpio init\n");
905 /* do the formalities */
907 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
908 if (res < 0) {
909 printk(KERN_ERR "gpio: couldn't get a major number.\n");
910 return res;
913 /* Clear all leds */
914 #if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
915 LED_NETWORK_SET(0);
916 LED_ACTIVE_SET(0);
917 LED_DISK_READ(0);
918 LED_DISK_WRITE(0);
920 #if defined (CONFIG_ETRAX_CSP0_LEDS)
921 for (i = 0; i < 32; i++) {
922 LED_BIT_SET(i);
924 #endif
926 #endif
927 /* The I/O interface allocation watcher will be called when
928 * registering it. */
929 if (cris_io_interface_register_watcher(ioif_watcher)){
930 printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n");
933 printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n");
934 /* We call etrax_gpio_wake_up_check() from timer interrupt and
935 * from cpu_idle() in kernel/process.c
936 * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
937 * in some tests.
939 if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
940 IRQF_SHARED | IRQF_DISABLED,"gpio poll", NULL)) {
941 printk(KERN_CRIT "err: timer0 irq for gpio\n");
943 if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
944 IRQF_SHARED | IRQF_DISABLED,"gpio PA", NULL)) {
945 printk(KERN_CRIT "err: PA irq for gpio\n");
949 return res;
952 /* this makes sure that gpio_init is called during kernel boot */
954 module_init(gpio_init);