aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/intc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh/intc.c')
-rw-r--r--drivers/sh/intc.c123
1 files changed, 109 insertions, 14 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 559b5fe9dc0f..a7e5c2e9986c 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -2,6 +2,7 @@
2 * Shared interrupt handling code for IPR and INTC2 types of IRQs. 2 * Shared interrupt handling code for IPR and INTC2 types of IRQs.
3 * 3 *
4 * Copyright (C) 2007, 2008 Magnus Damm 4 * Copyright (C) 2007, 2008 Magnus Damm
5 * Copyright (C) 2009 Paul Mundt
5 * 6 *
6 * Based on intc2.c and ipr.c 7 * Based on intc2.c and ipr.c
7 * 8 *
@@ -24,6 +25,7 @@
24#include <linux/sysdev.h> 25#include <linux/sysdev.h>
25#include <linux/list.h> 26#include <linux/list.h>
26#include <linux/topology.h> 27#include <linux/topology.h>
28#include <linux/bitmap.h>
27 29
28#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ 30#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
29 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ 31 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -59,6 +61,20 @@ struct intc_desc_int {
59 61
60static LIST_HEAD(intc_list); 62static LIST_HEAD(intc_list);
61 63
64/*
65 * The intc_irq_map provides a global map of bound IRQ vectors for a
66 * given platform. Allocation of IRQs are either static through the CPU
67 * vector map, or dynamic in the case of board mux vectors or MSI.
68 *
69 * As this is a central point for all IRQ controllers on the system,
70 * each of the available sources are mapped out here. This combined with
71 * sparseirq makes it quite trivial to keep the vector map tightly packed
72 * when dynamically creating IRQs, as well as tying in to otherwise
73 * unused irq_desc positions in the sparse array.
74 */
75static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
76static DEFINE_SPINLOCK(vector_lock);
77
62#ifdef CONFIG_SMP 78#ifdef CONFIG_SMP
63#define IS_SMP(x) x.smp 79#define IS_SMP(x) x.smp
64#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c)) 80#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
@@ -70,9 +86,7 @@ static LIST_HEAD(intc_list);
70#endif 86#endif
71 87
72static unsigned int intc_prio_level[NR_IRQS]; /* for now */ 88static unsigned int intc_prio_level[NR_IRQS]; /* for now */
73#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
74static unsigned long ack_handle[NR_IRQS]; 89static unsigned long ack_handle[NR_IRQS];
75#endif
76 90
77static inline struct intc_desc_int *get_intc_desc(unsigned int irq) 91static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
78{ 92{
@@ -250,7 +264,6 @@ static int intc_set_wake(unsigned int irq, unsigned int on)
250 return 0; /* allow wakeup, but setup hardware in intc_suspend() */ 264 return 0; /* allow wakeup, but setup hardware in intc_suspend() */
251} 265}
252 266
253#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
254static void intc_mask_ack(unsigned int irq) 267static void intc_mask_ack(unsigned int irq)
255{ 268{
256 struct intc_desc_int *d = get_intc_desc(irq); 269 struct intc_desc_int *d = get_intc_desc(irq);
@@ -282,7 +295,6 @@ static void intc_mask_ack(unsigned int irq)
282 } 295 }
283 } 296 }
284} 297}
285#endif
286 298
287static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, 299static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
288 unsigned int nr_hp, 300 unsigned int nr_hp,
@@ -501,7 +513,6 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
501 return 0; 513 return 0;
502} 514}
503 515
504#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
505static unsigned int __init intc_ack_data(struct intc_desc *desc, 516static unsigned int __init intc_ack_data(struct intc_desc *desc,
506 struct intc_desc_int *d, 517 struct intc_desc_int *d,
507 intc_enum enum_id) 518 intc_enum enum_id)
@@ -533,7 +544,6 @@ static unsigned int __init intc_ack_data(struct intc_desc *desc,
533 544
534 return 0; 545 return 0;
535} 546}
536#endif
537 547
538static unsigned int __init intc_sense_data(struct intc_desc *desc, 548static unsigned int __init intc_sense_data(struct intc_desc *desc,
539 struct intc_desc_int *d, 549 struct intc_desc_int *d,
@@ -572,6 +582,11 @@ static void __init intc_register_irq(struct intc_desc *desc,
572 struct intc_handle_int *hp; 582 struct intc_handle_int *hp;
573 unsigned int data[2], primary; 583 unsigned int data[2], primary;
574 584
585 /*
586 * Register the IRQ position with the global IRQ map
587 */
588 set_bit(irq, intc_irq_map);
589
575 /* Prefer single interrupt source bitmap over other combinations: 590 /* Prefer single interrupt source bitmap over other combinations:
576 * 1. bitmap, single interrupt source 591 * 1. bitmap, single interrupt source
577 * 2. priority, single interrupt source 592 * 2. priority, single interrupt source
@@ -641,10 +656,8 @@ static void __init intc_register_irq(struct intc_desc *desc,
641 /* irq should be disabled by default */ 656 /* irq should be disabled by default */
642 d->chip.mask(irq); 657 d->chip.mask(irq);
643 658
644#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
645 if (desc->ack_regs) 659 if (desc->ack_regs)
646 ack_handle[irq] = intc_ack_data(desc, d, enum_id); 660 ack_handle[irq] = intc_ack_data(desc, d, enum_id);
647#endif
648} 661}
649 662
650static unsigned int __init save_reg(struct intc_desc_int *d, 663static unsigned int __init save_reg(struct intc_desc_int *d,
@@ -681,10 +694,8 @@ void __init register_intc_controller(struct intc_desc *desc)
681 d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0; 694 d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
682 d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; 695 d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
683 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; 696 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
684
685#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
686 d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0; 697 d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
687#endif 698
688 d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); 699 d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
689#ifdef CONFIG_SMP 700#ifdef CONFIG_SMP
690 d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); 701 d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
@@ -727,14 +738,12 @@ void __init register_intc_controller(struct intc_desc *desc)
727 d->chip.set_type = intc_set_sense; 738 d->chip.set_type = intc_set_sense;
728 d->chip.set_wake = intc_set_wake; 739 d->chip.set_wake = intc_set_wake;
729 740
730#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
731 if (desc->ack_regs) { 741 if (desc->ack_regs) {
732 for (i = 0; i < desc->nr_ack_regs; i++) 742 for (i = 0; i < desc->nr_ack_regs; i++)
733 k += save_reg(d, k, desc->ack_regs[i].set_reg, 0); 743 k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
734 744
735 d->chip.mask_ack = intc_mask_ack; 745 d->chip.mask_ack = intc_mask_ack;
736 } 746 }
737#endif
738 747
739 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ 748 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
740 749
@@ -856,5 +865,91 @@ static int __init register_intc_sysdevs(void)
856 865
857 return error; 866 return error;
858} 867}
859
860device_initcall(register_intc_sysdevs); 868device_initcall(register_intc_sysdevs);
869
870/*
871 * Dynamic IRQ allocation and deallocation
872 */
873static unsigned int create_irq_on_node(unsigned int irq_want, int node)
874{
875 unsigned int irq = 0, new;
876 unsigned long flags;
877 struct irq_desc *desc;
878
879 spin_lock_irqsave(&vector_lock, flags);
880
881 /*
882 * First try the wanted IRQ, then scan.
883 */
884 if (test_and_set_bit(irq_want, intc_irq_map)) {
885 new = find_first_zero_bit(intc_irq_map, nr_irqs);
886 if (unlikely(new == nr_irqs))
887 goto out_unlock;
888
889 desc = irq_to_desc_alloc_node(new, node);
890 if (unlikely(!desc)) {
891 pr_info("can't get irq_desc for %d\n", new);
892 goto out_unlock;
893 }
894
895 desc = move_irq_desc(desc, node);
896 __set_bit(new, intc_irq_map);
897 irq = new;
898 }
899
900out_unlock:
901 spin_unlock_irqrestore(&vector_lock, flags);
902
903 if (irq > 0)
904 dynamic_irq_init(irq);
905
906 return irq;
907}
908
909int create_irq(void)
910{
911 int nid = cpu_to_node(smp_processor_id());
912 int irq;
913
914 irq = create_irq_on_node(NR_IRQS_LEGACY, nid);
915 if (irq == 0)
916 irq = -1;
917
918 return irq;
919}
920
921void destroy_irq(unsigned int irq)
922{
923 unsigned long flags;
924
925 dynamic_irq_cleanup(irq);
926
927 spin_lock_irqsave(&vector_lock, flags);
928 __clear_bit(irq, intc_irq_map);
929 spin_unlock_irqrestore(&vector_lock, flags);
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}