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