0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/types.h>
0011 #include <linux/kernel.h>
0012 #include <linux/irq.h>
0013 #include <linux/smp.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/init.h>
0016 #include <linux/cpu.h>
0017 #include <linux/of.h>
0018 #include <linux/of_address.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/msi.h>
0021 #include <linux/list.h>
0022
0023 #include <asm/smp.h>
0024 #include <asm/machdep.h>
0025 #include <asm/irq.h>
0026 #include <asm/errno.h>
0027 #include <asm/xics.h>
0028 #include <asm/opal.h>
0029 #include <asm/firmware.h>
0030
0031 struct ics_native {
0032 struct ics ics;
0033 struct device_node *node;
0034 void __iomem *base;
0035 u32 ibase;
0036 u32 icount;
0037 };
0038 #define to_ics_native(_ics) container_of(_ics, struct ics_native, ics)
0039
0040 static void __iomem *ics_native_xive(struct ics_native *in, unsigned int vec)
0041 {
0042 return in->base + 0x800 + ((vec - in->ibase) << 2);
0043 }
0044
0045 static void ics_native_unmask_irq(struct irq_data *d)
0046 {
0047 unsigned int vec = (unsigned int)irqd_to_hwirq(d);
0048 struct ics *ics = irq_data_get_irq_chip_data(d);
0049 struct ics_native *in = to_ics_native(ics);
0050 unsigned int server;
0051
0052 pr_devel("ics-native: unmask virq %d [hw 0x%x]\n", d->irq, vec);
0053
0054 if (vec < in->ibase || vec >= (in->ibase + in->icount))
0055 return;
0056
0057 server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
0058 out_be32(ics_native_xive(in, vec), (server << 8) | DEFAULT_PRIORITY);
0059 }
0060
0061 static unsigned int ics_native_startup(struct irq_data *d)
0062 {
0063 #ifdef CONFIG_PCI_MSI
0064
0065
0066
0067
0068
0069 if (irq_data_get_msi_desc(d))
0070 pci_msi_unmask_irq(d);
0071 #endif
0072
0073
0074 ics_native_unmask_irq(d);
0075 return 0;
0076 }
0077
0078 static void ics_native_do_mask(struct ics_native *in, unsigned int vec)
0079 {
0080 out_be32(ics_native_xive(in, vec), 0xff);
0081 }
0082
0083 static void ics_native_mask_irq(struct irq_data *d)
0084 {
0085 unsigned int vec = (unsigned int)irqd_to_hwirq(d);
0086 struct ics *ics = irq_data_get_irq_chip_data(d);
0087 struct ics_native *in = to_ics_native(ics);
0088
0089 pr_devel("ics-native: mask virq %d [hw 0x%x]\n", d->irq, vec);
0090
0091 if (vec < in->ibase || vec >= (in->ibase + in->icount))
0092 return;
0093 ics_native_do_mask(in, vec);
0094 }
0095
0096 static int ics_native_set_affinity(struct irq_data *d,
0097 const struct cpumask *cpumask,
0098 bool force)
0099 {
0100 unsigned int vec = (unsigned int)irqd_to_hwirq(d);
0101 struct ics *ics = irq_data_get_irq_chip_data(d);
0102 struct ics_native *in = to_ics_native(ics);
0103 int server;
0104 u32 xive;
0105
0106 if (vec < in->ibase || vec >= (in->ibase + in->icount))
0107 return -EINVAL;
0108
0109 server = xics_get_irq_server(d->irq, cpumask, 1);
0110 if (server == -1) {
0111 pr_warn("%s: No online cpus in the mask %*pb for irq %d\n",
0112 __func__, cpumask_pr_args(cpumask), d->irq);
0113 return -1;
0114 }
0115
0116 xive = in_be32(ics_native_xive(in, vec));
0117 xive = (xive & 0xff) | (server << 8);
0118 out_be32(ics_native_xive(in, vec), xive);
0119
0120 return IRQ_SET_MASK_OK;
0121 }
0122
0123 static struct irq_chip ics_native_irq_chip = {
0124 .name = "ICS",
0125 .irq_startup = ics_native_startup,
0126 .irq_mask = ics_native_mask_irq,
0127 .irq_unmask = ics_native_unmask_irq,
0128 .irq_eoi = NULL,
0129 .irq_set_affinity = ics_native_set_affinity,
0130 .irq_set_type = xics_set_irq_type,
0131 .irq_retrigger = xics_retrigger,
0132 };
0133
0134 static int ics_native_check(struct ics *ics, unsigned int hw_irq)
0135 {
0136 struct ics_native *in = to_ics_native(ics);
0137
0138 pr_devel("%s: hw_irq=0x%x\n", __func__, hw_irq);
0139
0140 if (hw_irq < in->ibase || hw_irq >= (in->ibase + in->icount))
0141 return -EINVAL;
0142
0143 return 0;
0144 }
0145
0146 static void ics_native_mask_unknown(struct ics *ics, unsigned long vec)
0147 {
0148 struct ics_native *in = to_ics_native(ics);
0149
0150 if (vec < in->ibase || vec >= (in->ibase + in->icount))
0151 return;
0152
0153 ics_native_do_mask(in, vec);
0154 }
0155
0156 static long ics_native_get_server(struct ics *ics, unsigned long vec)
0157 {
0158 struct ics_native *in = to_ics_native(ics);
0159 u32 xive;
0160
0161 if (vec < in->ibase || vec >= (in->ibase + in->icount))
0162 return -EINVAL;
0163
0164 xive = in_be32(ics_native_xive(in, vec));
0165 return (xive >> 8) & 0xfff;
0166 }
0167
0168 static int ics_native_host_match(struct ics *ics, struct device_node *node)
0169 {
0170 struct ics_native *in = to_ics_native(ics);
0171
0172 return in->node == node;
0173 }
0174
0175 static struct ics ics_native_template = {
0176 .check = ics_native_check,
0177 .mask_unknown = ics_native_mask_unknown,
0178 .get_server = ics_native_get_server,
0179 .host_match = ics_native_host_match,
0180 .chip = &ics_native_irq_chip,
0181 };
0182
0183 static int __init ics_native_add_one(struct device_node *np)
0184 {
0185 struct ics_native *ics;
0186 u32 ranges[2];
0187 int rc, count;
0188
0189 ics = kzalloc(sizeof(struct ics_native), GFP_KERNEL);
0190 if (!ics)
0191 return -ENOMEM;
0192 ics->node = of_node_get(np);
0193 memcpy(&ics->ics, &ics_native_template, sizeof(struct ics));
0194
0195 ics->base = of_iomap(np, 0);
0196 if (!ics->base) {
0197 pr_err("Failed to map %pOFP\n", np);
0198 rc = -ENOMEM;
0199 goto fail;
0200 }
0201
0202 count = of_property_count_u32_elems(np, "interrupt-ranges");
0203 if (count < 2 || count & 1) {
0204 pr_err("Failed to read interrupt-ranges of %pOFP\n", np);
0205 rc = -EINVAL;
0206 goto fail;
0207 }
0208 if (count > 2) {
0209 pr_warn("ICS %pOFP has %d ranges, only one supported\n",
0210 np, count >> 1);
0211 }
0212 rc = of_property_read_u32_array(np, "interrupt-ranges",
0213 ranges, 2);
0214 if (rc) {
0215 pr_err("Failed to read interrupt-ranges of %pOFP\n", np);
0216 goto fail;
0217 }
0218 ics->ibase = ranges[0];
0219 ics->icount = ranges[1];
0220
0221 pr_info("ICS native initialized for sources %d..%d\n",
0222 ics->ibase, ics->ibase + ics->icount - 1);
0223
0224
0225 xics_register_ics(&ics->ics);
0226
0227 return 0;
0228 fail:
0229 of_node_put(ics->node);
0230 kfree(ics);
0231 return rc;
0232 }
0233
0234 int __init ics_native_init(void)
0235 {
0236 struct device_node *ics;
0237 bool found_one = false;
0238
0239
0240
0241
0242 ics_native_irq_chip.irq_eoi = icp_ops->eoi;
0243
0244
0245 for_each_compatible_node(ics, NULL, "openpower,xics-sources") {
0246 if (ics_native_add_one(ics) == 0)
0247 found_one = true;
0248 }
0249
0250 if (found_one)
0251 pr_info("ICS native backend registered\n");
0252
0253 return found_one ? 0 : -ENODEV;
0254 }