aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/common/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/netlogic/common/irq.c')
-rw-r--r--arch/mips/netlogic/common/irq.c72
1 files changed, 55 insertions, 17 deletions
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 1c7e3a1b81ab..5afc4b7fce0f 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -180,6 +180,7 @@ static void __init nlm_init_percpu_irqs(void)
180#endif 180#endif
181} 181}
182 182
183
183void nlm_setup_pic_irq(int node, int picirq, int irq, int irt) 184void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
184{ 185{
185 struct nlm_pic_irq *pic_data; 186 struct nlm_pic_irq *pic_data;
@@ -207,32 +208,32 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
207 208
208static void nlm_init_node_irqs(int node) 209static void nlm_init_node_irqs(int node)
209{ 210{
210 int i, irt;
211 uint64_t irqmask;
212 struct nlm_soc_info *nodep; 211 struct nlm_soc_info *nodep;
212 int i, irt;
213 213
214 pr_info("Init IRQ for node %d\n", node); 214 pr_info("Init IRQ for node %d\n", node);
215 nodep = nlm_get_node(node); 215 nodep = nlm_get_node(node);
216 irqmask = PERCPU_IRQ_MASK; 216 nodep->irqmask = PERCPU_IRQ_MASK;
217 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) { 217 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
218 irt = nlm_irq_to_irt(i); 218 irt = nlm_irq_to_irt(i);
219 if (irt == -1) 219 if (irt == -1) /* unused irq */
220 continue; 220 continue;
221 nlm_setup_pic_irq(node, i, i, irt); 221 nodep->irqmask |= 1ull << i;
222 /* set interrupts to first cpu in node */ 222 if (irt == -2) /* not a direct PIC irq */
223 continue;
224
223 nlm_pic_init_irt(nodep->picbase, irt, i, 225 nlm_pic_init_irt(nodep->picbase, irt, i,
224 node * NLM_CPUS_PER_NODE, 0); 226 node * nlm_threads_per_node(), 0);
225 irqmask |= (1ull << i); 227 nlm_setup_pic_irq(node, i, i, irt);
226 } 228 }
227 nodep->irqmask = irqmask;
228} 229}
229 230
230void nlm_smp_irq_init(int hwcpuid) 231void nlm_smp_irq_init(int hwcpuid)
231{ 232{
232 int node, cpu; 233 int node, cpu;
233 234
234 node = hwcpuid / NLM_CPUS_PER_NODE; 235 node = nlm_cpuid_to_node(hwcpuid);
235 cpu = hwcpuid % NLM_CPUS_PER_NODE; 236 cpu = hwcpuid % nlm_threads_per_node();
236 237
237 if (cpu == 0 && node != 0) 238 if (cpu == 0 && node != 0)
238 nlm_init_node_irqs(node); 239 nlm_init_node_irqs(node);
@@ -256,13 +257,23 @@ asmlinkage void plat_irq_dispatch(void)
256 return; 257 return;
257 } 258 }
258 259
260#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP)
261 /* PCI interrupts need a second level dispatch for MSI bits */
262 if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) {
263 nlm_dispatch_msi(node, i);
264 return;
265 }
266 if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) {
267 nlm_dispatch_msix(node, i);
268 return;
269 }
270
271#endif
259 /* top level irq handling */ 272 /* top level irq handling */
260 do_IRQ(nlm_irq_to_xirq(node, i)); 273 do_IRQ(nlm_irq_to_xirq(node, i));
261} 274}
262 275
263#ifdef CONFIG_OF 276#ifdef CONFIG_OF
264static struct irq_domain *xlp_pic_domain;
265
266static const struct irq_domain_ops xlp_pic_irq_domain_ops = { 277static const struct irq_domain_ops xlp_pic_irq_domain_ops = {
267 .xlate = irq_domain_xlate_onetwocell, 278 .xlate = irq_domain_xlate_onetwocell,
268}; 279};
@@ -271,8 +282,9 @@ static int __init xlp_of_pic_init(struct device_node *node,
271 struct device_node *parent) 282 struct device_node *parent)
272{ 283{
273 const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1; 284 const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1;
285 struct irq_domain *xlp_pic_domain;
274 struct resource res; 286 struct resource res;
275 int socid, ret; 287 int socid, ret, bus;
276 288
277 /* we need a hack to get the PIC's SoC chip id */ 289 /* we need a hack to get the PIC's SoC chip id */
278 ret = of_address_to_resource(node, 0, &res); 290 ret = of_address_to_resource(node, 0, &res);
@@ -280,7 +292,34 @@ static int __init xlp_of_pic_init(struct device_node *node,
280 pr_err("PIC %s: reg property not found!\n", node->name); 292 pr_err("PIC %s: reg property not found!\n", node->name);
281 return -EINVAL; 293 return -EINVAL;
282 } 294 }
283 socid = (res.start >> 18) & 0x3; 295
296 if (cpu_is_xlp9xx()) {
297 bus = (res.start >> 20) & 0xf;
298 for (socid = 0; socid < NLM_NR_NODES; socid++) {
299 if (!nlm_node_present(socid))
300 continue;
301 if (nlm_get_node(socid)->socbus == bus)
302 break;
303 }
304 if (socid == NLM_NR_NODES) {
305 pr_err("PIC %s: Node mapping for bus %d not found!\n",
306 node->name, bus);
307 return -EINVAL;
308 }
309 } else {
310 socid = (res.start >> 18) & 0x3;
311 if (!nlm_node_present(socid)) {
312 pr_err("PIC %s: node %d does not exist!\n",
313 node->name, socid);
314 return -EINVAL;
315 }
316 }
317
318 if (!nlm_node_present(socid)) {
319 pr_err("PIC %s: node %d does not exist!\n", node->name, socid);
320 return -EINVAL;
321 }
322
284 xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs, 323 xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs,
285 nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE, 324 nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE,
286 &xlp_pic_irq_domain_ops, NULL); 325 &xlp_pic_irq_domain_ops, NULL);
@@ -288,8 +327,7 @@ static int __init xlp_of_pic_init(struct device_node *node,
288 pr_err("PIC %s: Creating legacy domain failed!\n", node->name); 327 pr_err("PIC %s: Creating legacy domain failed!\n", node->name);
289 return -EINVAL; 328 return -EINVAL;
290 } 329 }
291 pr_info("Node %d: IRQ domain created for PIC@%pa\n", socid, 330 pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res);
292 &res.start);
293 return 0; 331 return 0;
294} 332}
295 333