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