10b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/types.h> 20b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/kernel.h> 30b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/irq.h> 40b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/smp.h> 50b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/interrupt.h> 60b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/init.h> 70b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/cpu.h> 80b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/of.h> 90b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/spinlock.h> 100b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <linux/msi.h> 110b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 120b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/prom.h> 130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/smp.h> 140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/machdep.h> 150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/irq.h> 160b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/errno.h> 170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/xics.h> 180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#include <asm/rtas.h> 190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 200b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* RTAS service tokens */ 210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ibm_get_xive; 220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ibm_set_xive; 230b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ibm_int_on; 240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ibm_int_off; 250b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ics_rtas_map(struct ics *ics, unsigned int virq); 270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec); 280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic long ics_rtas_get_server(struct ics *ics, unsigned long vec); 295ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellermanstatic int ics_rtas_host_match(struct ics *ics, struct device_node *node); 300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt/* Only one global & state struct ics */ 320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic struct ics ics_rtas = { 330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .map = ics_rtas_map, 340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .mask_unknown = ics_rtas_mask_unknown, 350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .get_server = ics_rtas_get_server, 365ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman .host_match = ics_rtas_host_match, 370b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt}; 380b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void ics_rtas_unmask_irq(struct irq_data *d) 400b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 41476eb4912601a8c01e6702b9a029f476b4b131d2Grant Likely unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); 420b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int call_status; 430b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int server; 440b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 450b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt pr_devel("xics: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq); 460b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 470b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) 480b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 490b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 500b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt server = xics_get_irq_server(d->irq, d->affinity, 0); 510b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 520b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq, server, 530b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt DEFAULT_PRIORITY); 540b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (call_status != 0) { 550b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR 560b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt "%s: ibm_set_xive irq %u server %x returned %d\n", 570b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, hw_irq, server, call_status); 580b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 590b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 600b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 610b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Now unmask the interrupt (often a no-op) */ 620b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt call_status = rtas_call(ibm_int_on, 1, 1, NULL, hw_irq); 630b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (call_status != 0) { 640b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n", 650b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, hw_irq, call_status); 660b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 670b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 680b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 690b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 700b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic unsigned int ics_rtas_startup(struct irq_data *d) 710b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 720b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#ifdef CONFIG_PCI_MSI 730b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* 740b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * The generic MSI code returns with the interrupt disabled on the 750b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * card, using the MSI mask bits. Firmware doesn't appear to unmask 760b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * at that level, so we do it here by hand. 770b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 780b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (d->msi_desc) 790b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt unmask_msi_irq(d); 800b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt#endif 810b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* unmask it */ 820b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ics_rtas_unmask_irq(d); 830b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return 0; 840b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 850b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 860b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void ics_rtas_mask_real_irq(unsigned int hw_irq) 870b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 880b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int call_status; 890b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 900b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (hw_irq == XICS_IPI) 910b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 920b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 930b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt call_status = rtas_call(ibm_int_off, 1, 1, NULL, hw_irq); 940b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (call_status != 0) { 950b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n", 960b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, hw_irq, call_status); 970b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 980b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 990b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1000b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Have to set XIVE to 0xff to be able to remove a slot */ 1010b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq, 1020b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_default_server, 0xff); 1030b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (call_status != 0) { 1040b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n", 1050b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, hw_irq, call_status); 1060b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 1070b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 1080b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1090b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1100b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void ics_rtas_mask_irq(struct irq_data *d) 1110b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 112476eb4912601a8c01e6702b9a029f476b4b131d2Grant Likely unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); 1130b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1140b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt pr_devel("xics: mask virq %d [hw 0x%x]\n", d->irq, hw_irq); 1150b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1160b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) 1170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return; 1180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ics_rtas_mask_real_irq(hw_irq); 1190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1200b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ics_rtas_set_affinity(struct irq_data *d, 1220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt const struct cpumask *cpumask, 1230b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt bool force) 1240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 125476eb4912601a8c01e6702b9a029f476b4b131d2Grant Likely unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); 1260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int status; 1270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int xics_status[2]; 1280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int irq_server; 1290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) 1310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -1; 1320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt status = rtas_call(ibm_get_xive, 1, 3, xics_status, hw_irq); 1340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (status) { 1360b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n", 1370b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, hw_irq, status); 1380b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -1; 1390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 1400b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1410b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_server = xics_get_irq_server(d->irq, cpumask, 1); 1420b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (irq_server == -1) { 1430b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt char cpulist[128]; 1440b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); 1450b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_WARNING 1460b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt "%s: No online cpus in the mask %s for irq %d\n", 1470b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, cpulist, d->irq); 1480b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -1; 1490b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 1500b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1510b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt status = rtas_call(ibm_set_xive, 3, 1, NULL, 1520b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt hw_irq, irq_server, xics_status[1]); 1530b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1540b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (status) { 1550b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n", 1560b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt __func__, hw_irq, status); 1570b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -1; 1580b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt } 1590b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1600b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return IRQ_SET_MASK_OK; 1610b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1620b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1630b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic struct irq_chip ics_rtas_irq_chip = { 1640b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .name = "XICS", 1650b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_startup = ics_rtas_startup, 1660b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_mask = ics_rtas_mask_irq, 1670b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_unmask = ics_rtas_unmask_irq, 1680b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_eoi = NULL, /* Patched at init time */ 1690b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt .irq_set_affinity = ics_rtas_set_affinity 1700b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt}; 1710b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1720b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic int ics_rtas_map(struct ics *ics, unsigned int virq) 1730b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 174476eb4912601a8c01e6702b9a029f476b4b131d2Grant Likely unsigned int hw_irq = (unsigned int)virq_to_hw(virq); 1750b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int status[2]; 1760b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int rc; 1770b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1780b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)) 1790b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -EINVAL; 1800b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1810b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Check if RTAS knows about this interrupt */ 1820b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt rc = rtas_call(ibm_get_xive, 1, 3, status, hw_irq); 1830b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (rc) 1840b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -ENXIO; 1850b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1860b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_set_chip_and_handler(virq, &ics_rtas_irq_chip, handle_fasteoi_irq); 1870b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt irq_set_chip_data(virq, &ics_rtas); 1880b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1890b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return 0; 1900b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1910b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1920b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec) 1930b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1940b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ics_rtas_mask_real_irq(vec); 1950b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 1960b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 1970b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidtstatic long ics_rtas_get_server(struct ics *ics, unsigned long vec) 1980b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 1990b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt int rc, status[2]; 2000b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2010b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt rc = rtas_call(ibm_get_xive, 1, 3, status, vec); 2020b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (rc) 2030b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -1; 2040b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return status[0]; 2050b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 2060b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2075ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellermanstatic int ics_rtas_host_match(struct ics *ics, struct device_node *node) 2085ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman{ 2095ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman /* IBM machines have interrupt parents of various funky types for things 2105ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman * like vdevices, events, etc... The trick we use here is to match 2115ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman * everything here except the legacy 8259 which is compatible "chrp,iic" 2125ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman */ 2135ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman return !of_device_is_compatible(node, "chrp,iic"); 2145ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman} 2155ca123760177ed16cbd9bab609bff69eb8fc45bdMichael Ellerman 216174ea471c395d70ee0c839ad59ca49f3b702de58Daniel Borkmann__init int ics_rtas_init(void) 2170b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt{ 2180b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ibm_get_xive = rtas_token("ibm,get-xive"); 2190b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ibm_set_xive = rtas_token("ibm,set-xive"); 2200b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ibm_int_on = rtas_token("ibm,int-on"); 2210b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ibm_int_off = rtas_token("ibm,int-off"); 2220b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2230b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* We enable the RTAS "ICS" if RTAS is present with the 2240b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * appropriate tokens 2250b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 2260b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt if (ibm_get_xive == RTAS_UNKNOWN_SERVICE || 2270b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ibm_set_xive == RTAS_UNKNOWN_SERVICE) 2280b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return -ENODEV; 2290b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2300b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* We need to patch our irq chip's EOI to point to the 2310b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt * right ICP 2320b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt */ 2330b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt ics_rtas_irq_chip.irq_eoi = icp_ops->eoi; 2340b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2350b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt /* Register ourselves */ 2360b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt xics_register_ics(&ics_rtas); 2370b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 2380b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt return 0; 2390b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt} 2400b05ac6e24807f0c26f763b3a546c0bcbf84125fBenjamin Herrenschmidt 241