1use super::{super::DRIVERS, IrqManager};
6use crate::arch::constant::SUPERVISOR_EXTERNAL;
7use crate::device::device_tree::{DEVICE_TREE_INTC, DEVICE_TREE_REGISTRY};
8use crate::device::irq::IntcDriver;
9use crate::device::{DeviceType, Driver, IRQ_MANAGER};
10use crate::kernel::current_memory_space;
11use crate::mm::address::{Paddr, UsizeConvert};
12use crate::{pr_info, pr_warn};
13use crate::{sync::SpinLock as Mutex, util::read, util::write};
14use alloc::format;
15use alloc::string::String;
16use alloc::sync::Arc;
17use fdt::node::FdtNode;
18
19pub struct Plic {
21 base: usize,
22 manager: Mutex<IrqManager>,
23}
24
25impl Driver for Plic {
26 fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
32 let pending: u32 = read(self.base + 0x1000);
33 if pending != 0 {
34 let claim: u32 = read(self.base + 0x201004);
35 let manager = self.manager.lock();
36 let res = manager.try_handle_interrupt(Some(claim as usize));
37 write(self.base + 0x201004, claim);
38 res
39 } else {
40 false
41 }
42 }
43
44 fn device_type(&self) -> DeviceType {
48 DeviceType::Intc
49 }
50
51 fn get_id(&self) -> String {
55 format!("plic_{}", self.base)
56 }
57}
58
59impl IntcDriver for Plic {
60 fn register_local_irq(&self, irq: usize, driver: Arc<dyn Driver>) {
65 write(
66 self.base + 0x2080,
67 read::<u32>(self.base + 0x2080) | (1 << irq),
68 );
69 write(self.base + irq * 4, 7);
70 let mut manager = self.manager.lock();
71 manager.register_irq(irq, driver);
72 }
73}
74
75pub fn init_dt(dt: &FdtNode) {
79 if let Some(reg) = dt.reg().and_then(|mut reg| reg.next()) {
80 let paddr = reg.starting_address as usize;
81 let size = reg.size.unwrap_or(0);
82 if size == 0 {
83 pr_warn!("[Device] PLIC device tree node {} has no size", dt.name);
84 return;
85 }
86 let vaddr = current_memory_space()
87 .lock()
88 .map_mmio(Paddr::from_usize(paddr), size)
89 .ok()
90 .expect("Failed to map MMIO region");
91 let phandle = dt
92 .property("phandle")
93 .unwrap()
94 .as_usize()
95 .expect("Failed to convert 'phandle' property to usize");
96 let base = vaddr.as_usize();
97 let plic = Arc::new(Plic {
98 base,
99 manager: Mutex::new(IrqManager::new(false)),
100 });
101
102 write(base + 0x201000, 0);
104 DRIVERS.write().push(plic.clone());
105 IRQ_MANAGER
107 .write()
108 .register_irq(SUPERVISOR_EXTERNAL, plic.clone());
109 DEVICE_TREE_INTC
111 .write()
112 .insert(phandle.try_into().unwrap(), plic);
113 } else {
114 pr_warn!(
115 "[Device] PLIC device tree node {} has no 'reg' property",
116 dt.name
117 );
118 }
119 pr_info!(
120 "[Device] PLIC initialized from device tree node {}",
121 dt.name
122 );
123}
124
125pub fn driver_init() {
127 DEVICE_TREE_REGISTRY.write().insert("riscv,plic0", init_dt);
128}