aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-11-02 01:43:20 -0500
committerPaul Mundt <lethal@linux-sh.org>2009-11-02 01:43:20 -0500
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 7aa89fac1f81..e1913f28f418 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -263,6 +263,12 @@ void __init init_IRQ(void)
263{ 263{
264 plat_irq_setup(); 264 plat_irq_setup();
265 265
266 /*
267 * Pin any of the legacy IRQ vectors that haven't already been
268 * grabbed by the platform
269 */
270 reserve_irq_legacy();
271
266 /* Perform the machine specific initialisation */ 272 /* Perform the machine specific initialisation */
267 if (sh_mv.mv_init_irq) 273 if (sh_mv.mv_init_irq)
268 sh_mv.mv_init_irq(); 274 sh_mv.mv_init_irq();
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 4789df43c0f9..a7e5c2e9986c 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -928,3 +928,28 @@ void destroy_irq(unsigned int irq)
928 __clear_bit(irq, intc_irq_map); 928 __clear_bit(irq, intc_irq_map);
929 spin_unlock_irqrestore(&vector_lock, flags); 929 spin_unlock_irqrestore(&vector_lock, flags);
930} 930}
931
932int reserve_irq_vector(unsigned int irq)
933{
934 unsigned long flags;
935 int ret = 0;
936
937 spin_lock_irqsave(&vector_lock, flags);
938 if (test_and_set_bit(irq, intc_irq_map))
939 ret = -EBUSY;
940 spin_unlock_irqrestore(&vector_lock, flags);
941
942 return ret;
943}
944
945void reserve_irq_legacy(void)
946{
947 unsigned long flags;
948 int i, j;
949
950 spin_lock_irqsave(&vector_lock, flags);
951 j = find_first_bit(intc_irq_map, nr_irqs);
952 for (i = 0; i < j; i++)
953 __set_bit(i, intc_irq_map);
954 spin_unlock_irqrestore(&vector_lock, flags);
955}
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
index 4e4b22d50164..4ef246f14654 100644
--- a/include/linux/sh_intc.h
+++ b/include/linux/sh_intc.h
@@ -84,4 +84,7 @@ struct intc_desc symbol __initdata = { \
84void __init register_intc_controller(struct intc_desc *desc); 84void __init register_intc_controller(struct intc_desc *desc);
85int intc_set_priority(unsigned int irq, unsigned int prio); 85int intc_set_priority(unsigned int irq, unsigned int prio);
86 86
87int reserve_irq_vector(unsigned int irq);
88void reserve_irq_legacy(void);
89
87#endif /* __SH_INTC_H */ 90#endif /* __SH_INTC_H */