135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors/* 2c103de240439dfee24ac50eb99c8be3a30d13323Grant Likely * Timberdale FPGA GPIO driver 335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * Copyright (c) 2009 Intel Corporation 435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * 535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * This program is free software; you can redistribute it and/or modify 635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * it under the terms of the GNU General Public License version 2 as 735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * published by the Free Software Foundation. 835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * 935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * This program is distributed in the hope that it will be useful, 1035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * but WITHOUT ANY WARRANTY; without even the implied warranty of 1135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * GNU General Public License for more details. 1335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * 1435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * You should have received a copy of the GNU General Public License 1535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * along with this program; if not, write to the Free Software 1635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors */ 1835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 1935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors/* Supports: 2035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * Timberdale FPGA GPIO 2135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors */ 2235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 2335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#include <linux/module.h> 2435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#include <linux/gpio.h> 2535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#include <linux/platform_device.h> 26e3cb91ce1ac1d93a7cc6f81bb5247f7602b572bbDavid Miller#include <linux/irq.h> 2735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#include <linux/io.h> 2835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#include <linux/timb_gpio.h> 2935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#include <linux/interrupt.h> 305a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 3135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 3235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define DRIVER_NAME "timb-gpio" 3335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 3435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIOVAL 0x00 3535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIODIR 0x04 3635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIO_IER 0x08 3735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIO_ISR 0x0c 3835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIO_IPR 0x10 3935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIO_ICR 0x14 4035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIO_FLR 0x18 4135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#define TGPIO_LVR 0x1c 428c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors#define TGPIO_VER 0x20 438c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors#define TGPIO_BFLR 0x24 4435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 4535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstruct timbgpio { 4635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors void __iomem *membase; 4735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors spinlock_t lock; /* mutual exclusion */ 4835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct gpio_chip gpio; 4935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors int irq_base; 5076d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg unsigned long last_ier; 5135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors}; 5235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 5335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, 5435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors unsigned offset, bool enabled) 5535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 5635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); 5735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors u32 reg; 5835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 5935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors spin_lock(&tgpio->lock); 6035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors reg = ioread32(tgpio->membase + offset); 6135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 6235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (enabled) 6335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors reg |= (1 << index); 6435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors else 6535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors reg &= ~(1 << index); 6635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 6735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iowrite32(reg, tgpio->membase + offset); 6835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors spin_unlock(&tgpio->lock); 6935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 7035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return 0; 7135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 7235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 7335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) 7435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 7535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return timbgpio_update_bit(gpio, nr, TGPIODIR, true); 7635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 7735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 7835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) 7935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 8035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); 8135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors u32 value; 8235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 8335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors value = ioread32(tgpio->membase + TGPIOVAL); 8435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return (value & (1 << nr)) ? 1 : 0; 8535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 8635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 8735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic int timbgpio_gpio_direction_output(struct gpio_chip *gpio, 8835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors unsigned nr, int val) 8935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 9035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return timbgpio_update_bit(gpio, nr, TGPIODIR, false); 9135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 9235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 9335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic void timbgpio_gpio_set(struct gpio_chip *gpio, 9435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors unsigned nr, int val) 9535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 9635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0); 9735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 9835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 9935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) 10035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 10135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio); 10235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 10335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (tgpio->irq_base <= 0) 10435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return -EINVAL; 10535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 10635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return tgpio->irq_base + offset; 10735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 10835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 10935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors/* 11035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors * GPIO IRQ 11135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors */ 112a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhekstatic void timbgpio_irq_disable(struct irq_data *d) 11335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 114a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 115a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek int offset = d->irq - tgpio->irq_base; 11676d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg unsigned long flags; 11735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 11876d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg spin_lock_irqsave(&tgpio->lock, flags); 119d79550a7bc35c16476ebdc27c78378d8093390ecDan Carpenter tgpio->last_ier &= ~(1UL << offset); 12076d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 12176d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg spin_unlock_irqrestore(&tgpio->lock, flags); 12235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 12335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 124a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhekstatic void timbgpio_irq_enable(struct irq_data *d) 12535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 126a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 127a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek int offset = d->irq - tgpio->irq_base; 12876d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg unsigned long flags; 12935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 13076d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg spin_lock_irqsave(&tgpio->lock, flags); 131d79550a7bc35c16476ebdc27c78378d8093390ecDan Carpenter tgpio->last_ier |= 1UL << offset; 13276d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 13376d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg spin_unlock_irqrestore(&tgpio->lock, flags); 13435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 13535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 136a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhekstatic int timbgpio_irq_type(struct irq_data *d, unsigned trigger) 13735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 138a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 139a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek int offset = d->irq - tgpio->irq_base; 14035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors unsigned long flags; 1418c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors u32 lvr, flr, bflr = 0; 1428c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors u32 ver; 1432a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawall int ret = 0; 14435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 14535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (offset < 0 || offset > tgpio->gpio.ngpio) 14635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return -EINVAL; 14735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 1488c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors ver = ioread32(tgpio->membase + TGPIO_VER); 1498c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors 15035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors spin_lock_irqsave(&tgpio->lock, flags); 15135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 15235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors lvr = ioread32(tgpio->membase + TGPIO_LVR); 15335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors flr = ioread32(tgpio->membase + TGPIO_FLR); 1548c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors if (ver > 2) 1558c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors bflr = ioread32(tgpio->membase + TGPIO_BFLR); 15635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 15735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 1588c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors bflr &= ~(1 << offset); 15935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors flr &= ~(1 << offset); 16035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (trigger & IRQ_TYPE_LEVEL_HIGH) 16135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors lvr |= 1 << offset; 16235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors else 16335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors lvr &= ~(1 << offset); 16435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 16535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 1668c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { 1672a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawall if (ver < 3) { 1682a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawall ret = -EINVAL; 1692a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawall goto out; 1708a29a409671f82a21a56aeb42835f99795d0deb3Laurent Navet } else { 1718c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors flr |= 1 << offset; 1728c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors bflr |= 1 << offset; 1738c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors } 1748c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors } else { 1758c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors bflr &= ~(1 << offset); 17635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors flr |= 1 << offset; 17735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (trigger & IRQ_TYPE_EDGE_FALLING) 17835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors lvr &= ~(1 << offset); 1798c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors else 1808c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors lvr |= 1 << offset; 18135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 18235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 18335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iowrite32(lvr, tgpio->membase + TGPIO_LVR); 18435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iowrite32(flr, tgpio->membase + TGPIO_FLR); 1858c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors if (ver > 2) 1868c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors iowrite32(bflr, tgpio->membase + TGPIO_BFLR); 1878c35c89aa3d7e0f253c3a10456a8b075288b4565Richard Röjfors 18835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); 18935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 1902a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawallout: 1912a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawall spin_unlock_irqrestore(&tgpio->lock, flags); 1922a481800caf78f4750cc673c8baed12b5d703ff6Julia Lawall return ret; 19335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 19435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 1957f5db6a8022e8d4bb92b3d638068d2c2a9c9b59bLennert Buytenhekstatic void timbgpio_irq(unsigned int irq, struct irq_desc *desc) 19635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 197b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner struct timbgpio *tgpio = irq_get_handler_data(irq); 19835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors unsigned long ipr; 19935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors int offset; 20035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 2017f5db6a8022e8d4bb92b3d638068d2c2a9c9b59bLennert Buytenhek desc->irq_data.chip->irq_ack(irq_get_irq_data(irq)); 20235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors ipr = ioread32(tgpio->membase + TGPIO_IPR); 20335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iowrite32(ipr, tgpio->membase + TGPIO_ICR); 20435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 20576d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg /* 20676d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg * Some versions of the hardware trash the IER register if more than 20776d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg * one interrupt is received simultaneously. 20876d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg */ 20976d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg iowrite32(0, tgpio->membase + TGPIO_IER); 21076d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg 211984b3f5746ed2cde3d184651dabf26980f2b66e5Akinobu Mita for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) 21235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); 21376d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg 21476d800a5b6e198c4fda07b88bb42a545709f193bTomas Hallenberg iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 21535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 21635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 21735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic struct irq_chip timbgpio_irqchip = { 21835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors .name = "GPIO", 219a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek .irq_enable = timbgpio_irq_enable, 220a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek .irq_disable = timbgpio_irq_disable, 221a1f5f22adc3206c47e70652c12671666c65b579fLennert Buytenhek .irq_set_type = timbgpio_irq_type, 22235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors}; 22335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 2243836309d93462bbf34851c078be6e5e77d888e3dBill Pembertonstatic int timbgpio_probe(struct platform_device *pdev) 22535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 22635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors int err, i; 2270ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe struct device *dev = &pdev->dev; 22835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct gpio_chip *gc; 22935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct timbgpio *tgpio; 23035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct resource *iomem; 231e56aee1897fd27631c1cb28e12b0fb8f8f9736f7Jingoo Han struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev); 23235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors int irq = platform_get_irq(pdev, 0); 23335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 23435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (!pdata || pdata->nr_pins > 32) { 2350ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe dev_err(dev, "Invalid platform data\n"); 2360ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe return -EINVAL; 23735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 23835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 23935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 24035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (!iomem) { 2410ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe dev_err(dev, "Unable to get resource\n"); 2420ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe return -EINVAL; 24335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 24435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 2450ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL); 24635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (!tgpio) { 2470ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe dev_err(dev, "Memory alloc failed\n"); 2480ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe return -EINVAL; 24935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 25035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors tgpio->irq_base = pdata->irq_base; 25135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 25235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors spin_lock_init(&tgpio->lock); 25335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 2540ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe if (!devm_request_mem_region(dev, iomem->start, resource_size(iomem), 2550ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe DRIVER_NAME)) { 2560ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe dev_err(dev, "Region already claimed\n"); 2570ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe return -EBUSY; 25835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 25935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 2600ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe tgpio->membase = devm_ioremap(dev, iomem->start, resource_size(iomem)); 26135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (!tgpio->membase) { 2620ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe dev_err(dev, "Cannot ioremap\n"); 2630ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe return -ENOMEM; 26435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 26535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 26635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc = &tgpio->gpio; 26735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 26835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->label = dev_name(&pdev->dev); 26935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->owner = THIS_MODULE; 27035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->dev = &pdev->dev; 27135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->direction_input = timbgpio_gpio_direction_input; 27235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->get = timbgpio_gpio_get; 27335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->direction_output = timbgpio_gpio_direction_output; 27435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->set = timbgpio_gpio_set; 27535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL; 27635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->dbg_show = NULL; 27735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->base = pdata->gpio_base; 27835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors gc->ngpio = pdata->nr_pins; 2799fb1f39eb2d6707d265087ee186376e24995f55aLinus Walleij gc->can_sleep = false; 28035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 28135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors err = gpiochip_add(gc); 28235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (err) 2830ed3398ed8086597ff53d119fa48fa466f2f2754abdoulaye berthe return err; 28435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 28535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors platform_set_drvdata(pdev, tgpio); 28635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 28735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors /* make sure to disable interrupts */ 28835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors iowrite32(0x0, tgpio->membase + TGPIO_IER); 28935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 29035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (irq < 0 || tgpio->irq_base <= 0) 29135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return 0; 29235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 29335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors for (i = 0; i < pdata->nr_pins; i++) { 294e5428a682ca726249a89201c79ddd0599669c484Linus Walleij irq_set_chip_and_handler(tgpio->irq_base + i, 295e5428a682ca726249a89201c79ddd0599669c484Linus Walleij &timbgpio_irqchip, handle_simple_irq); 296b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip_data(tgpio->irq_base + i, tgpio); 29735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#ifdef CONFIG_ARM 29835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); 29935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors#endif 30035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 30135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 302b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_handler_data(irq, tgpio); 303b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chained_handler(irq, timbgpio_irq); 30435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 30535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return 0; 30635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 30735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 308206210ce68c1feb1d9d05839ceacc97ad1b0b324Bill Pembertonstatic int timbgpio_remove(struct platform_device *pdev) 30935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors{ 310e56aee1897fd27631c1cb28e12b0fb8f8f9736f7Jingoo Han struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev); 31135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors struct timbgpio *tgpio = platform_get_drvdata(pdev); 31235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors int irq = platform_get_irq(pdev, 0); 31335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 31435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors if (irq >= 0 && tgpio->irq_base > 0) { 31535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors int i; 3163271d382c3ffe61ef3d059ef47e635dbe031030eSamuel Ortiz for (i = 0; i < pdata->nr_pins; i++) { 317b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip(tgpio->irq_base + i, NULL); 318b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_chip_data(tgpio->irq_base + i, NULL); 31935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 32035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 321b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_handler(irq, NULL); 322b51804bcf0774a8bc6af1e8bb6ae818f4b71173aThomas Gleixner irq_set_handler_data(irq, NULL); 32335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors } 32435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 3259f5132ae82fdbb047cc187bf689a81c8cc0de7faabdoulaye berthe gpiochip_remove(&tgpio->gpio); 32635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 32735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors return 0; 32835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors} 32935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 33035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjforsstatic struct platform_driver timbgpio_platform_driver = { 33135570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors .driver = { 33235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors .name = DRIVER_NAME, 33335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors .owner = THIS_MODULE, 33435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors }, 33535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors .probe = timbgpio_probe, 33635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors .remove = timbgpio_remove, 33735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors}; 33835570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 33935570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors/*--------------------------------------------------------------------------*/ 34035570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 3416f61415e9c4c0ab02c8eda7671bb652db4863cc0Mark Brownmodule_platform_driver(timbgpio_platform_driver); 34235570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 34335570ac6039ef490b9c5abde1fee4803a39bf4e1Richard RöjforsMODULE_DESCRIPTION("Timberdale GPIO driver"); 34435570ac6039ef490b9c5abde1fee4803a39bf4e1Richard RöjforsMODULE_LICENSE("GPL v2"); 34535570ac6039ef490b9c5abde1fee4803a39bf4e1Richard RöjforsMODULE_AUTHOR("Mocean Laboratories"); 34635570ac6039ef490b9c5abde1fee4803a39bf4e1Richard RöjforsMODULE_ALIAS("platform:"DRIVER_NAME); 34735570ac6039ef490b9c5abde1fee4803a39bf4e1Richard Röjfors 348