1use kernel::utilities::cells::VolatileCell;
8use kernel::utilities::registers::interfaces::{Readable, Writeable};
9use kernel::utilities::registers::LocalRegisterCopy;
10use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
11use kernel::utilities::StaticRef;
12
13const MAX_INTERRUPTS: usize = 1023;
24const MAX_BIT_REGS: usize = MAX_INTERRUPTS.div_ceil(32);
26
27#[repr(C)]
33pub struct PlicRegisters {
34 _reserved0: u32,
36 priority: [ReadWrite<u32, priority::Register>; MAX_INTERRUPTS],
37 _reserved1: [u8; 0x1000 - (MAX_INTERRUPTS + 1) * 4],
38 pending: [ReadOnly<u32>; MAX_BIT_REGS],
40 _reserved2: [u8; 0x1000 - MAX_BIT_REGS * 4],
41 enable: [ReadWrite<u32>; MAX_BIT_REGS],
43 _reserved3: [u8; 0x20_0000 - 0x2000 - MAX_BIT_REGS * 4],
44 threshold: ReadWrite<u32, priority::Register>,
46 claim: ReadWrite<u32>,
48}
49
50const _: () = assert!(core::mem::offset_of!(PlicRegisters, priority) == 0x4);
52const _: () = assert!(core::mem::offset_of!(PlicRegisters, pending) == 0x1000);
53const _: () = assert!(core::mem::offset_of!(PlicRegisters, enable) == 0x2000);
54const _: () = assert!(core::mem::offset_of!(PlicRegisters, threshold) == 0x20_0000);
55const _: () = assert!(core::mem::offset_of!(PlicRegisters, claim) == 0x20_0004);
56
57struct RegsWrapper {
60 registers: StaticRef<PlicRegisters>,
61 total_ints: usize,
62}
63
64impl RegsWrapper {
65 const fn new(registers: StaticRef<PlicRegisters>, total_ints: usize) -> Self {
66 Self {
67 registers,
68 total_ints,
69 }
70 }
71
72 fn get_enable_regs(&self) -> &[ReadWrite<u32>] {
73 &self.registers.enable[0..self.total_ints.div_ceil(32)]
76 }
77
78 #[allow(dead_code)]
80 fn get_pending_regs(&self) -> &[ReadOnly<u32>] {
81 &self.registers.pending[0..self.total_ints.div_ceil(32)]
84 }
85
86 fn get_priority_regs(&self) -> &[ReadWrite<u32, priority::Register>] {
87 &self.registers.priority[0..self.total_ints]
89 }
90
91 fn get_threshold_reg(&self) -> &ReadWrite<u32, priority::Register> {
92 &self.registers.threshold
93 }
94
95 fn get_claim_reg(&self) -> &ReadWrite<u32> {
96 &self.registers.claim
97 }
98}
99
100register_bitfields![u32,
101 priority [
102 Priority OFFSET(0) NUMBITS(3) []
103 ]
104];
105
106pub struct Plic<const TOTAL_INTS: usize = 51> {
112 registers: RegsWrapper,
113 saved: [VolatileCell<LocalRegisterCopy<u32>>; 2],
114}
115
116impl<const TOTAL_INTS: usize> Plic<TOTAL_INTS> {
117 pub const fn new(base: StaticRef<PlicRegisters>) -> Self {
118 Plic {
119 registers: RegsWrapper::new(base, TOTAL_INTS),
120 saved: [
121 VolatileCell::new(LocalRegisterCopy::new(0)),
122 VolatileCell::new(LocalRegisterCopy::new(0)),
123 ],
124 }
125 }
126
127 pub fn clear_all_pending(&self) {
132 let claim = self.registers.get_claim_reg();
133 loop {
134 let id = claim.get();
135 if id == 0 {
136 break;
137 }
138 claim.set(id);
139 }
140 }
141
142 pub fn enable_specific_interrupts(&self, interrupts: &[u32]) {
144 let enable_regs = self.registers.get_enable_regs();
145 for interrupt in interrupts {
146 let offset = interrupt / 32;
147 let irq = interrupt % 32;
148 let old_value = enable_regs[offset as usize].get();
149 enable_regs[offset as usize].set(old_value | (1 << irq));
150
151 self.registers.get_priority_regs()[*interrupt as usize - 1]
156 .write(priority::Priority.val(4));
157 }
158 self.registers
160 .get_threshold_reg()
161 .write(priority::Priority.val(0));
162 }
163
164 pub fn disable_specific_interrupts(&self, interrupts: &[u32]) {
165 let enable_regs = self.registers.get_enable_regs();
166 for interrupt in interrupts {
167 let offset = interrupt / 32;
168 let irq = interrupt % 32;
169 let old_value = enable_regs[offset as usize].get();
170 enable_regs[offset as usize].set(old_value & !(1 << irq));
171 }
172 }
173
174 pub fn enable_all(&self) {
176 let enable_regs = self.registers.get_enable_regs();
177 let priority_regs = &self.registers.get_priority_regs();
178
179 for enable in enable_regs.iter() {
180 enable.set(0xFFFF_FFFF);
181 }
182
183 for priority in priority_regs.iter() {
186 priority.write(priority::Priority.val(4));
187 }
188
189 self.registers
191 .get_threshold_reg()
192 .write(priority::Priority.val(0));
193 }
194
195 pub fn disable_all(&self) {
197 let enable_regs = self.registers.get_enable_regs();
198
199 for enable in enable_regs.iter() {
200 enable.set(0);
201 }
202 }
203
204 pub fn next_pending(&self) -> Option<u32> {
208 let claim = self.registers.get_claim_reg().get();
209 if claim == 0 {
210 None
211 } else {
212 Some(claim)
213 }
214 }
215
216 pub unsafe fn save_interrupt(&self, index: u32) {
222 let offset = usize::from(index >= 32);
223 let irq = index % 32;
224
225 let new_saved = self.saved[offset].get().get() | 1 << irq;
227
228 self.saved[offset].set(LocalRegisterCopy::new(new_saved));
230 }
231
232 pub fn get_saved_interrupts(&self) -> Option<u32> {
236 for (i, pending) in self.saved.iter().enumerate() {
237 let saved = pending.get().get();
238 if saved != 0 {
239 return Some(saved.trailing_zeros() + (i as u32 * 32));
240 }
241 }
242
243 None
244 }
245
246 pub unsafe fn complete(&self, index: u32) {
250 self.registers.get_claim_reg().set(index);
251
252 let offset = usize::from(index >= 32);
253 let irq = index % 32;
254
255 let new_saved = self.saved[offset].get().get() & !(1 << irq);
257
258 self.saved[offset].set(LocalRegisterCopy::new(new_saved));
260 }
261
262 pub fn suppress_all(&self) {
265 self.registers
267 .get_threshold_reg()
268 .write(priority::Priority.val(0));
269 }
270}