os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/gpio.c

Go to the documentation of this file.
00001 /*
00002  * ETRAX CRISv32 general port I/O device
00003  *
00004  * Copyright (c) 1999-2006 Axis Communications AB
00005  *
00006  * Authors:    Bjorn Wesen      (initial version)
00007  *             Ola Knutsson     (LED handling)
00008  *             Johan Adolfsson  (read/set directions, write, port G,
00009  *                               port to ETRAX FS.
00010  *
00011  */
00012 
00013 #include <linux/module.h>
00014 #include <linux/sched.h>
00015 #include <linux/slab.h>
00016 #include <linux/ioport.h>
00017 #include <linux/errno.h>
00018 #include <linux/kernel.h>
00019 #include <linux/fs.h>
00020 #include <linux/string.h>
00021 #include <linux/poll.h>
00022 #include <linux/init.h>
00023 #include <linux/interrupt.h>
00024 #include <linux/spinlock.h>
00025 
00026 #include <asm/etraxgpio.h>
00027 #include <asm/arch/hwregs/reg_map.h>
00028 #include <asm/arch/hwregs/reg_rdwr.h>
00029 #include <asm/arch/hwregs/gio_defs.h>
00030 #include <asm/arch/hwregs/intr_vect_defs.h>
00031 #include <asm/io.h>
00032 #include <asm/system.h>
00033 #include <asm/irq.h>
00034 
00035 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00036 #include "i2c.h"
00037 
00038 #define VIRT_I2C_ADDR 0x40
00039 #endif
00040 
00041 
00042 /* The following gio ports on ETRAX FS is available:
00043  * pa  8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge
00044  * pb 18 bits
00045  * pc 18 bits
00046  * pd 18 bits
00047  * pe 18 bits
00048  * each port has a rw_px_dout, r_px_din and rw_px_oe register.
00049  */
00050 
00051 #define GPIO_MAJOR 120  /* experimental MAJOR number */
00052 
00053 #define D(x)
00054 
00055 #if 0
00056 static int dp_cnt;
00057 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
00058 #else
00059 #define DP(x)
00060 #endif
00061 
00062 static char gpio_name[] = "etrax gpio";
00063 
00064 #if 0
00065 static wait_queue_head_t *gpio_wq;
00066 #endif
00067 
00068 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00069 static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
00070                               unsigned long arg);
00071 #endif
00072 static int gpio_ioctl(struct inode *inode, struct file *file,
00073                       unsigned int cmd, unsigned long arg);
00074 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
00075                           loff_t *off);
00076 static int gpio_open(struct inode *inode, struct file *filp);
00077 static int gpio_release(struct inode *inode, struct file *filp);
00078 static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
00079 
00080 /* private data per open() of this driver */
00081 
00082 struct gpio_private {
00083         struct gpio_private *next;
00084         /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */
00085         unsigned char clk_mask;
00086         unsigned char data_mask;
00087         unsigned char write_msb;
00088         unsigned char pad1;
00089         /* These fields are generic */
00090         unsigned long highalarm, lowalarm;
00091         wait_queue_head_t alarm_wq;
00092         int minor;
00093 };
00094 
00095 /* linked list of alarms to check for */
00096 
00097 static struct gpio_private *alarmlist = 0;
00098 
00099 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
00100 static unsigned long gpio_pa_high_alarms = 0;
00101 static unsigned long gpio_pa_low_alarms = 0;
00102 
00103 static DEFINE_SPINLOCK(alarm_lock);
00104 
00105 #define NUM_PORTS (GPIO_MINOR_LAST+1)
00106 #define GIO_REG_RD_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg )
00107 #define GIO_REG_WR_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg )
00108 unsigned long led_dummy;
00109 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00110 static unsigned long virtual_dummy;
00111 static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;
00112 static unsigned short cached_virtual_gpio_read = 0;
00113 #endif
00114 
00115 static volatile unsigned long *data_out[NUM_PORTS] = { 
00116         GIO_REG_WR_ADDR(rw_pa_dout), 
00117         GIO_REG_WR_ADDR(rw_pb_dout), 
00118         &led_dummy,
00119         GIO_REG_WR_ADDR(rw_pc_dout), 
00120         GIO_REG_WR_ADDR(rw_pd_dout), 
00121         GIO_REG_WR_ADDR(rw_pe_dout),
00122 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00123         &virtual_dummy,
00124 #endif
00125 };
00126 
00127 static volatile unsigned long *data_in[NUM_PORTS] = { 
00128         GIO_REG_RD_ADDR(r_pa_din), 
00129         GIO_REG_RD_ADDR(r_pb_din), 
00130         &led_dummy,
00131         GIO_REG_RD_ADDR(r_pc_din), 
00132         GIO_REG_RD_ADDR(r_pd_din), 
00133         GIO_REG_RD_ADDR(r_pe_din),
00134 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00135         &virtual_dummy,
00136 #endif
00137 };
00138 
00139 static unsigned long changeable_dir[NUM_PORTS] = { 
00140         CONFIG_ETRAX_PA_CHANGEABLE_DIR,
00141         CONFIG_ETRAX_PB_CHANGEABLE_DIR,
00142         0,
00143         CONFIG_ETRAX_PC_CHANGEABLE_DIR,
00144         CONFIG_ETRAX_PD_CHANGEABLE_DIR, 
00145         CONFIG_ETRAX_PE_CHANGEABLE_DIR,
00146 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00147         CONFIG_ETRAX_PV_CHANGEABLE_DIR,
00148 #endif
00149 };
00150 
00151 static unsigned long changeable_bits[NUM_PORTS] = { 
00152         CONFIG_ETRAX_PA_CHANGEABLE_BITS,
00153         CONFIG_ETRAX_PB_CHANGEABLE_BITS,
00154         0,
00155         CONFIG_ETRAX_PC_CHANGEABLE_BITS,
00156         CONFIG_ETRAX_PD_CHANGEABLE_BITS,
00157         CONFIG_ETRAX_PE_CHANGEABLE_BITS,
00158 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00159         CONFIG_ETRAX_PV_CHANGEABLE_BITS,
00160 #endif
00161 };
00162 
00163 static volatile unsigned long *dir_oe[NUM_PORTS] = { 
00164         GIO_REG_WR_ADDR(rw_pa_oe), 
00165         GIO_REG_WR_ADDR(rw_pb_oe), 
00166         &led_dummy,
00167         GIO_REG_WR_ADDR(rw_pc_oe), 
00168         GIO_REG_WR_ADDR(rw_pd_oe), 
00169         GIO_REG_WR_ADDR(rw_pe_oe),
00170 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00171         &virtual_rw_pv_oe,
00172 #endif
00173 };
00174 
00175 
00176 
00177 static unsigned int 
00178 gpio_poll(struct file *file,
00179           poll_table *wait)
00180 {
00181         unsigned int mask = 0;
00182         struct gpio_private *priv = (struct gpio_private *)file->private_data;
00183         unsigned long data;
00184         poll_wait(file, &priv->alarm_wq, wait);
00185         if (priv->minor == GPIO_MINOR_A) {
00186                 reg_gio_rw_intr_cfg intr_cfg;
00187                 unsigned long tmp;
00188                 unsigned long flags;
00189 
00190                 local_irq_save(flags);
00191                 data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, REG_RD(gio, regi_gio, r_pa_din));
00192                 /* PA has support for interrupt
00193                  * lets activate high for those low and with highalarm set
00194                  */
00195                 intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
00196 
00197                 tmp = ~data & priv->highalarm & 0xFF;
00198                 if (tmp & (1 << 0)) {
00199                         intr_cfg.pa0 = regk_gio_hi;
00200                 }
00201                 if (tmp & (1 << 1)) {
00202                         intr_cfg.pa1 = regk_gio_hi;
00203                 }
00204                 if (tmp & (1 << 2)) {
00205                         intr_cfg.pa2 = regk_gio_hi;
00206                 }
00207                 if (tmp & (1 << 3)) {
00208                         intr_cfg.pa3 = regk_gio_hi;
00209                 }
00210                 if (tmp & (1 << 4)) {
00211                         intr_cfg.pa4 = regk_gio_hi;
00212                 }
00213                 if (tmp & (1 << 5)) {
00214                         intr_cfg.pa5 = regk_gio_hi;
00215                 }
00216                 if (tmp & (1 << 6)) {
00217                         intr_cfg.pa6 = regk_gio_hi;
00218                 }
00219                 if (tmp & (1 << 7)) {
00220                         intr_cfg.pa7 = regk_gio_hi;
00221                 }
00222                 /*
00223                  * lets activate low for those high and with lowalarm set
00224                  */
00225                 tmp = data & priv->lowalarm & 0xFF;
00226                 if (tmp & (1 << 0)) {
00227                         intr_cfg.pa0 = regk_gio_lo;
00228                 }
00229                 if (tmp & (1 << 1)) {
00230                         intr_cfg.pa1 = regk_gio_lo;
00231                 }
00232                 if (tmp & (1 << 2)) {
00233                         intr_cfg.pa2 = regk_gio_lo;
00234                 }
00235                 if (tmp & (1 << 3)) {
00236                         intr_cfg.pa3 = regk_gio_lo;
00237                 }
00238                 if (tmp & (1 << 4)) {
00239                         intr_cfg.pa4 = regk_gio_lo;
00240                 }
00241                 if (tmp & (1 << 5)) {
00242                         intr_cfg.pa5 = regk_gio_lo;
00243                 }
00244                 if (tmp & (1 << 6)) {
00245                         intr_cfg.pa6 = regk_gio_lo;
00246                 }
00247                 if (tmp & (1 << 7)) {
00248                         intr_cfg.pa7 = regk_gio_lo;
00249                 }
00250 
00251                 REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
00252                 local_irq_restore(flags);
00253         } else if (priv->minor <= GPIO_MINOR_E)
00254                 data = *data_in[priv->minor];
00255         else
00256                 return 0;
00257 
00258         if ((data & priv->highalarm) ||
00259             (~data & priv->lowalarm)) {
00260                 mask = POLLIN|POLLRDNORM;
00261         }
00262 
00263         DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
00264         return mask;
00265 }
00266 
00267 int etrax_gpio_wake_up_check(void)
00268 {
00269         struct gpio_private *priv;
00270         unsigned long data = 0;
00271         unsigned long flags;
00272         int ret = 0;
00273         spin_lock_irqsave(&alarm_lock, flags);
00274         priv = alarmlist;
00275         while (priv) {
00276 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00277                 if (priv->minor == GPIO_MINOR_V) {
00278                         data = (unsigned long)cached_virtual_gpio_read;
00279                 }
00280                 else {
00281                         data = *data_in[priv->minor];
00282                         if (priv->minor == GPIO_MINOR_A) {
00283                                 priv->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
00284                         }
00285                 }
00286 #else
00287                 data = *data_in[priv->minor];
00288 #endif
00289                 if ((data & priv->highalarm) ||
00290                     (~data & priv->lowalarm)) {
00291                         DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
00292                         wake_up_interruptible(&priv->alarm_wq);
00293                         ret = 1;
00294                 }
00295                 priv = priv->next;
00296         }
00297         spin_unlock_irqrestore(&alarm_lock, flags);
00298         return ret;
00299 }
00300 
00301 static irqreturn_t 
00302 gpio_poll_timer_interrupt(int irq, void *dev_id)
00303 {
00304         if (gpio_some_alarms) {
00305                 return IRQ_RETVAL(etrax_gpio_wake_up_check());
00306         }
00307         return IRQ_NONE;
00308 }
00309 
00310 static irqreturn_t
00311 gpio_pa_interrupt(int irq, void *dev_id)
00312 {
00313         reg_gio_rw_intr_mask intr_mask;
00314         reg_gio_r_masked_intr masked_intr;
00315         reg_gio_rw_ack_intr ack_intr;
00316         unsigned long tmp;
00317         unsigned long tmp2;
00318 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00319         unsigned char enable_gpiov_ack = 0;
00320 #endif
00321         
00322         /* Find what PA interrupts are active */
00323         masked_intr = REG_RD(gio, regi_gio, r_masked_intr);
00324         tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);
00325 
00326         /* Find those that we have enabled */
00327         spin_lock(&alarm_lock);
00328         tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms);
00329         spin_unlock(&alarm_lock);
00330 
00331 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00332         /* Something changed on virtual GPIO. Interrupt is acked by
00333          * reading the device.
00334          */
00335         if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) {
00336                 i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read,
00337                          sizeof(cached_virtual_gpio_read));
00338                 enable_gpiov_ack = 1;
00339         }
00340 #endif
00341 
00342         /* Ack them */
00343         ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);
00344         REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);
00345 
00346         /* Disable those interrupts.. */
00347         intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
00348         tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);
00349         tmp2 &= ~tmp;
00350 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00351         /* Do not disable interrupt on virtual GPIO. Changes on virtual
00352          * pins are only noticed by an interrupt.
00353          */
00354         if (enable_gpiov_ack)   {
00355                 tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
00356         }
00357 #endif
00358         intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);
00359         REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
00360 
00361         if (gpio_some_alarms) {
00362                 return IRQ_RETVAL(etrax_gpio_wake_up_check());
00363         }
00364         return IRQ_NONE;
00365 }
00366 
00367 
00368 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
00369                           loff_t *off)
00370 {
00371         struct gpio_private *priv = (struct gpio_private *)file->private_data;
00372         unsigned char data, clk_mask, data_mask, write_msb;
00373         unsigned long flags;
00374         unsigned long shadow;
00375         volatile unsigned long *port;
00376         ssize_t retval = count;
00377         /* Only bits 0-7 may be used for write operations but allow all 
00378            devices except leds... */
00379 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00380         if (priv->minor == GPIO_MINOR_V) {
00381                 return -EFAULT;
00382         }
00383 #endif
00384         if (priv->minor == GPIO_MINOR_LEDS) {
00385                 return -EFAULT;
00386         }
00387 
00388         if (!access_ok(VERIFY_READ, buf, count)) {
00389                 return -EFAULT;
00390         }
00391         clk_mask = priv->clk_mask;
00392         data_mask = priv->data_mask;
00393         /* It must have been configured using the IO_CFG_WRITE_MODE */
00394         /* Perhaps a better error code? */
00395         if (clk_mask == 0 || data_mask == 0) {
00396                 return -EPERM;
00397         }
00398         write_msb = priv->write_msb;
00399         D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
00400         port = data_out[priv->minor];
00401 
00402         while (count--) {
00403                 int i;
00404                 data = *buf++;
00405                 if (priv->write_msb) {
00406                         for (i = 7; i >= 0;i--) {
00407                                 local_irq_save(flags);
00408                                 shadow = *port;
00409                                 *port = shadow &= ~clk_mask;
00410                                 if (data & 1<<i)
00411                                         *port = shadow |= data_mask;
00412                                 else
00413                                         *port = shadow &= ~data_mask;
00414                         /* For FPGA: min 5.0ns (DCC) before CCLK high */
00415                                 *port = shadow |= clk_mask;
00416                                 local_irq_restore(flags);
00417                         }
00418                 } else {
00419                         for (i = 0; i <= 7;i++) {
00420                                 local_irq_save(flags);
00421                                 shadow = *port;
00422                                 *port = shadow &= ~clk_mask;
00423                                 if (data & 1<<i)
00424                                         *port = shadow |= data_mask;
00425                                 else
00426                                         *port = shadow &= ~data_mask;
00427                         /* For FPGA: min 5.0ns (DCC) before CCLK high */
00428                                 *port = shadow |= clk_mask;
00429                                 local_irq_restore(flags);
00430                         }
00431                 }
00432         }
00433         return retval;
00434 }
00435 
00436 
00437 
00438 static int
00439 gpio_open(struct inode *inode, struct file *filp)
00440 {       
00441         struct gpio_private *priv;
00442         int p = iminor(inode);
00443 
00444         if (p > GPIO_MINOR_LAST)
00445                 return -EINVAL;
00446 
00447         priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), 
00448                                               GFP_KERNEL);
00449 
00450         if (!priv)
00451                 return -ENOMEM;
00452         memset(priv, 0, sizeof(*priv));
00453 
00454         priv->minor = p;
00455 
00456         /* initialize the io/alarm struct */
00457 
00458         priv->clk_mask = 0;
00459         priv->data_mask = 0;
00460         priv->highalarm = 0;
00461         priv->lowalarm = 0;
00462         init_waitqueue_head(&priv->alarm_wq);
00463 
00464         filp->private_data = (void *)priv;
00465 
00466         /* link it into our alarmlist */
00467         spin_lock_irq(&alarm_lock);
00468         priv->next = alarmlist;
00469         alarmlist = priv;
00470         spin_unlock_irq(&alarm_lock);
00471 
00472         return 0;
00473 }
00474 
00475 static int
00476 gpio_release(struct inode *inode, struct file *filp)
00477 {
00478         struct gpio_private *p;
00479         struct gpio_private *todel;
00480         /* local copies while updating them: */
00481         unsigned long a_high, a_low;
00482         unsigned long some_alarms;
00483 
00484         /* unlink from alarmlist and free the private structure */
00485 
00486         spin_lock_irq(&alarm_lock);
00487         p = alarmlist;
00488         todel = (struct gpio_private *)filp->private_data;
00489 
00490         if (p == todel) {
00491                 alarmlist = todel->next;
00492         } else {
00493                 while (p->next != todel)
00494                         p = p->next;
00495                 p->next = todel->next;
00496         }
00497 
00498         kfree(todel);
00499         /* Check if there are still any alarms set */
00500         p = alarmlist;
00501         some_alarms = 0;
00502         a_high = 0;
00503         a_low = 0;
00504         while (p) {
00505                 if (p->minor == GPIO_MINOR_A) {
00506 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00507                         p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
00508 #endif
00509                         a_high |= p->highalarm;
00510                         a_low |= p->lowalarm;
00511                 }
00512 
00513                 if (p->highalarm | p->lowalarm) {
00514                         some_alarms = 1;
00515                 }
00516                 p = p->next;
00517         }
00518 
00519 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00520         /* Variables 'some_alarms' and 'a_low' needs to be set here again
00521          * to ensure that interrupt for virtual GPIO is handled.
00522          */
00523         some_alarms = 1;
00524         a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
00525 #endif
00526 
00527         gpio_some_alarms = some_alarms;
00528         gpio_pa_high_alarms = a_high;
00529         gpio_pa_low_alarms = a_low;
00530         spin_unlock_irq(&alarm_lock);
00531 
00532         return 0;
00533 }
00534 
00535 /* Main device API. ioctl's to read/set/clear bits, as well as to 
00536  * set alarms to wait for using a subsequent select().
00537  */
00538 
00539 unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
00540 {
00541         /* Set direction 0=unchanged 1=input, 
00542          * return mask with 1=input 
00543          */
00544         unsigned long flags;
00545         unsigned long dir_shadow;
00546 
00547         local_irq_save(flags);
00548         dir_shadow = *dir_oe[priv->minor];
00549         dir_shadow &= ~(arg & changeable_dir[priv->minor]);
00550         *dir_oe[priv->minor] = dir_shadow;
00551         local_irq_restore(flags);
00552 
00553         if (priv->minor == GPIO_MINOR_A)
00554                 dir_shadow ^= 0xFF;    /* Only 8 bits */
00555 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00556         else if (priv->minor == GPIO_MINOR_V)
00557                 dir_shadow ^= 0xFFFF;  /* Only 16 bits */
00558 #endif
00559         else
00560                 dir_shadow ^= 0x3FFFF; /* Only 18 bits */
00561         return dir_shadow;
00562 
00563 } /* setget_input */
00564 
00565 unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
00566 {
00567         unsigned long flags;
00568         unsigned long dir_shadow;
00569 
00570         local_irq_save(flags);
00571         dir_shadow = *dir_oe[priv->minor];
00572         dir_shadow |=  (arg & changeable_dir[priv->minor]);
00573         *dir_oe[priv->minor] = dir_shadow;
00574         local_irq_restore(flags);
00575         return dir_shadow;
00576 } /* setget_output */
00577 
00578 static int
00579 gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
00580 
00581 static int
00582 gpio_ioctl(struct inode *inode, struct file *file,
00583            unsigned int cmd, unsigned long arg)
00584 {
00585         unsigned long flags;
00586         unsigned long val;
00587         unsigned long shadow;
00588         struct gpio_private *priv = (struct gpio_private *)file->private_data;
00589         if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
00590                 return -EINVAL;
00591         }
00592 
00593 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00594         if (priv->minor == GPIO_MINOR_V)
00595                 return virtual_gpio_ioctl(file, cmd, arg);
00596 #endif
00597 
00598         switch (_IOC_NR(cmd)) {
00599         case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
00600                 // read the port
00601                 return *data_in[priv->minor];
00602                 break;
00603         case IO_SETBITS:
00604                 local_irq_save(flags);
00605                 // set changeable bits with a 1 in arg
00606                 shadow = *data_out[priv->minor];
00607                 shadow |=  (arg & changeable_bits[priv->minor]);
00608                 *data_out[priv->minor] = shadow;
00609                 local_irq_restore(flags);
00610                 break;
00611         case IO_CLRBITS:
00612                 local_irq_save(flags);
00613                 // clear changeable bits with a 1 in arg
00614                 shadow = *data_out[priv->minor];
00615                 shadow &=  ~(arg & changeable_bits[priv->minor]);
00616                 *data_out[priv->minor] = shadow;
00617                 local_irq_restore(flags);
00618                 break;
00619         case IO_HIGHALARM:
00620                 // set alarm when bits with 1 in arg go high
00621                 priv->highalarm |= arg;
00622                 spin_lock_irqsave(&alarm_lock, flags);
00623                 gpio_some_alarms = 1;
00624                 if (priv->minor == GPIO_MINOR_A) {
00625                         gpio_pa_high_alarms |= arg;
00626                 }
00627                 spin_unlock_irqrestore(&alarm_lock, flags);
00628                 break;
00629         case IO_LOWALARM:
00630                 // set alarm when bits with 1 in arg go low
00631                 priv->lowalarm |= arg;
00632                 spin_lock_irqsave(&alarm_lock, flags);
00633                 gpio_some_alarms = 1;
00634                 if (priv->minor == GPIO_MINOR_A) {
00635                         gpio_pa_low_alarms |= arg;
00636                 }
00637                 spin_unlock_irqrestore(&alarm_lock, flags);
00638                 break;
00639         case IO_CLRALARM:
00640                 // clear alarm for bits with 1 in arg
00641                 priv->highalarm &= ~arg;
00642                 priv->lowalarm  &= ~arg;
00643                 spin_lock_irqsave(&alarm_lock, flags);
00644                 if (priv->minor == GPIO_MINOR_A) {
00645                         if (gpio_pa_high_alarms & arg || 
00646                             gpio_pa_low_alarms & arg) {
00647                                 /* Must update the gpio_pa_*alarms masks */
00648                         }
00649                 }
00650                 spin_unlock_irqrestore(&alarm_lock, flags);
00651                 break;
00652         case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
00653                 /* Read direction 0=input 1=output */
00654                 return *dir_oe[priv->minor];
00655         case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
00656                 /* Set direction 0=unchanged 1=input, 
00657                  * return mask with 1=input 
00658                  */
00659                 return setget_input(priv, arg);
00660                 break;
00661         case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
00662                 /* Set direction 0=unchanged 1=output, 
00663                  * return mask with 1=output 
00664                  */
00665                 return setget_output(priv, arg);
00666 
00667         case IO_CFG_WRITE_MODE: 
00668         {
00669                 unsigned long dir_shadow;
00670                 dir_shadow = *dir_oe[priv->minor];
00671 
00672                 priv->clk_mask = arg & 0xFF;
00673                 priv->data_mask = (arg >> 8) & 0xFF;
00674                 priv->write_msb = (arg >> 16) & 0x01;
00675                 /* Check if we're allowed to change the bits and
00676                  * the direction is correct
00677                  */
00678                 if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
00679                       (priv->data_mask & changeable_bits[priv->minor]) &&
00680                       (priv->clk_mask & dir_shadow) &&
00681                       (priv->data_mask & dir_shadow)))
00682                 {
00683                         priv->clk_mask = 0;
00684                         priv->data_mask = 0;
00685                         return -EPERM;
00686                 }
00687                 break;
00688         }
00689         case IO_READ_INBITS: 
00690                 /* *arg is result of reading the input pins */
00691                 val = *data_in[priv->minor];
00692                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00693                         return -EFAULT;
00694                 return 0;
00695                 break;
00696         case IO_READ_OUTBITS:
00697                  /* *arg is result of reading the output shadow */
00698                 val = *data_out[priv->minor];
00699                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00700                         return -EFAULT;
00701                 break;
00702         case IO_SETGET_INPUT: 
00703                 /* bits set in *arg is set to input,
00704                  * *arg updated with current input pins.
00705                  */
00706                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
00707                         return -EFAULT;
00708                 val = setget_input(priv, val);
00709                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00710                         return -EFAULT;
00711                 break;
00712         case IO_SETGET_OUTPUT:
00713                 /* bits set in *arg is set to output,
00714                  * *arg updated with current output pins.
00715                  */
00716                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
00717                         return -EFAULT;
00718                 val = setget_output(priv, val);
00719                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00720                         return -EFAULT;
00721                 break;
00722         default:
00723                 if (priv->minor == GPIO_MINOR_LEDS)
00724                         return gpio_leds_ioctl(cmd, arg);
00725                 else
00726                         return -EINVAL;
00727         } /* switch */
00728 
00729         return 0;
00730 }
00731 
00732 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00733 static int
00734 virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
00735 {
00736         unsigned long flags;
00737         unsigned short val;
00738         unsigned short shadow;
00739         struct gpio_private *priv = (struct gpio_private *)file->private_data;
00740 
00741         switch (_IOC_NR(cmd)) {
00742         case IO_SETBITS:
00743                 local_irq_save(flags);
00744                 // set changeable bits with a 1 in arg
00745                 i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00746                 shadow |= ~*dir_oe[priv->minor];
00747                 shadow |= (arg & changeable_bits[priv->minor]);
00748                 i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00749                 local_irq_restore(flags);
00750                 break;
00751         case IO_CLRBITS:
00752                 local_irq_save(flags);
00753                 // clear changeable bits with a 1 in arg
00754                 i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00755                 shadow |= ~*dir_oe[priv->minor];
00756                 shadow &= ~(arg & changeable_bits[priv->minor]);
00757                 i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00758                 local_irq_restore(flags);
00759                 break;
00760         case IO_HIGHALARM:
00761                 // set alarm when bits with 1 in arg go high
00762                 priv->highalarm |= arg;
00763                 spin_lock(&alarm_lock);
00764                 gpio_some_alarms = 1;
00765                 spin_unlock(&alarm_lock);
00766                 break;
00767         case IO_LOWALARM:
00768                 // set alarm when bits with 1 in arg go low
00769                 priv->lowalarm |= arg;
00770                 spin_lock(&alarm_lock);
00771                 gpio_some_alarms = 1;
00772                 spin_unlock(&alarm_lock);
00773                 break;
00774         case IO_CLRALARM:
00775                 // clear alarm for bits with 1 in arg
00776                 priv->highalarm &= ~arg;
00777                 priv->lowalarm  &= ~arg;
00778                 spin_lock(&alarm_lock);
00779                 spin_unlock(&alarm_lock);
00780                 break;
00781         case IO_CFG_WRITE_MODE: 
00782         {
00783                 unsigned long dir_shadow;
00784                 dir_shadow = *dir_oe[priv->minor];
00785                 
00786                 priv->clk_mask = arg & 0xFF;
00787                 priv->data_mask = (arg >> 8) & 0xFF;
00788                 priv->write_msb = (arg >> 16) & 0x01;
00789                 /* Check if we're allowed to change the bits and
00790                  * the direction is correct
00791                  */
00792                 if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
00793                       (priv->data_mask & changeable_bits[priv->minor]) &&
00794                       (priv->clk_mask & dir_shadow) &&
00795                       (priv->data_mask & dir_shadow)))
00796                 {
00797                         priv->clk_mask = 0;
00798                         priv->data_mask = 0;
00799                         return -EPERM;
00800                 }
00801                 break;
00802         }
00803         case IO_READ_INBITS: 
00804                 /* *arg is result of reading the input pins */
00805                 val = cached_virtual_gpio_read;
00806                 val &= ~*dir_oe[priv->minor];
00807                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00808                         return -EFAULT;
00809                 return 0;
00810                 break;
00811         case IO_READ_OUTBITS:
00812                  /* *arg is result of reading the output shadow */
00813                 i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));
00814                 val &= *dir_oe[priv->minor];
00815                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00816                         return -EFAULT;
00817                 break;
00818         case IO_SETGET_INPUT:
00819         {
00820                 /* bits set in *arg is set to input,
00821                  * *arg updated with current input pins.
00822                  */
00823                 unsigned short input_mask = ~*dir_oe[priv->minor];
00824                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
00825                         return -EFAULT;
00826                 val = setget_input(priv, val);
00827                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00828                         return -EFAULT;
00829                 if ((input_mask & val) != input_mask) {
00830                         /* Input pins changed. All ports desired as input
00831                          * should be set to logic 1.
00832                          */
00833                         unsigned short change = input_mask ^ val;
00834                         i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00835                         shadow &= ~change;
00836                         shadow |= val;
00837                         i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00838                 }
00839                 break;
00840         }
00841         case IO_SETGET_OUTPUT:
00842                 /* bits set in *arg is set to output,
00843                  * *arg updated with current output pins.
00844                  */
00845                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
00846                         return -EFAULT;
00847                 val = setget_output(priv, val);
00848                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
00849                         return -EFAULT;
00850                 break;
00851         default:
00852                 return -EINVAL;
00853         } /* switch */
00854   return 0;
00855 }
00856 #endif /* CONFIG_ETRAX_VIRTUAL_GPIO */
00857 
00858 static int
00859 gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
00860 {
00861         unsigned char green;
00862         unsigned char red;
00863 
00864         switch (_IOC_NR(cmd)) {
00865         case IO_LEDACTIVE_SET:
00866                 green = ((unsigned char) arg) & 1;
00867                 red   = (((unsigned char) arg) >> 1) & 1;
00868                 LED_ACTIVE_SET_G(green);
00869                 LED_ACTIVE_SET_R(red);
00870                 break;
00871 
00872         default:
00873                 return -EINVAL;
00874         } /* switch */
00875 
00876         return 0;
00877 }
00878 
00879 struct file_operations gpio_fops = {
00880         .owner       = THIS_MODULE,
00881         .poll        = gpio_poll,
00882         .ioctl       = gpio_ioctl,
00883         .write       = gpio_write,
00884         .open        = gpio_open,
00885         .release     = gpio_release,
00886 };
00887 
00888 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00889 static void
00890 virtual_gpio_init(void)
00891 {
00892         reg_gio_rw_intr_cfg intr_cfg;
00893         reg_gio_rw_intr_mask intr_mask;
00894         unsigned short shadow;
00895 
00896         shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */
00897         shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT;
00898         i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
00899 
00900         /* Set interrupt mask and on what state the interrupt shall trigger.
00901          * For virtual gpio the interrupt shall trigger on logic '0'.
00902          */
00903         intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
00904         intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
00905 
00906         switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) {
00907          case 0:
00908           intr_cfg.pa0 = regk_gio_lo;
00909           intr_mask.pa0 = regk_gio_yes;
00910           break;
00911          case 1:
00912           intr_cfg.pa1 = regk_gio_lo;
00913           intr_mask.pa1 = regk_gio_yes;
00914           break;
00915          case 2:
00916           intr_cfg.pa2 = regk_gio_lo;
00917           intr_mask.pa2 = regk_gio_yes;
00918           break;
00919          case 3:
00920           intr_cfg.pa3 = regk_gio_lo;
00921           intr_mask.pa3 = regk_gio_yes;
00922           break;
00923          case 4:
00924           intr_cfg.pa4 = regk_gio_lo;
00925           intr_mask.pa4 = regk_gio_yes;
00926           break;
00927          case 5:
00928           intr_cfg.pa5 = regk_gio_lo;
00929           intr_mask.pa5 = regk_gio_yes;
00930           break;
00931          case 6:
00932           intr_cfg.pa6 = regk_gio_lo;
00933           intr_mask.pa6 = regk_gio_yes;
00934           break;
00935          case 7:
00936           intr_cfg.pa7 = regk_gio_lo;
00937           intr_mask.pa7 = regk_gio_yes;
00938           break;
00939         }
00940 
00941         REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
00942         REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
00943 
00944         gpio_pa_low_alarms |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
00945         gpio_some_alarms = 1;
00946 }
00947 #endif
00948 
00949 /* main driver initialization routine, called from mem.c */
00950 
00951 static __init int
00952 gpio_init(void)
00953 {
00954         int res;
00955         reg_intr_vect_rw_mask intr_mask;
00956 
00957         /* do the formalities */
00958 
00959         res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
00960         if (res < 0) {
00961                 printk(KERN_ERR "gpio: couldn't get a major number.\n");
00962                 return res;
00963         }
00964 
00965         /* Clear all leds */
00966 /*
00967         LED_NETWORK_GRP0_SET(0);
00968         LED_NETWORK_GRP1_SET(0);
00969         LED_ACTIVE_SET(0);
00970         LED_DISK_READ(0);
00971         LED_DISK_WRITE(0);
00972 */
00973         printk("ETRAX FS GPIO driver v2.5, (c) 2003-2006 Axis Communications AB\n");
00974         /* We call etrax_gpio_wake_up_check() from timer interrupt and
00975          * from cpu_idle() in kernel/process.c
00976          * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
00977          * in some tests.
00978          */  
00979         if (request_irq(TIMER_INTR_VECT, gpio_poll_timer_interrupt,
00980                         IRQF_SHARED | IRQF_DISABLED,"gpio poll", &alarmlist)) {
00981                 printk("err: timer0 irq for gpio\n");
00982         }
00983         if (request_irq(GEN_IO_INTR_VECT, gpio_pa_interrupt,
00984                         IRQF_SHARED | IRQF_DISABLED,"gpio PA", &alarmlist)) {
00985                 printk("err: PA irq for gpio\n");
00986         }
00987         /* enable the gio and timer irq in global config */
00988         intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
00989         intr_mask.timer = 1;
00990         intr_mask.gen_io = 1;
00991         REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
00992 
00993 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
00994         virtual_gpio_init();
00995 #endif
00996 
00997         return res;
00998 }
00999 
01000 /* this makes sure that gpio_init is called during kernel boot */
01001 
01002 module_init(gpio_init);

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1