Path: blob/master/arch/cris/arch-v32/drivers/mach-a3/gpio.c
15133 views
/*1* Artec-3 general port I/O device2*3* Copyright (c) 2007 Axis Communications AB4*5* Authors: Bjorn Wesen (initial version)6* Ola Knutsson (LED handling)7* Johan Adolfsson (read/set directions, write, port G,8* port to ETRAX FS.9* Ricard Wanderlof (PWM for Artpec-3)10*11*/1213#include <linux/module.h>14#include <linux/sched.h>15#include <linux/slab.h>16#include <linux/ioport.h>17#include <linux/errno.h>18#include <linux/kernel.h>19#include <linux/fs.h>20#include <linux/string.h>21#include <linux/poll.h>22#include <linux/init.h>23#include <linux/interrupt.h>24#include <linux/spinlock.h>25#include <linux/mutex.h>2627#include <asm/etraxgpio.h>28#include <hwregs/reg_map.h>29#include <hwregs/reg_rdwr.h>30#include <hwregs/gio_defs.h>31#include <hwregs/intr_vect_defs.h>32#include <asm/io.h>33#include <asm/system.h>34#include <asm/irq.h>35#include <mach/pinmux.h>3637#ifdef CONFIG_ETRAX_VIRTUAL_GPIO38#include "../i2c.h"3940#define VIRT_I2C_ADDR 0x4041#endif4243/* The following gio ports on ARTPEC-3 is available:44* pa 32 bits45* pb 32 bits46* pc 16 bits47* each port has a rw_px_dout, r_px_din and rw_px_oe register.48*/4950#define GPIO_MAJOR 120 /* experimental MAJOR number */5152#define I2C_INTERRUPT_BITS 0x300 /* i2c0_done and i2c1_done bits */5354#define D(x)5556#if 057static int dp_cnt;58#define DP(x) \59do { \60dp_cnt++; \61if (dp_cnt % 1000 == 0) \62x; \63} while (0)64#else65#define DP(x)66#endif6768static DEFINE_MUTEX(gpio_mutex);69static char gpio_name[] = "etrax gpio";7071#ifdef CONFIG_ETRAX_VIRTUAL_GPIO72static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,73unsigned long arg);74#endif75static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);76static ssize_t gpio_write(struct file *file, const char __user *buf,77size_t count, loff_t *off);78static int gpio_open(struct inode *inode, struct file *filp);79static int gpio_release(struct inode *inode, struct file *filp);80static unsigned int gpio_poll(struct file *filp,81struct poll_table_struct *wait);8283/* private data per open() of this driver */8485struct gpio_private {86struct gpio_private *next;87/* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */88unsigned char clk_mask;89unsigned char data_mask;90unsigned char write_msb;91unsigned char pad1;92/* These fields are generic */93unsigned long highalarm, lowalarm;94wait_queue_head_t alarm_wq;95int minor;96};9798static void gpio_set_alarm(struct gpio_private *priv);99static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg);100static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,101unsigned long arg);102103104/* linked list of alarms to check for */105106static struct gpio_private *alarmlist;107108static int wanted_interrupts;109110static DEFINE_SPINLOCK(gpio_lock);111112#define NUM_PORTS (GPIO_MINOR_LAST+1)113#define GIO_REG_RD_ADDR(reg) \114(unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)115#define GIO_REG_WR_ADDR(reg) \116(unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg)117static unsigned long led_dummy;118static unsigned long port_d_dummy; /* Only input on Artpec-3 */119#ifdef CONFIG_ETRAX_VIRTUAL_GPIO120static unsigned long port_e_dummy; /* Non existent on Artpec-3 */121static unsigned long virtual_dummy;122static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;123static unsigned short cached_virtual_gpio_read;124#endif125126static unsigned long *data_out[NUM_PORTS] = {127GIO_REG_WR_ADDR(rw_pa_dout),128GIO_REG_WR_ADDR(rw_pb_dout),129&led_dummy,130GIO_REG_WR_ADDR(rw_pc_dout),131&port_d_dummy,132#ifdef CONFIG_ETRAX_VIRTUAL_GPIO133&port_e_dummy,134&virtual_dummy,135#endif136};137138static unsigned long *data_in[NUM_PORTS] = {139GIO_REG_RD_ADDR(r_pa_din),140GIO_REG_RD_ADDR(r_pb_din),141&led_dummy,142GIO_REG_RD_ADDR(r_pc_din),143GIO_REG_RD_ADDR(r_pd_din),144#ifdef CONFIG_ETRAX_VIRTUAL_GPIO145&port_e_dummy,146&virtual_dummy,147#endif148};149150static unsigned long changeable_dir[NUM_PORTS] = {151CONFIG_ETRAX_PA_CHANGEABLE_DIR,152CONFIG_ETRAX_PB_CHANGEABLE_DIR,1530,154CONFIG_ETRAX_PC_CHANGEABLE_DIR,1550,156#ifdef CONFIG_ETRAX_VIRTUAL_GPIO1570,158CONFIG_ETRAX_PV_CHANGEABLE_DIR,159#endif160};161162static unsigned long changeable_bits[NUM_PORTS] = {163CONFIG_ETRAX_PA_CHANGEABLE_BITS,164CONFIG_ETRAX_PB_CHANGEABLE_BITS,1650,166CONFIG_ETRAX_PC_CHANGEABLE_BITS,1670,168#ifdef CONFIG_ETRAX_VIRTUAL_GPIO1690,170CONFIG_ETRAX_PV_CHANGEABLE_BITS,171#endif172};173174static unsigned long *dir_oe[NUM_PORTS] = {175GIO_REG_WR_ADDR(rw_pa_oe),176GIO_REG_WR_ADDR(rw_pb_oe),177&led_dummy,178GIO_REG_WR_ADDR(rw_pc_oe),179&port_d_dummy,180#ifdef CONFIG_ETRAX_VIRTUAL_GPIO181&port_e_dummy,182&virtual_rw_pv_oe,183#endif184};185186static void gpio_set_alarm(struct gpio_private *priv)187{188int bit;189int intr_cfg;190int mask;191int pins;192unsigned long flags;193194spin_lock_irqsave(&gpio_lock, flags);195intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg);196pins = REG_RD_INT(gio, regi_gio, rw_intr_pins);197mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS;198199for (bit = 0; bit < 32; bit++) {200int intr = bit % 8;201int pin = bit / 8;202if (priv->minor < GPIO_MINOR_LEDS)203pin += priv->minor * 4;204else205pin += (priv->minor - 1) * 4;206207if (priv->highalarm & (1<<bit)) {208intr_cfg |= (regk_gio_hi << (intr * 3));209mask |= 1 << intr;210wanted_interrupts = mask & 0xff;211pins |= pin << (intr * 4);212} else if (priv->lowalarm & (1<<bit)) {213intr_cfg |= (regk_gio_lo << (intr * 3));214mask |= 1 << intr;215wanted_interrupts = mask & 0xff;216pins |= pin << (intr * 4);217}218}219220REG_WR_INT(gio, regi_gio, rw_intr_cfg, intr_cfg);221REG_WR_INT(gio, regi_gio, rw_intr_pins, pins);222REG_WR_INT(gio, regi_gio, rw_intr_mask, mask);223224spin_unlock_irqrestore(&gpio_lock, flags);225}226227static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)228{229unsigned int mask = 0;230struct gpio_private *priv = file->private_data;231unsigned long data;232unsigned long tmp;233234if (priv->minor >= GPIO_MINOR_PWM0 &&235priv->minor <= GPIO_MINOR_LAST_PWM)236return 0;237238poll_wait(file, &priv->alarm_wq, wait);239if (priv->minor <= GPIO_MINOR_D) {240data = readl(data_in[priv->minor]);241REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts);242tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask);243tmp &= I2C_INTERRUPT_BITS;244tmp |= wanted_interrupts;245REG_WR_INT(gio, regi_gio, rw_intr_mask, tmp);246} else247return 0;248249if ((data & priv->highalarm) || (~data & priv->lowalarm))250mask = POLLIN|POLLRDNORM;251252DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask));253return mask;254}255256static irqreturn_t gpio_interrupt(int irq, void *dev_id)257{258reg_gio_rw_intr_mask intr_mask;259reg_gio_r_masked_intr masked_intr;260reg_gio_rw_ack_intr ack_intr;261unsigned long flags;262unsigned long tmp;263unsigned long tmp2;264#ifdef CONFIG_ETRAX_VIRTUAL_GPIO265unsigned char enable_gpiov_ack = 0;266#endif267268/* Find what PA interrupts are active */269masked_intr = REG_RD(gio, regi_gio, r_masked_intr);270tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);271272/* Find those that we have enabled */273spin_lock_irqsave(&gpio_lock, flags);274tmp &= wanted_interrupts;275spin_unlock_irqrestore(&gpio_lock, flags);276277#ifdef CONFIG_ETRAX_VIRTUAL_GPIO278/* Something changed on virtual GPIO. Interrupt is acked by279* reading the device.280*/281if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) {282i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read,283sizeof(cached_virtual_gpio_read));284enable_gpiov_ack = 1;285}286#endif287288/* Ack them */289ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);290REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);291292/* Disable those interrupts.. */293intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);294tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);295tmp2 &= ~tmp;296#ifdef CONFIG_ETRAX_VIRTUAL_GPIO297/* Do not disable interrupt on virtual GPIO. Changes on virtual298* pins are only noticed by an interrupt.299*/300if (enable_gpiov_ack)301tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);302#endif303intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);304REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);305306return IRQ_RETVAL(tmp);307}308309static void gpio_write_bit(unsigned long *port, unsigned char data, int bit,310unsigned char clk_mask, unsigned char data_mask)311{312unsigned long shadow = readl(port) & ~clk_mask;313writel(shadow, port);314if (data & 1 << bit)315shadow |= data_mask;316else317shadow &= ~data_mask;318writel(shadow, port);319/* For FPGA: min 5.0ns (DCC) before CCLK high */320shadow |= clk_mask;321writel(shadow, port);322}323324static void gpio_write_byte(struct gpio_private *priv, unsigned long *port,325unsigned char data)326{327int i;328329if (priv->write_msb)330for (i = 7; i >= 0; i--)331gpio_write_bit(port, data, i, priv->clk_mask,332priv->data_mask);333else334for (i = 0; i <= 7; i++)335gpio_write_bit(port, data, i, priv->clk_mask,336priv->data_mask);337}338339340static ssize_t gpio_write(struct file *file, const char __user *buf,341size_t count, loff_t *off)342{343struct gpio_private *priv = file->private_data;344unsigned long flags;345ssize_t retval = count;346/* Only bits 0-7 may be used for write operations but allow all347devices except leds... */348#ifdef CONFIG_ETRAX_VIRTUAL_GPIO349if (priv->minor == GPIO_MINOR_V)350return -EFAULT;351#endif352if (priv->minor == GPIO_MINOR_LEDS)353return -EFAULT;354355if (priv->minor >= GPIO_MINOR_PWM0 &&356priv->minor <= GPIO_MINOR_LAST_PWM)357return -EFAULT;358359if (!access_ok(VERIFY_READ, buf, count))360return -EFAULT;361362/* It must have been configured using the IO_CFG_WRITE_MODE */363/* Perhaps a better error code? */364if (priv->clk_mask == 0 || priv->data_mask == 0)365return -EPERM;366367D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X "368"msb: %i\n",369count, priv->data_mask, priv->clk_mask, priv->write_msb));370371spin_lock_irqsave(&gpio_lock, flags);372373while (count--)374gpio_write_byte(priv, data_out[priv->minor], *buf++);375376spin_unlock_irqrestore(&gpio_lock, flags);377return retval;378}379380static int gpio_open(struct inode *inode, struct file *filp)381{382struct gpio_private *priv;383int p = iminor(inode);384385if (p > GPIO_MINOR_LAST_PWM ||386(p > GPIO_MINOR_LAST && p < GPIO_MINOR_PWM0))387return -EINVAL;388389priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL);390391if (!priv)392return -ENOMEM;393394mutex_lock(&gpio_mutex);395memset(priv, 0, sizeof(*priv));396397priv->minor = p;398filp->private_data = priv;399400/* initialize the io/alarm struct, not for PWM ports though */401if (p <= GPIO_MINOR_LAST) {402403priv->clk_mask = 0;404priv->data_mask = 0;405priv->highalarm = 0;406priv->lowalarm = 0;407408init_waitqueue_head(&priv->alarm_wq);409410/* link it into our alarmlist */411spin_lock_irq(&gpio_lock);412priv->next = alarmlist;413alarmlist = priv;414spin_unlock_irq(&gpio_lock);415}416417mutex_unlock(&gpio_mutex);418return 0;419}420421static int gpio_release(struct inode *inode, struct file *filp)422{423struct gpio_private *p;424struct gpio_private *todel;425/* local copies while updating them: */426unsigned long a_high, a_low;427428/* prepare to free private structure */429todel = filp->private_data;430431/* unlink from alarmlist - only for non-PWM ports though */432if (todel->minor <= GPIO_MINOR_LAST) {433spin_lock_irq(&gpio_lock);434p = alarmlist;435436if (p == todel)437alarmlist = todel->next;438else {439while (p->next != todel)440p = p->next;441p->next = todel->next;442}443444/* Check if there are still any alarms set */445p = alarmlist;446a_high = 0;447a_low = 0;448while (p) {449if (p->minor == GPIO_MINOR_A) {450#ifdef CONFIG_ETRAX_VIRTUAL_GPIO451p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);452#endif453a_high |= p->highalarm;454a_low |= p->lowalarm;455}456457p = p->next;458}459460#ifdef CONFIG_ETRAX_VIRTUAL_GPIO461/* Variable 'a_low' needs to be set here again462* to ensure that interrupt for virtual GPIO is handled.463*/464a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);465#endif466467spin_unlock_irq(&gpio_lock);468}469kfree(todel);470471return 0;472}473474/* Main device API. ioctl's to read/set/clear bits, as well as to475* set alarms to wait for using a subsequent select().476*/477478inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)479{480/* Set direction 0=unchanged 1=input,481* return mask with 1=input482*/483unsigned long flags;484unsigned long dir_shadow;485486spin_lock_irqsave(&gpio_lock, flags);487488dir_shadow = readl(dir_oe[priv->minor]) &489~(arg & changeable_dir[priv->minor]);490writel(dir_shadow, dir_oe[priv->minor]);491492spin_unlock_irqrestore(&gpio_lock, flags);493494if (priv->minor == GPIO_MINOR_C)495dir_shadow ^= 0xFFFF; /* Only 16 bits */496#ifdef CONFIG_ETRAX_VIRTUAL_GPIO497else if (priv->minor == GPIO_MINOR_V)498dir_shadow ^= 0xFFFF; /* Only 16 bits */499#endif500else501dir_shadow ^= 0xFFFFFFFF; /* PA, PB and PD 32 bits */502503return dir_shadow;504505} /* setget_input */506507static inline unsigned long setget_output(struct gpio_private *priv,508unsigned long arg)509{510unsigned long flags;511unsigned long dir_shadow;512513spin_lock_irqsave(&gpio_lock, flags);514515dir_shadow = readl(dir_oe[priv->minor]) |516(arg & changeable_dir[priv->minor]);517writel(dir_shadow, dir_oe[priv->minor]);518519spin_unlock_irqrestore(&gpio_lock, flags);520return dir_shadow;521} /* setget_output */522523static long gpio_ioctl_unlocked(struct file *file,524unsigned int cmd, unsigned long arg)525{526unsigned long flags;527unsigned long val;528unsigned long shadow;529struct gpio_private *priv = file->private_data;530531if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)532return -ENOTTY;533534/* Check for special ioctl handlers first */535536#ifdef CONFIG_ETRAX_VIRTUAL_GPIO537if (priv->minor == GPIO_MINOR_V)538return virtual_gpio_ioctl(file, cmd, arg);539#endif540541if (priv->minor == GPIO_MINOR_LEDS)542return gpio_leds_ioctl(cmd, arg);543544if (priv->minor >= GPIO_MINOR_PWM0 &&545priv->minor <= GPIO_MINOR_LAST_PWM)546return gpio_pwm_ioctl(priv, cmd, arg);547548switch (_IOC_NR(cmd)) {549case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */550/* Read the port. */551return readl(data_in[priv->minor]);552case IO_SETBITS:553spin_lock_irqsave(&gpio_lock, flags);554/* Set changeable bits with a 1 in arg. */555shadow = readl(data_out[priv->minor]) |556(arg & changeable_bits[priv->minor]);557writel(shadow, data_out[priv->minor]);558spin_unlock_irqrestore(&gpio_lock, flags);559break;560case IO_CLRBITS:561spin_lock_irqsave(&gpio_lock, flags);562/* Clear changeable bits with a 1 in arg. */563shadow = readl(data_out[priv->minor]) &564~(arg & changeable_bits[priv->minor]);565writel(shadow, data_out[priv->minor]);566spin_unlock_irqrestore(&gpio_lock, flags);567break;568case IO_HIGHALARM:569/* Set alarm when bits with 1 in arg go high. */570priv->highalarm |= arg;571gpio_set_alarm(priv);572break;573case IO_LOWALARM:574/* Set alarm when bits with 1 in arg go low. */575priv->lowalarm |= arg;576gpio_set_alarm(priv);577break;578case IO_CLRALARM:579/* Clear alarm for bits with 1 in arg. */580priv->highalarm &= ~arg;581priv->lowalarm &= ~arg;582gpio_set_alarm(priv);583break;584case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */585/* Read direction 0=input 1=output */586return readl(dir_oe[priv->minor]);587588case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */589/* Set direction 0=unchanged 1=input,590* return mask with 1=input591*/592return setget_input(priv, arg);593594case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */595/* Set direction 0=unchanged 1=output,596* return mask with 1=output597*/598return setget_output(priv, arg);599600case IO_CFG_WRITE_MODE:601{602int res = -EPERM;603unsigned long dir_shadow, clk_mask, data_mask, write_msb;604605clk_mask = arg & 0xFF;606data_mask = (arg >> 8) & 0xFF;607write_msb = (arg >> 16) & 0x01;608609/* Check if we're allowed to change the bits and610* the direction is correct611*/612spin_lock_irqsave(&gpio_lock, flags);613dir_shadow = readl(dir_oe[priv->minor]);614if ((clk_mask & changeable_bits[priv->minor]) &&615(data_mask & changeable_bits[priv->minor]) &&616(clk_mask & dir_shadow) &&617(data_mask & dir_shadow)) {618priv->clk_mask = clk_mask;619priv->data_mask = data_mask;620priv->write_msb = write_msb;621res = 0;622}623spin_unlock_irqrestore(&gpio_lock, flags);624625return res;626}627case IO_READ_INBITS:628/* *arg is result of reading the input pins */629val = readl(data_in[priv->minor]);630if (copy_to_user((void __user *)arg, &val, sizeof(val)))631return -EFAULT;632return 0;633case IO_READ_OUTBITS:634/* *arg is result of reading the output shadow */635val = *data_out[priv->minor];636if (copy_to_user((void __user *)arg, &val, sizeof(val)))637return -EFAULT;638break;639case IO_SETGET_INPUT:640/* bits set in *arg is set to input,641* *arg updated with current input pins.642*/643if (copy_from_user(&val, (void __user *)arg, sizeof(val)))644return -EFAULT;645val = setget_input(priv, val);646if (copy_to_user((void __user *)arg, &val, sizeof(val)))647return -EFAULT;648break;649case IO_SETGET_OUTPUT:650/* bits set in *arg is set to output,651* *arg updated with current output pins.652*/653if (copy_from_user(&val, (void __user *)arg, sizeof(val)))654return -EFAULT;655val = setget_output(priv, val);656if (copy_to_user((void __user *)arg, &val, sizeof(val)))657return -EFAULT;658break;659default:660return -EINVAL;661} /* switch */662663return 0;664}665666static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)667{668long ret;669670mutex_lock(&gpio_mutex);671ret = gpio_ioctl_unlocked(file, cmd, arg);672mutex_unlock(&gpio_mutex);673674return ret;675}676677#ifdef CONFIG_ETRAX_VIRTUAL_GPIO678static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,679unsigned long arg)680{681unsigned long flags;682unsigned short val;683unsigned short shadow;684struct gpio_private *priv = file->private_data;685686switch (_IOC_NR(cmd)) {687case IO_SETBITS:688spin_lock_irqsave(&gpio_lock, flags);689/* Set changeable bits with a 1 in arg. */690i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));691shadow |= ~readl(dir_oe[priv->minor]) |692(arg & changeable_bits[priv->minor]);693i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));694spin_unlock_irqrestore(&gpio_lock, flags);695break;696case IO_CLRBITS:697spin_lock_irqsave(&gpio_lock, flags);698/* Clear changeable bits with a 1 in arg. */699i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));700shadow |= ~readl(dir_oe[priv->minor]) &701~(arg & changeable_bits[priv->minor]);702i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));703spin_unlock_irqrestore(&gpio_lock, flags);704break;705case IO_HIGHALARM:706/* Set alarm when bits with 1 in arg go high. */707priv->highalarm |= arg;708break;709case IO_LOWALARM:710/* Set alarm when bits with 1 in arg go low. */711priv->lowalarm |= arg;712break;713case IO_CLRALARM:714/* Clear alarm for bits with 1 in arg. */715priv->highalarm &= ~arg;716priv->lowalarm &= ~arg;717break;718case IO_CFG_WRITE_MODE:719{720unsigned long dir_shadow;721dir_shadow = readl(dir_oe[priv->minor]);722723priv->clk_mask = arg & 0xFF;724priv->data_mask = (arg >> 8) & 0xFF;725priv->write_msb = (arg >> 16) & 0x01;726/* Check if we're allowed to change the bits and727* the direction is correct728*/729if (!((priv->clk_mask & changeable_bits[priv->minor]) &&730(priv->data_mask & changeable_bits[priv->minor]) &&731(priv->clk_mask & dir_shadow) &&732(priv->data_mask & dir_shadow))) {733priv->clk_mask = 0;734priv->data_mask = 0;735return -EPERM;736}737break;738}739case IO_READ_INBITS:740/* *arg is result of reading the input pins */741val = cached_virtual_gpio_read & ~readl(dir_oe[priv->minor]);742if (copy_to_user((void __user *)arg, &val, sizeof(val)))743return -EFAULT;744return 0;745746case IO_READ_OUTBITS:747/* *arg is result of reading the output shadow */748i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));749val &= readl(dir_oe[priv->minor]);750if (copy_to_user((void __user *)arg, &val, sizeof(val)))751return -EFAULT;752break;753case IO_SETGET_INPUT:754{755/* bits set in *arg is set to input,756* *arg updated with current input pins.757*/758unsigned short input_mask = ~readl(dir_oe[priv->minor]);759if (copy_from_user(&val, (void __user *)arg, sizeof(val)))760return -EFAULT;761val = setget_input(priv, val);762if (copy_to_user((void __user *)arg, &val, sizeof(val)))763return -EFAULT;764if ((input_mask & val) != input_mask) {765/* Input pins changed. All ports desired as input766* should be set to logic 1.767*/768unsigned short change = input_mask ^ val;769i2c_read(VIRT_I2C_ADDR, (void *)&shadow,770sizeof(shadow));771shadow &= ~change;772shadow |= val;773i2c_write(VIRT_I2C_ADDR, (void *)&shadow,774sizeof(shadow));775}776break;777}778case IO_SETGET_OUTPUT:779/* bits set in *arg is set to output,780* *arg updated with current output pins.781*/782if (copy_from_user(&val, (void __user *)arg, sizeof(val)))783return -EFAULT;784val = setget_output(priv, val);785if (copy_to_user((void __user *)arg, &val, sizeof(val)))786return -EFAULT;787break;788default:789return -EINVAL;790} /* switch */791return 0;792}793#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */794795static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg)796{797unsigned char green;798unsigned char red;799800switch (_IOC_NR(cmd)) {801case IO_LEDACTIVE_SET:802green = ((unsigned char) arg) & 1;803red = (((unsigned char) arg) >> 1) & 1;804CRIS_LED_ACTIVE_SET_G(green);805CRIS_LED_ACTIVE_SET_R(red);806break;807808default:809return -EINVAL;810} /* switch */811812return 0;813}814815static int gpio_pwm_set_mode(unsigned long arg, int pwm_port)816{817int pinmux_pwm = pinmux_pwm0 + pwm_port;818int mode;819reg_gio_rw_pwm0_ctrl rw_pwm_ctrl = {820.ccd_val = 0,821.ccd_override = regk_gio_no,822.mode = regk_gio_no823};824int allocstatus;825826if (get_user(mode, &((struct io_pwm_set_mode *) arg)->mode))827return -EFAULT;828rw_pwm_ctrl.mode = mode;829if (mode != PWM_OFF)830allocstatus = crisv32_pinmux_alloc_fixed(pinmux_pwm);831else832allocstatus = crisv32_pinmux_dealloc_fixed(pinmux_pwm);833if (allocstatus)834return allocstatus;835REG_WRITE(reg_gio_rw_pwm0_ctrl, REG_ADDR(gio, regi_gio, rw_pwm0_ctrl) +83612 * pwm_port, rw_pwm_ctrl);837return 0;838}839840static int gpio_pwm_set_period(unsigned long arg, int pwm_port)841{842struct io_pwm_set_period periods;843reg_gio_rw_pwm0_var rw_pwm_widths;844845if (copy_from_user(&periods, (void __user *)arg, sizeof(periods)))846return -EFAULT;847if (periods.lo > 8191 || periods.hi > 8191)848return -EINVAL;849rw_pwm_widths.lo = periods.lo;850rw_pwm_widths.hi = periods.hi;851REG_WRITE(reg_gio_rw_pwm0_var, REG_ADDR(gio, regi_gio, rw_pwm0_var) +85212 * pwm_port, rw_pwm_widths);853return 0;854}855856static int gpio_pwm_set_duty(unsigned long arg, int pwm_port)857{858unsigned int duty;859reg_gio_rw_pwm0_data rw_pwm_duty;860861if (get_user(duty, &((struct io_pwm_set_duty *) arg)->duty))862return -EFAULT;863if (duty > 255)864return -EINVAL;865rw_pwm_duty.data = duty;866REG_WRITE(reg_gio_rw_pwm0_data, REG_ADDR(gio, regi_gio, rw_pwm0_data) +86712 * pwm_port, rw_pwm_duty);868return 0;869}870871static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,872unsigned long arg)873{874int pwm_port = priv->minor - GPIO_MINOR_PWM0;875876switch (_IOC_NR(cmd)) {877case IO_PWM_SET_MODE:878return gpio_pwm_set_mode(arg, pwm_port);879case IO_PWM_SET_PERIOD:880return gpio_pwm_set_period(arg, pwm_port);881case IO_PWM_SET_DUTY:882return gpio_pwm_set_duty(arg, pwm_port);883default:884return -EINVAL;885}886return 0;887}888889static const struct file_operations gpio_fops = {890.owner = THIS_MODULE,891.poll = gpio_poll,892.unlocked_ioctl = gpio_ioctl,893.write = gpio_write,894.open = gpio_open,895.release = gpio_release,896.llseek = noop_llseek,897};898899#ifdef CONFIG_ETRAX_VIRTUAL_GPIO900static void __init virtual_gpio_init(void)901{902reg_gio_rw_intr_cfg intr_cfg;903reg_gio_rw_intr_mask intr_mask;904unsigned short shadow;905906shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */907shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT;908i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));909910/* Set interrupt mask and on what state the interrupt shall trigger.911* For virtual gpio the interrupt shall trigger on logic '0'.912*/913intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);914intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);915916switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) {917case 0:918intr_cfg.pa0 = regk_gio_lo;919intr_mask.pa0 = regk_gio_yes;920break;921case 1:922intr_cfg.pa1 = regk_gio_lo;923intr_mask.pa1 = regk_gio_yes;924break;925case 2:926intr_cfg.pa2 = regk_gio_lo;927intr_mask.pa2 = regk_gio_yes;928break;929case 3:930intr_cfg.pa3 = regk_gio_lo;931intr_mask.pa3 = regk_gio_yes;932break;933case 4:934intr_cfg.pa4 = regk_gio_lo;935intr_mask.pa4 = regk_gio_yes;936break;937case 5:938intr_cfg.pa5 = regk_gio_lo;939intr_mask.pa5 = regk_gio_yes;940break;941case 6:942intr_cfg.pa6 = regk_gio_lo;943intr_mask.pa6 = regk_gio_yes;944break;945case 7:946intr_cfg.pa7 = regk_gio_lo;947intr_mask.pa7 = regk_gio_yes;948break;949}950951REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);952REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);953}954#endif955956/* main driver initialization routine, called from mem.c */957958static int __init gpio_init(void)959{960int res;961962printk(KERN_INFO "ETRAX FS GPIO driver v2.7, (c) 2003-2008 "963"Axis Communications AB\n");964965/* do the formalities */966967res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);968if (res < 0) {969printk(KERN_ERR "gpio: couldn't get a major number.\n");970return res;971}972973/* Clear all leds */974CRIS_LED_NETWORK_GRP0_SET(0);975CRIS_LED_NETWORK_GRP1_SET(0);976CRIS_LED_ACTIVE_SET(0);977CRIS_LED_DISK_READ(0);978CRIS_LED_DISK_WRITE(0);979980int res2 = request_irq(GIO_INTR_VECT, gpio_interrupt,981IRQF_SHARED | IRQF_DISABLED, "gpio", &alarmlist);982if (res2) {983printk(KERN_ERR "err: irq for gpio\n");984return res2;985}986987/* No IRQs by default. */988REG_WR_INT(gio, regi_gio, rw_intr_pins, 0);989990#ifdef CONFIG_ETRAX_VIRTUAL_GPIO991virtual_gpio_init();992#endif993994return res;995}996997/* this makes sure that gpio_init is called during kernel boot */998999module_init(gpio_init);100010011002