Lines Matching +full:c900 +full:- +full:plic

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
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()
194 .name = "SiFive PLIC",
209 .name = "SiFive PLIC",
227 if (!test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_set_type()
240 return -EINVAL; in plic_irq_set_type()
253 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_suspend()
255 for (i = 0; i < priv->nr_irqs; i++) in plic_irq_suspend()
256 if (readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)) in plic_irq_suspend()
257 __set_bit(i, priv->prio_save); in plic_irq_suspend()
259 __clear_bit(i, priv->prio_save); in plic_irq_suspend()
264 if (!handler->present) in plic_irq_suspend()
267 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_irq_suspend()
268 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_suspend()
269 reg = handler->enable_base + i * sizeof(u32); in plic_irq_suspend()
270 handler->enable_save[i] = readl(reg); in plic_irq_suspend()
272 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_irq_suspend()
285 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_resume()
287 for (i = 0; i < priv->nr_irqs; i++) { in plic_irq_resume()
289 writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0, in plic_irq_resume()
290 priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); in plic_irq_resume()
296 if (!handler->present) in plic_irq_resume()
299 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_irq_resume()
300 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_resume()
301 reg = handler->enable_base + i * sizeof(u32); in plic_irq_resume()
302 writel(handler->enable_save[i], reg); in plic_irq_resume()
304 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_irq_resume()
316 struct plic_priv *priv = d->host_data; in plic_irqdomain_map()
318 irq_domain_set_info(d, irq, hwirq, &plic_chip, d->host_data, in plic_irqdomain_map()
321 irq_set_affinity(irq, &priv->lmask); in plic_irqdomain_map()
330 struct plic_priv *priv = d->host_data; in plic_irq_domain_translate()
333 if (fwspec->param[0] >= priv->gsi_base) in plic_irq_domain_translate()
334 fwspec->param[0] = fwspec->param[0] - priv->gsi_base; in plic_irq_domain_translate()
336 if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_domain_translate()
370 * Handling an interrupt is a two-step process: first you claim the interrupt
379 void __iomem *claim = handler->hart_base + CONTEXT_CLAIM; in plic_handle_irq()
382 WARN_ON_ONCE(!handler->present); in plic_handle_irq()
387 int err = generic_handle_domain_irq(handler->priv->irqdomain, in plic_handle_irq()
391 handler->priv->fwnode, hwirq); in plic_handle_irq()
401 writel(threshold, handler->hart_base + CONTEXT_THRESHOLD); in plic_set_threshold()
421 handler->priv->fwnode, cpu); in plic_starting_cpu()
428 { .compatible = "sifive,plic-1.0.0" },
432 { .compatible = "thead,c900-plic",
461 pr_err("%pfwP: no PLIC context available\n", fwnode); in plic_parse_nr_irqs_and_contexts()
462 return -EINVAL; in plic_parse_nr_irqs_and_contexts()
476 pr_err("%pfwP: no PLIC context available\n", fwnode); in plic_parse_nr_irqs_and_contexts()
477 return -EINVAL; in plic_parse_nr_irqs_and_contexts()
496 return -EINVAL; in plic_parse_context_parent()
533 plic_quirks = (unsigned long)id->data; in plic_probe()
537 return -ENOMEM; in plic_probe()
539 regs = devm_platform_ioremap_resource(to_platform_device(fwnode->dev), 0); in plic_probe()
550 error = -ENOMEM; in plic_probe()
554 priv->fwnode = fwnode; in plic_probe()
555 priv->plic_quirks = plic_quirks; in plic_probe()
556 priv->nr_irqs = nr_irqs; in plic_probe()
557 priv->regs = regs; in plic_probe()
558 priv->gsi_base = gsi_base; in plic_probe()
559 priv->acpi_plic_id = id; in plic_probe()
561 priv->prio_save = bitmap_zalloc(nr_irqs, GFP_KERNEL); in plic_probe()
562 if (!priv->prio_save) { in plic_probe()
563 error = -ENOMEM; in plic_probe()
569 priv->acpi_plic_id); in plic_probe()
578 context_id = acpi_rintc_get_plic_context(priv->acpi_plic_id, i); in plic_probe()
590 /* Disable S-mode enable bits if running in M-mode. */ in plic_probe()
592 void __iomem *enable_base = priv->regs + in plic_probe()
608 * When running in M-mode we need to ignore the S-mode handler. in plic_probe()
613 if (handler->present) { in plic_probe()
619 cpumask_set_cpu(cpu, &priv->lmask); in plic_probe()
620 handler->present = true; in plic_probe()
621 handler->hart_base = priv->regs + CONTEXT_BASE + in plic_probe()
623 raw_spin_lock_init(&handler->enable_lock); in plic_probe()
624 handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + in plic_probe()
626 handler->priv = priv; in plic_probe()
628 handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32), in plic_probe()
629 sizeof(*handler->enable_save), GFP_KERNEL); in plic_probe()
630 if (!handler->enable_save) { in plic_probe()
631 error = -ENOMEM; in plic_probe()
637 writel(1, priv->regs + PRIORITY_BASE + in plic_probe()
643 priv->irqdomain = irq_domain_create_linear(fwnode, nr_irqs + 1, in plic_probe()
645 if (WARN_ON(!priv->irqdomain)) { in plic_probe()
646 error = -ENOMEM; in plic_probe()
651 * We can have multiple PLIC instances so setup global state in plic_probe()
661 if (!handler->present) { in plic_probe()
676 "irqchip/sifive/plic:starting", in plic_probe()
685 acpi_dev_clear_dependencies(ACPI_COMPANION(fwnode->dev)); in plic_probe()
694 if (plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu, priv->acpi_plic_id)) in plic_probe()
700 handler->present = false; in plic_probe()
701 handler->hart_base = NULL; in plic_probe()
702 handler->enable_base = NULL; in plic_probe()
703 kfree(handler->enable_save); in plic_probe()
704 handler->enable_save = NULL; in plic_probe()
705 handler->priv = NULL; in plic_probe()
707 bitmap_free(priv->prio_save); in plic_probe()
717 return plic_probe(pdev->dev.fwnode); in plic_platform_probe()
722 .name = "riscv-plic",
734 return plic_probe(&node->fwnode); in plic_early_probe()
737 IRQCHIP_DECLARE(riscv, "allwinner,sun20i-d1-plic", plic_early_probe);