1/* $Id: gpio.c,v 1.1.1.1 2007-08-03 18:51:41 $ 2 * 3 * ETRAX CRISv32 general port I/O device 4 * 5 * Copyright (c) 1999, 2000, 2001, 2002, 2003 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 * port to ETRAX FS. 11 * 12 * $Log: not supported by cvs2svn $ 13 * Revision 1.16 2005/06/19 17:06:49 starvik 14 * Merge of Linux 2.6.12. 15 * 16 * Revision 1.15 2005/05/25 08:22:20 starvik 17 * Changed GPIO port order to fit packages/devices/axis-2.4. 18 * 19 * Revision 1.14 2005/04/24 18:35:08 starvik 20 * Updated with final register headers. 21 * 22 * Revision 1.13 2005/03/15 15:43:00 starvik 23 * dev_id needs to be supplied for shared IRQs. 24 * 25 * Revision 1.12 2005/03/10 17:12:00 starvik 26 * Protect alarm list with spinlock. 27 * 28 * Revision 1.11 2005/01/05 06:08:59 starvik 29 * No need to do local_irq_disable after local_irq_save. 30 * 31 * Revision 1.10 2004/11/19 08:38:31 starvik 32 * Removed old crap. 33 * 34 * Revision 1.9 2004/05/14 07:58:02 starvik 35 * Merge of changes from 2.4 36 * 37 * Revision 1.8 2003/09/11 07:29:50 starvik 38 * Merge of Linux 2.6.0-test5 39 * 40 * Revision 1.7 2003/07/10 13:25:46 starvik 41 * Compiles for 2.5.74 42 * Lindented ethernet.c 43 * 44 * Revision 1.6 2003/07/04 08:27:46 starvik 45 * Merge of Linux 2.5.74 46 * 47 * Revision 1.5 2003/06/10 08:26:37 johana 48 * Etrax -> ETRAX CRISv32 49 * 50 * Revision 1.4 2003/06/05 14:22:48 johana 51 * Initialise some_alarms. 52 * 53 * Revision 1.3 2003/06/05 10:15:46 johana 54 * New INTR_VECT macros. 55 * Enable interrupts in global config. 56 * 57 * Revision 1.2 2003/06/03 15:52:50 johana 58 * Initial CRIS v32 version. 59 * 60 * Revision 1.1 2003/06/03 08:53:15 johana 61 * Copy of os/lx25/arch/cris/arch-v10/drivers/gpio.c version 1.7. 62 * 63 */ 64 65 66#include <linux/module.h> 67#include <linux/sched.h> 68#include <linux/slab.h> 69#include <linux/ioport.h> 70#include <linux/errno.h> 71#include <linux/kernel.h> 72#include <linux/fs.h> 73#include <linux/string.h> 74#include <linux/poll.h> 75#include <linux/init.h> 76#include <linux/interrupt.h> 77#include <linux/spinlock.h> 78 79#include <asm/etraxgpio.h> 80#include <asm/arch/hwregs/reg_map.h> 81#include <asm/arch/hwregs/reg_rdwr.h> 82#include <asm/arch/hwregs/gio_defs.h> 83#include <asm/arch/hwregs/intr_vect_defs.h> 84#include <asm/io.h> 85#include <asm/system.h> 86#include <asm/irq.h> 87 88/* The following gio ports on ETRAX FS is available: 89 * pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge 90 * pb 18 bits 91 * pc 18 bits 92 * pd 18 bits 93 * pe 18 bits 94 * each port has a rw_px_dout, r_px_din and rw_px_oe register. 95 */ 96 97#define GPIO_MAJOR 120 /* experimental MAJOR number */ 98 99#define D(x) 100 101#define DP(x) 102 103static char gpio_name[] = "etrax gpio"; 104 105 106static int gpio_ioctl(struct inode *inode, struct file *file, 107 unsigned int cmd, unsigned long arg); 108static ssize_t gpio_write(struct file * file, const char * buf, size_t count, 109 loff_t *off); 110static int gpio_open(struct inode *inode, struct file *filp); 111static int gpio_release(struct inode *inode, struct file *filp); 112static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait); 113 114/* private data per open() of this driver */ 115 116struct gpio_private { 117 struct gpio_private *next; 118 /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */ 119 unsigned char clk_mask; 120 unsigned char data_mask; 121 unsigned char write_msb; 122 unsigned char pad1; 123 /* These fields are generic */ 124 unsigned long highalarm, lowalarm; 125 wait_queue_head_t alarm_wq; 126 int minor; 127}; 128 129/* linked list of alarms to check for */ 130 131static struct gpio_private *alarmlist = 0; 132 133static int gpio_some_alarms = 0; /* Set if someone uses alarm */ 134static unsigned long gpio_pa_high_alarms = 0; 135static unsigned long gpio_pa_low_alarms = 0; 136 137static DEFINE_SPINLOCK(alarm_lock); 138 139#define NUM_PORTS (GPIO_MINOR_LAST+1) 140#define GIO_REG_RD_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg ) 141#define GIO_REG_WR_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg ) 142unsigned long led_dummy; 143 144static volatile unsigned long *data_out[NUM_PORTS] = { 145 GIO_REG_WR_ADDR(rw_pa_dout), 146 GIO_REG_WR_ADDR(rw_pb_dout), 147 &led_dummy, 148 GIO_REG_WR_ADDR(rw_pc_dout), 149 GIO_REG_WR_ADDR(rw_pd_dout), 150 GIO_REG_WR_ADDR(rw_pe_dout), 151}; 152 153static volatile unsigned long *data_in[NUM_PORTS] = { 154 GIO_REG_RD_ADDR(r_pa_din), 155 GIO_REG_RD_ADDR(r_pb_din), 156 &led_dummy, 157 GIO_REG_RD_ADDR(r_pc_din), 158 GIO_REG_RD_ADDR(r_pd_din), 159 GIO_REG_RD_ADDR(r_pe_din), 160}; 161 162static unsigned long changeable_dir[NUM_PORTS] = { 163 CONFIG_ETRAX_PA_CHANGEABLE_DIR, 164 CONFIG_ETRAX_PB_CHANGEABLE_DIR, 165 0, 166 CONFIG_ETRAX_PC_CHANGEABLE_DIR, 167 CONFIG_ETRAX_PD_CHANGEABLE_DIR, 168 CONFIG_ETRAX_PE_CHANGEABLE_DIR, 169}; 170 171static unsigned long changeable_bits[NUM_PORTS] = { 172 CONFIG_ETRAX_PA_CHANGEABLE_BITS, 173 CONFIG_ETRAX_PB_CHANGEABLE_BITS, 174 0, 175 CONFIG_ETRAX_PC_CHANGEABLE_BITS, 176 CONFIG_ETRAX_PD_CHANGEABLE_BITS, 177 CONFIG_ETRAX_PE_CHANGEABLE_BITS, 178}; 179 180static volatile unsigned long *dir_oe[NUM_PORTS] = { 181 GIO_REG_WR_ADDR(rw_pa_oe), 182 GIO_REG_WR_ADDR(rw_pb_oe), 183 &led_dummy, 184 GIO_REG_WR_ADDR(rw_pc_oe), 185 GIO_REG_WR_ADDR(rw_pd_oe), 186 GIO_REG_WR_ADDR(rw_pe_oe), 187}; 188 189 190 191static unsigned int 192gpio_poll(struct file *file, 193 poll_table *wait) 194{ 195 unsigned int mask = 0; 196 struct gpio_private *priv = (struct gpio_private *)file->private_data; 197 unsigned long data; 198 poll_wait(file, &priv->alarm_wq, wait); 199 if (priv->minor == GPIO_MINOR_A) { 200 reg_gio_rw_intr_cfg intr_cfg; 201 unsigned long tmp; 202 unsigned long flags; 203 204 local_irq_save(flags); 205 data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, REG_RD(gio, regi_gio, r_pa_din)); 206 /* PA has support for interrupt 207 * lets activate high for those low and with highalarm set 208 */ 209 intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); 210 211 tmp = ~data & priv->highalarm & 0xFF; 212 if (tmp & (1 << 0)) { 213 intr_cfg.pa0 = regk_gio_hi; 214 } 215 if (tmp & (1 << 1)) { 216 intr_cfg.pa1 = regk_gio_hi; 217 } 218 if (tmp & (1 << 2)) { 219 intr_cfg.pa2 = regk_gio_hi; 220 } 221 if (tmp & (1 << 3)) { 222 intr_cfg.pa3 = regk_gio_hi; 223 } 224 if (tmp & (1 << 4)) { 225 intr_cfg.pa4 = regk_gio_hi; 226 } 227 if (tmp & (1 << 5)) { 228 intr_cfg.pa5 = regk_gio_hi; 229 } 230 if (tmp & (1 << 6)) { 231 intr_cfg.pa6 = regk_gio_hi; 232 } 233 if (tmp & (1 << 7)) { 234 intr_cfg.pa7 = regk_gio_hi; 235 } 236 /* 237 * lets activate low for those high and with lowalarm set 238 */ 239 tmp = data & priv->lowalarm & 0xFF; 240 if (tmp & (1 << 0)) { 241 intr_cfg.pa0 = regk_gio_lo; 242 } 243 if (tmp & (1 << 1)) { 244 intr_cfg.pa1 = regk_gio_lo; 245 } 246 if (tmp & (1 << 2)) { 247 intr_cfg.pa2 = regk_gio_lo; 248 } 249 if (tmp & (1 << 3)) { 250 intr_cfg.pa3 = regk_gio_lo; 251 } 252 if (tmp & (1 << 4)) { 253 intr_cfg.pa4 = regk_gio_lo; 254 } 255 if (tmp & (1 << 5)) { 256 intr_cfg.pa5 = regk_gio_lo; 257 } 258 if (tmp & (1 << 6)) { 259 intr_cfg.pa6 = regk_gio_lo; 260 } 261 if (tmp & (1 << 7)) { 262 intr_cfg.pa7 = regk_gio_lo; 263 } 264 265 REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); 266 local_irq_restore(flags); 267 } else if (priv->minor <= GPIO_MINOR_E) 268 data = *data_in[priv->minor]; 269 else 270 return 0; 271 272 if ((data & priv->highalarm) || 273 (~data & priv->lowalarm)) { 274 mask = POLLIN|POLLRDNORM; 275 } 276 277 DP(printk("gpio_poll ready: mask 0x%08X\n", mask)); 278 return mask; 279} 280 281int etrax_gpio_wake_up_check(void) 282{ 283 struct gpio_private *priv = alarmlist; 284 unsigned long data = 0; 285 int ret = 0; 286 while (priv) { 287 data = *data_in[priv->minor]; 288 if ((data & priv->highalarm) || 289 (~data & priv->lowalarm)) { 290 DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor)); 291 wake_up_interruptible(&priv->alarm_wq); 292 ret = 1; 293 } 294 priv = priv->next; 295 } 296 return ret; 297} 298 299static irqreturn_t 300gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 301{ 302 if (gpio_some_alarms) { 303 return IRQ_RETVAL(etrax_gpio_wake_up_check()); 304 } 305 return IRQ_NONE; 306} 307 308static irqreturn_t 309gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) 310{ 311 reg_gio_rw_intr_mask intr_mask; 312 reg_gio_r_masked_intr masked_intr; 313 reg_gio_rw_ack_intr ack_intr; 314 unsigned long tmp; 315 unsigned long tmp2; 316 317 /* Find what PA interrupts are active */ 318 masked_intr = REG_RD(gio, regi_gio, r_masked_intr); 319 tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr); 320 321 /* Find those that we have enabled */ 322 spin_lock(&alarm_lock); 323 tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms); 324 spin_unlock(&alarm_lock); 325 326 /* Ack them */ 327 ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp); 328 REG_WR(gio, regi_gio, rw_ack_intr, ack_intr); 329 330 /* Disable those interrupts.. */ 331 intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); 332 tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask); 333 tmp2 &= ~tmp; 334 intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2); 335 REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); 336 337 if (gpio_some_alarms) { 338 return IRQ_RETVAL(etrax_gpio_wake_up_check()); 339 } 340 return IRQ_NONE; 341} 342 343 344static ssize_t gpio_write(struct file * file, const char * buf, size_t count, 345 loff_t *off) 346{ 347 struct gpio_private *priv = (struct gpio_private *)file->private_data; 348 unsigned char data, clk_mask, data_mask, write_msb; 349 unsigned long flags; 350 unsigned long shadow; 351 volatile unsigned long *port; 352 ssize_t retval = count; 353 /* Only bits 0-7 may be used for write operations but allow all 354 devices except leds... */ 355 if (priv->minor == GPIO_MINOR_LEDS) { 356 return -EFAULT; 357 } 358 359 if (!access_ok(VERIFY_READ, buf, count)) { 360 return -EFAULT; 361 } 362 clk_mask = priv->clk_mask; 363 data_mask = priv->data_mask; 364 /* It must have been configured using the IO_CFG_WRITE_MODE */ 365 /* Perhaps a better error code? */ 366 if (clk_mask == 0 || data_mask == 0) { 367 return -EPERM; 368 } 369 write_msb = priv->write_msb; 370 D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb)); 371 port = data_out[priv->minor]; 372 373 while (count--) { 374 int i; 375 data = *buf++; 376 if (priv->write_msb) { 377 for (i = 7; i >= 0;i--) { 378 local_irq_save(flags); 379 shadow = *port; 380 *port = shadow &= ~clk_mask; 381 if (data & 1<<i) 382 *port = shadow |= data_mask; 383 else 384 *port = shadow &= ~data_mask; 385 /* For FPGA: min 5.0ns (DCC) before CCLK high */ 386 *port = shadow |= clk_mask; 387 local_irq_restore(flags); 388 } 389 } else { 390 for (i = 0; i <= 7;i++) { 391 local_irq_save(flags); 392 shadow = *port; 393 *port = shadow &= ~clk_mask; 394 if (data & 1<<i) 395 *port = shadow |= data_mask; 396 else 397 *port = shadow &= ~data_mask; 398 /* For FPGA: min 5.0ns (DCC) before CCLK high */ 399 *port = shadow |= clk_mask; 400 local_irq_restore(flags); 401 } 402 } 403 } 404 return retval; 405} 406 407 408 409static int 410gpio_open(struct inode *inode, struct file *filp) 411{ 412 struct gpio_private *priv; 413 int p = iminor(inode); 414 415 if (p > GPIO_MINOR_LAST) 416 return -EINVAL; 417 418 priv = kmalloc(sizeof(struct gpio_private), 419 GFP_KERNEL); 420 421 if (!priv) 422 return -ENOMEM; 423 424 priv->minor = p; 425 426 /* initialize the io/alarm struct and link it into our alarmlist */ 427 428 priv->next = alarmlist; 429 alarmlist = priv; 430 priv->clk_mask = 0; 431 priv->data_mask = 0; 432 priv->highalarm = 0; 433 priv->lowalarm = 0; 434 init_waitqueue_head(&priv->alarm_wq); 435 436 filp->private_data = (void *)priv; 437 438 return 0; 439} 440 441static int 442gpio_release(struct inode *inode, struct file *filp) 443{ 444 struct gpio_private *p = alarmlist; 445 struct gpio_private *todel = (struct gpio_private *)filp->private_data; 446 /* local copies while updating them: */ 447 unsigned long a_high, a_low; 448 unsigned long some_alarms; 449 450 /* unlink from alarmlist and free the private structure */ 451 452 if (p == todel) { 453 alarmlist = todel->next; 454 } else { 455 while (p->next != todel) 456 p = p->next; 457 p->next = todel->next; 458 } 459 460 kfree(todel); 461 /* Check if there are still any alarms set */ 462 p = alarmlist; 463 some_alarms = 0; 464 a_high = 0; 465 a_low = 0; 466 while (p) { 467 if (p->minor == GPIO_MINOR_A) { 468 a_high |= p->highalarm; 469 a_low |= p->lowalarm; 470 } 471 472 if (p->highalarm | p->lowalarm) { 473 some_alarms = 1; 474 } 475 p = p->next; 476 } 477 478 spin_lock(&alarm_lock); 479 gpio_some_alarms = some_alarms; 480 gpio_pa_high_alarms = a_high; 481 gpio_pa_low_alarms = a_low; 482 spin_unlock(&alarm_lock); 483 484 return 0; 485} 486 487/* Main device API. ioctl's to read/set/clear bits, as well as to 488 * set alarms to wait for using a subsequent select(). 489 */ 490 491unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg) 492{ 493 /* Set direction 0=unchanged 1=input, 494 * return mask with 1=input 495 */ 496 unsigned long flags; 497 unsigned long dir_shadow; 498 499 local_irq_save(flags); 500 dir_shadow = *dir_oe[priv->minor]; 501 dir_shadow &= ~(arg & changeable_dir[priv->minor]); 502 *dir_oe[priv->minor] = dir_shadow; 503 local_irq_restore(flags); 504 505 if (priv->minor == GPIO_MINOR_A) 506 dir_shadow ^= 0xFF; /* Only 8 bits */ 507 else 508 dir_shadow ^= 0x3FFFF; /* Only 18 bits */ 509 return dir_shadow; 510 511} /* setget_input */ 512 513unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg) 514{ 515 unsigned long flags; 516 unsigned long dir_shadow; 517 518 local_irq_save(flags); 519 dir_shadow = *dir_oe[priv->minor]; 520 dir_shadow |= (arg & changeable_dir[priv->minor]); 521 *dir_oe[priv->minor] = dir_shadow; 522 local_irq_restore(flags); 523 return dir_shadow; 524} /* setget_output */ 525 526static int 527gpio_leds_ioctl(unsigned int cmd, unsigned long arg); 528 529static int 530gpio_ioctl(struct inode *inode, struct file *file, 531 unsigned int cmd, unsigned long arg) 532{ 533 unsigned long flags; 534 unsigned long val; 535 unsigned long shadow; 536 struct gpio_private *priv = (struct gpio_private *)file->private_data; 537 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) { 538 return -EINVAL; 539 } 540 541 switch (_IOC_NR(cmd)) { 542 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ 543 // read the port 544 return *data_in[priv->minor]; 545 break; 546 case IO_SETBITS: 547 local_irq_save(flags); 548 if (arg & 0x04) 549 printk("GPIO SET 2\n"); 550 // set changeable bits with a 1 in arg 551 shadow = *data_out[priv->minor]; 552 shadow |= (arg & changeable_bits[priv->minor]); 553 *data_out[priv->minor] = shadow; 554 local_irq_restore(flags); 555 break; 556 case IO_CLRBITS: 557 local_irq_save(flags); 558 if (arg & 0x04) 559 printk("GPIO CLR 2\n"); 560 // clear changeable bits with a 1 in arg 561 shadow = *data_out[priv->minor]; 562 shadow &= ~(arg & changeable_bits[priv->minor]); 563 *data_out[priv->minor] = shadow; 564 local_irq_restore(flags); 565 break; 566 case IO_HIGHALARM: 567 // set alarm when bits with 1 in arg go high 568 priv->highalarm |= arg; 569 spin_lock(&alarm_lock); 570 gpio_some_alarms = 1; 571 if (priv->minor == GPIO_MINOR_A) { 572 gpio_pa_high_alarms |= arg; 573 } 574 spin_unlock(&alarm_lock); 575 break; 576 case IO_LOWALARM: 577 // set alarm when bits with 1 in arg go low 578 priv->lowalarm |= arg; 579 spin_lock(&alarm_lock); 580 gpio_some_alarms = 1; 581 if (priv->minor == GPIO_MINOR_A) { 582 gpio_pa_low_alarms |= arg; 583 } 584 spin_unlock(&alarm_lock); 585 break; 586 case IO_CLRALARM: 587 // clear alarm for bits with 1 in arg 588 priv->highalarm &= ~arg; 589 priv->lowalarm &= ~arg; 590 spin_lock(&alarm_lock); 591 if (priv->minor == GPIO_MINOR_A) { 592 if (gpio_pa_high_alarms & arg || 593 gpio_pa_low_alarms & arg) { 594 /* Must update the gpio_pa_*alarms masks */ 595 } 596 } 597 spin_unlock(&alarm_lock); 598 break; 599 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ 600 /* Read direction 0=input 1=output */ 601 return *dir_oe[priv->minor]; 602 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ 603 /* Set direction 0=unchanged 1=input, 604 * return mask with 1=input 605 */ 606 return setget_input(priv, arg); 607 break; 608 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ 609 /* Set direction 0=unchanged 1=output, 610 * return mask with 1=output 611 */ 612 return setget_output(priv, arg); 613 614 case IO_CFG_WRITE_MODE: 615 { 616 unsigned long dir_shadow; 617 dir_shadow = *dir_oe[priv->minor]; 618 619 priv->clk_mask = arg & 0xFF; 620 priv->data_mask = (arg >> 8) & 0xFF; 621 priv->write_msb = (arg >> 16) & 0x01; 622 /* Check if we're allowed to change the bits and 623 * the direction is correct 624 */ 625 if (!((priv->clk_mask & changeable_bits[priv->minor]) && 626 (priv->data_mask & changeable_bits[priv->minor]) && 627 (priv->clk_mask & dir_shadow) && 628 (priv->data_mask & dir_shadow))) 629 { 630 priv->clk_mask = 0; 631 priv->data_mask = 0; 632 return -EPERM; 633 } 634 break; 635 } 636 case IO_READ_INBITS: 637 /* *arg is result of reading the input pins */ 638 val = *data_in[priv->minor]; 639 if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) 640 return -EFAULT; 641 return 0; 642 break; 643 case IO_READ_OUTBITS: 644 /* *arg is result of reading the output shadow */ 645 val = *data_out[priv->minor]; 646 if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) 647 return -EFAULT; 648 break; 649 case IO_SETGET_INPUT: 650 /* bits set in *arg is set to input, 651 * *arg updated with current input pins. 652 */ 653 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) 654 return -EFAULT; 655 val = setget_input(priv, val); 656 if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) 657 return -EFAULT; 658 break; 659 case IO_SETGET_OUTPUT: 660 /* bits set in *arg is set to output, 661 * *arg updated with current output pins. 662 */ 663 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) 664 return -EFAULT; 665 val = setget_output(priv, val); 666 if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) 667 return -EFAULT; 668 break; 669 default: 670 if (priv->minor == GPIO_MINOR_LEDS) 671 return gpio_leds_ioctl(cmd, arg); 672 else 673 return -EINVAL; 674 } /* switch */ 675 676 return 0; 677} 678 679static int 680gpio_leds_ioctl(unsigned int cmd, unsigned long arg) 681{ 682 unsigned char green; 683 unsigned char red; 684 685 switch (_IOC_NR(cmd)) { 686 case IO_LEDACTIVE_SET: 687 green = ((unsigned char) arg) & 1; 688 red = (((unsigned char) arg) >> 1) & 1; 689 LED_ACTIVE_SET_G(green); 690 LED_ACTIVE_SET_R(red); 691 break; 692 693 default: 694 return -EINVAL; 695 } /* switch */ 696 697 return 0; 698} 699 700const struct file_operations gpio_fops = { 701 .owner = THIS_MODULE, 702 .poll = gpio_poll, 703 .ioctl = gpio_ioctl, 704 .write = gpio_write, 705 .open = gpio_open, 706 .release = gpio_release, 707}; 708 709 710/* main driver initialization routine, called from mem.c */ 711 712static __init int 713gpio_init(void) 714{ 715 int res; 716 reg_intr_vect_rw_mask intr_mask; 717 718 /* do the formalities */ 719 720 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops); 721 if (res < 0) { 722 printk(KERN_ERR "gpio: couldn't get a major number.\n"); 723 return res; 724 } 725 726 /* Clear all leds */ 727 LED_NETWORK_SET(0); 728 LED_ACTIVE_SET(0); 729 LED_DISK_READ(0); 730 LED_DISK_WRITE(0); 731 732 printk("ETRAX FS GPIO driver v2.5, (c) 2003-2005 Axis Communications AB\n"); 733 /* We call etrax_gpio_wake_up_check() from timer interrupt and 734 * from cpu_idle() in kernel/process.c 735 * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms 736 * in some tests. 737 */ 738 if (request_irq(TIMER_INTR_VECT, gpio_poll_timer_interrupt, 739 IRQF_SHARED | IRQF_DISABLED,"gpio poll", &alarmlist)) { 740 printk("err: timer0 irq for gpio\n"); 741 } 742 if (request_irq(GEN_IO_INTR_VECT, gpio_pa_interrupt, 743 IRQF_SHARED | IRQF_DISABLED,"gpio PA", &alarmlist)) { 744 printk("err: PA irq for gpio\n"); 745 } 746 /* enable the gio and timer irq in global config */ 747 intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); 748 intr_mask.timer = 1; 749 intr_mask.gen_io = 1; 750 REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); 751 752 return res; 753} 754 755/* this makes sure that gpio_init is called during kernel boot */ 756 757module_init(gpio_init); 758