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