1use crate::registers::top_earlgrey::RV_PLIC_BASE_ADDR;
8use kernel::utilities::cells::VolatileCell;
9use kernel::utilities::registers::interfaces::{Readable, Writeable};
10use kernel::utilities::registers::LocalRegisterCopy;
11use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
12use kernel::utilities::StaticRef;
13
14pub const PLIC_BASE: StaticRef<PlicRegisters> =
15 unsafe { StaticRef::new(RV_PLIC_BASE_ADDR as *const PlicRegisters) };
16
17pub static mut PLIC: Plic = Plic::new(PLIC_BASE);
18
19pub const PLIC_REGS: usize = 6;
20pub const PLIC_IRQ_NUM: usize = 185;
21
22register_structs! {
23 pub PlicRegisters {
24 (0x000 => priority: [ReadWrite<u32, priority::Register>; PLIC_IRQ_NUM]),
26 (0x2e4 => _reserved0),
27 (0x1000 => pending: [ReadOnly<u32>; PLIC_REGS]),
29 (0x1018 => _reserved1),
30 (0x2000 => enable: [ReadWrite<u32>; PLIC_REGS]),
32 (0x2018 => _reserved2),
33 (0x200000 => threshold: ReadWrite<u32, priority::Register>),
35 (0x200004 => claim: ReadWrite<u32>),
37 (0x200008 => _reserved3),
38 (0x4000000 => msip: ReadWrite<u32>),
40 (0x4000004 => _reserved4),
41 (0x4004000 => alert_test: ReadWrite<u32>),
42 (0x4004004 => @END),
43 }
44}
45
46register_bitfields![u32,
47 priority [
48 Priority OFFSET(0) NUMBITS(2) []
49 ]
50];
51
52pub struct Plic {
53 registers: StaticRef<PlicRegisters>,
54 saved: [VolatileCell<LocalRegisterCopy<u32>>; PLIC_REGS],
55}
56
57impl Plic {
58 pub const fn new(base: StaticRef<PlicRegisters>) -> Self {
59 Plic {
60 registers: base,
61 saved: [
62 VolatileCell::new(LocalRegisterCopy::new(0)),
63 VolatileCell::new(LocalRegisterCopy::new(0)),
64 VolatileCell::new(LocalRegisterCopy::new(0)),
65 VolatileCell::new(LocalRegisterCopy::new(0)),
66 VolatileCell::new(LocalRegisterCopy::new(0)),
67 VolatileCell::new(LocalRegisterCopy::new(0)),
68 ],
69 }
70 }
71
72 pub fn clear_all_pending(&self) {
74 unimplemented!()
75 }
76
77 pub fn enable_all(&self) {
79 for enable in self.registers.enable.iter() {
80 enable.set(0xFFFF_FFFF);
81 }
82
83 for priority in self.registers.priority.iter() {
86 priority.write(priority::Priority.val(3));
87 }
88
89 self.registers.threshold.write(priority::Priority.val(1));
91 }
92
93 pub fn disable(&self, index: u32) {
95 if index >= PLIC_IRQ_NUM as u32 {
96 panic!("Invalid IRQ: {}", index)
97 }
98 let offset = (index / 32) as usize;
99 let mask = !(1 << (index % 32));
100
101 self.registers.enable[offset].set(self.registers.enable[offset].get() & mask);
102 }
103
104 pub fn disable_all(&self) {
106 for enable in self.registers.enable.iter() {
107 enable.set(0);
108 }
109 }
110
111 pub fn next_pending(&self) -> Option<u32> {
115 let claim = self.registers.claim.get();
116 if claim == 0 {
117 None
118 } else {
119 Some(claim)
120 }
121 }
122
123 pub unsafe fn save_interrupt(&self, index: u32) {
129 if index >= PLIC_IRQ_NUM as u32 {
130 panic!("Invalid IRQ: {}", index)
131 }
132 let offset = (index / 32) as usize;
133 let mask = 1 << (index % 32);
134
135 let new_saved = self.saved[offset].get().get() | mask;
137
138 self.saved[offset].set(LocalRegisterCopy::new(new_saved));
140 }
141
142 pub fn get_saved_interrupts(&self) -> Option<u32> {
146 for (i, pending) in self.saved.iter().enumerate() {
147 let saved = pending.get().get();
148 if saved != 0 {
149 return Some(saved.trailing_zeros() + (i as u32 * 32));
150 }
151 }
152 None
153 }
154
155 pub unsafe fn complete(&self, index: u32) {
159 self.registers.claim.set(index);
160 if index >= PLIC_IRQ_NUM as u32 {
161 panic!("Invalid IRQ: {}", index)
162 }
163 let offset = (index / 32) as usize;
164 let mask = !(1 << (index % 32));
165
166 let new_saved = self.saved[offset].get().get() & mask;
168
169 self.saved[offset].set(LocalRegisterCopy::new(new_saved));
171 }
172}