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

1 // SPDX-License-Identifier: GPL-2.0
6 #define pr_fmt(fmt) "riscv-plic: " fmt
25 * This driver implements a version of the RISC-V PLIC with the actual layout
28 * https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf
30 * The largest number supported by devices marked as 'sifive,plic-1.0.0', is
31 * 1024, of which device 0 is defined as non-existent by the RISC-V Privileged
32 * Spec.
112 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_toggle()
113 __plic_toggle(handler->enable_base, hwirq, enable); in plic_toggle()
114 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_toggle()
125 plic_toggle(handler, d->hwirq, enable); in plic_irq_toggle()
133 writel(1, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); in plic_irq_unmask()
140 writel(0, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); in plic_irq_mask()
159 plic_toggle(handler, d->hwirq, 1); in plic_irq_eoi()
160 writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); in plic_irq_eoi()
161 plic_toggle(handler, d->hwirq, 0); in plic_irq_eoi()
163 writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); in plic_irq_eoi()
175 cpu = cpumask_first_and(&priv->lmask, mask_val); in plic_set_affinity()
177 cpu = cpumask_first_and_and(&priv->lmask, mask_val, cpu_online_mask); in plic_set_affinity()
180 return -EINVAL; in plic_set_affinity()
229 if (!test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_set_type()
242 return -EINVAL; in plic_irq_set_type()
255 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_suspend()
258 for (i = 1; i < priv->nr_irqs; i++) { in plic_irq_suspend()
259 __assign_bit(i, priv->prio_save, in plic_irq_suspend()
260 readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)); in plic_irq_suspend()
266 if (!handler->present) in plic_irq_suspend()
269 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_irq_suspend()
270 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_suspend()
271 reg = handler->enable_base + i * sizeof(u32); in plic_irq_suspend()
272 handler->enable_save[i] = readl(reg); in plic_irq_suspend()
274 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_irq_suspend()
287 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_resume()
290 for (i = 1; i < priv->nr_irqs; i++) { in plic_irq_resume()
292 writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0, in plic_irq_resume()
293 priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); in plic_irq_resume()
299 if (!handler->present) in plic_irq_resume()
302 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_irq_resume()
303 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_resume()
304 reg = handler->enable_base + i * sizeof(u32); in plic_irq_resume()
305 writel(handler->enable_save[i], reg); in plic_irq_resume()
307 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_irq_resume()
319 struct plic_priv *priv = d->host_data; in plic_irqdomain_map()
321 irq_domain_set_info(d, irq, hwirq, &plic_chip, d->host_data, in plic_irqdomain_map()
324 irq_set_affinity(irq, &priv->lmask); in plic_irqdomain_map()
333 struct plic_priv *priv = d->host_data; in plic_irq_domain_translate()
336 if (fwspec->param[0] >= priv->gsi_base) in plic_irq_domain_translate()
337 fwspec->param[0] = fwspec->param[0] - priv->gsi_base; in plic_irq_domain_translate()
339 if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_domain_translate()
373 * Handling an interrupt is a two-step process: first you claim the interrupt
382 void __iomem *claim = handler->hart_base + CONTEXT_CLAIM; in plic_handle_irq()
385 WARN_ON_ONCE(!handler->present); in plic_handle_irq()
390 int err = generic_handle_domain_irq(handler->priv->irqdomain, in plic_handle_irq()
394 handler->priv->fwnode, hwirq); in plic_handle_irq()
404 writel(threshold, handler->hart_base + CONTEXT_THRESHOLD); in plic_set_threshold()
424 handler->priv->fwnode, cpu); in plic_starting_cpu()
431 { .compatible = "sifive,plic-1.0.0" },
432 { .compatible = "riscv,plic0" },
435 { .compatible = "thead,c900-plic",
465 return -EINVAL; in plic_parse_nr_irqs_and_contexts()
471 rc = of_property_read_u32(to_of_node(fwnode), "riscv,ndev", nr_irqs); in plic_parse_nr_irqs_and_contexts()
473 pr_err("%pfwP: riscv,ndev property not available\n", fwnode); in plic_parse_nr_irqs_and_contexts()
480 return -EINVAL; in plic_parse_nr_irqs_and_contexts()
499 return -EINVAL; in plic_parse_context_parent()
536 plic_quirks = (unsigned long)id->data; in plic_probe()
540 return -ENOMEM; in plic_probe()
542 regs = devm_platform_ioremap_resource(to_platform_device(fwnode->dev), 0); in plic_probe()
553 error = -ENOMEM; in plic_probe()
557 priv->fwnode = fwnode; in plic_probe()
558 priv->plic_quirks = plic_quirks; in plic_probe()
559 priv->nr_irqs = nr_irqs; in plic_probe()
560 priv->regs = regs; in plic_probe()
561 priv->gsi_base = gsi_base; in plic_probe()
562 priv->acpi_plic_id = id; in plic_probe()
564 priv->prio_save = bitmap_zalloc(nr_irqs, GFP_KERNEL); in plic_probe()
565 if (!priv->prio_save) { in plic_probe()
566 error = -ENOMEM; in plic_probe()
572 priv->acpi_plic_id); in plic_probe()
581 context_id = acpi_rintc_get_plic_context(priv->acpi_plic_id, i); in plic_probe()
593 /* Disable S-mode enable bits if running in M-mode. */ in plic_probe()
595 void __iomem *enable_base = priv->regs + in plic_probe()
611 * When running in M-mode we need to ignore the S-mode handler. in plic_probe()
616 if (handler->present) { in plic_probe()
622 cpumask_set_cpu(cpu, &priv->lmask); in plic_probe()
623 handler->present = true; in plic_probe()
624 handler->hart_base = priv->regs + CONTEXT_BASE + in plic_probe()
626 raw_spin_lock_init(&handler->enable_lock); in plic_probe()
627 handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + in plic_probe()
629 handler->priv = priv; in plic_probe()
631 handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32), in plic_probe()
632 sizeof(*handler->enable_save), GFP_KERNEL); in plic_probe()
633 if (!handler->enable_save) { in plic_probe()
634 error = -ENOMEM; in plic_probe()
640 writel(1, priv->regs + PRIORITY_BASE + in plic_probe()
646 priv->irqdomain = irq_domain_create_linear(fwnode, nr_irqs + 1, in plic_probe()
648 if (WARN_ON(!priv->irqdomain)) { in plic_probe()
649 error = -ENOMEM; in plic_probe()
664 if (!handler->present) { in plic_probe()
688 acpi_dev_clear_dependencies(ACPI_COMPANION(fwnode->dev)); in plic_probe()
697 if (plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu, priv->acpi_plic_id)) in plic_probe()
703 handler->present = false; in plic_probe()
704 handler->hart_base = NULL; in plic_probe()
705 handler->enable_base = NULL; in plic_probe()
706 kfree(handler->enable_save); in plic_probe()
707 handler->enable_save = NULL; in plic_probe()
708 handler->priv = NULL; in plic_probe()
710 bitmap_free(priv->prio_save); in plic_probe()
720 return plic_probe(pdev->dev.fwnode); in plic_platform_probe()
725 .name = "riscv-plic",
737 return plic_probe(&node->fwnode); in plic_early_probe()
740 IRQCHIP_DECLARE(riscv, "allwinner,sun20i-d1-plic", plic_early_probe);