xref: /rk3399_rockchip-uboot/drivers/irq/irq-gpio-v2.c (revision 976ec9cc9d23b47015a8103d5b1a870be4247070)
10fdee37bSJoseph Chen /*
20fdee37bSJoseph Chen  * (C) Copyright 2020 Rockchip Electronics Co., Ltd
30fdee37bSJoseph Chen  *
40fdee37bSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
50fdee37bSJoseph Chen  */
60fdee37bSJoseph Chen 
70fdee37bSJoseph Chen #include <dm.h>
80fdee37bSJoseph Chen #include <malloc.h>
90fdee37bSJoseph Chen #include "irq-internal.h"
100fdee37bSJoseph Chen 
110fdee37bSJoseph Chen typedef enum GPIOIntType {
120fdee37bSJoseph Chen 	GPIOLevelLow = 0,
130fdee37bSJoseph Chen 	GPIOLevelHigh,
140fdee37bSJoseph Chen 	GPIOEdgelFalling,
150fdee37bSJoseph Chen 	GPIOEdgelRising
160fdee37bSJoseph Chen } eGPIOIntType_t;
170fdee37bSJoseph Chen 
180fdee37bSJoseph Chen typedef enum eGPIOPinLevel {
190fdee37bSJoseph Chen 	GPIO_LOW = 0,
200fdee37bSJoseph Chen 	GPIO_HIGH
210fdee37bSJoseph Chen } eGPIOPinLevel_t;
220fdee37bSJoseph Chen 
230fdee37bSJoseph Chen typedef enum eGPIOPinDirection {
240fdee37bSJoseph Chen 	GPIO_IN = 0,
250fdee37bSJoseph Chen 	GPIO_OUT
260fdee37bSJoseph Chen } eGPIOPinDirection_t;
270fdee37bSJoseph Chen 
280fdee37bSJoseph Chen #define GPIO_SWPORT_DR		0x00
290fdee37bSJoseph Chen #define GPIO_SWPORT_DDR		0x08
300fdee37bSJoseph Chen #define GPIO_INTEN		0x10
310fdee37bSJoseph Chen #define GPIO_INTEN_L		0x10
320fdee37bSJoseph Chen #define GPIO_INTEN_H		0x14
330fdee37bSJoseph Chen #define GPIO_INTMASK		0x18
340fdee37bSJoseph Chen #define GPIO_INTTYPE_LEVEL	0x20
350fdee37bSJoseph Chen #define GPIO_INTTYPE_LEVEL_L	0x20
360fdee37bSJoseph Chen #define GPIO_INTTYPE_LEVEL_H	0x24
370fdee37bSJoseph Chen #define GPIO_INT_POLARITY	0x28
380fdee37bSJoseph Chen #define GPIO_DEBOUNCE		0x38
390fdee37bSJoseph Chen #define GPIO_INT_STATUS		0x50
400fdee37bSJoseph Chen #define GPIO_INT_RAWSTATUS	0x58
410fdee37bSJoseph Chen #define GPIO_PORTS_EOI		0x60
420fdee37bSJoseph Chen #define GPIO_EXT_PORT		0x70
430fdee37bSJoseph Chen 
440fdee37bSJoseph Chen #define WMSK_SETBIT(n)		(n << 16 | n)
450fdee37bSJoseph Chen #define WMSK_CLRBIT(n)		(n << 16)
460fdee37bSJoseph Chen #define REG_PLUS4(off, n)	(off + (n >= BIT(16) ? 4 : 0))
470fdee37bSJoseph Chen #define BIT_SUB16(n)		(n >= BIT(16) ? (n >> 16) : n)
480fdee37bSJoseph Chen 
offset_to_bit(unsigned offset)490fdee37bSJoseph Chen static inline unsigned offset_to_bit(unsigned offset)
500fdee37bSJoseph Chen {
510fdee37bSJoseph Chen 	return (1 << offset);
520fdee37bSJoseph Chen }
530fdee37bSJoseph Chen 
gpio_bit_op(void __iomem * regbase,unsigned int offset,u32 bit,unsigned char flag)540fdee37bSJoseph Chen static void gpio_bit_op(void __iomem *regbase, unsigned int offset,
550fdee37bSJoseph Chen 			u32 bit, unsigned char flag)
560fdee37bSJoseph Chen {
570fdee37bSJoseph Chen 	u32 val;
580fdee37bSJoseph Chen 
590fdee37bSJoseph Chen 	offset = REG_PLUS4(offset, bit);
600fdee37bSJoseph Chen 	bit = BIT_SUB16(bit);
610fdee37bSJoseph Chen 
620fdee37bSJoseph Chen 	val = flag ? WMSK_SETBIT(bit) : WMSK_CLRBIT(bit);
630fdee37bSJoseph Chen 	writel(val, regbase + offset);
640fdee37bSJoseph Chen }
650fdee37bSJoseph Chen 
gpio_bit_rd(void __iomem * regbase,unsigned int offset,u32 bit)660fdee37bSJoseph Chen static int gpio_bit_rd(void __iomem *regbase, unsigned int offset, u32 bit)
670fdee37bSJoseph Chen {
680fdee37bSJoseph Chen 	offset = REG_PLUS4(offset, bit);
690fdee37bSJoseph Chen 	bit = BIT_SUB16(bit);
700fdee37bSJoseph Chen 
710fdee37bSJoseph Chen 	return readl(regbase + offset) & bit ? 1 : 0;
720fdee37bSJoseph Chen }
730fdee37bSJoseph Chen 
gpio_irq_unmask(void __iomem * regbase,unsigned int bit)740fdee37bSJoseph Chen static void gpio_irq_unmask(void __iomem *regbase, unsigned int bit)
750fdee37bSJoseph Chen {
760fdee37bSJoseph Chen 	gpio_bit_op(regbase, GPIO_INTEN, bit, 1);
770fdee37bSJoseph Chen }
780fdee37bSJoseph Chen 
gpio_irq_mask(void __iomem * regbase,unsigned int bit)790fdee37bSJoseph Chen static void gpio_irq_mask(void __iomem *regbase, unsigned int bit)
800fdee37bSJoseph Chen {
810fdee37bSJoseph Chen 	gpio_bit_op(regbase, GPIO_INTEN, bit, 0);
820fdee37bSJoseph Chen }
830fdee37bSJoseph Chen 
gpio_irq_ack(void __iomem * regbase,unsigned int bit)840fdee37bSJoseph Chen static void gpio_irq_ack(void __iomem *regbase, unsigned int bit)
850fdee37bSJoseph Chen {
860fdee37bSJoseph Chen 	gpio_bit_op(regbase, GPIO_PORTS_EOI, bit, 1);
870fdee37bSJoseph Chen }
880fdee37bSJoseph Chen 
generic_gpio_handle_irq(int irq,void * data __always_unused)890fdee37bSJoseph Chen static void generic_gpio_handle_irq(int irq, void *data __always_unused)
900fdee37bSJoseph Chen {
910fdee37bSJoseph Chen 	struct gpio_bank *bank = gpio_id_to_bank(irq - IRQ_GPIO0);
920fdee37bSJoseph Chen 	unsigned gpio_irq, pin, h_pin, unmasked = 0;
930fdee37bSJoseph Chen 	u32 isr, ilr_l, ilr_h;
940fdee37bSJoseph Chen 
950fdee37bSJoseph Chen 	isr = readl(bank->regbase + GPIO_INT_STATUS);
960fdee37bSJoseph Chen 	ilr_l = readl(bank->regbase + GPIO_INTTYPE_LEVEL_L);
970fdee37bSJoseph Chen 	ilr_h = readl(bank->regbase + GPIO_INTTYPE_LEVEL_H);
980fdee37bSJoseph Chen 	gpio_irq = bank->irq_base;
990fdee37bSJoseph Chen 
1000fdee37bSJoseph Chen 	while (isr) {
1010fdee37bSJoseph Chen 		pin = fls(isr) - 1;
1020fdee37bSJoseph Chen 
1030fdee37bSJoseph Chen 		/* first mask and ack irq */
1040fdee37bSJoseph Chen 		gpio_irq_mask(bank->regbase, offset_to_bit(pin));
1050fdee37bSJoseph Chen 		gpio_irq_ack(bank->regbase, offset_to_bit(pin));
1060fdee37bSJoseph Chen 
1070fdee37bSJoseph Chen 		/*
1080fdee37bSJoseph Chen 		 * If gpio is edge triggered, clear condition before executing
1090fdee37bSJoseph Chen 		 * the handler, so that we don't miss next edges trigger.
1100fdee37bSJoseph Chen 		 */
1110fdee37bSJoseph Chen 		if (pin < 16) {
1120fdee37bSJoseph Chen 			if (ilr_l & (1 << pin)) {
1130fdee37bSJoseph Chen 				unmasked = 1;
1140fdee37bSJoseph Chen 				gpio_irq_unmask(bank->regbase, offset_to_bit(pin));
1150fdee37bSJoseph Chen 			}
1160fdee37bSJoseph Chen 		} else {
1170fdee37bSJoseph Chen 			h_pin = pin - 16;
1180fdee37bSJoseph Chen 			if (ilr_h & (1 << h_pin)) {
1190fdee37bSJoseph Chen 				unmasked = 1;
120*976ec9ccSJoseph Chen 				gpio_irq_unmask(bank->regbase, offset_to_bit(pin));
1210fdee37bSJoseph Chen 			}
1220fdee37bSJoseph Chen 		}
1230fdee37bSJoseph Chen 		__generic_gpio_handle_irq(gpio_irq + pin);
1240fdee37bSJoseph Chen 
1250fdee37bSJoseph Chen 		isr &= ~(1 << pin);
1260fdee37bSJoseph Chen 
1270fdee37bSJoseph Chen 		if (!unmasked)
1280fdee37bSJoseph Chen 			gpio_irq_unmask(bank->regbase, offset_to_bit(pin));
1290fdee37bSJoseph Chen 	}
1300fdee37bSJoseph Chen }
1310fdee37bSJoseph Chen 
gpio_set_intr_type(void __iomem * regbase,unsigned int bit,eGPIOIntType_t type)1320fdee37bSJoseph Chen static void gpio_set_intr_type(void __iomem *regbase,
1330fdee37bSJoseph Chen 			       unsigned int bit,
1340fdee37bSJoseph Chen 			       eGPIOIntType_t type)
1350fdee37bSJoseph Chen {
1360fdee37bSJoseph Chen 	switch (type) {
1370fdee37bSJoseph Chen 	case GPIOLevelLow:
1380fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
1390fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
1400fdee37bSJoseph Chen 		break;
1410fdee37bSJoseph Chen 	case GPIOLevelHigh:
1420fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
1430fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
1440fdee37bSJoseph Chen 		break;
1450fdee37bSJoseph Chen 	case GPIOEdgelFalling:
1460fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
1470fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
1480fdee37bSJoseph Chen 		break;
1490fdee37bSJoseph Chen 	case GPIOEdgelRising:
1500fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
1510fdee37bSJoseph Chen 		gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
1520fdee37bSJoseph Chen 		break;
1530fdee37bSJoseph Chen 	}
1540fdee37bSJoseph Chen }
1550fdee37bSJoseph Chen 
gpio_get_intr_type(void __iomem * regbase,unsigned int bit)1560fdee37bSJoseph Chen static int gpio_get_intr_type(void __iomem *regbase,
1570fdee37bSJoseph Chen 			      unsigned int bit)
1580fdee37bSJoseph Chen {
1590fdee37bSJoseph Chen 	u32 polarity, level, magic = 0;
1600fdee37bSJoseph Chen 	int type;
1610fdee37bSJoseph Chen 
1620fdee37bSJoseph Chen 	polarity = gpio_bit_rd(regbase, GPIO_INT_POLARITY, bit);
1630fdee37bSJoseph Chen 	level = gpio_bit_rd(regbase, GPIO_INTTYPE_LEVEL, bit);
1640fdee37bSJoseph Chen 	magic = (polarity << 1) | (level << 0);
1650fdee37bSJoseph Chen 
1660fdee37bSJoseph Chen 	switch (magic) {
1670fdee37bSJoseph Chen 	case 0x00:
1680fdee37bSJoseph Chen 		type = GPIOLevelLow;
1690fdee37bSJoseph Chen 		break;
1700fdee37bSJoseph Chen 	case 0x02:
1710fdee37bSJoseph Chen 		type = GPIOLevelHigh;
1720fdee37bSJoseph Chen 		break;
1730fdee37bSJoseph Chen 	case 0x01:
1740fdee37bSJoseph Chen 		type = GPIOEdgelFalling;
1750fdee37bSJoseph Chen 		break;
1760fdee37bSJoseph Chen 	case 0x03:
1770fdee37bSJoseph Chen 		type = GPIOEdgelRising;
1780fdee37bSJoseph Chen 		break;
1790fdee37bSJoseph Chen 	default:
1800fdee37bSJoseph Chen 		type = -EINVAL;
1810fdee37bSJoseph Chen 	}
1820fdee37bSJoseph Chen 
1830fdee37bSJoseph Chen 	return type;
1840fdee37bSJoseph Chen }
1850fdee37bSJoseph Chen 
gpio_irq_set_type(int gpio_irq,unsigned int type)1860fdee37bSJoseph Chen static int gpio_irq_set_type(int gpio_irq, unsigned int type)
1870fdee37bSJoseph Chen {
1880fdee37bSJoseph Chen 	int gpio = irq_to_gpio(gpio_irq);
1890fdee37bSJoseph Chen 	struct gpio_bank *bank = gpio_to_bank(gpio);
1900fdee37bSJoseph Chen 	eGPIOIntType_t int_type = 0;
1910fdee37bSJoseph Chen 
1920fdee37bSJoseph Chen 	if (!bank)
1930fdee37bSJoseph Chen 		return -EINVAL;
1940fdee37bSJoseph Chen 
1950fdee37bSJoseph Chen 	gpio &= GPIO_PIN_MASK;
1960fdee37bSJoseph Chen 	if (gpio >= bank->ngpio)
1970fdee37bSJoseph Chen 		return -EINVAL;
1980fdee37bSJoseph Chen 
1990fdee37bSJoseph Chen 	switch (type) {
2000fdee37bSJoseph Chen 	case IRQ_TYPE_EDGE_RISING:
2010fdee37bSJoseph Chen 		int_type = GPIOEdgelRising;
2020fdee37bSJoseph Chen 		break;
2030fdee37bSJoseph Chen 	case IRQ_TYPE_EDGE_FALLING:
2040fdee37bSJoseph Chen 		int_type = GPIOEdgelFalling;
2050fdee37bSJoseph Chen 		break;
2060fdee37bSJoseph Chen 	case IRQ_TYPE_LEVEL_HIGH:
2070fdee37bSJoseph Chen 		int_type = GPIOLevelHigh;
2080fdee37bSJoseph Chen 		break;
2090fdee37bSJoseph Chen 	case IRQ_TYPE_LEVEL_LOW:
2100fdee37bSJoseph Chen 		int_type = GPIOLevelLow;
2110fdee37bSJoseph Chen 		break;
2120fdee37bSJoseph Chen 	default:
2130fdee37bSJoseph Chen 		return -EINVAL;
2140fdee37bSJoseph Chen 	}
2150fdee37bSJoseph Chen 
2160fdee37bSJoseph Chen 	/* Before set interrupt type, gpio must set input */
2170fdee37bSJoseph Chen 	gpio_bit_op(bank->regbase, GPIO_SWPORT_DDR,
2180fdee37bSJoseph Chen 		    offset_to_bit(gpio), GPIO_IN);
2190fdee37bSJoseph Chen 	gpio_set_intr_type(bank->regbase, offset_to_bit(gpio), int_type);
2200fdee37bSJoseph Chen 
2210fdee37bSJoseph Chen 	return 0;
2220fdee37bSJoseph Chen }
2230fdee37bSJoseph Chen 
gpio_irq_revert_type(int gpio_irq)2240fdee37bSJoseph Chen static int gpio_irq_revert_type(int gpio_irq)
2250fdee37bSJoseph Chen {
2260fdee37bSJoseph Chen 	int gpio = irq_to_gpio(gpio_irq);
2270fdee37bSJoseph Chen 	struct gpio_bank *bank = gpio_to_bank(gpio);
2280fdee37bSJoseph Chen 	eGPIOIntType_t int_type = 0;
2290fdee37bSJoseph Chen 	int type;
2300fdee37bSJoseph Chen 
2310fdee37bSJoseph Chen 	if (!bank)
2320fdee37bSJoseph Chen 		return -EINVAL;
2330fdee37bSJoseph Chen 
2340fdee37bSJoseph Chen 	gpio &= GPIO_PIN_MASK;
2350fdee37bSJoseph Chen 	if (gpio >= bank->ngpio)
2360fdee37bSJoseph Chen 		return -EINVAL;
2370fdee37bSJoseph Chen 
2380fdee37bSJoseph Chen 	type = gpio_get_intr_type(bank->regbase, offset_to_bit(gpio));
2390fdee37bSJoseph Chen 	switch (type) {
2400fdee37bSJoseph Chen 	case GPIOEdgelFalling:
2410fdee37bSJoseph Chen 		int_type = GPIOEdgelRising;
2420fdee37bSJoseph Chen 		break;
2430fdee37bSJoseph Chen 	case GPIOEdgelRising:
2440fdee37bSJoseph Chen 		int_type = GPIOEdgelFalling;
2450fdee37bSJoseph Chen 		break;
2460fdee37bSJoseph Chen 	case GPIOLevelHigh:
2470fdee37bSJoseph Chen 		int_type = GPIOLevelLow;
2480fdee37bSJoseph Chen 		break;
2490fdee37bSJoseph Chen 	case GPIOLevelLow:
2500fdee37bSJoseph Chen 		int_type = GPIOLevelHigh;
2510fdee37bSJoseph Chen 		break;
2520fdee37bSJoseph Chen 	default:
2530fdee37bSJoseph Chen 		return -EINVAL;
2540fdee37bSJoseph Chen 	}
2550fdee37bSJoseph Chen 
2560fdee37bSJoseph Chen 	gpio_set_intr_type(bank->regbase, offset_to_bit(gpio), int_type);
2570fdee37bSJoseph Chen 
2580fdee37bSJoseph Chen 	return 0;
2590fdee37bSJoseph Chen }
2600fdee37bSJoseph Chen 
gpio_irq_get_gpio_level(int gpio_irq)2610fdee37bSJoseph Chen static int gpio_irq_get_gpio_level(int gpio_irq)
2620fdee37bSJoseph Chen {
2630fdee37bSJoseph Chen 	int gpio = irq_to_gpio(gpio_irq);
2640fdee37bSJoseph Chen 	struct gpio_bank *bank = gpio_to_bank(gpio);
2650fdee37bSJoseph Chen 
2660fdee37bSJoseph Chen 	if (!bank)
2670fdee37bSJoseph Chen 		return -EINVAL;
2680fdee37bSJoseph Chen 
2690fdee37bSJoseph Chen 	gpio &= GPIO_PIN_MASK;
2700fdee37bSJoseph Chen 	if (gpio >= bank->ngpio)
2710fdee37bSJoseph Chen 		return -EINVAL;
2720fdee37bSJoseph Chen 
273af1f96e9SJoseph Chen 	/* NOTE: GPIO_EXT_PORT doesn't have _H/_L registers */
274af1f96e9SJoseph Chen 	return readl(bank->regbase + GPIO_EXT_PORT) & offset_to_bit(gpio) ? 1 : 0;
2750fdee37bSJoseph Chen }
2760fdee37bSJoseph Chen 
gpio_irq_enable(int gpio_irq)2770fdee37bSJoseph Chen static int gpio_irq_enable(int gpio_irq)
2780fdee37bSJoseph Chen {
2790fdee37bSJoseph Chen 	int gpio = irq_to_gpio(gpio_irq);
2800fdee37bSJoseph Chen 	struct gpio_bank *bank = gpio_to_bank(gpio);
2810fdee37bSJoseph Chen 
2820fdee37bSJoseph Chen 	if (!bank)
2830fdee37bSJoseph Chen 		return -EINVAL;
2840fdee37bSJoseph Chen 
2850fdee37bSJoseph Chen 	gpio &= GPIO_PIN_MASK;
2860fdee37bSJoseph Chen 	if (gpio >= bank->ngpio)
2870fdee37bSJoseph Chen 		return -EINVAL;
2880fdee37bSJoseph Chen 
2890fdee37bSJoseph Chen 	gpio_irq_unmask(bank->regbase, offset_to_bit(gpio));
2900fdee37bSJoseph Chen 
2910fdee37bSJoseph Chen 	if (bank->use_count == 0)
2920fdee37bSJoseph Chen 		irq_handler_enable(IRQ_GPIO0 + bank->id);
2930fdee37bSJoseph Chen 	bank->use_count++;
2940fdee37bSJoseph Chen 
2950fdee37bSJoseph Chen 	return 0;
2960fdee37bSJoseph Chen }
2970fdee37bSJoseph Chen 
gpio_irq_disable(int irq)2980fdee37bSJoseph Chen static int gpio_irq_disable(int irq)
2990fdee37bSJoseph Chen {
3000fdee37bSJoseph Chen 	int gpio = irq_to_gpio(irq);
3010fdee37bSJoseph Chen 	struct gpio_bank *bank = gpio_to_bank(gpio);
3020fdee37bSJoseph Chen 
3030fdee37bSJoseph Chen 	if (!bank)
3040fdee37bSJoseph Chen 		return -EINVAL;
3050fdee37bSJoseph Chen 
3060fdee37bSJoseph Chen 	if (bank->use_count <= 0)
3070fdee37bSJoseph Chen 		return 0;
3080fdee37bSJoseph Chen 
3090fdee37bSJoseph Chen 	gpio &= GPIO_PIN_MASK;
3100fdee37bSJoseph Chen 	if (gpio >= bank->ngpio)
3110fdee37bSJoseph Chen 		return -EINVAL;
3120fdee37bSJoseph Chen 
3130fdee37bSJoseph Chen 	gpio_irq_mask(bank->regbase, offset_to_bit(gpio));
3140fdee37bSJoseph Chen 
3150fdee37bSJoseph Chen 	if (bank->use_count == 1)
3160fdee37bSJoseph Chen 		irq_handler_disable(IRQ_GPIO0 + bank->id);
3170fdee37bSJoseph Chen 	bank->use_count--;
3180fdee37bSJoseph Chen 
3190fdee37bSJoseph Chen 	return 0;
3200fdee37bSJoseph Chen }
3210fdee37bSJoseph Chen 
gpio_irq_init(void)3220fdee37bSJoseph Chen static int gpio_irq_init(void)
3230fdee37bSJoseph Chen {
3240fdee37bSJoseph Chen 	struct gpio_bank *bank = NULL;
3250fdee37bSJoseph Chen 	int i = 0;
3260fdee37bSJoseph Chen 
3270fdee37bSJoseph Chen 	for (i = 0; i < GPIO_BANK_NUM; i++) {
3280fdee37bSJoseph Chen 		struct udevice *dev;
3290fdee37bSJoseph Chen 
3300fdee37bSJoseph Chen 		dev = malloc(sizeof(*dev));
3310fdee37bSJoseph Chen 		if (!dev)
3320fdee37bSJoseph Chen 			return -ENOMEM;
3330fdee37bSJoseph Chen 
3340fdee37bSJoseph Chen 		bank = gpio_id_to_bank(i);
3350fdee37bSJoseph Chen 		if (bank) {
3360fdee37bSJoseph Chen 			dev->name = bank->name;
3370fdee37bSJoseph Chen 
3380fdee37bSJoseph Chen 			/* disable gpio pin interrupt */
3390fdee37bSJoseph Chen 			writel(0xffff0000, bank->regbase + GPIO_INTEN_L);
3400fdee37bSJoseph Chen 			writel(0xffff0000, bank->regbase + GPIO_INTEN_H);
3410fdee37bSJoseph Chen 
3420fdee37bSJoseph Chen 			/* register gpio group irq handler */
3430fdee37bSJoseph Chen 			irq_install_handler(IRQ_GPIO0 + bank->id,
3440fdee37bSJoseph Chen 			(interrupt_handler_t *)generic_gpio_handle_irq, dev);
3450fdee37bSJoseph Chen 
3460fdee37bSJoseph Chen 			/* default disable all gpio group interrupt */
3470fdee37bSJoseph Chen 			irq_handler_disable(IRQ_GPIO0 + bank->id);
3480fdee37bSJoseph Chen 		}
3490fdee37bSJoseph Chen 	}
3500fdee37bSJoseph Chen 
3510fdee37bSJoseph Chen 	return 0;
3520fdee37bSJoseph Chen }
3530fdee37bSJoseph Chen 
3540fdee37bSJoseph Chen static struct irq_chip gpio_irq_chip = {
3550fdee37bSJoseph Chen 	.name		= "gpio-irq-chip",
3560fdee37bSJoseph Chen 	.irq_init	= gpio_irq_init,
3570fdee37bSJoseph Chen 	.irq_enable	= gpio_irq_enable,
3580fdee37bSJoseph Chen 	.irq_disable	= gpio_irq_disable,
3590fdee37bSJoseph Chen 	.irq_set_type	= gpio_irq_set_type,
3600fdee37bSJoseph Chen 	.irq_revert_type = gpio_irq_revert_type,
3610fdee37bSJoseph Chen 	.irq_get_gpio_level = gpio_irq_get_gpio_level,
3620fdee37bSJoseph Chen };
3630fdee37bSJoseph Chen 
arch_gpio_get_irqchip(void)3640fdee37bSJoseph Chen struct irq_chip *arch_gpio_get_irqchip(void)
3650fdee37bSJoseph Chen {
3660fdee37bSJoseph Chen 	return &gpio_irq_chip;
3670fdee37bSJoseph Chen }
3680fdee37bSJoseph Chen 
369