diff options
Diffstat (limited to 'arch/arm/mach-omap2/irq.c')
| -rw-r--r-- | arch/arm/mach-omap2/irq.c | 60 | 
1 files changed, 50 insertions, 10 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 1fef061f792..26eaf37ce4d 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -11,12 +11,16 @@   * for more details.   */  #include <linux/kernel.h> +#include <linux/module.h>  #include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/io.h>  #include <mach/hardware.h>  #include <asm/exception.h>  #include <asm/mach/irq.h> +#include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/of_address.h>  /* selected INTC register offsets */ @@ -57,6 +61,8 @@ static struct omap_irq_bank {  	},  }; +static struct irq_domain *domain; +  /* Structure to save interrupt controller context */  struct omap3_intc_regs {  	u32 sysconfig; @@ -147,17 +153,27 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)  				IRQ_NOREQUEST | IRQ_NOPROBE, 0);  } -static void __init omap_init_irq(u32 base, int nr_irqs) +static void __init omap_init_irq(u32 base, int nr_irqs, +				 struct device_node *node)  {  	void __iomem *omap_irq_base;  	unsigned long nr_of_irqs = 0;  	unsigned int nr_banks = 0; -	int i, j; +	int i, j, irq_base;  	omap_irq_base = ioremap(base, SZ_4K);  	if (WARN_ON(!omap_irq_base))  		return; +	irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); +	if (irq_base < 0) { +		pr_warn("Couldn't allocate IRQ numbers\n"); +		irq_base = 0; +	} + +	domain = irq_domain_add_legacy(node, nr_irqs, irq_base, 0, +				       &irq_domain_simple_ops, NULL); +  	for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {  		struct omap_irq_bank *bank = irq_banks + i; @@ -166,36 +182,36 @@ static void __init omap_init_irq(u32 base, int nr_irqs)  		/* Static mapping, never released */  		bank->base_reg = ioremap(base, SZ_4K);  		if (!bank->base_reg) { -			printk(KERN_ERR "Could not ioremap irq bank%i\n", i); +			pr_err("Could not ioremap irq bank%i\n", i);  			continue;  		}  		omap_irq_bank_init_one(bank);  		for (j = 0; j < bank->nr_irqs; j += 32) -			omap_alloc_gc(bank->base_reg + j, j, 32); +			omap_alloc_gc(bank->base_reg + j, j + irq_base, 32);  		nr_of_irqs += bank->nr_irqs;  		nr_banks++;  	} -	printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n", -	       nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : ""); +	pr_info("Total of %ld interrupts on %d active controller%s\n", +		nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");  }  void __init omap2_init_irq(void)  { -	omap_init_irq(OMAP24XX_IC_BASE, 96); +	omap_init_irq(OMAP24XX_IC_BASE, 96, NULL);  }  void __init omap3_init_irq(void)  { -	omap_init_irq(OMAP34XX_IC_BASE, 96); +	omap_init_irq(OMAP34XX_IC_BASE, 96, NULL);  }  void __init ti81xx_init_irq(void)  { -	omap_init_irq(OMAP34XX_IC_BASE, 128); +	omap_init_irq(OMAP34XX_IC_BASE, 128, NULL);  }  static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) @@ -225,8 +241,10 @@ out:  		irqnr = readl_relaxed(base_addr + INTCPS_SIR_IRQ_OFFSET);  		irqnr &= ACTIVEIRQ_MASK; -		if (irqnr) +		if (irqnr) { +			irqnr = irq_find_mapping(domain, irqnr);  			handle_IRQ(irqnr, regs); +		}  	} while (irqnr);  } @@ -236,6 +254,28 @@ asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs  	omap_intc_handle_irq(base_addr, regs);  } +int __init omap_intc_of_init(struct device_node *node, +			     struct device_node *parent) +{ +	struct resource res; +	u32 nr_irqs = 96; + +	if (WARN_ON(!node)) +		return -ENODEV; + +	if (of_address_to_resource(node, 0, &res)) { +		WARN(1, "unable to get intc registers\n"); +		return -EINVAL; +	} + +	if (of_property_read_u32(node, "ti,intc-size", &nr_irqs)) +		pr_warn("unable to get intc-size, default to %d\n", nr_irqs); + +	omap_init_irq(res.start, nr_irqs, of_node_get(node)); + +	return 0; +} +  #ifdef CONFIG_ARCH_OMAP3  static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];  |