Lines Matching +full:riscv +full:- +full:v +full:- +full:spec

1 // SPDX-License-Identifier: GPL-2.0
24 * This driver implements a version of the RISC-V PLIC with the actual layout
27 * https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf
29 * The largest number supported by devices marked as 'sifive,plic-1.0.0', is
30 * 1024, of which device 0 is defined as non-existent by the RISC-V Privileged
31 * Spec.
106 raw_spin_lock(&handler->enable_lock); in plic_toggle()
107 __plic_toggle(handler->enable_base, hwirq, enable); in plic_toggle()
108 raw_spin_unlock(&handler->enable_lock); in plic_toggle()
119 plic_toggle(handler, d->hwirq, enable); in plic_irq_toggle()
137 writel(1, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); in plic_irq_unmask()
144 writel(0, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); in plic_irq_mask()
151 writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); in plic_irq_eoi()
162 cpumask_and(&amask, &priv->lmask, mask_val); in plic_set_affinity()
170 return -EINVAL; in plic_set_affinity()
217 if (!test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_set_type()
230 return -EINVAL; in plic_irq_set_type()
242 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_suspend()
244 for (i = 0; i < priv->nr_irqs; i++) in plic_irq_suspend()
245 if (readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)) in plic_irq_suspend()
246 __set_bit(i, priv->prio_save); in plic_irq_suspend()
248 __clear_bit(i, priv->prio_save); in plic_irq_suspend()
253 if (!handler->present) in plic_irq_suspend()
256 raw_spin_lock(&handler->enable_lock); in plic_irq_suspend()
257 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_suspend()
258 reg = handler->enable_base + i * sizeof(u32); in plic_irq_suspend()
259 handler->enable_save[i] = readl(reg); in plic_irq_suspend()
261 raw_spin_unlock(&handler->enable_lock); in plic_irq_suspend()
273 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_resume()
275 for (i = 0; i < priv->nr_irqs; i++) { in plic_irq_resume()
277 writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0, in plic_irq_resume()
278 priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); in plic_irq_resume()
284 if (!handler->present) in plic_irq_resume()
287 raw_spin_lock(&handler->enable_lock); in plic_irq_resume()
288 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_resume()
289 reg = handler->enable_base + i * sizeof(u32); in plic_irq_resume()
290 writel(handler->enable_save[i], reg); in plic_irq_resume()
292 raw_spin_unlock(&handler->enable_lock); in plic_irq_resume()
304 struct plic_priv *priv = d->host_data; in plic_irqdomain_map()
306 irq_domain_set_info(d, irq, hwirq, &plic_chip, d->host_data, in plic_irqdomain_map()
309 irq_set_affinity(irq, &priv->lmask); in plic_irqdomain_map()
318 struct plic_priv *priv = d->host_data; in plic_irq_domain_translate()
320 if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_domain_translate()
354 * Handling an interrupt is a two-step process: first you claim the interrupt
363 void __iomem *claim = handler->hart_base + CONTEXT_CLAIM; in plic_handle_irq()
366 WARN_ON_ONCE(!handler->present); in plic_handle_irq()
371 int err = generic_handle_domain_irq(handler->priv->irqdomain, in plic_handle_irq()
384 writel(threshold, handler->hart_base + CONTEXT_THRESHOLD); in plic_set_threshold()
421 return -ENOMEM; in __plic_init()
423 priv->plic_quirks = plic_quirks; in __plic_init()
425 priv->regs = of_iomap(node, 0); in __plic_init()
426 if (WARN_ON(!priv->regs)) { in __plic_init()
427 error = -EIO; in __plic_init()
431 error = -EINVAL; in __plic_init()
432 of_property_read_u32(node, "riscv,ndev", &nr_irqs); in __plic_init()
436 priv->nr_irqs = nr_irqs; in __plic_init()
438 priv->prio_save = bitmap_alloc(nr_irqs, GFP_KERNEL); in __plic_init()
439 if (!priv->prio_save) in __plic_init()
446 error = -ENOMEM; in __plic_init()
447 priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1, in __plic_init()
449 if (WARN_ON(!priv->irqdomain)) in __plic_init()
468 /* Disable S-mode enable bits if running in M-mode. */ in __plic_init()
470 void __iomem *enable_base = priv->regs + in __plic_init()
501 * When running in M-mode we need to ignore the S-mode handler. in __plic_init()
506 if (handler->present) { in __plic_init()
512 cpumask_set_cpu(cpu, &priv->lmask); in __plic_init()
513 handler->present = true; in __plic_init()
514 handler->hart_base = priv->regs + CONTEXT_BASE + in __plic_init()
516 raw_spin_lock_init(&handler->enable_lock); in __plic_init()
517 handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + in __plic_init()
519 handler->priv = priv; in __plic_init()
521 handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32), in __plic_init()
522 sizeof(*handler->enable_save), GFP_KERNEL); in __plic_init()
523 if (!handler->enable_save) in __plic_init()
528 writel(1, priv->regs + PRIORITY_BASE + in __plic_init()
539 if (handler->present && !plic_cpuhp_setup_done) { in __plic_init()
554 kfree(handler->enable_save); in __plic_init()
557 kfree(priv->prio_save); in __plic_init()
559 iounmap(priv->regs); in __plic_init()
571 IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init);
572 IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */
581 IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_edge_init);