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