summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-11-02 15:43:20 +0900
committerPaul Mundt <lethal@linux-sh.org>2009-11-02 15:43:20 +0900
commit45b9deaf14e74543371aa8faea69c14e27b038c6 (patch)
tree485b9beab7f908557ab816fa473d7a5bdb494841
parent3d0de414423a20af741b692243317f423827489b (diff)
sh: intc: Handle legacy IRQ reservation in vector map.
Different CPUs will have different starting vectors, with varying amounts of reserved or unusable vector space prior to the first slot. This introduces a legacy vector reservation system that inserts itself in between the CPU vector map registration and the platform specific IRQ setup. This works fine in practice as the only new vectors that boards need to establish on their own should be dynamically allocated rather than arbitrarily assigned. As a plus, this also makes all of the converted platforms sparseirq ready. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/irq.c6
-rw-r--r--drivers/sh/intc.c25
-rw-r--r--include/linux/sh_intc.h3
3 files changed, 34 insertions, 0 deletions
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 7aa89fac1f8..e1913f28f41 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -263,6 +263,12 @@ void __init init_IRQ(void)
{
plat_irq_setup();
+ /*
+ * Pin any of the legacy IRQ vectors that haven't already been
+ * grabbed by the platform
+ */
+ reserve_irq_legacy();
+
/* Perform the machine specific initialisation */
if (sh_mv.mv_init_irq)
sh_mv.mv_init_irq();
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 4789df43c0f..a7e5c2e9986 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -928,3 +928,28 @@ void destroy_irq(unsigned int irq)
__clear_bit(irq, intc_irq_map);
spin_unlock_irqrestore(&vector_lock, flags);
}
+
+int reserve_irq_vector(unsigned int irq)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&vector_lock, flags);
+ if (test_and_set_bit(irq, intc_irq_map))
+ ret = -EBUSY;
+ spin_unlock_irqrestore(&vector_lock, flags);
+
+ return ret;
+}
+
+void reserve_irq_legacy(void)
+{
+ unsigned long flags;
+ int i, j;
+
+ spin_lock_irqsave(&vector_lock, flags);
+ j = find_first_bit(intc_irq_map, nr_irqs);
+ for (i = 0; i < j; i++)
+ __set_bit(i, intc_irq_map);
+ spin_unlock_irqrestore(&vector_lock, flags);
+}
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
index 4e4b22d5016..4ef246f1465 100644
--- a/include/linux/sh_intc.h
+++ b/include/linux/sh_intc.h
@@ -84,4 +84,7 @@ struct intc_desc symbol __initdata = { \
void __init register_intc_controller(struct intc_desc *desc);
int intc_set_priority(unsigned int irq, unsigned int prio);
+int reserve_irq_vector(unsigned int irq);
+void reserve_irq_legacy(void);
+
#endif /* __SH_INTC_H */