hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/irqchip/irq-dw-apb-ictl.c
....@@ -17,6 +17,7 @@
1717 #include <linux/irqchip/chained_irq.h>
1818 #include <linux/of_address.h>
1919 #include <linux/of_irq.h>
20
+#include <linux/interrupt.h>
2021
2122 #define APB_INT_ENABLE_L 0x00
2223 #define APB_INT_ENABLE_H 0x04
....@@ -26,7 +27,28 @@
2627 #define APB_INT_FINALSTATUS_H 0x34
2728 #define APB_INT_BASE_OFFSET 0x04
2829
29
-static void dw_apb_ictl_handler(struct irq_desc *desc)
30
+/* irq domain of the primary interrupt controller. */
31
+static struct irq_domain *dw_apb_ictl_irq_domain;
32
+
33
+static void __irq_entry dw_apb_ictl_handle_irq(struct pt_regs *regs)
34
+{
35
+ struct irq_domain *d = dw_apb_ictl_irq_domain;
36
+ int n;
37
+
38
+ for (n = 0; n < d->revmap_size; n += 32) {
39
+ struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, n);
40
+ u32 stat = readl_relaxed(gc->reg_base + APB_INT_FINALSTATUS_L);
41
+
42
+ while (stat) {
43
+ u32 hwirq = ffs(stat) - 1;
44
+
45
+ handle_domain_irq(d, hwirq, regs);
46
+ stat &= ~BIT(hwirq);
47
+ }
48
+ }
49
+}
50
+
51
+static void dw_apb_ictl_handle_irq_cascaded(struct irq_desc *desc)
3052 {
3153 struct irq_domain *d = irq_desc_get_handler_data(desc);
3254 struct irq_chip *chip = irq_desc_get_chip(desc);
....@@ -43,12 +65,36 @@
4365 u32 virq = irq_find_mapping(d, gc->irq_base + hwirq);
4466
4567 generic_handle_irq(virq);
46
- stat &= ~(1 << hwirq);
68
+ stat &= ~BIT(hwirq);
4769 }
4870 }
4971
5072 chained_irq_exit(chip, desc);
5173 }
74
+
75
+static int dw_apb_ictl_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
76
+ unsigned int nr_irqs, void *arg)
77
+{
78
+ int i, ret;
79
+ irq_hw_number_t hwirq;
80
+ unsigned int type = IRQ_TYPE_NONE;
81
+ struct irq_fwspec *fwspec = arg;
82
+
83
+ ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type);
84
+ if (ret)
85
+ return ret;
86
+
87
+ for (i = 0; i < nr_irqs; i++)
88
+ irq_map_generic_chip(domain, virq + i, hwirq + i);
89
+
90
+ return 0;
91
+}
92
+
93
+static const struct irq_domain_ops dw_apb_ictl_irq_domain_ops = {
94
+ .translate = irq_domain_translate_onecell,
95
+ .alloc = dw_apb_ictl_irq_domain_alloc,
96
+ .free = irq_domain_free_irqs_top,
97
+};
5298
5399 #ifdef CONFIG_PM
54100 static void dw_apb_ictl_resume(struct irq_data *d)
....@@ -68,19 +114,27 @@
68114 static int __init dw_apb_ictl_init(struct device_node *np,
69115 struct device_node *parent)
70116 {
117
+ const struct irq_domain_ops *domain_ops;
71118 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
72119 struct resource r;
73120 struct irq_domain *domain;
74121 struct irq_chip_generic *gc;
75122 void __iomem *iobase;
76
- int ret, nrirqs, irq, i;
123
+ int ret, nrirqs, parent_irq, i;
77124 u32 reg;
78125
79
- /* Map the parent interrupt for the chained handler */
80
- irq = irq_of_parse_and_map(np, 0);
81
- if (irq <= 0) {
82
- pr_err("%pOF: unable to parse irq\n", np);
83
- return -EINVAL;
126
+ if (!parent) {
127
+ /* Used as the primary interrupt controller */
128
+ parent_irq = 0;
129
+ domain_ops = &dw_apb_ictl_irq_domain_ops;
130
+ } else {
131
+ /* Map the parent interrupt for the chained handler */
132
+ parent_irq = irq_of_parse_and_map(np, 0);
133
+ if (parent_irq <= 0) {
134
+ pr_err("%pOF: unable to parse irq\n", np);
135
+ return -EINVAL;
136
+ }
137
+ domain_ops = &irq_generic_chip_ops;
84138 }
85139
86140 ret = of_address_to_resource(np, 0, &r);
....@@ -105,7 +159,7 @@
105159 * DW IP can be configured to allow 2-64 irqs. We can determine
106160 * the number of irqs supported by writing into enable register
107161 * and look for bits not set, as corresponding flip-flops will
108
- * have been removed by sythesis tool.
162
+ * have been removed by synthesis tool.
109163 */
110164
111165 /* mask and enable all interrupts */
....@@ -120,8 +174,7 @@
120174 else
121175 nrirqs = fls(readl_relaxed(iobase + APB_INT_ENABLE_L));
122176
123
- domain = irq_domain_add_linear(np, nrirqs,
124
- &irq_generic_chip_ops, NULL);
177
+ domain = irq_domain_add_linear(np, nrirqs, domain_ops, NULL);
125178 if (!domain) {
126179 pr_err("%pOF: unable to add irq domain\n", np);
127180 ret = -ENOMEM;
....@@ -146,7 +199,13 @@
146199 gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume;
147200 }
148201
149
- irq_set_chained_handler_and_data(irq, dw_apb_ictl_handler, domain);
202
+ if (parent_irq) {
203
+ irq_set_chained_handler_and_data(parent_irq,
204
+ dw_apb_ictl_handle_irq_cascaded, domain);
205
+ } else {
206
+ dw_apb_ictl_irq_domain = domain;
207
+ set_handle_irq(dw_apb_ictl_handle_irq);
208
+ }
150209
151210 return 0;
152211