1 /* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 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.12 2004/08/24 07:19:59 starvik
15 * Revision 1.11 2004/05/14 07:58:03 starvik
16 * Merge of changes from 2.4
18 * Revision 1.9 2003/09/11 07:29:48 starvik
19 * Merge of Linux 2.6.0-test5
21 * Revision 1.8 2003/07/04 08:27:37 starvik
22 * Merge of Linux 2.5.74
24 * Revision 1.7 2003/01/10 07:44:07 starvik
25 * init_ioremap is now called by kernel before drivers are initialized
27 * Revision 1.6 2002/12/11 13:13:57 starvik
28 * Added arch/ to v10 specific includes
29 * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
31 * Revision 1.5 2002/11/20 11:56:11 starvik
32 * Merge of Linux 2.5.48
34 * Revision 1.4 2002/11/18 10:10:05 starvik
35 * Linux 2.5 port of latest gpio.c from Linux 2.4
37 * Revision 1.20 2002/10/16 21:16:24 johana
38 * Added support for PA high level interrupt.
39 * That gives 2ms response time with iodtest for high levels and 2-12 ms
40 * response time on low levels if the check is not made in
41 * process.c:cpu_idle() as well.
43 * Revision 1.19 2002/10/14 18:27:33 johana
44 * Implemented alarm handling so select() now works.
45 * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
47 * Otherwise I get 15-18 ms (same as doing the poll in userspace -
49 * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
51 * TODO? Perhaps call request_irq()/free_irq() only when needed?
52 * Increased version to 2.5
54 * Revision 1.18 2002/10/11 15:02:00 johana
55 * Mask inverted 8 bit value in setget_input().
57 * Revision 1.17 2002/06/17 15:53:01 johana
58 * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
59 * that take a pointer as argument and thus can handle 32 bit ports (G)
61 * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
62 * (especially if Port G bit 31 is used)
64 * Revision 1.16 2002/06/17 09:59:51 johana
65 * Returning 32 bit values in the ioctl return value doesn't work if bit
66 * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
67 * A new set of ioctl's will be added.
69 * Revision 1.15 2002/05/06 13:19:13 johana
70 * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
72 * Revision 1.14 2002/04/12 12:01:53 johana
73 * Use global r_port_g_data_shadow.
74 * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
76 * Revision 1.13 2002/04/10 12:03:55 johana
77 * Added support for port G /dev/gpiog (minor 3).
78 * Changed indentation on switch cases.
79 * Fixed other spaces to tabs.
81 * Revision 1.12 2001/11/12 19:42:15 pkj
82 * * Corrected return values from gpio_leds_ioctl().
83 * * Fixed compiler warnings.
85 * Revision 1.11 2001/10/30 14:39:12 johana
86 * Added D() around gpio_write printk.
88 * Revision 1.10 2001/10/25 10:24:42 johana
89 * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
90 * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
91 * from ~60 seconds to 4 seconds).
92 * Added save_flags/cli/restore_flags in ioctl.
94 * Revision 1.9 2001/05/04 14:16:07 matsfg
95 * Corrected spelling error
97 * Revision 1.8 2001/04/27 13:55:26 matsfg
99 * Turns off all LEDS on init.
100 * Added support for shutdown and powerbutton.
102 * Revision 1.7 2001/04/04 13:30:08 matsfg
103 * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
105 * Revision 1.6 2001/03/26 16:03:06 bjornw
106 * Needs linux/config.h
108 * Revision 1.5 2001/03/26 14:22:03 bjornw
109 * Namechange of some config options
111 * Revision 1.4 2001/02/27 13:52:48 bjornw
114 * Revision 1.3 2001/01/24 15:06:48 bjornw
115 * gpio_wq correct type
117 * Revision 1.2 2001/01/18 16:07:30 bjornw
120 * Revision 1.1 2001/01/18 15:55:16 bjornw
121 * Verbatim copy of etraxgpio.c from elinux 2.0 added
126 #include <linux/config.h>
128 #include <linux/module.h>
129 #include <linux/sched.h>
130 #include <linux/slab.h>
131 #include <linux/ioport.h>
132 #include <linux/errno.h>
133 #include <linux/kernel.h>
134 #include <linux/fs.h>
135 #include <linux/string.h>
136 #include <linux/poll.h>
137 #include <linux/init.h>
138 #include <linux/interrupt.h>
140 #include <asm/etraxgpio.h>
141 #include <asm/arch/svinto.h>
143 #include <asm/system.h>
146 #define GPIO_MAJOR 120 /* experimental MAJOR number */
152 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
157 static char gpio_name
[] = "etrax gpio";
160 static wait_queue_head_t
*gpio_wq
;
163 static int gpio_ioctl(struct inode
*inode
, struct file
*file
,
164 unsigned int cmd
, unsigned long arg
);
165 static ssize_t
gpio_write(struct file
* file
, const char * buf
, size_t count
,
167 static int gpio_open(struct inode
*inode
, struct file
*filp
);
168 static int gpio_release(struct inode
*inode
, struct file
*filp
);
169 static unsigned int gpio_poll(struct file
*filp
, struct poll_table_struct
*wait
);
171 /* private data per open() of this driver */
173 struct gpio_private
{
174 struct gpio_private
*next
;
175 /* These fields are for PA and PB only */
176 volatile unsigned char *port
, *shadow
;
177 volatile unsigned char *dir
, *dir_shadow
;
178 unsigned char changeable_dir
;
179 unsigned char changeable_bits
;
180 unsigned char clk_mask
;
181 unsigned char data_mask
;
182 unsigned char write_msb
;
183 unsigned char pad1
, pad2
, pad3
;
184 /* These fields are generic */
185 unsigned long highalarm
, lowalarm
;
186 wait_queue_head_t alarm_wq
;
190 /* linked list of alarms to check for */
192 static struct gpio_private
*alarmlist
= 0;
194 static int gpio_some_alarms
= 0; /* Set if someone uses alarm */
195 static unsigned long gpio_pa_irq_enabled_mask
= 0;
197 /* Port A and B use 8 bit access, but Port G is 32 bit */
198 #define NUM_PORTS (GPIO_MINOR_B+1)
200 static volatile unsigned char *ports
[NUM_PORTS
] = {
204 static volatile unsigned char *shads
[NUM_PORTS
] = {
205 &port_pa_data_shadow
,
209 /* What direction bits that are user changeable 1=changeable*/
210 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
211 #define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
213 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
214 #define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
217 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
218 #define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
220 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
221 #define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
225 static unsigned char changeable_dir
[NUM_PORTS
] = {
226 CONFIG_ETRAX_PA_CHANGEABLE_DIR
,
227 CONFIG_ETRAX_PB_CHANGEABLE_DIR
229 static unsigned char changeable_bits
[NUM_PORTS
] = {
230 CONFIG_ETRAX_PA_CHANGEABLE_BITS
,
231 CONFIG_ETRAX_PB_CHANGEABLE_BITS
234 static volatile unsigned char *dir
[NUM_PORTS
] = {
239 static volatile unsigned char *dir_shadow
[NUM_PORTS
] = {
244 /* Port G is 32 bit, handle it special, some bits are both inputs
245 and outputs at the same time, only some of the bits can change direction
246 and some of them in groups of 8 bit. */
247 static unsigned long changeable_dir_g
;
248 static unsigned long dir_g_in_bits
;
249 static unsigned long dir_g_out_bits
;
250 static unsigned long dir_g_shadow
; /* 1=output */
252 #define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
257 gpio_poll(struct file
*file
,
260 unsigned int mask
= 0;
261 struct gpio_private
*priv
= (struct gpio_private
*)file
->private_data
;
263 poll_wait(file
, &priv
->alarm_wq
, wait
);
264 if (priv
->minor
== GPIO_MINOR_A
) {
267 data
= *R_PORT_PA_DATA
;
268 /* PA has support for high level interrupt -
269 * lets activate for those low and with highalarm set
271 tmp
= ~data
& priv
->highalarm
& 0xFF;
272 tmp
= (tmp
<< R_IRQ_MASK1_SET__pa0__BITNR
);
273 save_flags(flags
); cli();
274 gpio_pa_irq_enabled_mask
|= tmp
;
275 *R_IRQ_MASK1_SET
= tmp
;
276 restore_flags(flags
);
278 } else if (priv
->minor
== GPIO_MINOR_B
)
279 data
= *R_PORT_PB_DATA
;
280 else if (priv
->minor
== GPIO_MINOR_G
)
281 data
= *R_PORT_G_DATA
;
285 if ((data
& priv
->highalarm
) ||
286 (~data
& priv
->lowalarm
)) {
287 mask
= POLLIN
|POLLRDNORM
;
290 DP(printk("gpio_poll ready: mask 0x%08X\n", mask
));
294 int etrax_gpio_wake_up_check(void)
296 struct gpio_private
*priv
= alarmlist
;
297 unsigned long data
= 0;
300 if (USE_PORTS(priv
)) {
302 } else if (priv
->minor
== GPIO_MINOR_G
) {
303 data
= *R_PORT_G_DATA
;
305 if ((data
& priv
->highalarm
) ||
306 (~data
& priv
->lowalarm
)) {
307 DP(printk("etrax_gpio_wake_up_check %i\n",priv
->minor
));
308 wake_up_interruptible(&priv
->alarm_wq
);
317 gpio_poll_timer_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
319 if (gpio_some_alarms
) {
320 etrax_gpio_wake_up_check();
327 gpio_pa_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
330 /* Find what PA interrupts are active */
331 tmp
= (*R_IRQ_READ1
);
333 /* Find those that we have enabled */
334 tmp
&= gpio_pa_irq_enabled_mask
;
337 *R_IRQ_MASK1_CLR
= tmp
;
338 gpio_pa_irq_enabled_mask
&= ~tmp
;
340 if (gpio_some_alarms
) {
341 return IRQ_RETVAL(etrax_gpio_wake_up_check());
347 static ssize_t
gpio_write(struct file
* file
, const char * buf
, size_t count
,
350 struct gpio_private
*priv
= (struct gpio_private
*)file
->private_data
;
351 unsigned char data
, clk_mask
, data_mask
, write_msb
;
353 ssize_t retval
= count
;
354 if (priv
->minor
!=GPIO_MINOR_A
&& priv
->minor
!= GPIO_MINOR_B
) {
358 if (!access_ok(VERIFY_READ
, buf
, count
)) {
361 clk_mask
= priv
->clk_mask
;
362 data_mask
= priv
->data_mask
;
363 /* It must have been configured using the IO_CFG_WRITE_MODE */
364 /* Perhaps a better error code? */
365 if (clk_mask
== 0 || data_mask
== 0) {
368 write_msb
= priv
->write_msb
;
369 D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count
, data_mask
, clk_mask
, write_msb
));
373 if (priv
->write_msb
) {
374 for (i
= 7; i
>= 0;i
--) {
375 local_irq_save(flags
); local_irq_disable();
376 *priv
->port
= *priv
->shadow
&= ~clk_mask
;
378 *priv
->port
= *priv
->shadow
|= data_mask
;
380 *priv
->port
= *priv
->shadow
&= ~data_mask
;
381 /* For FPGA: min 5.0ns (DCC) before CCLK high */
382 *priv
->port
= *priv
->shadow
|= clk_mask
;
383 local_irq_restore(flags
);
386 for (i
= 0; i
<= 7;i
++) {
387 local_irq_save(flags
); local_irq_disable();
388 *priv
->port
= *priv
->shadow
&= ~clk_mask
;
390 *priv
->port
= *priv
->shadow
|= data_mask
;
392 *priv
->port
= *priv
->shadow
&= ~data_mask
;
393 /* For FPGA: min 5.0ns (DCC) before CCLK high */
394 *priv
->port
= *priv
->shadow
|= clk_mask
;
395 local_irq_restore(flags
);
405 gpio_open(struct inode
*inode
, struct file
*filp
)
407 struct gpio_private
*priv
;
408 int p
= MINOR(inode
->i_rdev
);
410 if (p
> GPIO_MINOR_LAST
)
413 priv
= (struct gpio_private
*)kmalloc(sizeof(struct gpio_private
),
421 /* initialize the io/alarm struct and link it into our alarmlist */
423 priv
->next
= alarmlist
;
425 if (USE_PORTS(priv
)) { /* A and B */
426 priv
->port
= ports
[p
];
427 priv
->shadow
= shads
[p
];
429 priv
->dir_shadow
= dir_shadow
[p
];
430 priv
->changeable_dir
= changeable_dir
[p
];
431 priv
->changeable_bits
= changeable_bits
[p
];
436 priv
->dir_shadow
= NULL
;
437 priv
->changeable_dir
= 0;
438 priv
->changeable_bits
= 0;
445 init_waitqueue_head(&priv
->alarm_wq
);
447 filp
->private_data
= (void *)priv
;
453 gpio_release(struct inode
*inode
, struct file
*filp
)
455 struct gpio_private
*p
= alarmlist
;
456 struct gpio_private
*todel
= (struct gpio_private
*)filp
->private_data
;
458 /* unlink from alarmlist and free the private structure */
461 alarmlist
= todel
->next
;
463 while (p
->next
!= todel
)
465 p
->next
= todel
->next
;
469 /* Check if there are still any alarms set */
472 if (p
->highalarm
| p
->lowalarm
) {
473 gpio_some_alarms
= 1;
478 gpio_some_alarms
= 0;
483 /* Main device API. ioctl's to read/set/clear bits, as well as to
484 * set alarms to wait for using a subsequent select().
487 unsigned long inline setget_input(struct gpio_private
*priv
, unsigned long arg
)
489 /* Set direction 0=unchanged 1=input,
490 * return mask with 1=input
493 if (USE_PORTS(priv
)) {
494 local_irq_save(flags
); local_irq_disable();
495 *priv
->dir
= *priv
->dir_shadow
&=
496 ~((unsigned char)arg
& priv
->changeable_dir
);
497 local_irq_restore(flags
);
498 return ~(*priv
->dir_shadow
) & 0xFF; /* Only 8 bits */
499 } else if (priv
->minor
== GPIO_MINOR_G
) {
500 /* We must fiddle with R_GEN_CONFIG to change dir */
501 save_flags(flags
); cli();
502 if (((arg
& dir_g_in_bits
) != arg
) &&
503 (arg
& changeable_dir_g
)) {
504 arg
&= changeable_dir_g
;
505 /* Clear bits in genconfig to set to input */
507 genconfig_shadow
&= ~IO_MASK(R_GEN_CONFIG
,g0dir
);
508 dir_g_in_bits
|= (1<<0);
509 dir_g_out_bits
&= ~(1<<0);
511 if ((arg
& 0x0000FF00) == 0x0000FF00) {
512 genconfig_shadow
&= ~IO_MASK(R_GEN_CONFIG
,g8_15dir
);
513 dir_g_in_bits
|= 0x0000FF00;
514 dir_g_out_bits
&= ~0x0000FF00;
516 if ((arg
& 0x00FF0000) == 0x00FF0000) {
517 genconfig_shadow
&= ~IO_MASK(R_GEN_CONFIG
,g16_23dir
);
518 dir_g_in_bits
|= 0x00FF0000;
519 dir_g_out_bits
&= ~0x00FF0000;
522 genconfig_shadow
&= ~IO_MASK(R_GEN_CONFIG
,g24dir
);
523 dir_g_in_bits
|= (1<<24);
524 dir_g_out_bits
&= ~(1<<24);
526 D(printk(KERN_INFO
"gpio: SETINPUT on port G set "
527 "genconfig to 0x%08lX "
529 "out_bits: 0x%08lX\n",
530 (unsigned long)genconfig_shadow
,
531 dir_g_in_bits
, dir_g_out_bits
));
532 *R_GEN_CONFIG
= genconfig_shadow
;
533 /* Must be a >120 ns delay before writing this again */
536 restore_flags(flags
);
537 return dir_g_in_bits
;
542 unsigned long inline setget_output(struct gpio_private
*priv
, unsigned long arg
)
545 if (USE_PORTS(priv
)) {
546 local_irq_save(flags
); local_irq_disable();
547 *priv
->dir
= *priv
->dir_shadow
|=
548 ((unsigned char)arg
& priv
->changeable_dir
);
549 local_irq_restore(flags
);
550 return *priv
->dir_shadow
;
551 } else if (priv
->minor
== GPIO_MINOR_G
) {
552 /* We must fiddle with R_GEN_CONFIG to change dir */
553 save_flags(flags
); cli();
554 if (((arg
& dir_g_out_bits
) != arg
) &&
555 (arg
& changeable_dir_g
)) {
556 /* Set bits in genconfig to set to output */
558 genconfig_shadow
|= IO_MASK(R_GEN_CONFIG
,g0dir
);
559 dir_g_out_bits
|= (1<<0);
560 dir_g_in_bits
&= ~(1<<0);
562 if ((arg
& 0x0000FF00) == 0x0000FF00) {
563 genconfig_shadow
|= IO_MASK(R_GEN_CONFIG
,g8_15dir
);
564 dir_g_out_bits
|= 0x0000FF00;
565 dir_g_in_bits
&= ~0x0000FF00;
567 if ((arg
& 0x00FF0000) == 0x00FF0000) {
568 genconfig_shadow
|= IO_MASK(R_GEN_CONFIG
,g16_23dir
);
569 dir_g_out_bits
|= 0x00FF0000;
570 dir_g_in_bits
&= ~0x00FF0000;
573 genconfig_shadow
|= IO_MASK(R_GEN_CONFIG
,g24dir
);
574 dir_g_out_bits
|= (1<<24);
575 dir_g_in_bits
&= ~(1<<24);
577 D(printk(KERN_INFO
"gpio: SETOUTPUT on port G set "
578 "genconfig to 0x%08lX "
580 "out_bits: 0x%08lX\n",
581 (unsigned long)genconfig_shadow
,
582 dir_g_in_bits
, dir_g_out_bits
));
583 *R_GEN_CONFIG
= genconfig_shadow
;
584 /* Must be a >120 ns delay before writing this again */
586 restore_flags(flags
);
587 return dir_g_out_bits
& 0x7FFFFFFF;
590 } /* setget_output */
593 gpio_leds_ioctl(unsigned int cmd
, unsigned long arg
);
596 gpio_ioctl(struct inode
*inode
, struct file
*file
,
597 unsigned int cmd
, unsigned long arg
)
601 struct gpio_private
*priv
= (struct gpio_private
*)file
->private_data
;
602 if (_IOC_TYPE(cmd
) != ETRAXGPIO_IOCTYPE
) {
606 switch (_IOC_NR(cmd
)) {
607 case IO_READBITS
: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
609 if (USE_PORTS(priv
)) {
611 } else if (priv
->minor
== GPIO_MINOR_G
) {
612 return (*R_PORT_G_DATA
) & 0x7FFFFFFF;
616 local_irq_save(flags
); local_irq_disable();
617 // set changeable bits with a 1 in arg
618 if (USE_PORTS(priv
)) {
619 *priv
->port
= *priv
->shadow
|=
620 ((unsigned char)arg
& priv
->changeable_bits
);
621 } else if (priv
->minor
== GPIO_MINOR_G
) {
622 *R_PORT_G_DATA
= port_g_data_shadow
|= (arg
& dir_g_out_bits
);
624 local_irq_restore(flags
);
627 local_irq_save(flags
); local_irq_disable();
628 // clear changeable bits with a 1 in arg
629 if (USE_PORTS(priv
)) {
630 *priv
->port
= *priv
->shadow
&=
631 ~((unsigned char)arg
& priv
->changeable_bits
);
632 } else if (priv
->minor
== GPIO_MINOR_G
) {
633 *R_PORT_G_DATA
= port_g_data_shadow
&= ~((unsigned long)arg
& dir_g_out_bits
);
635 local_irq_restore(flags
);
638 // set alarm when bits with 1 in arg go high
639 priv
->highalarm
|= arg
;
640 gpio_some_alarms
= 1;
643 // set alarm when bits with 1 in arg go low
644 priv
->lowalarm
|= arg
;
645 gpio_some_alarms
= 1;
648 // clear alarm for bits with 1 in arg
649 priv
->highalarm
&= ~arg
;
650 priv
->lowalarm
&= ~arg
;
652 /* Must update gpio_some_alarms */
653 struct gpio_private
*p
= alarmlist
;
657 if (p
->highalarm
| p
->lowalarm
) {
663 gpio_some_alarms
= some_alarms
;
666 case IO_READDIR
: /* Use IO_SETGET_INPUT/OUTPUT instead! */
667 /* Read direction 0=input 1=output */
668 if (USE_PORTS(priv
)) {
669 return *priv
->dir_shadow
;
670 } else if (priv
->minor
== GPIO_MINOR_G
) {
671 /* Note: Some bits are both in and out,
672 * Those that are dual is set here as well.
674 return (dir_g_shadow
| dir_g_out_bits
) & 0x7FFFFFFF;
676 case IO_SETINPUT
: /* Use IO_SETGET_INPUT instead! */
677 /* Set direction 0=unchanged 1=input,
678 * return mask with 1=input
680 return setget_input(priv
, arg
) & 0x7FFFFFFF;
682 case IO_SETOUTPUT
: /* Use IO_SETGET_OUTPUT instead! */
683 /* Set direction 0=unchanged 1=output,
684 * return mask with 1=output
686 return setget_output(priv
, arg
) & 0x7FFFFFFF;
692 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
693 return (*R_PORT_G_DATA
& ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT
));
698 case IO_CFG_WRITE_MODE
:
699 priv
->clk_mask
= arg
& 0xFF;
700 priv
->data_mask
= (arg
>> 8) & 0xFF;
701 priv
->write_msb
= (arg
>> 16) & 0x01;
702 /* Check if we're allowed to change the bits and
703 * the direction is correct
705 if (!((priv
->clk_mask
& priv
->changeable_bits
) &&
706 (priv
->data_mask
& priv
->changeable_bits
) &&
707 (priv
->clk_mask
& *priv
->dir_shadow
) &&
708 (priv
->data_mask
& *priv
->dir_shadow
)))
716 /* *arg is result of reading the input pins */
717 if (USE_PORTS(priv
)) {
719 } else if (priv
->minor
== GPIO_MINOR_G
) {
720 val
= *R_PORT_G_DATA
;
722 if (copy_to_user((unsigned long*)arg
, &val
, sizeof(val
)))
726 case IO_READ_OUTBITS
:
727 /* *arg is result of reading the output shadow */
728 if (USE_PORTS(priv
)) {
730 } else if (priv
->minor
== GPIO_MINOR_G
) {
731 val
= port_g_data_shadow
;
733 if (copy_to_user((unsigned long*)arg
, &val
, sizeof(val
)))
736 case IO_SETGET_INPUT
:
737 /* bits set in *arg is set to input,
738 * *arg updated with current input pins.
740 if (copy_from_user(&val
, (unsigned long*)arg
, sizeof(val
)))
742 val
= setget_input(priv
, val
);
743 if (copy_to_user((unsigned long*)arg
, &val
, sizeof(val
)))
746 case IO_SETGET_OUTPUT
:
747 /* bits set in *arg is set to output,
748 * *arg updated with current output pins.
750 if (copy_from_user(&val
, (unsigned long*)arg
, sizeof(val
)))
752 val
= setget_output(priv
, val
);
753 if (copy_to_user((unsigned long*)arg
, &val
, sizeof(val
)))
757 if (priv
->minor
== GPIO_MINOR_LEDS
)
758 return gpio_leds_ioctl(cmd
, arg
);
767 gpio_leds_ioctl(unsigned int cmd
, unsigned long arg
)
772 switch (_IOC_NR(cmd
)) {
773 case IO_LEDACTIVE_SET
:
774 green
= ((unsigned char) arg
) & 1;
775 red
= (((unsigned char) arg
) >> 1) & 1;
776 LED_ACTIVE_SET_G(green
);
777 LED_ACTIVE_SET_R(red
);
795 struct file_operations gpio_fops
= {
796 .owner
= THIS_MODULE
,
801 .release
= gpio_release
,
805 static void __init
gpio_init_port_g(void)
807 #define GROUPA (0x0000FF3F)
808 #define GROUPB (1<<6 | 1<<7)
809 #define GROUPC (1<<30 | 1<<31)
810 #define GROUPD (0x3FFF0000)
811 #define GROUPD_LOW (0x00FF0000)
812 unsigned long used_in_bits
= 0;
813 unsigned long used_out_bits
= 0;
814 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, scsi0
, select
)){
815 used_in_bits
|= GROUPA
| GROUPB
| 0 | 0;
816 used_out_bits
|= GROUPA
| GROUPB
| 0 | 0;
818 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, ata
, select
)) {
819 used_in_bits
|= GROUPA
| GROUPB
| GROUPC
| (GROUPD
& ~(1<<25|1<<26));
820 used_out_bits
|= GROUPA
| GROUPB
| GROUPC
| GROUPD
;
823 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, par0
, select
)) {
824 used_in_bits
|= (GROUPA
& ~(1<<0)) | 0 | 0 | 0;
825 used_out_bits
|= (GROUPA
& ~(1<<0)) | 0 | 0 | 0;
827 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, ser2
, select
)) {
828 used_in_bits
|= 0 | GROUPB
| 0 | 0;
829 used_out_bits
|= 0 | GROUPB
| 0 | 0;
831 /* mio same as shared RAM ? */
832 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, mio
, select
)) {
833 used_in_bits
|= (GROUPA
& ~(1<<0)) | 0 |0 |GROUPD_LOW
;
834 used_out_bits
|= (GROUPA
& ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW
;
836 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, scsi1
, select
)) {
837 used_in_bits
|= 0 | 0 | GROUPC
| GROUPD
;
838 used_out_bits
|= 0 | 0 | GROUPC
| GROUPD
;
840 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, scsi0w
, select
)) {
841 used_in_bits
|= GROUPA
| GROUPB
| 0 | (GROUPD_LOW
| 1<<24);
842 used_out_bits
|= GROUPA
| GROUPB
| 0 | (GROUPD_LOW
| 1<<24 | 1<<25|1<<26);
845 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, par1
, select
)) {
846 used_in_bits
|= 0 | 0 | 0 | (GROUPD
& ~(1<<24));
847 used_out_bits
|= 0 | 0 | 0 | (GROUPD
& ~(1<<24));
849 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, ser3
, select
)) {
850 used_in_bits
|= 0 | 0 | GROUPC
| 0;
851 used_out_bits
|= 0 | 0 | GROUPC
| 0;
853 /* mio same as shared RAM-W? */
854 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, mio_w
, select
)) {
855 used_in_bits
|= (GROUPA
& ~(1<<0)) | 0 | 0 |GROUPD_LOW
;
856 used_out_bits
|= (GROUPA
& ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW
;
858 /* TODO: USB p2, parw, sync ser3? */
860 /* Initialise the dir_g_shadow etc. depending on genconfig */
861 /* 0=input 1=output */
862 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, g0dir
, out
))
863 dir_g_shadow
|= (1 << 0);
864 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, g8_15dir
, out
))
865 dir_g_shadow
|= 0x0000FF00;
866 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, g16_23dir
, out
))
867 dir_g_shadow
|= 0x00FF0000;
868 if (genconfig_shadow
& IO_STATE(R_GEN_CONFIG
, g24dir
, out
))
869 dir_g_shadow
|= (1 << 24);
871 dir_g_in_bits
= ~used_in_bits
;
872 dir_g_out_bits
= ~used_out_bits
;
874 changeable_dir_g
= 0x01FFFF01; /* all that can change dir */
875 changeable_dir_g
&= dir_g_out_bits
;
876 changeable_dir_g
&= dir_g_in_bits
;
877 /* Correct the bits that can change direction */
878 dir_g_out_bits
&= ~changeable_dir_g
;
879 dir_g_out_bits
|= dir_g_shadow
;
880 dir_g_in_bits
&= ~changeable_dir_g
;
881 dir_g_in_bits
|= (~dir_g_shadow
& changeable_dir_g
);
884 printk(KERN_INFO
"GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
885 dir_g_in_bits
, dir_g_out_bits
, (unsigned long)*R_PORT_G_DATA
);
886 printk(KERN_INFO
"GPIO port G: dir: %08lX changeable: %08lX\n",
887 dir_g_shadow
, changeable_dir_g
);
890 /* main driver initialization routine, called from mem.c */
896 #if defined (CONFIG_ETRAX_CSP0_LEDS)
900 /* do the formalities */
902 res
= register_chrdev(GPIO_MAJOR
, gpio_name
, &gpio_fops
);
904 printk(KERN_ERR
"gpio: couldn't get a major number.\n");
909 #if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
915 #if defined (CONFIG_ETRAX_CSP0_LEDS)
916 for (i
= 0; i
< 32; i
++) {
923 printk(KERN_INFO
"ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
924 /* We call etrax_gpio_wake_up_check() from timer interrupt and
925 * from cpu_idle() in kernel/process.c
926 * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
929 if (request_irq(TIMER0_IRQ_NBR
, gpio_poll_timer_interrupt
,
930 SA_SHIRQ
| SA_INTERRUPT
,"gpio poll", NULL
)) {
931 printk(KERN_CRIT
"err: timer0 irq for gpio\n");
933 if (request_irq(PA_IRQ_NBR
, gpio_pa_interrupt
,
934 SA_SHIRQ
| SA_INTERRUPT
,"gpio PA", NULL
)) {
935 printk(KERN_CRIT
"err: PA irq for gpio\n");
942 /* this makes sure that gpio_init is called during kernel boot */
944 module_init(gpio_init
);