Path: blob/master/arch/arm/mach-davinci/gpio-tnetv107x.c
10699 views
/*1* Texas Instruments TNETV107X GPIO Controller2*3* Copyright (C) 2010 Texas Instruments4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public License as7* published by the Free Software Foundation version 2.8*9* This program is distributed "as is" WITHOUT ANY WARRANTY of any10* kind, whether express or implied; without even the implied warranty11* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*/14#include <linux/kernel.h>15#include <linux/init.h>16#include <linux/gpio.h>1718#include <mach/common.h>19#include <mach/tnetv107x.h>2021struct tnetv107x_gpio_regs {22u32 idver;23u32 data_in[3];24u32 data_out[3];25u32 direction[3];26u32 enable[3];27};2829#define gpio_reg_index(gpio) ((gpio) >> 5)30#define gpio_reg_bit(gpio) BIT((gpio) & 0x1f)3132#define gpio_reg_rmw(reg, mask, val) \33__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))3435#define gpio_reg_set_bit(reg, gpio) \36gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))3738#define gpio_reg_clear_bit(reg, gpio) \39gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)4041#define gpio_reg_get_bit(reg, gpio) \42(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))4344#define chip2controller(chip) \45container_of(chip, struct davinci_gpio_controller, chip)4647#define TNETV107X_GPIO_CTLRS DIV_ROUND_UP(TNETV107X_N_GPIO, 32)4849static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];5051static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)52{53struct davinci_gpio_controller *ctlr = chip2controller(chip);54struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;55unsigned gpio = chip->base + offset;56unsigned long flags;5758spin_lock_irqsave(&ctlr->lock, flags);5960gpio_reg_set_bit(regs->enable, gpio);6162spin_unlock_irqrestore(&ctlr->lock, flags);6364return 0;65}6667static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)68{69struct davinci_gpio_controller *ctlr = chip2controller(chip);70struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;71unsigned gpio = chip->base + offset;72unsigned long flags;7374spin_lock_irqsave(&ctlr->lock, flags);7576gpio_reg_clear_bit(regs->enable, gpio);7778spin_unlock_irqrestore(&ctlr->lock, flags);79}8081static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)82{83struct davinci_gpio_controller *ctlr = chip2controller(chip);84struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;85unsigned gpio = chip->base + offset;86unsigned long flags;8788spin_lock_irqsave(&ctlr->lock, flags);8990gpio_reg_set_bit(regs->direction, gpio);9192spin_unlock_irqrestore(&ctlr->lock, flags);9394return 0;95}9697static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,98unsigned offset, int value)99{100struct davinci_gpio_controller *ctlr = chip2controller(chip);101struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;102unsigned gpio = chip->base + offset;103unsigned long flags;104105spin_lock_irqsave(&ctlr->lock, flags);106107if (value)108gpio_reg_set_bit(regs->data_out, gpio);109else110gpio_reg_clear_bit(regs->data_out, gpio);111112gpio_reg_clear_bit(regs->direction, gpio);113114spin_unlock_irqrestore(&ctlr->lock, flags);115116return 0;117}118119static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)120{121struct davinci_gpio_controller *ctlr = chip2controller(chip);122struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;123unsigned gpio = chip->base + offset;124int ret;125126ret = gpio_reg_get_bit(regs->data_in, gpio);127128return ret ? 1 : 0;129}130131static void tnetv107x_gpio_set(struct gpio_chip *chip,132unsigned offset, int value)133{134struct davinci_gpio_controller *ctlr = chip2controller(chip);135struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;136unsigned gpio = chip->base + offset;137unsigned long flags;138139spin_lock_irqsave(&ctlr->lock, flags);140141if (value)142gpio_reg_set_bit(regs->data_out, gpio);143else144gpio_reg_clear_bit(regs->data_out, gpio);145146spin_unlock_irqrestore(&ctlr->lock, flags);147}148149static int __init tnetv107x_gpio_setup(void)150{151int i, base;152unsigned ngpio;153struct davinci_soc_info *soc_info = &davinci_soc_info;154struct tnetv107x_gpio_regs *regs;155struct davinci_gpio_controller *ctlr;156157if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)158return 0;159160ngpio = soc_info->gpio_num;161if (ngpio == 0) {162pr_err("GPIO setup: how many GPIOs?\n");163return -EINVAL;164}165166if (WARN_ON(TNETV107X_N_GPIO < ngpio))167ngpio = TNETV107X_N_GPIO;168169regs = ioremap(soc_info->gpio_base, SZ_4K);170if (WARN_ON(!regs))171return -EINVAL;172173for (i = 0, base = 0; base < ngpio; i++, base += 32) {174ctlr = &chips[i];175176ctlr->chip.label = "tnetv107x";177ctlr->chip.can_sleep = 0;178ctlr->chip.base = base;179ctlr->chip.ngpio = ngpio - base;180if (ctlr->chip.ngpio > 32)181ctlr->chip.ngpio = 32;182183ctlr->chip.request = tnetv107x_gpio_request;184ctlr->chip.free = tnetv107x_gpio_free;185ctlr->chip.direction_input = tnetv107x_gpio_dir_in;186ctlr->chip.get = tnetv107x_gpio_get;187ctlr->chip.direction_output = tnetv107x_gpio_dir_out;188ctlr->chip.set = tnetv107x_gpio_set;189190spin_lock_init(&ctlr->lock);191192ctlr->regs = regs;193ctlr->set_data = ®s->data_out[i];194ctlr->clr_data = ®s->data_out[i];195ctlr->in_data = ®s->data_in[i];196197gpiochip_add(&ctlr->chip);198}199200soc_info->gpio_ctlrs = chips;201soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);202return 0;203}204pure_initcall(tnetv107x_gpio_setup);205206207