linux/drivers/gpio/gpio-ks8695.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-ks8695/gpio.c
   3 *
   4 * Copyright (C) 2006 Andrew Victor
   5 * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
   6 *                     Daniel Silverstone <dsilvers@simtec.co.uk>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21#include <linux/gpio/driver.h>
  22#include <linux/kernel.h>
  23#include <linux/mm.h>
  24#include <linux/init.h>
  25#include <linux/debugfs.h>
  26#include <linux/seq_file.h>
  27#include <linux/module.h>
  28#include <linux/io.h>
  29
  30#include <mach/hardware.h>
  31#include <asm/mach/irq.h>
  32
  33#include <mach/regs-gpio.h>
  34#include <mach/gpio-ks8695.h>
  35
  36/*
  37 * Configure a GPIO line for either GPIO function, or its internal
  38 * function (Interrupt, Timer, etc).
  39 */
  40static void ks8695_gpio_mode(unsigned int pin, short gpio)
  41{
  42        unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
  43        unsigned long x, flags;
  44
  45        if (pin > KS8695_GPIO_5)        /* only GPIO 0..5 have internal functions */
  46                return;
  47
  48        local_irq_save(flags);
  49
  50        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
  51        if (gpio)                       /* GPIO: set bit to 0 */
  52                x &= ~enable[pin];
  53        else                            /* Internal function: set bit to 1 */
  54                x |= enable[pin];
  55        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
  56
  57        local_irq_restore(flags);
  58}
  59
  60
  61static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
  62
  63/*
  64 * Configure GPIO pin as external interrupt source.
  65 */
  66int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
  67{
  68        unsigned long x, flags;
  69
  70        if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
  71                return -EINVAL;
  72
  73        local_irq_save(flags);
  74
  75        /* set pin as input */
  76        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
  77        x &= ~IOPM(pin);
  78        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
  79
  80        local_irq_restore(flags);
  81
  82        /* Set IRQ triggering type */
  83        irq_set_irq_type(gpio_irq[pin], type);
  84
  85        /* enable interrupt mode */
  86        ks8695_gpio_mode(pin, 0);
  87
  88        return 0;
  89}
  90EXPORT_SYMBOL(ks8695_gpio_interrupt);
  91
  92
  93
  94/* .... Generic GPIO interface .............................................. */
  95
  96/*
  97 * Configure the GPIO line as an input.
  98 */
  99static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
 100{
 101        unsigned long x, flags;
 102
 103        if (pin > KS8695_GPIO_15)
 104                return -EINVAL;
 105
 106        /* set pin to GPIO mode */
 107        ks8695_gpio_mode(pin, 1);
 108
 109        local_irq_save(flags);
 110
 111        /* set pin as input */
 112        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
 113        x &= ~IOPM(pin);
 114        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
 115
 116        local_irq_restore(flags);
 117
 118        return 0;
 119}
 120
 121
 122/*
 123 * Configure the GPIO line as an output, with default state.
 124 */
 125static int ks8695_gpio_direction_output(struct gpio_chip *gc,
 126                                        unsigned int pin, int state)
 127{
 128        unsigned long x, flags;
 129
 130        if (pin > KS8695_GPIO_15)
 131                return -EINVAL;
 132
 133        /* set pin to GPIO mode */
 134        ks8695_gpio_mode(pin, 1);
 135
 136        local_irq_save(flags);
 137
 138        /* set line state */
 139        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 140        if (state)
 141                x |= IOPD(pin);
 142        else
 143                x &= ~IOPD(pin);
 144        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
 145
 146        /* set pin as output */
 147        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
 148        x |= IOPM(pin);
 149        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
 150
 151        local_irq_restore(flags);
 152
 153        return 0;
 154}
 155
 156
 157/*
 158 * Set the state of an output GPIO line.
 159 */
 160static void ks8695_gpio_set_value(struct gpio_chip *gc,
 161                                  unsigned int pin, int state)
 162{
 163        unsigned long x, flags;
 164
 165        if (pin > KS8695_GPIO_15)
 166                return;
 167
 168        local_irq_save(flags);
 169
 170        /* set output line state */
 171        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 172        if (state)
 173                x |= IOPD(pin);
 174        else
 175                x &= ~IOPD(pin);
 176        __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
 177
 178        local_irq_restore(flags);
 179}
 180
 181
 182/*
 183 * Read the state of a GPIO line.
 184 */
 185static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
 186{
 187        unsigned long x;
 188
 189        if (pin > KS8695_GPIO_15)
 190                return -EINVAL;
 191
 192        x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 193        return (x & IOPD(pin)) != 0;
 194}
 195
 196
 197/*
 198 * Map GPIO line to IRQ number.
 199 */
 200static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
 201{
 202        if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
 203                return -EINVAL;
 204
 205        return gpio_irq[pin];
 206}
 207
 208/* GPIOLIB interface */
 209
 210static struct gpio_chip ks8695_gpio_chip = {
 211        .label                  = "KS8695",
 212        .direction_input        = ks8695_gpio_direction_input,
 213        .direction_output       = ks8695_gpio_direction_output,
 214        .get                    = ks8695_gpio_get_value,
 215        .set                    = ks8695_gpio_set_value,
 216        .to_irq                 = ks8695_gpio_to_irq,
 217        .base                   = 0,
 218        .ngpio                  = 16,
 219        .can_sleep              = false,
 220};
 221
 222/* Register the GPIOs */
 223void ks8695_register_gpios(void)
 224{
 225        if (gpiochip_add_data(&ks8695_gpio_chip, NULL))
 226                printk(KERN_ERR "Unable to register core GPIOs\n");
 227}
 228
 229/* .... Debug interface ..................................................... */
 230
 231#ifdef CONFIG_DEBUG_FS
 232
 233static int ks8695_gpio_show(struct seq_file *s, void *unused)
 234{
 235        unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
 236        unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
 237        unsigned long mode, ctrl, data;
 238        int i;
 239
 240        mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
 241        ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
 242        data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 243
 244        seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
 245
 246        for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
 247                seq_printf(s, "%i:\t", i);
 248
 249                seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
 250
 251                if (i <= KS8695_GPIO_3) {
 252                        if (ctrl & enable[i]) {
 253                                seq_printf(s, "EXT%i ", i);
 254
 255                                switch ((ctrl & intmask[i]) >> (4 * i)) {
 256                                case IOPC_TM_LOW:
 257                                        seq_printf(s, "(Low)");         break;
 258                                case IOPC_TM_HIGH:
 259                                        seq_printf(s, "(High)");        break;
 260                                case IOPC_TM_RISING:
 261                                        seq_printf(s, "(Rising)");      break;
 262                                case IOPC_TM_FALLING:
 263                                        seq_printf(s, "(Falling)");     break;
 264                                case IOPC_TM_EDGE:
 265                                        seq_printf(s, "(Edges)");       break;
 266                                }
 267                        } else
 268                                seq_printf(s, "GPIO\t");
 269                } else if (i <= KS8695_GPIO_5) {
 270                        if (ctrl & enable[i])
 271                                seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
 272                        else
 273                                seq_printf(s, "GPIO\t");
 274                } else {
 275                        seq_printf(s, "GPIO\t");
 276                }
 277
 278                seq_printf(s, "\t");
 279
 280                seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
 281        }
 282        return 0;
 283}
 284
 285static int ks8695_gpio_open(struct inode *inode, struct file *file)
 286{
 287        return single_open(file, ks8695_gpio_show, NULL);
 288}
 289
 290static const struct file_operations ks8695_gpio_operations = {
 291        .open           = ks8695_gpio_open,
 292        .read           = seq_read,
 293        .llseek         = seq_lseek,
 294        .release        = single_release,
 295};
 296
 297static int __init ks8695_gpio_debugfs_init(void)
 298{
 299        /* /sys/kernel/debug/ks8695_gpio */
 300        (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
 301        return 0;
 302}
 303postcore_initcall(ks8695_gpio_debugfs_init);
 304
 305#endif
 306