Merge head 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
[pandora-kernel.git] / arch / cris / arch-v10 / drivers / gpio.c
1 /* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 starvik Exp $
2  *
3  * Etrax general port I/O device
4  *
5  * Copyright (c) 1999, 2000, 2001, 2002 Axis Communications AB
6  *
7  * Authors:    Bjorn Wesen      (initial version)
8  *             Ola Knutsson     (LED handling)
9  *             Johan Adolfsson  (read/set directions, write, port G)
10  *
11  * $Log: gpio.c,v $
12  * Revision 1.17  2005/06/19 17:06:46  starvik
13  * Merge of Linux 2.6.12.
14  *
15  * Revision 1.16  2005/03/07 13:02:29  starvik
16  * Protect driver global states with spinlock
17  *
18  * Revision 1.15  2005/01/05 06:08:55  starvik
19  * No need to do local_irq_disable after local_irq_save.
20  *
21  * Revision 1.14  2004/12/13 12:21:52  starvik
22  * Added I/O and DMA allocators from Linux 2.4
23  *
24  * Revision 1.12  2004/08/24 07:19:59  starvik
25  * Whitespace cleanup
26  *
27  * Revision 1.11  2004/05/14 07:58:03  starvik
28  * Merge of changes from 2.4
29  *
30  * Revision 1.9  2003/09/11 07:29:48  starvik
31  * Merge of Linux 2.6.0-test5
32  *
33  * Revision 1.8  2003/07/04 08:27:37  starvik
34  * Merge of Linux 2.5.74
35  *
36  * Revision 1.7  2003/01/10 07:44:07  starvik
37  * init_ioremap is now called by kernel before drivers are initialized
38  *
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)
42  *
43  * Revision 1.5  2002/11/20 11:56:11  starvik
44  * Merge of Linux 2.5.48
45  *
46  * Revision 1.4  2002/11/18 10:10:05  starvik
47  * Linux 2.5 port of latest gpio.c from Linux 2.4
48  *
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.
54  *
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
65  *
66  * Revision 1.18  2002/10/11 15:02:00  johana
67  * Mask inverted 8 bit value in setget_input().
68  *
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)
75  *
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.
80  *
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.
83  *
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.
87  *
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.
92  *
93  * Revision 1.12  2001/11/12 19:42:15  pkj
94  * * Corrected return values from gpio_leds_ioctl().
95  * * Fixed compiler warnings.
96  *
97  * Revision 1.11  2001/10/30 14:39:12  johana
98  * Added D() around gpio_write printk.
99  *
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.
105  *
106  * Revision 1.9  2001/05/04 14:16:07  matsfg
107  * Corrected spelling error
108  *
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.
113  *
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
116  *
117  * Revision 1.6  2001/03/26 16:03:06  bjornw
118  * Needs linux/config.h
119  *
120  * Revision 1.5  2001/03/26 14:22:03  bjornw
121  * Namechange of some config options
122  *
123  * Revision 1.4  2001/02/27 13:52:48  bjornw
124  * malloc.h -> slab.h
125  *
126  * Revision 1.3  2001/01/24 15:06:48  bjornw
127  * gpio_wq correct type
128  *
129  * Revision 1.2  2001/01/18 16:07:30  bjornw
130  * 2.4 port
131  *
132  * Revision 1.1  2001/01/18 15:55:16  bjornw
133  * Verbatim copy of etraxgpio.c from elinux 2.0 added
134  *
135  *
136  */
137
138 #include <linux/config.h>
139
140 #include <linux/module.h>
141 #include <linux/sched.h>
142 #include <linux/slab.h>
143 #include <linux/ioport.h>
144 #include <linux/errno.h>
145 #include <linux/kernel.h>
146 #include <linux/fs.h>
147 #include <linux/string.h>
148 #include <linux/poll.h>
149 #include <linux/init.h>
150 #include <linux/interrupt.h>
151
152 #include <asm/etraxgpio.h>
153 #include <asm/arch/svinto.h>
154 #include <asm/io.h>
155 #include <asm/system.h>
156 #include <asm/irq.h>
157 #include <asm/arch/io_interface_mux.h>
158
159 #define GPIO_MAJOR 120  /* experimental MAJOR number */
160
161 #define D(x)
162
163 #if 0
164 static int dp_cnt;
165 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
166 #else
167 #define DP(x)
168 #endif
169         
170 static char gpio_name[] = "etrax gpio";
171
172 #if 0
173 static wait_queue_head_t *gpio_wq;
174 #endif
175
176 static int gpio_ioctl(struct inode *inode, struct file *file,
177                       unsigned int cmd, unsigned long arg);
178 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
179                           loff_t *off);
180 static int gpio_open(struct inode *inode, struct file *filp);
181 static int gpio_release(struct inode *inode, struct file *filp);
182 static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
183
184 /* private data per open() of this driver */
185
186 struct gpio_private {
187         struct gpio_private *next;
188         /* These fields are for PA and PB only */
189         volatile unsigned char *port, *shadow;
190         volatile unsigned char *dir, *dir_shadow;
191         unsigned char changeable_dir;
192         unsigned char changeable_bits;
193         unsigned char clk_mask;
194         unsigned char data_mask;
195         unsigned char write_msb;
196         unsigned char pad1, pad2, pad3;
197         /* These fields are generic */
198         unsigned long highalarm, lowalarm;
199         wait_queue_head_t alarm_wq;
200         int minor;
201 };
202
203 /* linked list of alarms to check for */
204
205 static struct gpio_private *alarmlist = 0;
206
207 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
208 static unsigned long gpio_pa_irq_enabled_mask = 0;
209
210 static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */
211
212 /* Port A and B use 8 bit access, but Port G is 32 bit */
213 #define NUM_PORTS (GPIO_MINOR_B+1)
214
215 static volatile unsigned char *ports[NUM_PORTS] = { 
216         R_PORT_PA_DATA, 
217         R_PORT_PB_DATA,
218 };
219 static volatile unsigned char *shads[NUM_PORTS] = {
220         &port_pa_data_shadow, 
221         &port_pb_data_shadow
222 };
223
224 /* What direction bits that are user changeable 1=changeable*/
225 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
226 #define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
227 #endif
228 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
229 #define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
230 #endif
231
232 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
233 #define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
234 #endif
235 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
236 #define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
237 #endif
238
239
240 static unsigned char changeable_dir[NUM_PORTS] = { 
241         CONFIG_ETRAX_PA_CHANGEABLE_DIR,
242         CONFIG_ETRAX_PB_CHANGEABLE_DIR 
243 };
244 static unsigned char changeable_bits[NUM_PORTS] = { 
245         CONFIG_ETRAX_PA_CHANGEABLE_BITS,
246         CONFIG_ETRAX_PB_CHANGEABLE_BITS 
247 };
248
249 static volatile unsigned char *dir[NUM_PORTS] = { 
250         R_PORT_PA_DIR, 
251         R_PORT_PB_DIR 
252 };
253
254 static volatile unsigned char *dir_shadow[NUM_PORTS] = {
255         &port_pa_dir_shadow, 
256         &port_pb_dir_shadow 
257 };
258
259 /* All bits in port g that can change dir. */
260 static const unsigned long int changeable_dir_g_mask = 0x01FFFF01;
261
262 /* Port G is 32 bit, handle it special, some bits are both inputs 
263    and outputs at the same time, only some of the bits can change direction
264    and some of them in groups of 8 bit. */
265 static unsigned long changeable_dir_g;
266 static unsigned long dir_g_in_bits;
267 static unsigned long dir_g_out_bits;
268 static unsigned long dir_g_shadow; /* 1=output */
269
270 #define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
271
272
273
274 static unsigned int 
275 gpio_poll(struct file *file,
276           poll_table *wait)
277 {
278         unsigned int mask = 0;
279         struct gpio_private *priv = (struct gpio_private *)file->private_data;
280         unsigned long data;
281         spin_lock(&gpio_lock);
282         poll_wait(file, &priv->alarm_wq, wait);
283         if (priv->minor == GPIO_MINOR_A) {
284                 unsigned long flags;
285                 unsigned long tmp;
286                 data = *R_PORT_PA_DATA;
287                 /* PA has support for high level interrupt -
288                  * lets activate for those low and with highalarm set
289                  */
290                 tmp = ~data & priv->highalarm & 0xFF;
291                 tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
292                 local_irq_save(flags);
293                 gpio_pa_irq_enabled_mask |= tmp;
294                 *R_IRQ_MASK1_SET = tmp;
295                 local_irq_restore(flags);
296
297         } else if (priv->minor == GPIO_MINOR_B)
298                 data = *R_PORT_PB_DATA;
299         else if (priv->minor == GPIO_MINOR_G)
300                 data = *R_PORT_G_DATA;
301         else
302                 return 0;
303         
304         if ((data & priv->highalarm) ||
305             (~data & priv->lowalarm)) {
306                 mask = POLLIN|POLLRDNORM;
307         }
308
309         spin_unlock(&gpio_lock);
310         
311         DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
312
313         return mask;
314 }
315
316 int etrax_gpio_wake_up_check(void)
317 {
318         struct gpio_private *priv = alarmlist;
319         unsigned long data = 0;
320         int ret = 0;
321         spin_lock(&gpio_lock);
322         while (priv) {
323                 if (USE_PORTS(priv)) {
324                         data = *priv->port;
325                 } else if (priv->minor == GPIO_MINOR_G) {
326                         data = *R_PORT_G_DATA;
327                 }
328                 if ((data & priv->highalarm) ||
329                     (~data & priv->lowalarm)) {
330                         DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
331                         wake_up_interruptible(&priv->alarm_wq);
332                         ret = 1;
333                 }
334                 priv = priv->next;
335         }
336         spin_unlock(&gpio_lock);
337         return ret;
338 }
339
340 static irqreturn_t
341 gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
342 {
343         if (gpio_some_alarms) {
344                 etrax_gpio_wake_up_check();
345                 return IRQ_HANDLED;
346         }
347         return IRQ_NONE;
348 }
349
350 static irqreturn_t
351 gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
352 {
353         unsigned long tmp;
354         spin_lock(&gpio_lock);
355         /* Find what PA interrupts are active */
356         tmp = (*R_IRQ_READ1);
357
358         /* Find those that we have enabled */
359         tmp &= gpio_pa_irq_enabled_mask;
360
361         /* Clear them.. */
362         *R_IRQ_MASK1_CLR = tmp;
363         gpio_pa_irq_enabled_mask &= ~tmp;
364
365         spin_unlock(&gpio_lock);
366
367         if (gpio_some_alarms) {
368                 return IRQ_RETVAL(etrax_gpio_wake_up_check());
369         }
370         return IRQ_NONE;
371 }
372
373
374 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
375                           loff_t *off)
376 {
377         struct gpio_private *priv = (struct gpio_private *)file->private_data;
378         unsigned char data, clk_mask, data_mask, write_msb;
379         unsigned long flags;
380
381         spin_lock(&gpio_lock);
382
383         ssize_t retval = count;
384         if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
385                 return -EFAULT;
386         }
387     
388         if (!access_ok(VERIFY_READ, buf, count)) {
389                 return -EFAULT;
390         }
391         clk_mask = priv->clk_mask;
392         data_mask = priv->data_mask;
393         /* It must have been configured using the IO_CFG_WRITE_MODE */
394         /* Perhaps a better error code? */
395         if (clk_mask == 0 || data_mask == 0) {
396                 return -EPERM;
397         }
398         write_msb = priv->write_msb;
399         D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
400         while (count--) {
401                 int i;
402                 data = *buf++;
403                 if (priv->write_msb) {
404                         for (i = 7; i >= 0;i--) {
405                                 local_irq_save(flags);
406                                 *priv->port = *priv->shadow &= ~clk_mask;
407                                 if (data & 1<<i)
408                                         *priv->port = *priv->shadow |= data_mask;
409                                 else
410                                         *priv->port = *priv->shadow &= ~data_mask;
411                         /* For FPGA: min 5.0ns (DCC) before CCLK high */
412                                 *priv->port = *priv->shadow |= clk_mask;
413                                 local_irq_restore(flags);
414                         }
415                 } else {
416                         for (i = 0; i <= 7;i++) {
417                                 local_irq_save(flags);
418                                 *priv->port = *priv->shadow &= ~clk_mask;
419                                 if (data & 1<<i)
420                                         *priv->port = *priv->shadow |= data_mask;
421                                 else
422                                         *priv->port = *priv->shadow &= ~data_mask;
423                         /* For FPGA: min 5.0ns (DCC) before CCLK high */
424                                 *priv->port = *priv->shadow |= clk_mask;
425                                 local_irq_restore(flags);
426                         }
427                 }
428         }
429         spin_unlock(&gpio_lock);
430         return retval;
431 }
432
433
434
435 static int
436 gpio_open(struct inode *inode, struct file *filp)
437 {
438         struct gpio_private *priv;
439         int p = MINOR(inode->i_rdev);
440
441         if (p > GPIO_MINOR_LAST)
442                 return -EINVAL;
443
444         priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), 
445                                               GFP_KERNEL);
446
447         if (!priv)
448                 return -ENOMEM;
449
450         priv->minor = p;
451
452         /* initialize the io/alarm struct and link it into our alarmlist */
453
454         priv->next = alarmlist;
455         alarmlist = priv;
456         if (USE_PORTS(priv)) { /* A and B */
457                 priv->port = ports[p];
458                 priv->shadow = shads[p];
459                 priv->dir = dir[p];
460                 priv->dir_shadow = dir_shadow[p];
461                 priv->changeable_dir = changeable_dir[p];
462                 priv->changeable_bits = changeable_bits[p];
463         } else {
464                 priv->port = NULL;
465                 priv->shadow = NULL;
466                 priv->dir = NULL;
467                 priv->dir_shadow = NULL;
468                 priv->changeable_dir = 0;
469                 priv->changeable_bits = 0;
470         }
471
472         priv->highalarm = 0;
473         priv->lowalarm = 0;
474         priv->clk_mask = 0;
475         priv->data_mask = 0;
476         init_waitqueue_head(&priv->alarm_wq);
477
478         filp->private_data = (void *)priv;
479
480         return 0;
481 }
482
483 static int
484 gpio_release(struct inode *inode, struct file *filp)
485 {
486         struct gpio_private *p;
487         struct gpio_private *todel;
488
489         spin_lock(&gpio_lock);
490
491         p = alarmlist;
492         todel = (struct gpio_private *)filp->private_data;
493
494         /* unlink from alarmlist and free the private structure */
495
496         if (p == todel) {
497                 alarmlist = todel->next;
498         } else {
499                 while (p->next != todel)
500                         p = p->next;
501                 p->next = todel->next;
502         }
503
504         kfree(todel);
505         /* Check if there are still any alarms set */
506         p = alarmlist;
507         while (p) {
508                 if (p->highalarm | p->lowalarm) {
509                         gpio_some_alarms = 1;
510                         return 0;
511                 }
512                 p = p->next;
513         }
514         gpio_some_alarms = 0;
515         spin_unlock(&gpio_lock);
516         return 0;
517 }
518
519 /* Main device API. ioctl's to read/set/clear bits, as well as to 
520  * set alarms to wait for using a subsequent select().
521  */
522
523 unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
524 {
525         /* Set direction 0=unchanged 1=input, 
526          * return mask with 1=input 
527          */
528         unsigned long flags;
529         if (USE_PORTS(priv)) {
530                 local_irq_save(flags);
531                 *priv->dir = *priv->dir_shadow &= 
532                 ~((unsigned char)arg & priv->changeable_dir);
533                 local_irq_restore(flags);
534                 return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
535         } else if (priv->minor == GPIO_MINOR_G) {
536                 /* We must fiddle with R_GEN_CONFIG to change dir */
537                 local_irq_save(flags);
538                 if (((arg & dir_g_in_bits) != arg) && 
539                     (arg & changeable_dir_g)) {
540                         arg &= changeable_dir_g;
541                         /* Clear bits in genconfig to set to input */
542                         if (arg & (1<<0)) {
543                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
544                                 dir_g_in_bits |= (1<<0);
545                                 dir_g_out_bits &= ~(1<<0);
546                         }
547                         if ((arg & 0x0000FF00) == 0x0000FF00) {
548                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
549                                 dir_g_in_bits |= 0x0000FF00;
550                                 dir_g_out_bits &= ~0x0000FF00;
551                         }
552                         if ((arg & 0x00FF0000) == 0x00FF0000) {
553                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
554                                 dir_g_in_bits |= 0x00FF0000;
555                                 dir_g_out_bits &= ~0x00FF0000;
556                         }
557                         if (arg & (1<<24)) {
558                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
559                                 dir_g_in_bits |= (1<<24);
560                                 dir_g_out_bits &= ~(1<<24);
561                         }
562                         D(printk(KERN_INFO "gpio: SETINPUT on port G set "
563                                  "genconfig to 0x%08lX "
564                                  "in_bits: 0x%08lX "
565                                  "out_bits: 0x%08lX\n",
566                                  (unsigned long)genconfig_shadow,
567                                  dir_g_in_bits, dir_g_out_bits));
568                         *R_GEN_CONFIG = genconfig_shadow;
569                         /* Must be a >120 ns delay before writing this again */
570                                 
571                 }
572                 local_irq_restore(flags);
573                 return dir_g_in_bits;
574         }
575         return 0;
576 } /* setget_input */
577
578 unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
579 {
580         unsigned long flags;
581         if (USE_PORTS(priv)) {
582                 local_irq_save(flags);
583                 *priv->dir = *priv->dir_shadow |= 
584                   ((unsigned char)arg & priv->changeable_dir);
585                 local_irq_restore(flags);
586                 return *priv->dir_shadow;
587         } else if (priv->minor == GPIO_MINOR_G) {
588                 /* We must fiddle with R_GEN_CONFIG to change dir */                    
589                 local_irq_save(flags);
590                 if (((arg & dir_g_out_bits) != arg) &&
591                     (arg & changeable_dir_g)) {
592                         /* Set bits in genconfig to set to output */
593                         if (arg & (1<<0)) {
594                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
595                                 dir_g_out_bits |= (1<<0);
596                                 dir_g_in_bits &= ~(1<<0);
597                         }
598                         if ((arg & 0x0000FF00) == 0x0000FF00) {
599                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
600                                 dir_g_out_bits |= 0x0000FF00;
601                                 dir_g_in_bits &= ~0x0000FF00;
602                         }
603                         if ((arg & 0x00FF0000) == 0x00FF0000) {
604                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
605                                 dir_g_out_bits |= 0x00FF0000;
606                                 dir_g_in_bits &= ~0x00FF0000;
607                         }
608                         if (arg & (1<<24)) {
609                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
610                                 dir_g_out_bits |= (1<<24);
611                                 dir_g_in_bits &= ~(1<<24);
612                         }
613                         D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
614                                  "genconfig to 0x%08lX "
615                                  "in_bits: 0x%08lX "
616                                  "out_bits: 0x%08lX\n",
617                                  (unsigned long)genconfig_shadow,
618                                  dir_g_in_bits, dir_g_out_bits));
619                         *R_GEN_CONFIG = genconfig_shadow;
620                         /* Must be a >120 ns delay before writing this again */
621                 }
622                 local_irq_restore(flags);
623                 return dir_g_out_bits & 0x7FFFFFFF;
624         }
625         return 0;
626 } /* setget_output */
627
628 static int
629 gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
630
631 static int
632 gpio_ioctl(struct inode *inode, struct file *file,
633            unsigned int cmd, unsigned long arg)
634 {
635         unsigned long flags;
636         unsigned long val;
637         int ret = 0;
638
639         struct gpio_private *priv = (struct gpio_private *)file->private_data;
640         if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
641                 return -EINVAL;
642         }
643
644         spin_lock(&gpio_lock);
645
646         switch (_IOC_NR(cmd)) {
647         case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
648                 // read the port
649                 if (USE_PORTS(priv)) {
650                         ret =  *priv->port;
651                 } else if (priv->minor == GPIO_MINOR_G) {
652                         ret =  (*R_PORT_G_DATA) & 0x7FFFFFFF;
653                 }
654                 break;
655         case IO_SETBITS:
656                 local_irq_save(flags);
657                 // set changeable bits with a 1 in arg
658                 if (USE_PORTS(priv)) {
659                         *priv->port = *priv->shadow |= 
660                           ((unsigned char)arg & priv->changeable_bits);
661                 } else if (priv->minor == GPIO_MINOR_G) {
662                         *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
663                 }
664                 local_irq_restore(flags);
665                 break;
666         case IO_CLRBITS:
667                 local_irq_save(flags);
668                 // clear changeable bits with a 1 in arg
669                 if (USE_PORTS(priv)) {
670                         *priv->port = *priv->shadow &= 
671                          ~((unsigned char)arg & priv->changeable_bits);
672                 } else if (priv->minor == GPIO_MINOR_G) {
673                         *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
674                 }
675                 local_irq_restore(flags);
676                 break;
677         case IO_HIGHALARM:
678                 // set alarm when bits with 1 in arg go high
679                 priv->highalarm |= arg;
680                 gpio_some_alarms = 1;
681                 break;
682         case IO_LOWALARM:
683                 // set alarm when bits with 1 in arg go low
684                 priv->lowalarm |= arg;
685                 gpio_some_alarms = 1;
686                 break;
687         case IO_CLRALARM:
688                 // clear alarm for bits with 1 in arg
689                 priv->highalarm &= ~arg;
690                 priv->lowalarm  &= ~arg;
691                 {
692                         /* Must update gpio_some_alarms */
693                         struct gpio_private *p = alarmlist;
694                         int some_alarms;
695                         some_alarms = 0;
696                         while (p) {
697                                 if (p->highalarm | p->lowalarm) {
698                                         some_alarms = 1;
699                                         break;
700                                 }
701                                 p = p->next;
702                         }
703                         gpio_some_alarms = some_alarms;
704                 }
705                 break;
706         case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
707                 /* Read direction 0=input 1=output */
708                 if (USE_PORTS(priv)) {
709                         ret = *priv->dir_shadow;
710                 } else if (priv->minor == GPIO_MINOR_G) {
711                         /* Note: Some bits are both in and out,
712                          * Those that are dual is set here as well.
713                          */
714                         ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
715                 }
716                 break;
717         case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
718                 /* Set direction 0=unchanged 1=input, 
719                  * return mask with 1=input 
720                  */
721                 ret = setget_input(priv, arg) & 0x7FFFFFFF;
722                 break;
723         case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
724                 /* Set direction 0=unchanged 1=output, 
725                  * return mask with 1=output 
726                  */
727                 ret =  setget_output(priv, arg) & 0x7FFFFFFF;
728                 break;
729         case IO_SHUTDOWN:
730                 SOFT_SHUTDOWN();
731                 break;
732         case IO_GET_PWR_BT:
733 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
734                 ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
735 #else
736                 ret = 0;
737 #endif
738                 break;
739         case IO_CFG_WRITE_MODE:
740                 priv->clk_mask = arg & 0xFF;
741                 priv->data_mask = (arg >> 8) & 0xFF;
742                 priv->write_msb = (arg >> 16) & 0x01;
743                 /* Check if we're allowed to change the bits and
744                  * the direction is correct
745                  */
746                 if (!((priv->clk_mask & priv->changeable_bits) &&
747                       (priv->data_mask & priv->changeable_bits) &&
748                       (priv->clk_mask & *priv->dir_shadow) &&
749                       (priv->data_mask & *priv->dir_shadow)))
750                 {
751                         priv->clk_mask = 0;
752                         priv->data_mask = 0;
753                         ret = -EPERM;
754                 }
755                 break;
756         case IO_READ_INBITS: 
757                 /* *arg is result of reading the input pins */
758                 if (USE_PORTS(priv)) {
759                         val = *priv->port;
760                 } else if (priv->minor == GPIO_MINOR_G) {
761                         val = *R_PORT_G_DATA;
762                 }
763                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
764                         ret = -EFAULT;
765                 break;
766         case IO_READ_OUTBITS:
767                  /* *arg is result of reading the output shadow */
768                 if (USE_PORTS(priv)) {
769                         val = *priv->shadow;
770                 } else if (priv->minor == GPIO_MINOR_G) {
771                         val = port_g_data_shadow;
772                 }
773                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
774                         ret = -EFAULT;
775                 break;
776         case IO_SETGET_INPUT: 
777                 /* bits set in *arg is set to input,
778                  * *arg updated with current input pins.
779                  */
780                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
781                 {
782                         ret = -EFAULT;
783                         break;
784                 }
785                 val = setget_input(priv, val);
786                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
787                         ret = -EFAULT;
788                 break;
789         case IO_SETGET_OUTPUT:
790                 /* bits set in *arg is set to output,
791                  * *arg updated with current output pins.
792                  */
793                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
794                 {
795                         ret = -EFAULT;
796                         break;
797                 }
798                 val = setget_output(priv, val);
799                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
800                         ret = -EFAULT;
801                 break;
802         default:
803                 if (priv->minor == GPIO_MINOR_LEDS)
804                         ret = gpio_leds_ioctl(cmd, arg);
805                 else
806                         ret = -EINVAL;
807         } /* switch */
808
809         spin_unlock(&gpio_lock);
810         return ret;
811 }
812
813 static int
814 gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
815 {
816         unsigned char green;
817         unsigned char red;
818
819         switch (_IOC_NR(cmd)) {
820         case IO_LEDACTIVE_SET:
821                 green = ((unsigned char) arg) & 1;
822                 red   = (((unsigned char) arg) >> 1) & 1;
823                 LED_ACTIVE_SET_G(green);
824                 LED_ACTIVE_SET_R(red);
825                 break;
826
827         case IO_LED_SETBIT:
828                 LED_BIT_SET(arg);
829                 break;
830
831         case IO_LED_CLRBIT:
832                 LED_BIT_CLR(arg);
833                 break;
834
835         default:
836                 return -EINVAL;
837         } /* switch */
838
839         return 0;
840 }
841
842 struct file_operations gpio_fops = {
843         .owner       = THIS_MODULE,
844         .poll        = gpio_poll,
845         .ioctl       = gpio_ioctl,
846         .write       = gpio_write,
847         .open        = gpio_open,
848         .release     = gpio_release,
849 };
850
851
852 void ioif_watcher(const unsigned int gpio_in_available,
853                   const unsigned int gpio_out_available,
854                   const unsigned char pa_available,
855                   const unsigned char pb_available)
856 {
857         unsigned long int flags;
858         D(printk("gpio.c: ioif_watcher called\n"));
859         D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n",
860                  gpio_in_available, gpio_out_available, pa_available, pb_available));
861
862         spin_lock_irqsave(&gpio_lock, flags);
863
864         dir_g_in_bits = gpio_in_available;
865         dir_g_out_bits = gpio_out_available;
866
867         /* Initialise the dir_g_shadow etc. depending on genconfig */
868         /* 0=input 1=output */
869         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out)) 
870                 dir_g_shadow |= (1 << 0);
871         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
872                 dir_g_shadow |= 0x0000FF00;
873         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))
874                 dir_g_shadow |= 0x00FF0000;
875         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
876                 dir_g_shadow |= (1 << 24);
877
878         changeable_dir_g = changeable_dir_g_mask;
879         changeable_dir_g &= dir_g_out_bits;
880         changeable_dir_g &= dir_g_in_bits;
881         /* Correct the bits that can change direction */ 
882         dir_g_out_bits &= ~changeable_dir_g;
883         dir_g_out_bits |= dir_g_shadow;
884         dir_g_in_bits &= ~changeable_dir_g;
885         dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
886
887         spin_unlock_irqrestore(&gpio_lock, flags);
888
889         printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
890                dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
891         printk(KERN_INFO "GPIO port G: dir: %08lX changeable: %08lX\n",
892                dir_g_shadow, changeable_dir_g);
893 }
894
895 /* main driver initialization routine, called from mem.c */
896
897 static __init int
898 gpio_init(void)
899 {
900         int res;
901 #if defined (CONFIG_ETRAX_CSP0_LEDS)
902         int i;
903 #endif
904         printk("gpio init\n");
905
906         /* do the formalities */
907
908         res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
909         if (res < 0) {
910                 printk(KERN_ERR "gpio: couldn't get a major number.\n");
911                 return res;
912         }
913
914         /* Clear all leds */
915 #if defined (CONFIG_ETRAX_CSP0_LEDS) ||  defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
916         LED_NETWORK_SET(0);
917         LED_ACTIVE_SET(0);
918         LED_DISK_READ(0);
919         LED_DISK_WRITE(0);
920
921 #if defined (CONFIG_ETRAX_CSP0_LEDS)
922         for (i = 0; i < 32; i++) {
923                 LED_BIT_SET(i);
924         }
925 #endif
926
927 #endif
928         /* The I/O interface allocation watcher will be called when
929          * registering it. */
930         if (cris_io_interface_register_watcher(ioif_watcher)){
931                 printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n");
932         }
933
934         printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n");
935         /* We call etrax_gpio_wake_up_check() from timer interrupt and
936          * from cpu_idle() in kernel/process.c
937          * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
938          * in some tests.
939          */  
940         if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
941                         SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) {
942                 printk(KERN_CRIT "err: timer0 irq for gpio\n");
943         }
944         if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
945                         SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) {
946                 printk(KERN_CRIT "err: PA irq for gpio\n");
947         }
948         
949
950         return res;
951 }
952
953 /* this makes sure that gpio_init is called during kernel boot */
954
955 module_init(gpio_init);