cns3xxx: Adopt irq_domain support for cns3xxx gpio driver
Have gpio driver adopt irqdomain support so that there are non-overlapping allocations of irq numbers mapped to gpio's. Signed-off-by: Pushpal Sidhu <psidhu@gateworks.com> SVN-Revision: 42844
This commit is contained in:
parent
5fa47c3c04
commit
fa5237d936
1 changed files with 23 additions and 7 deletions
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/irqdomain.h>
|
||||||
|
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
|
|
||||||
|
@ -45,9 +46,9 @@
|
||||||
|
|
||||||
struct cns3xxx_gpio_chip {
|
struct cns3xxx_gpio_chip {
|
||||||
struct gpio_chip chip;
|
struct gpio_chip chip;
|
||||||
|
struct irq_domain *domain;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int secondary_irq_base;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cns3xxx_gpio_chip cns3xxx_gpio_chips[2];
|
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 =
|
struct cns3xxx_gpio_chip *cchip =
|
||||||
container_of(chip, struct cns3xxx_gpio_chip, chip);
|
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++) {
|
for (i = 0; i < 32; i++) {
|
||||||
if (reg & (1 << i)) {
|
if (reg & (1 << i)) {
|
||||||
/* let the generic IRQ layer handle an interrupt */
|
/* 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 irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||||
struct cns3xxx_gpio_chip *cchip = gc->private;
|
struct cns3xxx_gpio_chip *cchip = gc->private;
|
||||||
u32 gpio = d->irq - cchip->secondary_irq_base;
|
u32 gpio = d->hwirq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 method, edges, type;
|
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_generic *gc;
|
||||||
struct irq_chip_type *ct;
|
struct irq_chip_type *ct;
|
||||||
char gc_label[16];
|
char gc_label[16];
|
||||||
|
int irq_base;
|
||||||
|
|
||||||
if (cns3xxx_gpio_chip_count == ARRAY_SIZE(cns3xxx_gpio_chips))
|
if (cns3xxx_gpio_chip_count == ARRAY_SIZE(cns3xxx_gpio_chips))
|
||||||
return;
|
return;
|
||||||
|
@ -243,7 +245,6 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio,
|
||||||
cchip->chip.can_sleep = 0;
|
cchip->chip.can_sleep = 0;
|
||||||
spin_lock_init(&cchip->lock);
|
spin_lock_init(&cchip->lock);
|
||||||
cchip->base = (void __iomem *)base;
|
cchip->base = (void __iomem *)base;
|
||||||
cchip->secondary_irq_base = secondary_irq_base;
|
|
||||||
|
|
||||||
BUG_ON(gpiochip_add(&cchip->chip) < 0);
|
BUG_ON(gpiochip_add(&cchip->chip) < 0);
|
||||||
cns3xxx_gpio_chip_count++;
|
cns3xxx_gpio_chip_count++;
|
||||||
|
@ -251,11 +252,22 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio,
|
||||||
/* clear GPIO interrupts */
|
/* clear GPIO interrupts */
|
||||||
__raw_writel(0xffff, cchip->base + GPIO_INTERRUPT_CLEAR);
|
__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
|
* 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);
|
cchip->base, handle_edge_irq);
|
||||||
|
|
||||||
gc->private = cchip;
|
gc->private = cchip;
|
||||||
|
|
||||||
ct = gc->chip_types;
|
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_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
|
||||||
IRQ_NOREQUEST, 0);
|
IRQ_NOREQUEST, 0);
|
||||||
|
|
||||||
irq_set_chained_handler(irq, cns3xxx_gpio_irq_handler);
|
irq_set_chained_handler(irq, cns3xxx_gpio_irq_handler);
|
||||||
irq_set_handler_data(irq, cchip);
|
irq_set_handler_data(irq, cchip);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_irqdesc_free:
|
||||||
|
irq_free_descs(irq_base, ngpio);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue