linux/drivers/gpio/gpio-tnetv107x.c
<<
>>
Prefs
   1/*
   2 * Texas Instruments TNETV107X GPIO Controller
   3 *
   4 * Copyright (C) 2010 Texas Instruments
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation version 2.
   9 *
  10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  11 * kind, whether express or implied; without even the implied warranty
  12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15#include <linux/kernel.h>
  16#include <linux/init.h>
  17#include <linux/gpio.h>
  18
  19#include <mach/common.h>
  20#include <mach/tnetv107x.h>
  21
  22struct tnetv107x_gpio_regs {
  23        u32     idver;
  24        u32     data_in[3];
  25        u32     data_out[3];
  26        u32     direction[3];
  27        u32     enable[3];
  28};
  29
  30#define gpio_reg_index(gpio)    ((gpio) >> 5)
  31#define gpio_reg_bit(gpio)      BIT((gpio) & 0x1f)
  32
  33#define gpio_reg_rmw(reg, mask, val)    \
  34        __raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
  35
  36#define gpio_reg_set_bit(reg, gpio)     \
  37        gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
  38
  39#define gpio_reg_clear_bit(reg, gpio)   \
  40        gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
  41
  42#define gpio_reg_get_bit(reg, gpio)     \
  43        (__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
  44
  45#define chip2controller(chip)           \
  46        container_of(chip, struct davinci_gpio_controller, chip)
  47
  48#define TNETV107X_GPIO_CTLRS    DIV_ROUND_UP(TNETV107X_N_GPIO, 32)
  49
  50static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];
  51
  52static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)
  53{
  54        struct davinci_gpio_controller *ctlr = chip2controller(chip);
  55        struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
  56        unsigned gpio = chip->base + offset;
  57        unsigned long flags;
  58
  59        spin_lock_irqsave(&ctlr->lock, flags);
  60
  61        gpio_reg_set_bit(regs->enable, gpio);
  62
  63        spin_unlock_irqrestore(&ctlr->lock, flags);
  64
  65        return 0;
  66}
  67
  68static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)
  69{
  70        struct davinci_gpio_controller *ctlr = chip2controller(chip);
  71        struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
  72        unsigned gpio = chip->base + offset;
  73        unsigned long flags;
  74
  75        spin_lock_irqsave(&ctlr->lock, flags);
  76
  77        gpio_reg_clear_bit(regs->enable, gpio);
  78
  79        spin_unlock_irqrestore(&ctlr->lock, flags);
  80}
  81
  82static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
  83{
  84        struct davinci_gpio_controller *ctlr = chip2controller(chip);
  85        struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
  86        unsigned gpio = chip->base + offset;
  87        unsigned long flags;
  88
  89        spin_lock_irqsave(&ctlr->lock, flags);
  90
  91        gpio_reg_set_bit(regs->direction, gpio);
  92
  93        spin_unlock_irqrestore(&ctlr->lock, flags);
  94
  95        return 0;
  96}
  97
  98static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
  99                unsigned offset, int value)
 100{
 101        struct davinci_gpio_controller *ctlr = chip2controller(chip);
 102        struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
 103        unsigned gpio = chip->base + offset;
 104        unsigned long flags;
 105
 106        spin_lock_irqsave(&ctlr->lock, flags);
 107
 108        if (value)
 109                gpio_reg_set_bit(regs->data_out, gpio);
 110        else
 111                gpio_reg_clear_bit(regs->data_out, gpio);
 112
 113        gpio_reg_clear_bit(regs->direction, gpio);
 114
 115        spin_unlock_irqrestore(&ctlr->lock, flags);
 116
 117        return 0;
 118}
 119
 120static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)
 121{
 122        struct davinci_gpio_controller *ctlr = chip2controller(chip);
 123        struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
 124        unsigned gpio = chip->base + offset;
 125        int ret;
 126
 127        ret = gpio_reg_get_bit(regs->data_in, gpio);
 128
 129        return ret ? 1 : 0;
 130}
 131
 132static void tnetv107x_gpio_set(struct gpio_chip *chip,
 133                unsigned offset, int value)
 134{
 135        struct davinci_gpio_controller *ctlr = chip2controller(chip);
 136        struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
 137        unsigned gpio = chip->base + offset;
 138        unsigned long flags;
 139
 140        spin_lock_irqsave(&ctlr->lock, flags);
 141
 142        if (value)
 143                gpio_reg_set_bit(regs->data_out, gpio);
 144        else
 145                gpio_reg_clear_bit(regs->data_out, gpio);
 146
 147        spin_unlock_irqrestore(&ctlr->lock, flags);
 148}
 149
 150static int __init tnetv107x_gpio_setup(void)
 151{
 152        int i, base;
 153        unsigned ngpio;
 154        struct davinci_soc_info *soc_info = &davinci_soc_info;
 155        struct tnetv107x_gpio_regs *regs;
 156        struct davinci_gpio_controller *ctlr;
 157
 158        if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)
 159                return 0;
 160
 161        ngpio = soc_info->gpio_num;
 162        if (ngpio == 0) {
 163                pr_err("GPIO setup:  how many GPIOs?\n");
 164                return -EINVAL;
 165        }
 166
 167        if (WARN_ON(TNETV107X_N_GPIO < ngpio))
 168                ngpio = TNETV107X_N_GPIO;
 169
 170        regs = ioremap(soc_info->gpio_base, SZ_4K);
 171        if (WARN_ON(!regs))
 172                return -EINVAL;
 173
 174        for (i = 0, base = 0; base < ngpio; i++, base += 32) {
 175                ctlr = &chips[i];
 176
 177                ctlr->chip.label        = "tnetv107x";
 178                ctlr->chip.can_sleep    = 0;
 179                ctlr->chip.base         = base;
 180                ctlr->chip.ngpio        = ngpio - base;
 181                if (ctlr->chip.ngpio > 32)
 182                        ctlr->chip.ngpio = 32;
 183
 184                ctlr->chip.request              = tnetv107x_gpio_request;
 185                ctlr->chip.free                 = tnetv107x_gpio_free;
 186                ctlr->chip.direction_input      = tnetv107x_gpio_dir_in;
 187                ctlr->chip.get                  = tnetv107x_gpio_get;
 188                ctlr->chip.direction_output     = tnetv107x_gpio_dir_out;
 189                ctlr->chip.set                  = tnetv107x_gpio_set;
 190
 191                spin_lock_init(&ctlr->lock);
 192
 193                ctlr->regs      = regs;
 194                ctlr->set_data  = &regs->data_out[i];
 195                ctlr->clr_data  = &regs->data_out[i];
 196                ctlr->in_data   = &regs->data_in[i];
 197
 198                gpiochip_add(&ctlr->chip);
 199        }
 200
 201        soc_info->gpio_ctlrs = chips;
 202        soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
 203        return 0;
 204}
 205pure_initcall(tnetv107x_gpio_setup);
 206
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.