linux/arch/arm/mach-ks8695/gpio.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-ks8695/gpio.c
   3 *
   4 * Copyright (C) 2006 Andrew Victor
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/mm.h>
  22#include <linux/init.h>
  23#include <linux/module.h>
  24
  25#include <asm/io.h>
  26#include <asm/hardware.h>
  27#include <asm/mach/irq.h>
  28
  29#include <asm/arch/regs-gpio.h>
  30#include <asm/arch/gpio.h>
  31
  32/*
  33 * Configure a GPIO line for either GPIO function, or its internal
  34 * function (Interrupt, Timer, etc).
  35 */
  36static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
  37{
  38        unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
  39        unsigned long x, flags;
  40
  41        if (pin > KS8695_GPIO_5)        /* only GPIO 0..5 have internal functions */
  42                return;
  43
  44        local_irq_save(flags);
  45
  46        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
  47        if (gpio)                       /* GPIO: set bit to 0 */
  48                x &= ~enable[pin];
  49        else                            /* Internal function: set bit to 1 */
  50                x |= enable[pin];
  51        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
  52
  53        local_irq_restore(flags);
  54}
  55
  56
  57static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
  58
  59/*
  60 * Configure GPIO pin as external interrupt source.
  61 */
  62int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
  63{
  64        unsigned long x, flags;
  65
  66        if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
  67                return -EINVAL;
  68
  69        local_irq_save(flags);
  70
  71        /* set pin as input */
  72        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
  73        x &= ~IOPM_(pin);
  74        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
  75
  76        local_irq_restore(flags);
  77
  78        /* Set IRQ triggering type */
  79        set_irq_type(gpio_irq[pin], type);
  80
  81        /* enable interrupt mode */
  82        ks8695_gpio_mode(pin, 0);
  83
  84        return 0;
  85}
  86EXPORT_SYMBOL(ks8695_gpio_interrupt);
  87
  88
  89
  90/* .... Generic GPIO interface .............................................. */
  91
  92/*
  93 * Configure the GPIO line as an input.
  94 */
  95int __init_or_module gpio_direction_input(unsigned int pin)
  96{
  97        unsigned long x, flags;
  98
  99        if (pin > KS8695_GPIO_15)
 100                return -EINVAL;
 101
 102        /* set pin to GPIO mode */
 103        ks8695_gpio_mode(pin, 1);
 104
 105        local_irq_save(flags);
 106
 107        /* set pin as input */
 108        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
 109        x &= ~IOPM_(pin);
 110        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
 111
 112        local_irq_restore(flags);
 113
 114        return 0;
 115}
 116EXPORT_SYMBOL(gpio_direction_input);
 117
 118
 119/*
 120 * Configure the GPIO line as an output, with default state.
 121 */
 122int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
 123{
 124        unsigned long x, flags;
 125
 126        if (pin > KS8695_GPIO_15)
 127                return -EINVAL;
 128
 129        /* set pin to GPIO mode */
 130        ks8695_gpio_mode(pin, 1);
 131
 132        local_irq_save(flags);
 133
 134        /* set line state */
 135        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 136        if (state)
 137                x |= (1 << pin);
 138        else
 139                x &= ~(1 << pin);
 140        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
 141
 142        /* set pin as output */
 143        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
 144        x |= IOPM_(pin);
 145        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
 146
 147        local_irq_restore(flags);
 148
 149        return 0;
 150}
 151EXPORT_SYMBOL(gpio_direction_output);
 152
 153
 154/*
 155 * Set the state of an output GPIO line.
 156 */
 157void gpio_set_value(unsigned int pin, unsigned int state)
 158{
 159        unsigned long x, flags;
 160
 161        if (pin > KS8695_GPIO_15)
 162                return;
 163
 164        local_irq_save(flags);
 165
 166        /* set output line state */
 167        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 168        if (state)
 169                x |= (1 << pin);
 170        else
 171                x &= ~(1 << pin);
 172        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
 173
 174        local_irq_restore(flags);
 175}
 176EXPORT_SYMBOL(gpio_set_value);
 177
 178
 179/*
 180 * Read the state of a GPIO line.
 181 */
 182int gpio_get_value(unsigned int pin)
 183{
 184        unsigned long x;
 185
 186        if (pin > KS8695_GPIO_15)
 187                return -EINVAL;
 188
 189        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 190        return (x & (1 << pin)) != 0;
 191}
 192EXPORT_SYMBOL(gpio_get_value);
 193
 194
 195/*
 196 * Map GPIO line to IRQ number.
 197 */
 198int gpio_to_irq(unsigned int pin)
 199{
 200        if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
 201                return -EINVAL;
 202
 203        return gpio_irq[pin];
 204}
 205EXPORT_SYMBOL(gpio_to_irq);
 206
 207
 208/*
 209 * Map IRQ number to GPIO line.
 210 */
 211int irq_to_gpio(unsigned int irq)
 212{
 213        if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
 214                return -EINVAL;
 215
 216        return (irq - KS8695_IRQ_EXTERN0);
 217}
 218EXPORT_SYMBOL(irq_to_gpio);
 219