Lines Matching +full:hart +full:- +full:index +full:- +full:bits

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
46 * Each hart context has a vector of interrupt enable bits associated with it.
53 * Each hart context has a set of control registers associated with it. Right
54 * now there's only two: a source priority threshold over which the hart will
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()
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 __assign_bit(i, priv->prio_save, in plic_irq_suspend()
257 readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)); in plic_irq_suspend()
263 if (!handler->present) in plic_irq_suspend()
266 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_irq_suspend()
267 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_suspend()
268 reg = handler->enable_base + i * sizeof(u32); in plic_irq_suspend()
269 handler->enable_save[i] = readl(reg); in plic_irq_suspend()
271 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_irq_suspend()
279 unsigned int i, index, cpu; in plic_irq_resume() local
284 priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv; in plic_irq_resume()
286 for (i = 0; i < priv->nr_irqs; i++) { in plic_irq_resume()
287 index = BIT_WORD(i); in plic_irq_resume()
288 writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0, in plic_irq_resume()
289 priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); in plic_irq_resume()
295 if (!handler->present) in plic_irq_resume()
298 raw_spin_lock_irqsave(&handler->enable_lock, flags); in plic_irq_resume()
299 for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { in plic_irq_resume()
300 reg = handler->enable_base + i * sizeof(u32); in plic_irq_resume()
301 writel(handler->enable_save[i], reg); in plic_irq_resume()
303 raw_spin_unlock_irqrestore(&handler->enable_lock, flags); in plic_irq_resume()
315 struct plic_priv *priv = d->host_data; in plic_irqdomain_map()
317 irq_domain_set_info(d, irq, hwirq, &plic_chip, d->host_data, in plic_irqdomain_map()
320 irq_set_affinity(irq, &priv->lmask); in plic_irqdomain_map()
329 struct plic_priv *priv = d->host_data; in plic_irq_domain_translate()
332 if (fwspec->param[0] >= priv->gsi_base) in plic_irq_domain_translate()
333 fwspec->param[0] = fwspec->param[0] - priv->gsi_base; in plic_irq_domain_translate()
335 if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) in plic_irq_domain_translate()
369 * Handling an interrupt is a two-step process: first you claim the interrupt
378 void __iomem *claim = handler->hart_base + CONTEXT_CLAIM; in plic_handle_irq()
381 WARN_ON_ONCE(!handler->present); in plic_handle_irq()
386 int err = generic_handle_domain_irq(handler->priv->irqdomain, in plic_handle_irq()
390 handler->priv->fwnode, hwirq); in plic_handle_irq()
400 writel(threshold, handler->hart_base + CONTEXT_THRESHOLD); in plic_set_threshold()
420 handler->priv->fwnode, cpu); in plic_starting_cpu()
427 { .compatible = "sifive,plic-1.0.0" },
431 { .compatible = "thead,c900-plic",
461 return -EINVAL; in plic_parse_nr_irqs_and_contexts()
476 return -EINVAL; in plic_parse_nr_irqs_and_contexts()
495 return -EINVAL; in plic_parse_context_parent()
532 plic_quirks = (unsigned long)id->data; in plic_probe()
536 return -ENOMEM; in plic_probe()
538 regs = devm_platform_ioremap_resource(to_platform_device(fwnode->dev), 0); in plic_probe()
549 error = -ENOMEM; in plic_probe()
553 priv->fwnode = fwnode; in plic_probe()
554 priv->plic_quirks = plic_quirks; in plic_probe()
555 priv->nr_irqs = nr_irqs; in plic_probe()
556 priv->regs = regs; in plic_probe()
557 priv->gsi_base = gsi_base; in plic_probe()
558 priv->acpi_plic_id = id; in plic_probe()
560 priv->prio_save = bitmap_zalloc(nr_irqs, GFP_KERNEL); in plic_probe()
561 if (!priv->prio_save) { in plic_probe()
562 error = -ENOMEM; in plic_probe()
568 priv->acpi_plic_id); in plic_probe()
577 context_id = acpi_rintc_get_plic_context(priv->acpi_plic_id, i); in plic_probe()
589 /* Disable S-mode enable bits if running in M-mode. */ in plic_probe()
591 void __iomem *enable_base = priv->regs + in plic_probe()
607 * When running in M-mode we need to ignore the S-mode handler. in plic_probe()
612 if (handler->present) { in plic_probe()
618 cpumask_set_cpu(cpu, &priv->lmask); in plic_probe()
619 handler->present = true; in plic_probe()
620 handler->hart_base = priv->regs + CONTEXT_BASE + in plic_probe()
622 raw_spin_lock_init(&handler->enable_lock); in plic_probe()
623 handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + in plic_probe()
625 handler->priv = priv; in plic_probe()
627 handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32), in plic_probe()
628 sizeof(*handler->enable_save), GFP_KERNEL); in plic_probe()
629 if (!handler->enable_save) { in plic_probe()
630 error = -ENOMEM; in plic_probe()
636 writel(1, priv->regs + PRIORITY_BASE + in plic_probe()
642 priv->irqdomain = irq_domain_create_linear(fwnode, nr_irqs + 1, in plic_probe()
644 if (WARN_ON(!priv->irqdomain)) { in plic_probe()
645 error = -ENOMEM; in plic_probe()
660 if (!handler->present) { in plic_probe()
684 acpi_dev_clear_dependencies(ACPI_COMPANION(fwnode->dev)); in plic_probe()
693 if (plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu, priv->acpi_plic_id)) in plic_probe()
699 handler->present = false; in plic_probe()
700 handler->hart_base = NULL; in plic_probe()
701 handler->enable_base = NULL; in plic_probe()
702 kfree(handler->enable_save); in plic_probe()
703 handler->enable_save = NULL; in plic_probe()
704 handler->priv = NULL; in plic_probe()
706 bitmap_free(priv->prio_save); in plic_probe()
716 return plic_probe(pdev->dev.fwnode); in plic_platform_probe()
721 .name = "riscv-plic",
733 return plic_probe(&node->fwnode); in plic_early_probe()
736 IRQCHIP_DECLARE(riscv, "allwinner,sun20i-d1-plic", plic_early_probe);