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