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/driver.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
  34#define NUC900_GPIO_CHIP(name, base_gpio, nr_gpio)                      \
  35        {                                                               \
  36                .chip = {                                               \
  37                        .label            = name,                       \
  38                        .direction_input  = nuc900_dir_input,           \
  39                        .direction_output = nuc900_dir_output,          \
  40                        .get              = nuc900_gpio_get,            \
  41                        .set              = nuc900_gpio_set,            \
  42                        .base             = base_gpio,                  \
  43                        .ngpio            = nr_gpio,                    \
  44                }                                                       \
  45        }
  46
  47struct nuc900_gpio_chip {
  48        struct gpio_chip        chip;
  49        void __iomem            *regbase;       /* Base of group register*/
  50        spinlock_t              gpio_lock;
  51};
  52
  53static int nuc900_gpio_get(struct gpio_chip *chip, unsigned offset)
  54{
  55        struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
  56        void __iomem *pio = nuc900_gpio->regbase + GPIO_IN;
  57        unsigned int regval;
  58
  59        regval = __raw_readl(pio);
  60        regval &= GPIO_GPIO(offset);
  61
  62        return (regval != 0);
  63}
  64
  65static void nuc900_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
  66{
  67        struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
  68        void __iomem *pio = nuc900_gpio->regbase + GPIO_OUT;
  69        unsigned int regval;
  70        unsigned long flags;
  71
  72        spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
  73
  74        regval = __raw_readl(pio);
  75
  76        if (val)
  77                regval |= GPIO_GPIO(offset);
  78        else
  79                regval &= ~GPIO_GPIO(offset);
  80
  81        __raw_writel(regval, pio);
  82
  83        spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
  84}
  85
  86static int nuc900_dir_input(struct gpio_chip *chip, unsigned offset)
  87{
  88        struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
  89        void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
  90        unsigned int regval;
  91        unsigned long flags;
  92
  93        spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
  94
  95        regval = __raw_readl(pio);
  96        regval &= ~GPIO_GPIO(offset);
  97        __raw_writel(regval, pio);
  98
  99        spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
 100
 101        return 0;
 102}
 103
 104static int nuc900_dir_output(struct gpio_chip *chip, unsigned offset, int val)
 105{
 106        struct nuc900_gpio_chip *nuc900_gpio = gpiochip_get_data(chip);
 107        void __iomem *outreg = nuc900_gpio->regbase + GPIO_OUT;
 108        void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR;
 109        unsigned int regval;
 110        unsigned long flags;
 111
 112        spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags);
 113
 114        regval = __raw_readl(pio);
 115        regval |= GPIO_GPIO(offset);
 116        __raw_writel(regval, pio);
 117
 118        regval = __raw_readl(outreg);
 119
 120        if (val)
 121                regval |= GPIO_GPIO(offset);
 122        else
 123                regval &= ~GPIO_GPIO(offset);
 124
 125        __raw_writel(regval, outreg);
 126
 127        spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags);
 128
 129        return 0;
 130}
 131
 132static struct nuc900_gpio_chip nuc900_gpio[] = {
 133        NUC900_GPIO_CHIP("GROUPC", 0, 16),
 134        NUC900_GPIO_CHIP("GROUPD", 16, 10),
 135        NUC900_GPIO_CHIP("GROUPE", 26, 14),
 136        NUC900_GPIO_CHIP("GROUPF", 40, 10),
 137        NUC900_GPIO_CHIP("GROUPG", 50, 17),
 138        NUC900_GPIO_CHIP("GROUPH", 67, 8),
 139        NUC900_GPIO_CHIP("GROUPI", 75, 17),
 140};
 141
 142void __init nuc900_init_gpio(int nr_group)
 143{
 144        unsigned        i;
 145        struct nuc900_gpio_chip *gpio_chip;
 146
 147        for (i = 0; i < nr_group; i++) {
 148                gpio_chip = &nuc900_gpio[i];
 149                spin_lock_init(&gpio_chip->gpio_lock);
 150                gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
 151                gpiochip_add_data(&gpio_chip->chip, gpio_chip);
 152        }
 153}
 154