|
@@ -216,3 +216,114 @@ void __init omap3_init_irq(void)
|
|
|
|
|
|
void __init ti81xx_init_irq(void)
|
|
|
{
|
|
|
+ omap_init_irq(OMAP34XX_IC_BASE, 128, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ u32 irqnr;
|
|
|
+
|
|
|
+ do {
|
|
|
+ irqnr = readl_relaxed(base_addr + 0x98);
|
|
|
+ if (irqnr)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ irqnr = readl_relaxed(base_addr + 0xb8);
|
|
|
+ if (irqnr)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ irqnr = readl_relaxed(base_addr + 0xd8);
|
|
|
+#ifdef CONFIG_SOC_TI81XX
|
|
|
+ if (irqnr)
|
|
|
+ goto out;
|
|
|
+ irqnr = readl_relaxed(base_addr + 0xf8);
|
|
|
+#endif
|
|
|
+
|
|
|
+out:
|
|
|
+ if (!irqnr)
|
|
|
+ break;
|
|
|
+
|
|
|
+ irqnr = readl_relaxed(base_addr + INTCPS_SIR_IRQ_OFFSET);
|
|
|
+ irqnr &= ACTIVEIRQ_MASK;
|
|
|
+
|
|
|
+ if (irqnr) {
|
|
|
+ irqnr = irq_find_mapping(domain, irqnr);
|
|
|
+ handle_IRQ(irqnr, regs);
|
|
|
+ }
|
|
|
+ } while (irqnr);
|
|
|
+}
|
|
|
+
|
|
|
+asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs)
|
|
|
+{
|
|
|
+ void __iomem *base_addr = OMAP2_IRQ_BASE;
|
|
|
+ omap_intc_handle_irq(base_addr, regs);
|
|
|
+}
|
|
|
+
|
|
|
+int __init intc_of_init(struct device_node *node,
|
|
|
+ struct device_node *parent)
|
|
|
+{
|
|
|
+ struct resource res;
|
|
|
+ u32 nr_irq = 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_irq))
|
|
|
+ pr_warn("unable to get intc-size, default to %d\n", nr_irq);
|
|
|
+
|
|
|
+ omap_init_irq(res.start, nr_irq, of_node_get(node));
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct of_device_id irq_match[] __initdata = {
|
|
|
+ { .compatible = "ti,omap2-intc", .data = intc_of_init, },
|
|
|
+ { }
|
|
|
+};
|
|
|
+
|
|
|
+void __init omap_intc_of_init(void)
|
|
|
+{
|
|
|
+ of_irq_init(irq_match);
|
|
|
+}
|
|
|
+
|
|
|
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
|
|
|
+static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
|
|
|
+
|
|
|
+void omap_intc_save_context(void)
|
|
|
+{
|
|
|
+ int ind = 0, i = 0;
|
|
|
+ for (ind = 0; ind < ARRAY_SIZE(irq_banks); ind++) {
|
|
|
+ struct omap_irq_bank *bank = irq_banks + ind;
|
|
|
+ intc_context[ind].sysconfig =
|
|
|
+ intc_bank_read_reg(bank, INTC_SYSCONFIG);
|
|
|
+ intc_context[ind].protection =
|
|
|
+ intc_bank_read_reg(bank, INTC_PROTECTION);
|
|
|
+ intc_context[ind].idle =
|
|
|
+ intc_bank_read_reg(bank, INTC_IDLE);
|
|
|
+ intc_context[ind].threshold =
|
|
|
+ intc_bank_read_reg(bank, INTC_THRESHOLD);
|
|
|
+ for (i = 0; i < INTCPS_NR_IRQS; i++)
|
|
|
+ intc_context[ind].ilr[i] =
|
|
|
+ intc_bank_read_reg(bank, (0x100 + 0x4*i));
|
|
|
+ for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
|
|
|
+ intc_context[ind].mir[i] =
|
|
|
+ intc_bank_read_reg(&irq_banks[0], INTC_MIR0 +
|
|
|
+ (0x20 * i));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void omap_intc_restore_context(void)
|
|
|
+{
|
|
|
+ int ind = 0, i = 0;
|
|
|
+
|
|
|
+ for (ind = 0; ind < ARRAY_SIZE(irq_banks); ind++) {
|
|
|
+ struct omap_irq_bank *bank = irq_banks + ind;
|
|
|
+ intc_bank_write_reg(intc_context[ind].sysconfig,
|
|
|
+ bank, INTC_SYSCONFIG);
|
|
|
+ intc_bank_write_reg(intc_context[ind].sysconfig,
|
|
|
+ bank, INTC_SYSCONFIG);
|