summaryrefslogtreecommitdiff
path: root/drivers/plic.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-10-16 02:39:56 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-10-16 02:39:56 +0800
commit8cace3f05003c6cb4d38c36890055f03151c2ad4 (patch)
treeaa739deaac0266f17c4e91b333957501cb1ea2e9 /drivers/plic.cc
parent3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee (diff)
downloadlume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.gz
lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.xz
Remove old code
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
Diffstat (limited to 'drivers/plic.cc')
-rw-r--r--drivers/plic.cc259
1 files changed, 0 insertions, 259 deletions
diff --git a/drivers/plic.cc b/drivers/plic.cc
deleted file mode 100644
index 2818700..0000000
--- a/drivers/plic.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * plic.cc — Platform-Level Interrupt Controller (RISC-V)
- *
- * QEMU virt platform PLIC:
- * Base PA: 0x0C000000
- * Size: 0x04000000 (64MB)
- *
- * Register layout (per RISC-V PLIC spec):
- * 0x000000: Priority registers (source 0..1023, 4 bytes each)
- * 0x001000: Pending bits (source 0..1023, bit per source)
- * 0x002000: Enable bits per context
- * 0x200000: Threshold + claim/complete per context
- *
- * Context mapping for QEMU virt:
- * Context 2*hartid + 1 = S-mode context for hart N
- *
- * Reference: docs/specs/trap.md §5.1
- */
-
-#include <arch/config.h>
-#include <arch/cpu.h>
-#include <lume/addr.h>
-#include <lume/config.h>
-#include <lume/fdt.h>
-#include <lume/platform_device.h>
-#include <lume/irq.h>
-#include <lume/types.h>
-#include <lume/vmm.h>
-
-/* PLIC virtual base (after MMIO mapping) */
-static uint64 plic_va;
-
-extern "C" uint32 bsp_hart_id;
-
-/* PLIC register offsets */
-static constexpr uint64 PLIC_PRIORITY_BASE = 0x000000;
-static constexpr uint64 PLIC_PENDING_BASE = 0x001000;
-static constexpr uint64 PLIC_ENABLE_BASE = 0x002000;
-static constexpr uint64 PLIC_THRESHOLD_BASE = 0x200000;
-static constexpr uint64 PLIC_CLAIM_BASE = 0x200004;
-
-/* Each context's enable/threshold/claim region is 0x80 bytes apart for enable,
- * and 0x1000 bytes apart for threshold/claim. */
-static constexpr uint64 PLIC_ENABLE_STRIDE = 0x80;
-static constexpr uint64 PLIC_CONTEXT_STRIDE = 0x1000;
-
-/* Dynamic S-mode context mapping */
-static uint32 g_s_context[kMaxCpus];
-
-static inline uint64 s_context(uint64 hart_id) {
- if (hart_id < kMaxCpus)
- return g_s_context[hart_id];
- return 2 * hart_id + 1; /* safe fallback */
-}
-
-static bool str_equals_plic(const char *a, const char *b) {
- if (!a || !b)
- return false;
- while (*a && *a == *b) {
- a++;
- b++;
- }
- return *a == *b;
-}
-
-/* Read a 32-bit MMIO register */
-static inline uint32 plic_read32(uint64 offset) {
- return *reinterpret_cast<volatile uint32 *>(plic_va + offset);
-}
-
-/* Write a 32-bit MMIO register */
-static inline void plic_write32(uint64 offset, uint32 val) {
- *reinterpret_cast<volatile uint32 *>(plic_va + offset) = val;
-}
-
-/* ========================================================================
- * Public API
- * ======================================================================== */
-
-static void plic_probe(DeviceNode* node) {
- uint64 plic_pa = 0;
-
- /* Initialize default fallback mapping */
- for (uint32 i = 0; i < kMaxCpus; i++) {
- g_s_context[i] = 2 * i + 1;
- }
-
- /* Dynamically discover PLIC base address and context mapping from FDT */
- if (node) {
- plic_pa = node->get_prop_u64("reg", plic_pa);
-
- /* Build phandle to hart_id map */
- struct PhandleMap {
- uint32 phandle;
- uint32 hart_id;
- } pmap[kMaxCpus];
- int num_cpus = 0;
-
- DeviceNode *cpus_node = fdt_get_node_by_path("/cpus");
- if (cpus_node) {
- list_node *cur = cpus_node->children_list_head();
- list_node *end = cpus_node->children_list_sentinel();
- while (cur != end && num_cpus < kMaxCpus) {
- DeviceNode *cpu =
- list_entry<DeviceNode, &DeviceNode::sibling_link_>(cur);
- cur = cur->next;
-
- const char *type = cpu->get_prop_string("device_type");
- if (type && str_equals_plic(type, "cpu")) {
- uint32 hart_id = cpu->get_prop_u32("reg");
- DeviceNode *intc = cpu->find_child("interrupt-controller");
- if (intc) {
- uint32 phandle = intc->get_prop_u32("phandle");
- if (phandle == 0)
- phandle = intc->get_prop_u32("linux,phandle");
- if (phandle != 0) {
- pmap[num_cpus].phandle = phandle;
- pmap[num_cpus].hart_id = hart_id;
- num_cpus++;
- }
- }
- }
- }
- }
-
- /* Parse interrupts-extended */
- const FdtProperty *ie_prop = node->get_prop("interrupts-extended");
- if (ie_prop && ie_prop->len > 0) {
- uint32 len = ie_prop->len;
- const uint8 *val = static_cast<const uint8 *>(ie_prop->value);
- int context_idx = 0;
- /* Each entry is 2 cells (8 bytes): [phandle, interrupt_type] */
- for (uint32 i = 0; i + 7 < len; i += 8) {
- uint32 phandle = (uint32(val[i]) << 24) | (uint32(val[i + 1]) << 16) |
- (uint32(val[i + 2]) << 8) | val[i + 3];
- uint32 irq_type = (uint32(val[i + 4]) << 24) |
- (uint32(val[i + 5]) << 16) |
- (uint32(val[i + 6]) << 8) | val[i + 7];
-
- if (irq_type == 9) { /* IRQ_S_EXTERNAL */
- for (int h = 0; h < num_cpus; h++) {
- if (pmap[h].phandle == phandle) {
- if (pmap[h].hart_id < kMaxCpus) {
- g_s_context[pmap[h].hart_id] = context_idx;
- }
- break;
- }
- }
- }
- context_idx++;
- }
- }
- }
-
- if (plic_pa == 0) return;
-
- /* Map PLIC MMIO */
- vmm_map_kernel_mmio(plic_pa, 0x4000000);
- plic_va = pa_to_va(phys_addr(plic_pa)).raw;
-
- /* Use the actual BSP hart ID (it may not be hart 0) */
- uint64 ctx = s_context(bsp_hart_id);
-
- /* Set priority for all sources to 1 (minimum non-zero = enabled) */
- for (uint32 irq = 1; irq < IrqManager::kMaxIrqs; irq++) {
- plic_write32(PLIC_PRIORITY_BASE + irq * 4, 1);
- }
-
- /* Set threshold to 0 for BSP context (accept all priorities > 0) */
- plic_write32(PLIC_THRESHOLD_BASE + ctx * PLIC_CONTEXT_STRIDE, 0);
-}
-
-static void plic_init_ap() {
- uint64 ctx = s_context(arch::cpu::id());
-
- /* Set threshold to 0 for this AP's context */
- plic_write32(PLIC_THRESHOLD_BASE + ctx * PLIC_CONTEXT_STRIDE, 0);
-}
-
-static void plic_enable(uint32 irq) {
- if (irq == 0 || irq >= IrqManager::kMaxIrqs) {
- return;
- }
-
- uint64 ctx = s_context(arch::cpu::id());
- uint64 offset = PLIC_ENABLE_BASE + ctx * PLIC_ENABLE_STRIDE;
- uint32 word_index = irq / 32;
- uint32 bit_index = irq % 32;
-
- uint32 val = plic_read32(offset + word_index * 4);
- val |= (1U << bit_index);
- plic_write32(offset + word_index * 4, val);
-}
-
-static void plic_disable(uint32 irq) {
- if (irq == 0 || irq >= IrqManager::kMaxIrqs) {
- return;
- }
-
- uint64 ctx = s_context(arch::cpu::id());
- uint64 offset = PLIC_ENABLE_BASE + ctx * PLIC_ENABLE_STRIDE;
- uint32 word_index = irq / 32;
- uint32 bit_index = irq % 32;
-
- uint32 val = plic_read32(offset + word_index * 4);
- val &= ~(1U << bit_index);
- plic_write32(offset + word_index * 4, val);
-}
-
-static void plic_set_priority(uint32 irq, uint32 priority) {
- if (irq == 0 || irq >= IrqManager::kMaxIrqs)
- return;
- plic_write32(PLIC_PRIORITY_BASE + (irq * 4), priority);
-}
-
-static uint32 plic_claim() {
- uint64 ctx = s_context(arch::cpu::id());
- return plic_read32(PLIC_CLAIM_BASE + ctx * PLIC_CONTEXT_STRIDE);
-}
-
-static void plic_complete(uint32 irq) {
- uint64 ctx = s_context(arch::cpu::id());
- plic_write32(PLIC_CLAIM_BASE + ctx * PLIC_CONTEXT_STRIDE, irq);
-}
-
-static const IrqChip plic_chip = {
- "riscv,plic0",
- plic_claim,
- plic_complete,
- plic_init_ap,
- plic_enable,
- plic_disable,
- plic_set_priority
-};
-
-static int plic_platform_probe(platform_device* pdev) {
- plic_probe(pdev->of_node);
- g_irq_manager.set_chip(&plic_chip);
- return 0;
-}
-
-static const of_device_id plic_of_match[] = {
- { .compatible = "riscv,plic0", .data = nullptr },
- { .compatible = nullptr, .data = nullptr }, /* sentinel */
-};
-
-platform_driver plic_driver = {
- .driver = { .name = "plic", .bus = nullptr,
- .probe = nullptr, .remove = nullptr,
- .bus_node = {}, .devices = {} },
- .probe = plic_platform_probe,
- .remove = nullptr,
- .of_match_table = plic_of_match,
-};
-
-PLATFORM_DRIVER(plic_driver);