aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v10/drivers/gpio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/cris/arch-v10/drivers/gpio.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/cris/arch-v10/drivers/gpio.c')
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c944
1 files changed, 944 insertions, 0 deletions
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
new file mode 100644
index 000000000000..c095de82a0da
--- /dev/null
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -0,0 +1,944 @@
1/* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 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.12 2004/08/24 07:19:59 starvik
13 * Whitespace cleanup
14 *
15 * Revision 1.11 2004/05/14 07:58:03 starvik
16 * Merge of changes from 2.4
17 *
18 * Revision 1.9 2003/09/11 07:29:48 starvik
19 * Merge of Linux 2.6.0-test5
20 *
21 * Revision 1.8 2003/07/04 08:27:37 starvik
22 * Merge of Linux 2.5.74
23 *
24 * Revision 1.7 2003/01/10 07:44:07 starvik
25 * init_ioremap is now called by kernel before drivers are initialized
26 *
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)
30 *
31 * Revision 1.5 2002/11/20 11:56:11 starvik
32 * Merge of Linux 2.5.48
33 *
34 * Revision 1.4 2002/11/18 10:10:05 starvik
35 * Linux 2.5 port of latest gpio.c from Linux 2.4
36 *
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.
42 *
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
46 * cpu_idle().
47 * Otherwise I get 15-18 ms (same as doing the poll in userspace -
48 * but less overhead).
49 * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
50 * is in 2.4) as well?
51 * TODO? Perhaps call request_irq()/free_irq() only when needed?
52 * Increased version to 2.5
53 *
54 * Revision 1.18 2002/10/11 15:02:00 johana
55 * Mask inverted 8 bit value in setget_input().
56 *
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)
60 * correctly.
61 * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
62 * (especially if Port G bit 31 is used)
63 *
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.
68 *
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.
71 *
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.
75 *
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.
80 *
81 * Revision 1.12 2001/11/12 19:42:15 pkj
82 * * Corrected return values from gpio_leds_ioctl().
83 * * Fixed compiler warnings.
84 *
85 * Revision 1.11 2001/10/30 14:39:12 johana
86 * Added D() around gpio_write printk.
87 *
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.
93 *
94 * Revision 1.9 2001/05/04 14:16:07 matsfg
95 * Corrected spelling error
96 *
97 * Revision 1.8 2001/04/27 13:55:26 matsfg
98 * Moved initioremap.
99 * Turns off all LEDS on init.
100 * Added support for shutdown and powerbutton.
101 *
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
104 *
105 * Revision 1.6 2001/03/26 16:03:06 bjornw
106 * Needs linux/config.h
107 *
108 * Revision 1.5 2001/03/26 14:22:03 bjornw
109 * Namechange of some config options
110 *
111 * Revision 1.4 2001/02/27 13:52:48 bjornw
112 * malloc.h -> slab.h
113 *
114 * Revision 1.3 2001/01/24 15:06:48 bjornw
115 * gpio_wq correct type
116 *
117 * Revision 1.2 2001/01/18 16:07:30 bjornw
118 * 2.4 port
119 *
120 * Revision 1.1 2001/01/18 15:55:16 bjornw
121 * Verbatim copy of etraxgpio.c from elinux 2.0 added
122 *
123 *
124 */
125
126#include <linux/config.h>
127
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>
139
140#include <asm/etraxgpio.h>
141#include <asm/arch/svinto.h>
142#include <asm/io.h>
143#include <asm/system.h>
144#include <asm/irq.h>
145
146#define GPIO_MAJOR 120 /* experimental MAJOR number */
147
148#define D(x)
149
150#if 0
151static int dp_cnt;
152#define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
153#else
154#define DP(x)
155#endif
156
157static char gpio_name[] = "etrax gpio";
158
159#if 0
160static wait_queue_head_t *gpio_wq;
161#endif
162
163static int gpio_ioctl(struct inode *inode, struct file *file,
164 unsigned int cmd, unsigned long arg);
165static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
166 loff_t *off);
167static int gpio_open(struct inode *inode, struct file *filp);
168static int gpio_release(struct inode *inode, struct file *filp);
169static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
170
171/* private data per open() of this driver */
172
173struct 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;
187 int minor;
188};
189
190/* linked list of alarms to check for */
191
192static struct gpio_private *alarmlist = 0;
193
194static int gpio_some_alarms = 0; /* Set if someone uses alarm */
195static unsigned long gpio_pa_irq_enabled_mask = 0;
196
197/* Port A and B use 8 bit access, but Port G is 32 bit */
198#define NUM_PORTS (GPIO_MINOR_B+1)
199
200static volatile unsigned char *ports[NUM_PORTS] = {
201 R_PORT_PA_DATA,
202 R_PORT_PB_DATA,
203};
204static volatile unsigned char *shads[NUM_PORTS] = {
205 &port_pa_data_shadow,
206 &port_pb_data_shadow
207};
208
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
212#endif
213#ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
214#define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
215#endif
216
217#ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
218#define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
219#endif
220#ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
221#define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
222#endif
223
224
225static unsigned char changeable_dir[NUM_PORTS] = {
226 CONFIG_ETRAX_PA_CHANGEABLE_DIR,
227 CONFIG_ETRAX_PB_CHANGEABLE_DIR
228};
229static unsigned char changeable_bits[NUM_PORTS] = {
230 CONFIG_ETRAX_PA_CHANGEABLE_BITS,
231 CONFIG_ETRAX_PB_CHANGEABLE_BITS
232};
233
234static volatile unsigned char *dir[NUM_PORTS] = {
235 R_PORT_PA_DIR,
236 R_PORT_PB_DIR
237};
238
239static volatile unsigned char *dir_shadow[NUM_PORTS] = {
240 &port_pa_dir_shadow,
241 &port_pb_dir_shadow
242};
243
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. */
247static unsigned long changeable_dir_g;
248static unsigned long dir_g_in_bits;
249static unsigned long dir_g_out_bits;
250static unsigned long dir_g_shadow; /* 1=output */
251
252#define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
253
254
255
256static unsigned int
257gpio_poll(struct file *file,
258 poll_table *wait)
259{
260 unsigned int mask = 0;
261 struct gpio_private *priv = (struct gpio_private *)file->private_data;
262 unsigned long data;
263 poll_wait(file, &priv->alarm_wq, wait);
264 if (priv->minor == GPIO_MINOR_A) {
265 unsigned long flags;
266 unsigned long tmp;
267 data = *R_PORT_PA_DATA;
268 /* PA has support for high level interrupt -
269 * lets activate for those low and with highalarm set
270 */
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);
277
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;
282 else
283 return 0;
284
285 if ((data & priv->highalarm) ||
286 (~data & priv->lowalarm)) {
287 mask = POLLIN|POLLRDNORM;
288 }
289
290 DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
291 return mask;
292}
293
294int etrax_gpio_wake_up_check(void)
295{
296 struct gpio_private *priv = alarmlist;
297 unsigned long data = 0;
298 int ret = 0;
299 while (priv) {
300 if (USE_PORTS(priv)) {
301 data = *priv->port;
302 } else if (priv->minor == GPIO_MINOR_G) {
303 data = *R_PORT_G_DATA;
304 }
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);
309 ret = 1;
310 }
311 priv = priv->next;
312 }
313 return ret;
314}
315
316static irqreturn_t
317gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
318{
319 if (gpio_some_alarms) {
320 etrax_gpio_wake_up_check();
321 return IRQ_HANDLED;
322 }
323 return IRQ_NONE;
324}
325
326static irqreturn_t
327gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
328{
329 unsigned long tmp;
330 /* Find what PA interrupts are active */
331 tmp = (*R_IRQ_READ1);
332
333 /* Find those that we have enabled */
334 tmp &= gpio_pa_irq_enabled_mask;
335
336 /* Clear them.. */
337 *R_IRQ_MASK1_CLR = tmp;
338 gpio_pa_irq_enabled_mask &= ~tmp;
339
340 if (gpio_some_alarms) {
341 return IRQ_RETVAL(etrax_gpio_wake_up_check());
342 }
343 return IRQ_NONE;
344}
345
346
347static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
348 loff_t *off)
349{
350 struct gpio_private *priv = (struct gpio_private *)file->private_data;
351 unsigned char data, clk_mask, data_mask, write_msb;
352 unsigned long flags;
353 ssize_t retval = count;
354 if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
355 return -EFAULT;
356 }
357
358 if (!access_ok(VERIFY_READ, buf, count)) {
359 return -EFAULT;
360 }
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) {
366 return -EPERM;
367 }
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));
370 while (count--) {
371 int i;
372 data = *buf++;
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;
377 if (data & 1<<i)
378 *priv->port = *priv->shadow |= data_mask;
379 else
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);
384 }
385 } else {
386 for (i = 0; i <= 7;i++) {
387 local_irq_save(flags); local_irq_disable();
388 *priv->port = *priv->shadow &= ~clk_mask;
389 if (data & 1<<i)
390 *priv->port = *priv->shadow |= data_mask;
391 else
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);
396 }
397 }
398 }
399 return retval;
400}
401
402
403
404static int
405gpio_open(struct inode *inode, struct file *filp)
406{
407 struct gpio_private *priv;
408 int p = MINOR(inode->i_rdev);
409
410 if (p > GPIO_MINOR_LAST)
411 return -EINVAL;
412
413 priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
414 GFP_KERNEL);
415
416 if (!priv)
417 return -ENOMEM;
418
419 priv->minor = p;
420
421 /* initialize the io/alarm struct and link it into our alarmlist */
422
423 priv->next = alarmlist;
424 alarmlist = priv;
425 if (USE_PORTS(priv)) { /* A and B */
426 priv->port = ports[p];
427 priv->shadow = shads[p];
428 priv->dir = dir[p];
429 priv->dir_shadow = dir_shadow[p];
430 priv->changeable_dir = changeable_dir[p];
431 priv->changeable_bits = changeable_bits[p];
432 } else {
433 priv->port = NULL;
434 priv->shadow = NULL;
435 priv->dir = NULL;
436 priv->dir_shadow = NULL;
437 priv->changeable_dir = 0;
438 priv->changeable_bits = 0;
439 }
440
441 priv->highalarm = 0;
442 priv->lowalarm = 0;
443 priv->clk_mask = 0;
444 priv->data_mask = 0;
445 init_waitqueue_head(&priv->alarm_wq);
446
447 filp->private_data = (void *)priv;
448
449 return 0;
450}
451
452static int
453gpio_release(struct inode *inode, struct file *filp)
454{
455 struct gpio_private *p = alarmlist;
456 struct gpio_private *todel = (struct gpio_private *)filp->private_data;
457
458 /* unlink from alarmlist and free the private structure */
459
460 if (p == todel) {
461 alarmlist = todel->next;
462 } else {
463 while (p->next != todel)
464 p = p->next;
465 p->next = todel->next;
466 }
467
468 kfree(todel);
469 /* Check if there are still any alarms set */
470 p = alarmlist;
471 while (p) {
472 if (p->highalarm | p->lowalarm) {
473 gpio_some_alarms = 1;
474 return 0;
475 }
476 p = p->next;
477 }
478 gpio_some_alarms = 0;
479
480 return 0;
481}
482
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().
485 */
486
487unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
488{
489 /* Set direction 0=unchanged 1=input,
490 * return mask with 1=input
491 */
492 unsigned long flags;
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 */
506 if (arg & (1<<0)) {
507 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
508 dir_g_in_bits |= (1<<0);
509 dir_g_out_bits &= ~(1<<0);
510 }
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;
515 }
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;
520 }
521 if (arg & (1<<24)) {
522 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
523 dir_g_in_bits |= (1<<24);
524 dir_g_out_bits &= ~(1<<24);
525 }
526 D(printk(KERN_INFO "gpio: SETINPUT on port G set "
527 "genconfig to 0x%08lX "
528 "in_bits: 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 */
534
535 }
536 restore_flags(flags);
537 return dir_g_in_bits;
538 }
539 return 0;
540} /* setget_input */
541
542unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
543{
544 unsigned long flags;
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 */
557 if (arg & (1<<0)) {
558 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
559 dir_g_out_bits |= (1<<0);
560 dir_g_in_bits &= ~(1<<0);
561 }
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;
566 }
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;
571 }
572 if (arg & (1<<24)) {
573 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
574 dir_g_out_bits |= (1<<24);
575 dir_g_in_bits &= ~(1<<24);
576 }
577 D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
578 "genconfig to 0x%08lX "
579 "in_bits: 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 */
585 }
586 restore_flags(flags);
587 return dir_g_out_bits & 0x7FFFFFFF;
588 }
589 return 0;
590} /* setget_output */
591
592static int
593gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
594
595static int
596gpio_ioctl(struct inode *inode, struct file *file,
597 unsigned int cmd, unsigned long arg)
598{
599 unsigned long flags;
600 unsigned long val;
601 struct gpio_private *priv = (struct gpio_private *)file->private_data;
602 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
603 return -EINVAL;
604 }
605
606 switch (_IOC_NR(cmd)) {
607 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
608 // read the port
609 if (USE_PORTS(priv)) {
610 return *priv->port;
611 } else if (priv->minor == GPIO_MINOR_G) {
612 return (*R_PORT_G_DATA) & 0x7FFFFFFF;
613 }
614 break;
615 case IO_SETBITS:
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);
623 }
624 local_irq_restore(flags);
625 break;
626 case IO_CLRBITS:
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);
634 }
635 local_irq_restore(flags);
636 break;
637 case IO_HIGHALARM:
638 // set alarm when bits with 1 in arg go high
639 priv->highalarm |= arg;
640 gpio_some_alarms = 1;
641 break;
642 case IO_LOWALARM:
643 // set alarm when bits with 1 in arg go low
644 priv->lowalarm |= arg;
645 gpio_some_alarms = 1;
646 break;
647 case IO_CLRALARM:
648 // clear alarm for bits with 1 in arg
649 priv->highalarm &= ~arg;
650 priv->lowalarm &= ~arg;
651 {
652 /* Must update gpio_some_alarms */
653 struct gpio_private *p = alarmlist;
654 int some_alarms;
655 some_alarms = 0;
656 while (p) {
657 if (p->highalarm | p->lowalarm) {
658 some_alarms = 1;
659 break;
660 }
661 p = p->next;
662 }
663 gpio_some_alarms = some_alarms;
664 }
665 break;
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.
673 */
674 return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
675 }
676 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
677 /* Set direction 0=unchanged 1=input,
678 * return mask with 1=input
679 */
680 return setget_input(priv, arg) & 0x7FFFFFFF;
681 break;
682 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
683 /* Set direction 0=unchanged 1=output,
684 * return mask with 1=output
685 */
686 return setget_output(priv, arg) & 0x7FFFFFFF;
687
688 case IO_SHUTDOWN:
689 SOFT_SHUTDOWN();
690 break;
691 case IO_GET_PWR_BT:
692#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
693 return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
694#else
695 return 0;
696#endif
697 break;
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
704 */
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)))
709 {
710 priv->clk_mask = 0;
711 priv->data_mask = 0;
712 return -EPERM;
713 }
714 break;
715 case IO_READ_INBITS:
716 /* *arg is result of reading the input pins */
717 if (USE_PORTS(priv)) {
718 val = *priv->port;
719 } else if (priv->minor == GPIO_MINOR_G) {
720 val = *R_PORT_G_DATA;
721 }
722 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
723 return -EFAULT;
724 return 0;
725 break;
726 case IO_READ_OUTBITS:
727 /* *arg is result of reading the output shadow */
728 if (USE_PORTS(priv)) {
729 val = *priv->shadow;
730 } else if (priv->minor == GPIO_MINOR_G) {
731 val = port_g_data_shadow;
732 }
733 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
734 return -EFAULT;
735 break;
736 case IO_SETGET_INPUT:
737 /* bits set in *arg is set to input,
738 * *arg updated with current input pins.
739 */
740 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
741 return -EFAULT;
742 val = setget_input(priv, val);
743 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
744 return -EFAULT;
745 break;
746 case IO_SETGET_OUTPUT:
747 /* bits set in *arg is set to output,
748 * *arg updated with current output pins.
749 */
750 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
751 return -EFAULT;
752 val = setget_output(priv, val);
753 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
754 return -EFAULT;
755 break;
756 default:
757 if (priv->minor == GPIO_MINOR_LEDS)
758 return gpio_leds_ioctl(cmd, arg);
759 else
760 return -EINVAL;
761 } /* switch */
762
763 return 0;
764}
765
766static int
767gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
768{
769 unsigned char green;
770 unsigned char red;
771
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);
778 break;
779
780 case IO_LED_SETBIT:
781 LED_BIT_SET(arg);
782 break;
783
784 case IO_LED_CLRBIT:
785 LED_BIT_CLR(arg);
786 break;
787
788 default:
789 return -EINVAL;
790 } /* switch */
791
792 return 0;
793}
794
795struct file_operations gpio_fops = {
796 .owner = THIS_MODULE,
797 .poll = gpio_poll,
798 .ioctl = gpio_ioctl,
799 .write = gpio_write,
800 .open = gpio_open,
801 .release = gpio_release,
802};
803
804
805static void __init gpio_init_port_g(void)
806{
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;
817 }
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;
821 }
822
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;
826 }
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;
830 }
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;
835 }
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;
839 }
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);
843 }
844
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));
848 }
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;
852 }
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;
857 }
858 /* TODO: USB p2, parw, sync ser3? */
859
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);
870
871 dir_g_in_bits = ~used_in_bits;
872 dir_g_out_bits = ~used_out_bits;
873
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);
882
883
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);
888}
889
890/* main driver initialization routine, called from mem.c */
891
892static __init int
893gpio_init(void)
894{
895 int res;
896#if defined (CONFIG_ETRAX_CSP0_LEDS)
897 int i;
898#endif
899
900 /* do the formalities */
901
902 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
903 if (res < 0) {
904 printk(KERN_ERR "gpio: couldn't get a major number.\n");
905 return res;
906 }
907
908 /* Clear all leds */
909#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
910 LED_NETWORK_SET(0);
911 LED_ACTIVE_SET(0);
912 LED_DISK_READ(0);
913 LED_DISK_WRITE(0);
914
915#if defined (CONFIG_ETRAX_CSP0_LEDS)
916 for (i = 0; i < 32; i++) {
917 LED_BIT_SET(i);
918 }
919#endif
920
921#endif
922 gpio_init_port_g();
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
927 * in some tests.
928 */
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");
932 }
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");
936 }
937
938
939 return res;
940}
941
942/* this makes sure that gpio_init is called during kernel boot */
943
944module_init(gpio_init);