diff options
Diffstat (limited to 'target/linux')
-rw-r--r-- | target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/gpio.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/gpio.c b/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/gpio.c index 35434f8514..b6e40614d0 100644 --- a/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/gpio.c +++ b/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/gpio.c @@ -15,6 +15,7 @@ #include <linux/io.h> #include <linux/gpio.h> #include <linux/irq.h> +#include <linux/irqdomain.h> #include <asm/mach/irq.h> @@ -45,9 +46,9 @@ struct cns3xxx_gpio_chip { struct gpio_chip chip; + struct irq_domain *domain; spinlock_t lock; void __iomem *base; - int secondary_irq_base; }; static struct cns3xxx_gpio_chip cns3xxx_gpio_chips[2]; @@ -127,7 +128,7 @@ static int cns3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned pin) struct cns3xxx_gpio_chip *cchip = container_of(chip, struct cns3xxx_gpio_chip, chip); - return cchip->secondary_irq_base + pin; + return irq_find_mapping(cchip->domain, pin); } @@ -152,7 +153,7 @@ static void cns3xxx_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i < 32; i++) { if (reg & (1 << i)) { /* let the generic IRQ layer handle an interrupt */ - generic_handle_irq(cchip->secondary_irq_base + i); + generic_handle_irq(irq_find_mapping(cchip->domain, i)); } } @@ -163,7 +164,7 @@ static int cns3xxx_gpio_irq_set_type(struct irq_data *d, u32 irqtype) { struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct cns3xxx_gpio_chip *cchip = gc->private; - u32 gpio = d->irq - cchip->secondary_irq_base; + u32 gpio = d->hwirq; unsigned long flags; u32 method, edges, type; @@ -224,6 +225,7 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio, struct irq_chip_generic *gc; struct irq_chip_type *ct; char gc_label[16]; + int irq_base; if (cns3xxx_gpio_chip_count == ARRAY_SIZE(cns3xxx_gpio_chips)) return; @@ -243,7 +245,6 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio, cchip->chip.can_sleep = 0; spin_lock_init(&cchip->lock); cchip->base = (void __iomem *)base; - cchip->secondary_irq_base = secondary_irq_base; BUG_ON(gpiochip_add(&cchip->chip) < 0); cns3xxx_gpio_chip_count++; @@ -251,11 +252,22 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio, /* clear GPIO interrupts */ __raw_writel(0xffff, cchip->base + GPIO_INTERRUPT_CLEAR); + irq_base = irq_alloc_descs(-1, secondary_irq_base, ngpio, + numa_node_id()); + if (irq_base < 0) + goto out_irqdesc_free; + + cchip->domain = irq_domain_add_legacy(NULL, ngpio, irq_base, 0, + &irq_domain_simple_ops, NULL); + if (!cchip->domain) + goto out_irqdesc_free; + /* * IRQ chip init */ - gc = irq_alloc_generic_chip("cns3xxx_gpio_irq", 1, secondary_irq_base, + gc = irq_alloc_generic_chip("cns3xxx_gpio_irq", 1, irq_base, cchip->base, handle_edge_irq); + gc->private = cchip; ct = gc->chip_types; @@ -270,7 +282,11 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio, irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0); - irq_set_chained_handler(irq, cns3xxx_gpio_irq_handler); irq_set_handler_data(irq, cchip); + + return; + +out_irqdesc_free: + irq_free_descs(irq_base, ngpio); } |