linux/arch/arm/mach-w90x900/gpio.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-w90x900/gpio.c
   3 *
   4 * Generic nuc900 GPIO handling
   5 *
   6 *  Wan ZongShun <mcuos.com@gmail.com>
   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
  13#include <linux/clk.h>
  14#include <linux/errno.h>
  15#include <linux/interrupt.h>
  16#include <linux/irq.h>
  17#include <linux/debugfs.h>
  18#include <linux/seq_file.h>
  19#include <linux/kernel.h>
  20#include <linux/list.h>
  21#include <linux/module.h>
  22#include <linux/io.h>
  23#include <linux/gpio.h>
  24
  25#include <mach/hardware.h>
  26
  27#define GPIO_BASE               (W90X900_VA_GPIO)
  28#define GPIO_DIR                (0x04)
  29#define GPIO_OUT                (0x08)
  30#define GPIO_IN                 (0x0C)
  31#define GROUPINERV              (0x10)
  32#define GPIO_GPIO(Nb)           (0x00000001 << (Nb))
  33#define to_nuc900_gpio_chip(c) container_of(c, struct nuc900_gpio_chip, chip)
  34
  35#define NUC900_GPIO_CHIP(name, base_gpio, nr_gpio)                      \
  36        {                                                               \
  37                .chip = {                                               \
  38                        .label            = name,                       \
  39                        .direction_input  = nuc900_dir_input,           \
  40                        .direction_output = nuc900_dir_output,          \
  41                        .get              = nuc900_gpio_get,            \
  42                        .set              = nuc900_gpio_set,            \
  43                        .base             = base_gpio,                  \
  44                        .ngpio            = nr_gpio,                    \
  45                }                                                       \
  46        }
  47
  48struct nuc900_gpio_chip {
  49        struct gpio_chip        chip;
  50        void __iomem            *regbase;       /* Base of group register*/
  51        spinlock_t              gpio_lock;
  52};
  53
  54static int nuc900_gpio_get(struct gpio_chip *chip, unsigned offset)
  55{
  56        struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
  57        void __iomem *pio = nuc900_gpio->regbase + GPIO_IN;
  58        unsigned int regval;
  59
  60        regval = __raw_readl(pio);
  61        regval &= GPIO_GPIO(offset);
  62
  63        return (regval != 0);
  64}
  65
  66static void nuc900_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
  67{
  68        struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
  69        void __iomem *pio = nuc900_gpio->regbase + GPIO_OUT;
  70        unsigned int regval;
  71        unsigned long flags;
  72
  73        spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
  74
  75        regval = __raw_readl(pio);
  76
  77        if (val)
  78                regval |= GPIO_GPIO(offset);
  79        else
  80                regval &= ~GPIO_GPIO(offset);
  81
  82        __raw_writel(regval, pio);
  83
  84        spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
  85}
  86
  87static int nuc900_dir_input(struct gpio_chip *chip, unsigned offset)
  88{
  89        struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
  90        void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
  91        unsigned int regval;
  92        unsigned long flags;
  93
  94        spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
  95
  96        regval = __raw_readl(pio);
  97        regval &= ~GPIO_GPIO(offset);
  98        __raw_writel(regval, pio);
  99
 100        spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
 101
 102        return 0;
 103}
 104
 105static int nuc900_dir_output(struct gpio_chip *chip, unsigned offset, int val)
 106{
 107        struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip);
 108        void __iomem *outreg = nuc900_gpio->regbase + GPIO_OUT;
 109        void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
 110        unsigned int regval;
 111        unsigned long flags;
 112
 113        spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
 114
 115        regval = __raw_readl(pio);
 116        regval |= GPIO_GPIO(offset);
 117        __raw_writel(regval, pio);
 118
 119        regval = __raw_readl(outreg);
 120
 121        if (val)
 122                regval |= GPIO_GPIO(offset);
 123        else
 124                regval &= ~GPIO_GPIO(offset);
 125
 126        __raw_writel(regval, outreg);
 127
 128        spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
 129
 130        return 0;
 131}
 132
 133static struct nuc900_gpio_chip nuc900_gpio[] = {
 134        NUC900_GPIO_CHIP("GROUPC", 0, 16),
 135        NUC900_GPIO_CHIP("GROUPD", 16, 10),
 136        NUC900_GPIO_CHIP("GROUPE", 26, 14),
 137        NUC900_GPIO_CHIP("GROUPF", 40, 10),
 138        NUC900_GPIO_CHIP("GROUPG", 50, 17),
 139        NUC900_GPIO_CHIP("GROUPH", 67, 8),
 140        NUC900_GPIO_CHIP("GROUPI", 75, 17),
 141};
 142
 143void __init nuc900_init_gpio(int nr_group)
 144{
 145        unsigned        i;
 146        struct nuc900_gpio_chip *gpio_chip;
 147
 148        for (i = 0; i < nr_group; i++) {
 149                gpio_chip = &nuc900_gpio[i];
 150                spin_lock_init(&gpio_chip->gpio_lock);
 151                gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
 152                gpiochip_add(&gpio_chip->chip);
 153        }
 154}
 155