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.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/*
 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
 220/* GPIOLIB interface */
 221
 222static struct gpio_chip ks8695_gpio_chip = {
 223        .label                  = "KS8695",
 224        .direction_input        = ks8695_gpio_direction_input,
 225        .direction_output       = ks8695_gpio_direction_output,
 226        .get                    = ks8695_gpio_get_value,
 227        .set                    = ks8695_gpio_set_value,
 228        .to_irq                 = ks8695_gpio_to_irq,
 229        .base                   = 0,
 230        .ngpio                  = 16,
 231        .can_sleep              = 0,
 232};
 233
 234/* Register the GPIOs */
 235void ks8695_register_gpios(void)
 236{
 237        if (gpiochip_add(&ks8695_gpio_chip))
 238                printk(KERN_ERR "Unable to register core GPIOs\n");
 239}
 240
 241/* .... Debug interface ..................................................... */
 242
 243#ifdef CONFIG_DEBUG_FS
 244
 245static int ks8695_gpio_show(struct seq_file *s, void *unused)
 246{
 247        unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
 248        unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
 249        unsigned long mode, ctrl, data;
 250        int i;
 251
 252        mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
 253        ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
 254        data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
 255
 256        seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
 257
 258        for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
 259                seq_printf(s, "%i:\t", i);
 260
 261                seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
 262
 263                if (i <= KS8695_GPIO_3) {
 264                        if (ctrl & enable[i]) {
 265                                seq_printf(s, "EXT%i ", i);
 266
 267                                switch ((ctrl & intmask[i]) >> (4 * i)) {
 268                                        case IOPC_TM_LOW:
 269                                                seq_printf(s, "(Low)");         break;
 270                                        case IOPC_TM_HIGH:
 271                                                seq_printf(s, "(High)");        break;
 272                                        case IOPC_TM_RISING:
 273                                                seq_printf(s, "(Rising)");      break;
 274                                        case IOPC_TM_FALLING:
 275                                                seq_printf(s, "(Falling)");     break;
 276                                        case IOPC_TM_EDGE:
 277                                                seq_printf(s, "(Edges)");       break;
 278                                }
 279                        }
 280                        else
 281                                seq_printf(s, "GPIO\t");
 282                }
 283                else if (i <= KS8695_GPIO_5) {
 284                        if (ctrl & enable[i])
 285                                seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
 286                        else
 287                                seq_printf(s, "GPIO\t");
 288                }
 289                else
 290                        seq_printf(s, "GPIO\t");
 291
 292                seq_printf(s, "\t");
 293
 294                seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
 295        }
 296        return 0;
 297}
 298
 299static int ks8695_gpio_open(struct inode *inode, struct file *file)
 300{
 301        return single_open(file, ks8695_gpio_show, NULL);
 302}
 303
 304static const struct file_operations ks8695_gpio_operations = {
 305        .open           = ks8695_gpio_open,
 306        .read           = seq_read,
 307        .llseek         = seq_lseek,
 308        .release        = single_release,
 309};
 310
 311static int __init ks8695_gpio_debugfs_init(void)
 312{
 313        /* /sys/kernel/debug/ks8695_gpio */
 314        (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
 315        return 0;
 316}
 317postcore_initcall(ks8695_gpio_debugfs_init);
 318
 319#endif
 320
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.