diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/Kconfig | 4 | ||||
-rw-r--r-- | kernel/irq/Makefile | 1 | ||||
-rw-r--r-- | kernel/irq/irqdomain.c | 122 |
3 files changed, 127 insertions, 0 deletions
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index d1d051b38e0b..5a38bf4de641 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER | |||
52 | config GENERIC_IRQ_CHIP | 52 | config GENERIC_IRQ_CHIP |
53 | bool | 53 | bool |
54 | 54 | ||
55 | # Generic irq_domain hw <--> linux irq number translation | ||
56 | config IRQ_DOMAIN | ||
57 | bool | ||
58 | |||
55 | # Support forced irq threading | 59 | # Support forced irq threading |
56 | config IRQ_FORCED_THREADING | 60 | config IRQ_FORCED_THREADING |
57 | bool | 61 | bool |
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile index 73290056cfb6..fff17381f0af 100644 --- a/kernel/irq/Makefile +++ b/kernel/irq/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o | 2 | obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o |
3 | obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o | 3 | obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o |
4 | obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o | 4 | obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o |
5 | obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o | ||
5 | obj-$(CONFIG_PROC_FS) += proc.o | 6 | obj-$(CONFIG_PROC_FS) += proc.o |
6 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o | 7 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o |
7 | obj-$(CONFIG_PM_SLEEP) += pm.o | 8 | obj-$(CONFIG_PM_SLEEP) += pm.o |
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c new file mode 100644 index 000000000000..29c7bd42e25d --- /dev/null +++ b/kernel/irq/irqdomain.c | |||
@@ -0,0 +1,122 @@ | |||
1 | #include <linux/irq.h> | ||
2 | #include <linux/irqdomain.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/mutex.h> | ||
5 | #include <linux/of.h> | ||
6 | |||
7 | static LIST_HEAD(irq_domain_list); | ||
8 | static DEFINE_MUTEX(irq_domain_mutex); | ||
9 | |||
10 | /** | ||
11 | * irq_domain_add() - Register an irq_domain | ||
12 | * @domain: ptr to initialized irq_domain structure | ||
13 | * | ||
14 | * Registers an irq_domain structure. The irq_domain must at a minimum be | ||
15 | * initialized with an ops structure pointer, and either a ->to_irq hook or | ||
16 | * a valid irq_base value. Everything else is optional. | ||
17 | */ | ||
18 | void irq_domain_add(struct irq_domain *domain) | ||
19 | { | ||
20 | struct irq_data *d; | ||
21 | int hwirq; | ||
22 | |||
23 | /* | ||
24 | * This assumes that the irq_domain owner has already allocated | ||
25 | * the irq_descs. This block will be removed when support for dynamic | ||
26 | * allocation of irq_descs is added to irq_domain. | ||
27 | */ | ||
28 | for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { | ||
29 | d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); | ||
30 | if (d || d->domain) { | ||
31 | /* things are broken; just report, don't clean up */ | ||
32 | WARN(1, "error: irq_desc already assigned to a domain"); | ||
33 | return; | ||
34 | } | ||
35 | d->domain = domain; | ||
36 | d->hwirq = hwirq; | ||
37 | } | ||
38 | |||
39 | mutex_lock(&irq_domain_mutex); | ||
40 | list_add(&domain->list, &irq_domain_list); | ||
41 | mutex_unlock(&irq_domain_mutex); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * irq_domain_del() - Unregister an irq_domain | ||
46 | * @domain: ptr to registered irq_domain. | ||
47 | */ | ||
48 | void irq_domain_del(struct irq_domain *domain) | ||
49 | { | ||
50 | struct irq_data *d; | ||
51 | int hwirq; | ||
52 | |||
53 | mutex_lock(&irq_domain_mutex); | ||
54 | list_del(&domain->list); | ||
55 | mutex_unlock(&irq_domain_mutex); | ||
56 | |||
57 | /* Clear the irq_domain assignments */ | ||
58 | for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { | ||
59 | d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); | ||
60 | d->domain = NULL; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | #if defined(CONFIG_OF_IRQ) | ||
65 | /** | ||
66 | * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec | ||
67 | * | ||
68 | * Used by the device tree interrupt mapping code to translate a device tree | ||
69 | * interrupt specifier to a valid linux irq number. Returns either a valid | ||
70 | * linux IRQ number or 0. | ||
71 | * | ||
72 | * When the caller no longer need the irq number returned by this function it | ||
73 | * should arrange to call irq_dispose_mapping(). | ||
74 | */ | ||
75 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
76 | const u32 *intspec, unsigned int intsize) | ||
77 | { | ||
78 | struct irq_domain *domain; | ||
79 | unsigned long hwirq; | ||
80 | unsigned int irq, type; | ||
81 | int rc = -EINVAL; | ||
82 | |||
83 | /* Find a domain which can translate the irq spec */ | ||
84 | mutex_lock(&irq_domain_mutex); | ||
85 | list_for_each_entry(domain, &irq_domain_list, list) { | ||
86 | if (!domain->ops->dt_translate) | ||
87 | continue; | ||
88 | rc = domain->ops->dt_translate(domain, controller, | ||
89 | intspec, intsize, &hwirq, &type); | ||
90 | if (rc == 0) | ||
91 | break; | ||
92 | } | ||
93 | mutex_unlock(&irq_domain_mutex); | ||
94 | |||
95 | if (rc != 0) | ||
96 | return 0; | ||
97 | |||
98 | irq = irq_domain_to_irq(domain, hwirq); | ||
99 | if (type != IRQ_TYPE_NONE) | ||
100 | irq_set_irq_type(irq, type); | ||
101 | pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n", | ||
102 | controller->full_name, (int)hwirq, irq, type); | ||
103 | return irq; | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
106 | |||
107 | /** | ||
108 | * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping() | ||
109 | * @irq: linux irq number to be discarded | ||
110 | * | ||
111 | * Calling this function indicates the caller no longer needs a reference to | ||
112 | * the linux irq number returned by a prior call to irq_create_of_mapping(). | ||
113 | */ | ||
114 | void irq_dispose_mapping(unsigned int irq) | ||
115 | { | ||
116 | /* | ||
117 | * nothing yet; will be filled when support for dynamic allocation of | ||
118 | * irq_descs is added to irq_domain | ||
119 | */ | ||
120 | } | ||
121 | EXPORT_SYMBOL_GPL(irq_dispose_mapping); | ||
122 | #endif /* CONFIG_OF_IRQ */ | ||