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