Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/types.h>
0003 #include <linux/kernel.h>
0004 #include <linux/irq.h>
0005 #include <linux/smp.h>
0006 #include <linux/interrupt.h>
0007 #include <linux/init.h>
0008 #include <linux/cpu.h>
0009 #include <linux/of.h>
0010 #include <linux/spinlock.h>
0011 #include <linux/msi.h>
0012 
0013 #include <asm/smp.h>
0014 #include <asm/machdep.h>
0015 #include <asm/irq.h>
0016 #include <asm/errno.h>
0017 #include <asm/xics.h>
0018 #include <asm/rtas.h>
0019 
0020 /* RTAS service tokens */
0021 static int ibm_get_xive;
0022 static int ibm_set_xive;
0023 static int ibm_int_on;
0024 static int ibm_int_off;
0025 
0026 static void ics_rtas_unmask_irq(struct irq_data *d)
0027 {
0028     unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
0029     int call_status;
0030     int server;
0031 
0032     pr_devel("xics: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
0033 
0034     if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
0035         return;
0036 
0037     server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
0038 
0039     call_status = rtas_call_reentrant(ibm_set_xive, 3, 1, NULL, hw_irq,
0040                       server, DEFAULT_PRIORITY);
0041     if (call_status != 0) {
0042         printk(KERN_ERR
0043             "%s: ibm_set_xive irq %u server %x returned %d\n",
0044             __func__, hw_irq, server, call_status);
0045         return;
0046     }
0047 
0048     /* Now unmask the interrupt (often a no-op) */
0049     call_status = rtas_call_reentrant(ibm_int_on, 1, 1, NULL, hw_irq);
0050     if (call_status != 0) {
0051         printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
0052             __func__, hw_irq, call_status);
0053         return;
0054     }
0055 }
0056 
0057 static unsigned int ics_rtas_startup(struct irq_data *d)
0058 {
0059     /* unmask it */
0060     ics_rtas_unmask_irq(d);
0061     return 0;
0062 }
0063 
0064 static void ics_rtas_mask_real_irq(unsigned int hw_irq)
0065 {
0066     int call_status;
0067 
0068     if (hw_irq == XICS_IPI)
0069         return;
0070 
0071     call_status = rtas_call_reentrant(ibm_int_off, 1, 1, NULL, hw_irq);
0072     if (call_status != 0) {
0073         printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
0074             __func__, hw_irq, call_status);
0075         return;
0076     }
0077 
0078     /* Have to set XIVE to 0xff to be able to remove a slot */
0079     call_status = rtas_call_reentrant(ibm_set_xive, 3, 1, NULL, hw_irq,
0080                       xics_default_server, 0xff);
0081     if (call_status != 0) {
0082         printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
0083             __func__, hw_irq, call_status);
0084         return;
0085     }
0086 }
0087 
0088 static void ics_rtas_mask_irq(struct irq_data *d)
0089 {
0090     unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
0091 
0092     pr_devel("xics: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
0093 
0094     if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
0095         return;
0096     ics_rtas_mask_real_irq(hw_irq);
0097 }
0098 
0099 static int ics_rtas_set_affinity(struct irq_data *d,
0100                  const struct cpumask *cpumask,
0101                  bool force)
0102 {
0103     unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
0104     int status;
0105     int xics_status[2];
0106     int irq_server;
0107 
0108     if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
0109         return -1;
0110 
0111     status = rtas_call_reentrant(ibm_get_xive, 1, 3, xics_status, hw_irq);
0112 
0113     if (status) {
0114         printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
0115             __func__, hw_irq, status);
0116         return -1;
0117     }
0118 
0119     irq_server = xics_get_irq_server(d->irq, cpumask, 1);
0120     if (irq_server == -1) {
0121         pr_warn("%s: No online cpus in the mask %*pb for irq %d\n",
0122             __func__, cpumask_pr_args(cpumask), d->irq);
0123         return -1;
0124     }
0125 
0126     pr_debug("%s: irq %d [hw 0x%x] server: 0x%x\n", __func__, d->irq,
0127          hw_irq, irq_server);
0128 
0129     status = rtas_call_reentrant(ibm_set_xive, 3, 1, NULL,
0130                      hw_irq, irq_server, xics_status[1]);
0131 
0132     if (status) {
0133         printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
0134             __func__, hw_irq, status);
0135         return -1;
0136     }
0137 
0138     return IRQ_SET_MASK_OK;
0139 }
0140 
0141 static struct irq_chip ics_rtas_irq_chip = {
0142     .name = "XICS",
0143     .irq_startup = ics_rtas_startup,
0144     .irq_mask = ics_rtas_mask_irq,
0145     .irq_unmask = ics_rtas_unmask_irq,
0146     .irq_eoi = NULL, /* Patched at init time */
0147     .irq_set_affinity = ics_rtas_set_affinity,
0148     .irq_set_type = xics_set_irq_type,
0149     .irq_retrigger = xics_retrigger,
0150 };
0151 
0152 static int ics_rtas_check(struct ics *ics, unsigned int hw_irq)
0153 {
0154     int status[2];
0155     int rc;
0156 
0157     if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
0158         return -EINVAL;
0159 
0160     /* Check if RTAS knows about this interrupt */
0161     rc = rtas_call_reentrant(ibm_get_xive, 1, 3, status, hw_irq);
0162     if (rc)
0163         return -ENXIO;
0164 
0165     return 0;
0166 }
0167 
0168 static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec)
0169 {
0170     ics_rtas_mask_real_irq(vec);
0171 }
0172 
0173 static long ics_rtas_get_server(struct ics *ics, unsigned long vec)
0174 {
0175     int rc, status[2];
0176 
0177     rc = rtas_call_reentrant(ibm_get_xive, 1, 3, status, vec);
0178     if (rc)
0179         return -1;
0180     return status[0];
0181 }
0182 
0183 static int ics_rtas_host_match(struct ics *ics, struct device_node *node)
0184 {
0185     /* IBM machines have interrupt parents of various funky types for things
0186      * like vdevices, events, etc... The trick we use here is to match
0187      * everything here except the legacy 8259 which is compatible "chrp,iic"
0188      */
0189     return !of_device_is_compatible(node, "chrp,iic");
0190 }
0191 
0192 /* Only one global & state struct ics */
0193 static struct ics ics_rtas = {
0194     .check      = ics_rtas_check,
0195     .mask_unknown   = ics_rtas_mask_unknown,
0196     .get_server = ics_rtas_get_server,
0197     .host_match = ics_rtas_host_match,
0198     .chip = &ics_rtas_irq_chip,
0199 };
0200 
0201 __init int ics_rtas_init(void)
0202 {
0203     ibm_get_xive = rtas_token("ibm,get-xive");
0204     ibm_set_xive = rtas_token("ibm,set-xive");
0205     ibm_int_on  = rtas_token("ibm,int-on");
0206     ibm_int_off = rtas_token("ibm,int-off");
0207 
0208     /* We enable the RTAS "ICS" if RTAS is present with the
0209      * appropriate tokens
0210      */
0211     if (ibm_get_xive == RTAS_UNKNOWN_SERVICE ||
0212         ibm_set_xive == RTAS_UNKNOWN_SERVICE)
0213         return -ENODEV;
0214 
0215     /* We need to patch our irq chip's EOI to point to the
0216      * right ICP
0217      */
0218     ics_rtas_irq_chip.irq_eoi = icp_ops->eoi;
0219 
0220     /* Register ourselves */
0221     xics_register_ics(&ics_rtas);
0222 
0223     return 0;
0224 }
0225