linux/arch/arm/mach-gemini/gpio.c
<<
>>
Prefs
   1/*
   2 * Gemini gpiochip and interrupt routines
   3 *
   4 * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
   5 *
   6 * Based on plat-mxc/gpio.c:
   7 *  MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
   8 *  Copyright 2008 Juergen Beisert, kernel@pengutronix.de
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/init.h>
  18#include <linux/io.h>
  19#include <linux/irq.h>
  20#include <linux/gpio.h>
  21
  22#include <mach/hardware.h>
  23#include <mach/irqs.h>
  24#include <mach/gpio.h>
  25
  26#define GPIO_BASE(x)            IO_ADDRESS(GEMINI_GPIO_BASE(x))
  27
  28/* GPIO registers definition */
  29#define GPIO_DATA_OUT           0x0
  30#define GPIO_DATA_IN            0x4
  31#define GPIO_DIR                0x8
  32#define GPIO_DATA_SET           0x10
  33#define GPIO_DATA_CLR           0x14
  34#define GPIO_PULL_EN            0x18
  35#define GPIO_PULL_TYPE          0x1C
  36#define GPIO_INT_EN             0x20
  37#define GPIO_INT_STAT           0x24
  38#define GPIO_INT_MASK           0x2C
  39#define GPIO_INT_CLR            0x30
  40#define GPIO_INT_TYPE           0x34
  41#define GPIO_INT_BOTH_EDGE      0x38
  42#define GPIO_INT_LEVEL          0x3C
  43#define GPIO_DEBOUNCE_EN        0x40
  44#define GPIO_DEBOUNCE_PRESCALE  0x44
  45
  46#define GPIO_PORT_NUM           3
  47
  48static void _set_gpio_irqenable(void __iomem *base, unsigned int index,
  49                                int enable)
  50{
  51        unsigned int reg;
  52
  53        reg = __raw_readl(base + GPIO_INT_EN);
  54        reg = (reg & (~(1 << index))) | (!!enable << index);
  55        __raw_writel(reg, base + GPIO_INT_EN);
  56}
  57
  58static void gpio_ack_irq(struct irq_data *d)
  59{
  60        unsigned int gpio = irq_to_gpio(d->irq);
  61        void __iomem *base = GPIO_BASE(gpio / 32);
  62
  63        __raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
  64}
  65
  66static void gpio_mask_irq(struct irq_data *d)
  67{
  68        unsigned int gpio = irq_to_gpio(d->irq);
  69        void __iomem *base = GPIO_BASE(gpio / 32);
  70
  71        _set_gpio_irqenable(base, gpio % 32, 0);
  72}
  73
  74static void gpio_unmask_irq(struct irq_data *d)
  75{
  76        unsigned int gpio = irq_to_gpio(d->irq);
  77        void __iomem *base = GPIO_BASE(gpio / 32);
  78
  79        _set_gpio_irqenable(base, gpio % 32, 1);
  80}
  81
  82static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
  83{
  84        unsigned int gpio = irq_to_gpio(d->irq);
  85        unsigned int gpio_mask = 1 << (gpio % 32);
  86        void __iomem *base = GPIO_BASE(gpio / 32);
  87        unsigned int reg_both, reg_level, reg_type;
  88
  89        reg_type = __raw_readl(base + GPIO_INT_TYPE);
  90        reg_level = __raw_readl(base + GPIO_INT_LEVEL);
  91        reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
  92
  93        switch (type) {
  94        case IRQ_TYPE_EDGE_BOTH:
  95                reg_type &= ~gpio_mask;
  96                reg_both |= gpio_mask;
  97                break;
  98        case IRQ_TYPE_EDGE_RISING:
  99                reg_type &= ~gpio_mask;
 100                reg_both &= ~gpio_mask;
 101                reg_level &= ~gpio_mask;
 102                break;
 103        case IRQ_TYPE_EDGE_FALLING:
 104                reg_type &= ~gpio_mask;
 105                reg_both &= ~gpio_mask;
 106                reg_level |= gpio_mask;
 107                break;
 108        case IRQ_TYPE_LEVEL_HIGH:
 109                reg_type |= gpio_mask;
 110                reg_level &= ~gpio_mask;
 111                break;
 112        case IRQ_TYPE_LEVEL_LOW:
 113                reg_type |= gpio_mask;
 114                reg_level |= gpio_mask;
 115                break;
 116        default:
 117                return -EINVAL;
 118        }
 119
 120        __raw_writel(reg_type, base + GPIO_INT_TYPE);
 121        __raw_writel(reg_level, base + GPIO_INT_LEVEL);
 122        __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
 123
 124        gpio_ack_irq(d);
 125
 126        return 0;
 127}
 128
 129static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 130{
 131        unsigned int port = (unsigned int)irq_desc_get_handler_data(desc);
 132        unsigned int gpio_irq_no, irq_stat;
 133
 134        irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT);
 135
 136        gpio_irq_no = GPIO_IRQ_BASE + port * 32;
 137        for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
 138
 139                if ((irq_stat & 1) == 0)
 140                        continue;
 141
 142                generic_handle_irq(gpio_irq_no);
 143        }
 144}
 145
 146static struct irq_chip gpio_irq_chip = {
 147        .name = "GPIO",
 148        .irq_ack = gpio_ack_irq,
 149        .irq_mask = gpio_mask_irq,
 150        .irq_unmask = gpio_unmask_irq,
 151        .irq_set_type = gpio_set_irq_type,
 152};
 153
 154static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
 155                                int dir)
 156{
 157        void __iomem *base = GPIO_BASE(offset / 32);
 158        unsigned int reg;
 159
 160        reg = __raw_readl(base + GPIO_DIR);
 161        if (dir)
 162                reg |= 1 << (offset % 32);
 163        else
 164                reg &= ~(1 << (offset % 32));
 165        __raw_writel(reg, base + GPIO_DIR);
 166}
 167
 168static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 169{
 170        void __iomem *base = GPIO_BASE(offset / 32);
 171
 172        if (value)
 173                __raw_writel(1 << (offset % 32), base + GPIO_DATA_SET);
 174        else
 175                __raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR);
 176}
 177
 178static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset)
 179{
 180        void __iomem *base = GPIO_BASE(offset / 32);
 181
 182        return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1;
 183}
 184
 185static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 186{
 187        _set_gpio_direction(chip, offset, 0);
 188        return 0;
 189}
 190
 191static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 192                                        int value)
 193{
 194        _set_gpio_direction(chip, offset, 1);
 195        gemini_gpio_set(chip, offset, value);
 196        return 0;
 197}
 198
 199static struct gpio_chip gemini_gpio_chip = {
 200        .label                  = "Gemini",
 201        .direction_input        = gemini_gpio_direction_input,
 202        .get                    = gemini_gpio_get,
 203        .direction_output       = gemini_gpio_direction_output,
 204        .set                    = gemini_gpio_set,
 205        .base                   = 0,
 206        .ngpio                  = GPIO_PORT_NUM * 32,
 207};
 208
 209void __init gemini_gpio_init(void)
 210{
 211        int i, j;
 212
 213        for (i = 0; i < GPIO_PORT_NUM; i++) {
 214                /* disable, unmask and clear all interrupts */
 215                __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN);
 216                __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK);
 217                __raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR);
 218
 219                for (j = GPIO_IRQ_BASE + i * 32;
 220                     j < GPIO_IRQ_BASE + (i + 1) * 32; j++) {
 221                        irq_set_chip_and_handler(j, &gpio_irq_chip,
 222                                                 handle_edge_irq);
 223                        set_irq_flags(j, IRQF_VALID);
 224                }
 225
 226                irq_set_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
 227                irq_set_handler_data(IRQ_GPIO(i), (void *)i);
 228        }
 229
 230        BUG_ON(gpiochip_add(&gemini_gpio_chip));
 231}
 232