1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This file implements an irqchip for OPAL events. Whenever there is
4 * an interrupt that is handled by OPAL we get passed a list of events
5 * that Linux needs to do something about. These basically look like
6 * interrupts to Linux so we implement an irqchip to handle them.
8 * Copyright Alistair Popple, IBM Corporation 2014.
10 #include <linux/bitops.h>
11 #include <linux/irq.h>
12 #include <linux/irqchip.h>
13 #include <linux/irqdomain.h>
14 #include <linux/interrupt.h>
15 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/kthread.h>
19 #include <linux/delay.h>
20 #include <linux/slab.h>
21 #include <linux/of_irq.h>
23 #include <asm/machdep.h>
28 /* Maximum number of events supported by OPAL firmware */
29 #define MAX_NUM_EVENTS 64
31 struct opal_event_irqchip
{
32 struct irq_chip irqchip
;
33 struct irq_domain
*domain
;
36 static struct opal_event_irqchip opal_event_irqchip
;
37 static u64 last_outstanding_events
;
38 static int opal_irq_count
;
39 static struct resource
*opal_irqs
;
41 void opal_handle_events(void)
46 e
= READ_ONCE(last_outstanding_events
) & opal_event_irqchip
.mask
;
55 virq
= irq_find_mapping(opal_event_irqchip
.domain
, hwirq
);
58 generic_handle_irq(virq
);
65 last_outstanding_events
= 0;
66 if (opal_poll_events(&events
) != OPAL_SUCCESS
)
68 e
= be64_to_cpu(events
) & opal_event_irqchip
.mask
;
73 bool opal_have_pending_events(void)
75 if (last_outstanding_events
& opal_event_irqchip
.mask
)
80 static void opal_event_mask(struct irq_data
*d
)
82 clear_bit(d
->hwirq
, &opal_event_irqchip
.mask
);
85 static void opal_event_unmask(struct irq_data
*d
)
87 set_bit(d
->hwirq
, &opal_event_irqchip
.mask
);
88 if (opal_have_pending_events())
92 static int opal_event_set_type(struct irq_data
*d
, unsigned int flow_type
)
95 * For now we only support level triggered events. The irq
96 * handler will be called continuously until the event has
97 * been cleared in OPAL.
99 if (flow_type
!= IRQ_TYPE_LEVEL_HIGH
)
105 static struct opal_event_irqchip opal_event_irqchip
= {
108 .irq_mask
= opal_event_mask
,
109 .irq_unmask
= opal_event_unmask
,
110 .irq_set_type
= opal_event_set_type
,
115 static int opal_event_map(struct irq_domain
*d
, unsigned int irq
,
116 irq_hw_number_t hwirq
)
118 irq_set_chip_data(irq
, &opal_event_irqchip
);
119 irq_set_chip_and_handler(irq
, &opal_event_irqchip
.irqchip
,
125 static irqreturn_t
opal_interrupt(int irq
, void *data
)
129 opal_handle_interrupt(virq_to_hw(irq
), &events
);
130 last_outstanding_events
= be64_to_cpu(events
);
131 if (opal_have_pending_events())
137 static int opal_event_match(struct irq_domain
*h
, struct device_node
*node
,
138 enum irq_domain_bus_token bus_token
)
140 return irq_domain_get_of_node(h
) == node
;
143 static int opal_event_xlate(struct irq_domain
*h
, struct device_node
*np
,
144 const u32
*intspec
, unsigned int intsize
,
145 irq_hw_number_t
*out_hwirq
, unsigned int *out_flags
)
147 *out_hwirq
= intspec
[0];
148 *out_flags
= IRQ_TYPE_LEVEL_HIGH
;
153 static const struct irq_domain_ops opal_event_domain_ops
= {
154 .match
= opal_event_match
,
155 .map
= opal_event_map
,
156 .xlate
= opal_event_xlate
,
159 void opal_event_shutdown(void)
163 /* First free interrupts, which will also mask them */
164 for (i
= 0; i
< opal_irq_count
; i
++) {
165 if (!opal_irqs
|| !opal_irqs
[i
].start
)
168 if (in_interrupt() || irqs_disabled())
169 disable_irq_nosync(opal_irqs
[i
].start
);
171 free_irq(opal_irqs
[i
].start
, NULL
);
173 opal_irqs
[i
].start
= 0;
177 int __init
opal_event_init(void)
179 struct device_node
*dn
, *opal_node
;
180 bool old_style
= false;
183 opal_node
= of_find_node_by_path("/ibm,opal");
185 pr_warn("opal: Node not found\n");
189 /* If dn is NULL it means the domain won't be linked to a DT
190 * node so therefore irq_of_parse_and_map(...) wont work. But
191 * that shouldn't be problem because if we're running a
192 * version of skiboot that doesn't have the dn then the
193 * devices won't have the correct properties and will have to
194 * fall back to the legacy method (opal_event_request(...))
196 dn
= of_find_compatible_node(NULL
, NULL
, "ibm,opal-event");
197 opal_event_irqchip
.domain
= irq_domain_add_linear(dn
, MAX_NUM_EVENTS
,
198 &opal_event_domain_ops
, &opal_event_irqchip
);
200 if (!opal_event_irqchip
.domain
) {
201 pr_warn("opal: Unable to create irq domain\n");
206 /* Look for new-style (standard) "interrupts" property */
207 opal_irq_count
= of_irq_count(opal_node
);
209 /* Absent ? Look for the old one */
210 if (opal_irq_count
< 1) {
211 /* Get opal-interrupts property and names if present */
212 rc
= of_property_count_u32_elems(opal_node
, "opal-interrupts");
218 /* No interrupts ? Bail out */
222 pr_debug("OPAL: Found %d interrupts reserved for OPAL using %s scheme\n",
223 opal_irq_count
, old_style
? "old" : "new");
225 /* Allocate an IRQ resources array */
226 opal_irqs
= kcalloc(opal_irq_count
, sizeof(struct resource
), GFP_KERNEL
);
227 if (WARN_ON(!opal_irqs
)) {
232 /* Build the resources array */
234 /* Old style "opal-interrupts" property */
235 for (i
= 0; i
< opal_irq_count
; i
++) {
236 struct resource
*r
= &opal_irqs
[i
];
237 const char *name
= NULL
;
241 rc
= of_property_read_u32_index(opal_node
, "opal-interrupts",
243 if (WARN_ON(rc
< 0)) {
247 of_property_read_string_index(opal_node
, "opal-interrupts-names",
249 virq
= irq_create_mapping(NULL
, hw_irq
);
251 pr_warn("Failed to map OPAL irq 0x%x\n", hw_irq
);
254 r
->start
= r
->end
= virq
;
255 r
->flags
= IORESOURCE_IRQ
| IRQ_TYPE_LEVEL_LOW
;
259 /* new style standard "interrupts" property */
260 rc
= of_irq_to_resource_table(opal_node
, opal_irqs
, opal_irq_count
);
261 if (WARN_ON(rc
< 0)) {
266 if (WARN_ON(rc
< opal_irq_count
))
270 /* Install interrupt handlers */
271 for (i
= 0; i
< opal_irq_count
; i
++) {
272 struct resource
*r
= &opal_irqs
[i
];
276 if (r
->name
&& strlen(r
->name
))
277 name
= kasprintf(GFP_KERNEL
, "opal-%s", r
->name
);
279 name
= kasprintf(GFP_KERNEL
, "opal");
281 /* Install interrupt handler */
282 rc
= request_irq(r
->start
, opal_interrupt
, r
->flags
& IRQD_TRIGGER_MASK
,
285 pr_warn("Error %d requesting OPAL irq %d\n", rc
, (int)r
->start
);
291 of_node_put(opal_node
);
294 machine_arch_initcall(powernv
, opal_event_init
);
297 * opal_event_request(unsigned int opal_event_nr) - Request an event
298 * @opal_event_nr: the opal event number to request
300 * This routine can be used to find the linux virq number which can
301 * then be passed to request_irq to assign a handler for a particular
302 * opal event. This should only be used by legacy devices which don't
303 * have proper device tree bindings. Most devices should use
304 * irq_of_parse_and_map() instead.
306 int opal_event_request(unsigned int opal_event_nr
)
308 if (WARN_ON_ONCE(!opal_event_irqchip
.domain
))
311 return irq_create_mapping(opal_event_irqchip
.domain
, opal_event_nr
);
313 EXPORT_SYMBOL(opal_event_request
);