1/* arch/arm/mach-msm/generic_gpio.c 2 * 3 * Copyright (C) 2007 Google, Inc. 4 * 5 * This software is licensed under the terms of the GNU General Public 6 * License version 2, as published by the Free Software Foundation, and 7 * may be copied, distributed, and modified under those terms. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/errno.h> 19#include <linux/slab.h> 20#include <linux/spinlock.h> 21#include <asm/gpio.h> 22#include "gpio_chip.h" 23 24#define GPIO_NUM_TO_CHIP_INDEX(gpio) ((gpio)>>5) 25 26struct gpio_state { 27 unsigned long flags; 28 int refcount; 29}; 30 31static DEFINE_SPINLOCK(gpio_chips_lock); 32static LIST_HEAD(gpio_chip_list); 33static struct gpio_chip **gpio_chip_array; 34static unsigned long gpio_chip_array_size; 35 36int register_gpio_chip(struct gpio_chip *new_gpio_chip) 37{ 38 int err = 0; 39 struct gpio_chip *gpio_chip; 40 int i; 41 unsigned long irq_flags; 42 unsigned int chip_array_start_index, chip_array_end_index; 43 44 new_gpio_chip->state = kzalloc((new_gpio_chip->end + 1 - new_gpio_chip->start) * sizeof(new_gpio_chip->state[0]), GFP_KERNEL); 45 if (new_gpio_chip->state == NULL) { 46 printk(KERN_ERR "register_gpio_chip: failed to allocate state\n"); 47 return -ENOMEM; 48 } 49 50 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 51 chip_array_start_index = GPIO_NUM_TO_CHIP_INDEX(new_gpio_chip->start); 52 chip_array_end_index = GPIO_NUM_TO_CHIP_INDEX(new_gpio_chip->end); 53 if (chip_array_end_index >= gpio_chip_array_size) { 54 struct gpio_chip **new_gpio_chip_array; 55 unsigned long new_gpio_chip_array_size = chip_array_end_index + 1; 56 57 new_gpio_chip_array = kmalloc(new_gpio_chip_array_size * sizeof(new_gpio_chip_array[0]), GFP_ATOMIC); 58 if (new_gpio_chip_array == NULL) { 59 printk(KERN_ERR "register_gpio_chip: failed to allocate array\n"); 60 err = -ENOMEM; 61 goto failed; 62 } 63 for (i = 0; i < gpio_chip_array_size; i++) 64 new_gpio_chip_array[i] = gpio_chip_array[i]; 65 for (i = gpio_chip_array_size; i < new_gpio_chip_array_size; i++) 66 new_gpio_chip_array[i] = NULL; 67 gpio_chip_array = new_gpio_chip_array; 68 gpio_chip_array_size = new_gpio_chip_array_size; 69 } 70 list_for_each_entry(gpio_chip, &gpio_chip_list, list) { 71 if (gpio_chip->start > new_gpio_chip->end) { 72 list_add_tail(&new_gpio_chip->list, &gpio_chip->list); 73 goto added; 74 } 75 if (gpio_chip->end >= new_gpio_chip->start) { 76 printk(KERN_ERR "register_gpio_source %u-%u overlaps with %u-%u\n", 77 new_gpio_chip->start, new_gpio_chip->end, 78 gpio_chip->start, gpio_chip->end); 79 err = -EBUSY; 80 goto failed; 81 } 82 } 83 list_add_tail(&new_gpio_chip->list, &gpio_chip_list); 84added: 85 for (i = chip_array_start_index; i <= chip_array_end_index; i++) { 86 if (gpio_chip_array[i] == NULL || gpio_chip_array[i]->start > new_gpio_chip->start) 87 gpio_chip_array[i] = new_gpio_chip; 88 } 89failed: 90 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 91 if (err) 92 kfree(new_gpio_chip->state); 93 return err; 94} 95 96static struct gpio_chip *get_gpio_chip_locked(unsigned int gpio) 97{ 98 unsigned long i; 99 struct gpio_chip *chip; 100 101 i = GPIO_NUM_TO_CHIP_INDEX(gpio); 102 if (i >= gpio_chip_array_size) 103 return NULL; 104 chip = gpio_chip_array[i]; 105 if (chip == NULL) 106 return NULL; 107 list_for_each_entry_from(chip, &gpio_chip_list, list) { 108 if (gpio < chip->start) 109 return NULL; 110 if (gpio <= chip->end) 111 return chip; 112 } 113 return NULL; 114} 115 116static int request_gpio(unsigned int gpio, unsigned long flags) 117{ 118 int err = 0; 119 struct gpio_chip *chip; 120 unsigned long irq_flags; 121 unsigned long chip_index; 122 123 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 124 chip = get_gpio_chip_locked(gpio); 125 if (chip == NULL) { 126 err = -EINVAL; 127 goto err; 128 } 129 chip_index = gpio - chip->start; 130 if (chip->state[chip_index].refcount == 0) { 131 chip->configure(chip, gpio, flags); 132 chip->state[chip_index].flags = flags; 133 chip->state[chip_index].refcount++; 134 } else if ((flags & IRQF_SHARED) && (chip->state[chip_index].flags & IRQF_SHARED)) 135 chip->state[chip_index].refcount++; 136 else 137 err = -EBUSY; 138err: 139 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 140 return err; 141} 142 143int gpio_request(unsigned gpio, const char *label) 144{ 145 return request_gpio(gpio, 0); 146} 147EXPORT_SYMBOL(gpio_request); 148 149void gpio_free(unsigned gpio) 150{ 151 struct gpio_chip *chip; 152 unsigned long irq_flags; 153 unsigned long chip_index; 154 155 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 156 chip = get_gpio_chip_locked(gpio); 157 if (chip) { 158 chip_index = gpio - chip->start; 159 chip->state[chip_index].refcount--; 160 } 161 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 162} 163EXPORT_SYMBOL(gpio_free); 164 165static int gpio_get_irq_num(unsigned int gpio, unsigned int *irqp, unsigned long *irqnumflagsp) 166{ 167 int ret = -ENOTSUPP; 168 struct gpio_chip *chip; 169 unsigned long irq_flags; 170 171 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 172 chip = get_gpio_chip_locked(gpio); 173 if (chip && chip->get_irq_num) 174 ret = chip->get_irq_num(chip, gpio, irqp, irqnumflagsp); 175 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 176 return ret; 177} 178 179int gpio_to_irq(unsigned gpio) 180{ 181 int ret, irq; 182 ret = gpio_get_irq_num(gpio, &irq, NULL); 183 if (ret) 184 return ret; 185 return irq; 186} 187EXPORT_SYMBOL(gpio_to_irq); 188 189int gpio_configure(unsigned int gpio, unsigned long flags) 190{ 191 int ret = -ENOTSUPP; 192 struct gpio_chip *chip; 193 unsigned long irq_flags; 194 195 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 196 chip = get_gpio_chip_locked(gpio); 197 if (chip) 198 ret = chip->configure(chip, gpio, flags); 199 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 200 return ret; 201} 202EXPORT_SYMBOL(gpio_configure); 203 204int gpio_direction_input(unsigned gpio) 205{ 206 return gpio_configure(gpio, GPIOF_INPUT); 207} 208EXPORT_SYMBOL(gpio_direction_input); 209 210int gpio_direction_output(unsigned gpio, int value) 211{ 212 gpio_set_value(gpio, value); 213 return gpio_configure(gpio, GPIOF_DRIVE_OUTPUT); 214} 215EXPORT_SYMBOL(gpio_direction_output); 216 217int gpio_get_value(unsigned gpio) 218{ 219 int ret = -ENOTSUPP; 220 struct gpio_chip *chip; 221 unsigned long irq_flags; 222 223 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 224 chip = get_gpio_chip_locked(gpio); 225 if (chip && chip->read) 226 ret = chip->read(chip, gpio); 227 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 228 return ret; 229} 230EXPORT_SYMBOL(gpio_get_value); 231 232void gpio_set_value(unsigned gpio, int on) 233{ 234 int ret = -ENOTSUPP; 235 struct gpio_chip *chip; 236 unsigned long irq_flags; 237 238 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 239 chip = get_gpio_chip_locked(gpio); 240 if (chip && chip->write) 241 ret = chip->write(chip, gpio, on); 242 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 243} 244EXPORT_SYMBOL(gpio_set_value); 245 246int gpio_read_detect_status(unsigned int gpio) 247{ 248 int ret = -ENOTSUPP; 249 struct gpio_chip *chip; 250 unsigned long irq_flags; 251 252 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 253 chip = get_gpio_chip_locked(gpio); 254 if (chip && chip->read_detect_status) 255 ret = chip->read_detect_status(chip, gpio); 256 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 257 return ret; 258} 259EXPORT_SYMBOL(gpio_read_detect_status); 260 261int gpio_clear_detect_status(unsigned int gpio) 262{ 263 int ret = -ENOTSUPP; 264 struct gpio_chip *chip; 265 unsigned long irq_flags; 266 267 spin_lock_irqsave(&gpio_chips_lock, irq_flags); 268 chip = get_gpio_chip_locked(gpio); 269 if (chip && chip->clear_detect_status) 270 ret = chip->clear_detect_status(chip, gpio); 271 spin_unlock_irqrestore(&gpio_chips_lock, irq_flags); 272 return ret; 273} 274EXPORT_SYMBOL(gpio_clear_detect_status); 275