0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bitops.h>
0011 #include <linux/irq.h>
0012 #include <linux/irqchip.h>
0013 #include <linux/irqdomain.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/kthread.h>
0019 #include <linux/delay.h>
0020 #include <linux/slab.h>
0021 #include <linux/of_irq.h>
0022
0023 #include <asm/machdep.h>
0024 #include <asm/opal.h>
0025
0026 #include "powernv.h"
0027
0028
0029 #define MAX_NUM_EVENTS 64
0030
0031 struct opal_event_irqchip {
0032 struct irq_chip irqchip;
0033 struct irq_domain *domain;
0034 unsigned long mask;
0035 };
0036 static struct opal_event_irqchip opal_event_irqchip;
0037 static u64 last_outstanding_events;
0038 static int opal_irq_count;
0039 static struct resource *opal_irqs;
0040
0041 void opal_handle_events(void)
0042 {
0043 __be64 events = 0;
0044 u64 e;
0045
0046 e = READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask;
0047 again:
0048 while (e) {
0049 int hwirq;
0050
0051 hwirq = fls64(e) - 1;
0052 e &= ~BIT_ULL(hwirq);
0053
0054 local_irq_disable();
0055 irq_enter();
0056 generic_handle_domain_irq(opal_event_irqchip.domain, hwirq);
0057 irq_exit();
0058 local_irq_enable();
0059
0060 cond_resched();
0061 }
0062 last_outstanding_events = 0;
0063 if (opal_poll_events(&events) != OPAL_SUCCESS)
0064 return;
0065 e = be64_to_cpu(events) & opal_event_irqchip.mask;
0066 if (e)
0067 goto again;
0068 }
0069
0070 bool opal_have_pending_events(void)
0071 {
0072 if (last_outstanding_events & opal_event_irqchip.mask)
0073 return true;
0074 return false;
0075 }
0076
0077 static void opal_event_mask(struct irq_data *d)
0078 {
0079 clear_bit(d->hwirq, &opal_event_irqchip.mask);
0080 }
0081
0082 static void opal_event_unmask(struct irq_data *d)
0083 {
0084 set_bit(d->hwirq, &opal_event_irqchip.mask);
0085 if (opal_have_pending_events())
0086 opal_wake_poller();
0087 }
0088
0089 static int opal_event_set_type(struct irq_data *d, unsigned int flow_type)
0090 {
0091
0092
0093
0094
0095
0096 if (flow_type != IRQ_TYPE_LEVEL_HIGH)
0097 return -EINVAL;
0098
0099 return 0;
0100 }
0101
0102 static struct opal_event_irqchip opal_event_irqchip = {
0103 .irqchip = {
0104 .name = "OPAL EVT",
0105 .irq_mask = opal_event_mask,
0106 .irq_unmask = opal_event_unmask,
0107 .irq_set_type = opal_event_set_type,
0108 },
0109 .mask = 0,
0110 };
0111
0112 static int opal_event_map(struct irq_domain *d, unsigned int irq,
0113 irq_hw_number_t hwirq)
0114 {
0115 irq_set_chip_data(irq, &opal_event_irqchip);
0116 irq_set_chip_and_handler(irq, &opal_event_irqchip.irqchip,
0117 handle_level_irq);
0118
0119 return 0;
0120 }
0121
0122 static irqreturn_t opal_interrupt(int irq, void *data)
0123 {
0124 __be64 events;
0125
0126 opal_handle_interrupt(virq_to_hw(irq), &events);
0127 last_outstanding_events = be64_to_cpu(events);
0128 if (opal_have_pending_events())
0129 opal_wake_poller();
0130
0131 return IRQ_HANDLED;
0132 }
0133
0134 static int opal_event_match(struct irq_domain *h, struct device_node *node,
0135 enum irq_domain_bus_token bus_token)
0136 {
0137 return irq_domain_get_of_node(h) == node;
0138 }
0139
0140 static int opal_event_xlate(struct irq_domain *h, struct device_node *np,
0141 const u32 *intspec, unsigned int intsize,
0142 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
0143 {
0144 *out_hwirq = intspec[0];
0145 *out_flags = IRQ_TYPE_LEVEL_HIGH;
0146
0147 return 0;
0148 }
0149
0150 static const struct irq_domain_ops opal_event_domain_ops = {
0151 .match = opal_event_match,
0152 .map = opal_event_map,
0153 .xlate = opal_event_xlate,
0154 };
0155
0156 void opal_event_shutdown(void)
0157 {
0158 unsigned int i;
0159
0160
0161 for (i = 0; i < opal_irq_count; i++) {
0162 if (!opal_irqs || !opal_irqs[i].start)
0163 continue;
0164
0165 if (in_interrupt() || irqs_disabled())
0166 disable_irq_nosync(opal_irqs[i].start);
0167 else
0168 free_irq(opal_irqs[i].start, NULL);
0169
0170 opal_irqs[i].start = 0;
0171 }
0172 }
0173
0174 int __init opal_event_init(void)
0175 {
0176 struct device_node *dn, *opal_node;
0177 bool old_style = false;
0178 int i, rc = 0;
0179
0180 opal_node = of_find_node_by_path("/ibm,opal");
0181 if (!opal_node) {
0182 pr_warn("opal: Node not found\n");
0183 return -ENODEV;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193 dn = of_find_compatible_node(NULL, NULL, "ibm,opal-event");
0194 opal_event_irqchip.domain = irq_domain_add_linear(dn, MAX_NUM_EVENTS,
0195 &opal_event_domain_ops, &opal_event_irqchip);
0196 of_node_put(dn);
0197 if (!opal_event_irqchip.domain) {
0198 pr_warn("opal: Unable to create irq domain\n");
0199 rc = -ENOMEM;
0200 goto out;
0201 }
0202
0203
0204 opal_irq_count = of_irq_count(opal_node);
0205
0206
0207 if (opal_irq_count < 1) {
0208
0209 rc = of_property_count_u32_elems(opal_node, "opal-interrupts");
0210 if (rc > 0)
0211 opal_irq_count = rc;
0212 old_style = true;
0213 }
0214
0215
0216 if (!opal_irq_count)
0217 goto out;
0218
0219 pr_debug("OPAL: Found %d interrupts reserved for OPAL using %s scheme\n",
0220 opal_irq_count, old_style ? "old" : "new");
0221
0222
0223 opal_irqs = kcalloc(opal_irq_count, sizeof(struct resource), GFP_KERNEL);
0224 if (WARN_ON(!opal_irqs)) {
0225 rc = -ENOMEM;
0226 goto out;
0227 }
0228
0229
0230 if (old_style) {
0231
0232 for (i = 0; i < opal_irq_count; i++) {
0233 struct resource *r = &opal_irqs[i];
0234 const char *name = NULL;
0235 u32 hw_irq;
0236 int virq;
0237
0238 rc = of_property_read_u32_index(opal_node, "opal-interrupts",
0239 i, &hw_irq);
0240 if (WARN_ON(rc < 0)) {
0241 opal_irq_count = i;
0242 break;
0243 }
0244 of_property_read_string_index(opal_node, "opal-interrupts-names",
0245 i, &name);
0246 virq = irq_create_mapping(NULL, hw_irq);
0247 if (!virq) {
0248 pr_warn("Failed to map OPAL irq 0x%x\n", hw_irq);
0249 continue;
0250 }
0251 r->start = r->end = virq;
0252 r->flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW;
0253 r->name = name;
0254 }
0255 } else {
0256
0257 rc = of_irq_to_resource_table(opal_node, opal_irqs, opal_irq_count);
0258 if (WARN_ON(rc < 0)) {
0259 opal_irq_count = 0;
0260 kfree(opal_irqs);
0261 goto out;
0262 }
0263 if (WARN_ON(rc < opal_irq_count))
0264 opal_irq_count = rc;
0265 }
0266
0267
0268 for (i = 0; i < opal_irq_count; i++) {
0269 struct resource *r = &opal_irqs[i];
0270 const char *name;
0271
0272
0273 if (r->name && strlen(r->name))
0274 name = kasprintf(GFP_KERNEL, "opal-%s", r->name);
0275 else
0276 name = kasprintf(GFP_KERNEL, "opal");
0277
0278
0279 rc = request_irq(r->start, opal_interrupt, r->flags & IRQD_TRIGGER_MASK,
0280 name, NULL);
0281 if (rc) {
0282 pr_warn("Error %d requesting OPAL irq %d\n", rc, (int)r->start);
0283 continue;
0284 }
0285 }
0286 rc = 0;
0287 out:
0288 of_node_put(opal_node);
0289 return rc;
0290 }
0291 machine_arch_initcall(powernv, opal_event_init);
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 int opal_event_request(unsigned int opal_event_nr)
0304 {
0305 if (WARN_ON_ONCE(!opal_event_irqchip.domain))
0306 return 0;
0307
0308 return irq_create_mapping(opal_event_irqchip.domain, opal_event_nr);
0309 }
0310 EXPORT_SYMBOL(opal_event_request);