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