gpio-timberdale.c revision 2a481800caf78f4750cc673c8baed12b5d703ff6
1/* 2 * timbgpio.c timberdale FPGA GPIO driver 3 * Copyright (c) 2009 Intel Corporation 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 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 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19/* Supports: 20 * Timberdale FPGA GPIO 21 */ 22 23#include <linux/module.h> 24#include <linux/gpio.h> 25#include <linux/platform_device.h> 26#include <linux/irq.h> 27#include <linux/io.h> 28#include <linux/timb_gpio.h> 29#include <linux/interrupt.h> 30#include <linux/slab.h> 31 32#define DRIVER_NAME "timb-gpio" 33 34#define TGPIOVAL 0x00 35#define TGPIODIR 0x04 36#define TGPIO_IER 0x08 37#define TGPIO_ISR 0x0c 38#define TGPIO_IPR 0x10 39#define TGPIO_ICR 0x14 40#define TGPIO_FLR 0x18 41#define TGPIO_LVR 0x1c 42#define TGPIO_VER 0x20 43#define TGPIO_BFLR 0x24 44 45struct timbgpio { 46 void __iomem *membase; 47 spinlock_t lock; /* mutual exclusion */ 48 struct gpio_chip gpio; 49 int irq_base; 50}; 51 52static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, 53 unsigned offset, bool enabled) 54{ 55 struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); 56 u32 reg; 57 58 spin_lock(&tgpio->lock); 59 reg = ioread32(tgpio->membase + offset); 60 61 if (enabled) 62 reg |= (1 << index); 63 else 64 reg &= ~(1 << index); 65 66 iowrite32(reg, tgpio->membase + offset); 67 spin_unlock(&tgpio->lock); 68 69 return 0; 70} 71 72static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) 73{ 74 return timbgpio_update_bit(gpio, nr, TGPIODIR, true); 75} 76 77static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) 78{ 79 struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); 80 u32 value; 81 82 value = ioread32(tgpio->membase + TGPIOVAL); 83 return (value & (1 << nr)) ? 1 : 0; 84} 85 86static int timbgpio_gpio_direction_output(struct gpio_chip *gpio, 87 unsigned nr, int val) 88{ 89 return timbgpio_update_bit(gpio, nr, TGPIODIR, false); 90} 91 92static void timbgpio_gpio_set(struct gpio_chip *gpio, 93 unsigned nr, int val) 94{ 95 timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0); 96} 97 98static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) 99{ 100 struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); 101 102 if (tgpio->irq_base <= 0) 103 return -EINVAL; 104 105 return tgpio->irq_base + offset; 106} 107 108/* 109 * GPIO IRQ 110 */ 111static void timbgpio_irq_disable(unsigned irq) 112{ 113 struct timbgpio *tgpio = get_irq_chip_data(irq); 114 int offset = irq - tgpio->irq_base; 115 116 timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 0); 117} 118 119static void timbgpio_irq_enable(unsigned irq) 120{ 121 struct timbgpio *tgpio = get_irq_chip_data(irq); 122 int offset = irq - tgpio->irq_base; 123 124 timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 1); 125} 126 127static int timbgpio_irq_type(unsigned irq, unsigned trigger) 128{ 129 struct timbgpio *tgpio = get_irq_chip_data(irq); 130 int offset = irq - tgpio->irq_base; 131 unsigned long flags; 132 u32 lvr, flr, bflr = 0; 133 u32 ver; 134 int ret = 0; 135 136 if (offset < 0 || offset > tgpio->gpio.ngpio) 137 return -EINVAL; 138 139 ver = ioread32(tgpio->membase + TGPIO_VER); 140 141 spin_lock_irqsave(&tgpio->lock, flags); 142 143 lvr = ioread32(tgpio->membase + TGPIO_LVR); 144 flr = ioread32(tgpio->membase + TGPIO_FLR); 145 if (ver > 2) 146 bflr = ioread32(tgpio->membase + TGPIO_BFLR); 147 148 if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 149 bflr &= ~(1 << offset); 150 flr &= ~(1 << offset); 151 if (trigger & IRQ_TYPE_LEVEL_HIGH) 152 lvr |= 1 << offset; 153 else 154 lvr &= ~(1 << offset); 155 } 156 157 if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { 158 if (ver < 3) { 159 ret = -EINVAL; 160 goto out; 161 } 162 else { 163 flr |= 1 << offset; 164 bflr |= 1 << offset; 165 } 166 } else { 167 bflr &= ~(1 << offset); 168 flr |= 1 << offset; 169 if (trigger & IRQ_TYPE_EDGE_FALLING) 170 lvr &= ~(1 << offset); 171 else 172 lvr |= 1 << offset; 173 } 174 175 iowrite32(lvr, tgpio->membase + TGPIO_LVR); 176 iowrite32(flr, tgpio->membase + TGPIO_FLR); 177 if (ver > 2) 178 iowrite32(bflr, tgpio->membase + TGPIO_BFLR); 179 180 iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); 181 182out: 183 spin_unlock_irqrestore(&tgpio->lock, flags); 184 return ret; 185} 186 187static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) 188{ 189 struct timbgpio *tgpio = get_irq_data(irq); 190 unsigned long ipr; 191 int offset; 192 193 desc->chip->ack(irq); 194 ipr = ioread32(tgpio->membase + TGPIO_IPR); 195 iowrite32(ipr, tgpio->membase + TGPIO_ICR); 196 197 for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) 198 generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); 199} 200 201static struct irq_chip timbgpio_irqchip = { 202 .name = "GPIO", 203 .enable = timbgpio_irq_enable, 204 .disable = timbgpio_irq_disable, 205 .set_type = timbgpio_irq_type, 206}; 207 208static int __devinit timbgpio_probe(struct platform_device *pdev) 209{ 210 int err, i; 211 struct gpio_chip *gc; 212 struct timbgpio *tgpio; 213 struct resource *iomem; 214 struct timbgpio_platform_data *pdata = pdev->dev.platform_data; 215 int irq = platform_get_irq(pdev, 0); 216 217 if (!pdata || pdata->nr_pins > 32) { 218 err = -EINVAL; 219 goto err_mem; 220 } 221 222 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 223 if (!iomem) { 224 err = -EINVAL; 225 goto err_mem; 226 } 227 228 tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL); 229 if (!tgpio) { 230 err = -EINVAL; 231 goto err_mem; 232 } 233 tgpio->irq_base = pdata->irq_base; 234 235 spin_lock_init(&tgpio->lock); 236 237 if (!request_mem_region(iomem->start, resource_size(iomem), 238 DRIVER_NAME)) { 239 err = -EBUSY; 240 goto err_request; 241 } 242 243 tgpio->membase = ioremap(iomem->start, resource_size(iomem)); 244 if (!tgpio->membase) { 245 err = -ENOMEM; 246 goto err_ioremap; 247 } 248 249 gc = &tgpio->gpio; 250 251 gc->label = dev_name(&pdev->dev); 252 gc->owner = THIS_MODULE; 253 gc->dev = &pdev->dev; 254 gc->direction_input = timbgpio_gpio_direction_input; 255 gc->get = timbgpio_gpio_get; 256 gc->direction_output = timbgpio_gpio_direction_output; 257 gc->set = timbgpio_gpio_set; 258 gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL; 259 gc->dbg_show = NULL; 260 gc->base = pdata->gpio_base; 261 gc->ngpio = pdata->nr_pins; 262 gc->can_sleep = 0; 263 264 err = gpiochip_add(gc); 265 if (err) 266 goto err_chipadd; 267 268 platform_set_drvdata(pdev, tgpio); 269 270 /* make sure to disable interrupts */ 271 iowrite32(0x0, tgpio->membase + TGPIO_IER); 272 273 if (irq < 0 || tgpio->irq_base <= 0) 274 return 0; 275 276 for (i = 0; i < pdata->nr_pins; i++) { 277 set_irq_chip_and_handler_name(tgpio->irq_base + i, 278 &timbgpio_irqchip, handle_simple_irq, "mux"); 279 set_irq_chip_data(tgpio->irq_base + i, tgpio); 280#ifdef CONFIG_ARM 281 set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); 282#endif 283 } 284 285 set_irq_data(irq, tgpio); 286 set_irq_chained_handler(irq, timbgpio_irq); 287 288 return 0; 289 290err_chipadd: 291 iounmap(tgpio->membase); 292err_ioremap: 293 release_mem_region(iomem->start, resource_size(iomem)); 294err_request: 295 kfree(tgpio); 296err_mem: 297 printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err); 298 299 return err; 300} 301 302static int __devexit timbgpio_remove(struct platform_device *pdev) 303{ 304 int err; 305 struct timbgpio_platform_data *pdata = pdev->dev.platform_data; 306 struct timbgpio *tgpio = platform_get_drvdata(pdev); 307 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 308 int irq = platform_get_irq(pdev, 0); 309 310 if (irq >= 0 && tgpio->irq_base > 0) { 311 int i; 312 for (i = 0; i < pdata->nr_pins; i++) { 313 set_irq_chip(tgpio->irq_base + i, NULL); 314 set_irq_chip_data(tgpio->irq_base + i, NULL); 315 } 316 317 set_irq_handler(irq, NULL); 318 set_irq_data(irq, NULL); 319 } 320 321 err = gpiochip_remove(&tgpio->gpio); 322 if (err) 323 printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n"); 324 325 iounmap(tgpio->membase); 326 release_mem_region(iomem->start, resource_size(iomem)); 327 kfree(tgpio); 328 329 platform_set_drvdata(pdev, NULL); 330 331 return 0; 332} 333 334static struct platform_driver timbgpio_platform_driver = { 335 .driver = { 336 .name = DRIVER_NAME, 337 .owner = THIS_MODULE, 338 }, 339 .probe = timbgpio_probe, 340 .remove = timbgpio_remove, 341}; 342 343/*--------------------------------------------------------------------------*/ 344 345static int __init timbgpio_init(void) 346{ 347 return platform_driver_register(&timbgpio_platform_driver); 348} 349 350static void __exit timbgpio_exit(void) 351{ 352 platform_driver_unregister(&timbgpio_platform_driver); 353} 354 355module_init(timbgpio_init); 356module_exit(timbgpio_exit); 357 358MODULE_DESCRIPTION("Timberdale GPIO driver"); 359MODULE_LICENSE("GPL v2"); 360MODULE_AUTHOR("Mocean Laboratories"); 361MODULE_ALIAS("platform:"DRIVER_NAME); 362 363