1use kernel::utilities::cells::VolatileCell;
10use kernel::utilities::registers::interfaces::{Readable, Writeable};
11use kernel::utilities::registers::{
12 register_bitfields, register_structs, LocalRegisterCopy, ReadWrite,
13};
14use kernel::utilities::StaticRef;
15use riscv_csr::csr::ReadWriteRiscvCsr;
16
17register_structs! {
18 pub PicRegisters {
19 (0x000 => _reserved0),
21 (0x004 => meipl: [ReadWrite<u32, MEIPL::Register>; 255]),
22 (0x400 => _reserved1),
23 (0x1000 => meip: [ReadWrite<u32, MEIP::Register>; 8]),
25 (0x1020 => _reserved2),
26 (0x2004 => meie: [ReadWrite<u32, MEIE::Register>; 255]),
28 (0x2400 => _reserved3),
29 (0x3000 => mpiccfg: ReadWrite<u32, MPICCFG::Register>),
31 (0x3004 => _reserved4),
32 (0x4004 => meigwctrl: [ReadWrite<u32, MEIGWCTRL::Register>; 255]),
34 (0x4400 => _reserved5),
35 (0x5004 => meigwclr: [ReadWrite<u32>; 255]),
37 (0x5400 => @END),
38 }
39}
40
41register_bitfields![u32,
42 MPICCFG [
43 PRIORD OFFSET(0) NUMBITS(1) [
44 STANDARD = 0,
45 REVERSE = 1,
46 ]
47 ],
48 MEIPL [
49 PRIORITY OFFSET(0) NUMBITS(4) []
50 ],
51 MEIP [
52 INTPEND OFFSET(1) NUMBITS(31) []
53 ],
54 MEIE [
55 INTEN OFFSET(0) NUMBITS(1) [
56 ENABLE = 1,
57 DISABLE = 0,
58 ]
59 ],
60 MEIGWCTRL [
61 POLARITY OFFSET(0) NUMBITS(1) [
62 ACTIVE_HIGH = 0,
63 ACTIVE_LOW = 1,
64 ],
65 TYPE OFFSET(1) NUMBITS(1) [
66 LEVEL_TRIGGERED = 0,
67 EDGE_TRIGGERED = 1,
68 ]
69 ],
70];
71register_bitfields![usize,
72 MEIVT [
73 BASE OFFSET(10) NUMBITS(22) []
74 ],
75 MEIPT [
76 PRITHRESH OFFSET(0) NUMBITS(4) []
77 ],
78 MEICIDPL [
79 CLIDPRI OFFSET(0) NUMBITS(4) []
80 ],
81 MEICURPL [
82 CURRPRI OFFSET(0) NUMBITS(4) []
83 ],
84 MEICPCT [
85 RESERVED OFFSET(0) NUMBITS(32) []
86 ],
87 MEIHAP [
88 ZERO OFFSET(0) NUMBITS(2) [],
89 CLAIMID OFFSET(2) NUMBITS(8) [],
90 BASE OFFSET(10) NUMBITS(22) [],
91 ],
92];
93
94#[allow(dead_code)]
95pub struct Pic {
96 registers: StaticRef<PicRegisters>,
97 saved: [VolatileCell<LocalRegisterCopy<u32>>; 3],
98 meivt: ReadWriteRiscvCsr<usize, MEIVT::Register, 0xBC8>,
99 meipt: ReadWriteRiscvCsr<usize, MEIPT::Register, 0xBC9>,
100 meicpct: ReadWriteRiscvCsr<usize, MEICPCT::Register, 0xBCA>,
101 meicidpl: ReadWriteRiscvCsr<usize, MEICIDPL::Register, 0xBCB>,
102 meicurpl: ReadWriteRiscvCsr<usize, MEICURPL::Register, 0xBCC>,
103 meihap: ReadWriteRiscvCsr<usize, MEIHAP::Register, 0xFC8>,
104}
105
106impl Pic {
107 pub const fn new(base: StaticRef<PicRegisters>) -> Self {
108 Pic {
109 registers: base,
110 saved: [
111 VolatileCell::new(LocalRegisterCopy::new(0)),
112 VolatileCell::new(LocalRegisterCopy::new(0)),
113 VolatileCell::new(LocalRegisterCopy::new(0)),
114 ],
115 meivt: ReadWriteRiscvCsr::new(),
116 meipt: ReadWriteRiscvCsr::new(),
117 meicpct: ReadWriteRiscvCsr::new(),
118 meicidpl: ReadWriteRiscvCsr::new(),
119 meicurpl: ReadWriteRiscvCsr::new(),
120 meihap: ReadWriteRiscvCsr::new(),
121 }
122 }
123
124 pub fn clear_all_pending(&self) {
126 for clear in self.registers.meigwclr.iter() {
127 clear.set(0);
128 }
129 }
130
131 pub fn enable_all(&self) {
133 self.registers.mpiccfg.write(MPICCFG::PRIORD::STANDARD);
134
135 self.disable_all();
136
137 for priority in self.registers.meipl.iter() {
138 priority.write(MEIPL::PRIORITY.val(15));
139 }
140
141 for property in self.registers.meigwctrl.iter() {
142 property.write(MEIGWCTRL::POLARITY::ACTIVE_HIGH + MEIGWCTRL::TYPE::LEVEL_TRIGGERED);
143 }
144
145 self.clear_all_pending();
146
147 self.meipt.set(0);
148 self.meicidpl.set(0);
149 self.meicurpl.set(0);
150
151 for enable in self.registers.meie.iter() {
153 enable.write(MEIE::INTEN::ENABLE);
154 }
155 }
156 pub fn disable_all(&self) {
158 for enable in self.registers.meie.iter() {
159 enable.write(MEIE::INTEN::DISABLE);
160 }
161 }
162
163 pub fn next_pending(&self) -> Option<u32> {
167 self.meicpct.set(0);
168 let claimid = self.meihap.read(MEIHAP::CLAIMID);
169
170 if claimid == 0 {
171 None
172 } else {
173 self.registers.meigwclr[claimid - 1].set(0);
175 self.registers.meie[claimid - 1].write(MEIE::INTEN::DISABLE);
177
178 Some(claimid as u32)
179 }
180 }
181
182 pub fn save_interrupt(&self, index: u32) {
188 let offset = if index < 32 {
189 0
190 } else if index < 64 {
191 1
192 } else if index < 96 {
193 2
194 } else {
195 panic!("Unsupported index {}", index);
196 };
197 let irq = index % 32;
198
199 let new_saved = self.saved[offset].get().get() | 1 << irq;
201
202 self.saved[offset].set(LocalRegisterCopy::new(new_saved));
204 }
205
206 pub fn get_saved_interrupts(&self) -> Option<u32> {
210 for (i, pending) in self.saved.iter().enumerate() {
211 let saved = pending.get().get();
212 if saved != 0 {
213 return Some(saved.trailing_zeros() + (i as u32 * 32));
214 }
215 }
216
217 None
218 }
219
220 pub unsafe fn complete(&self, index: u32) {
228 self.registers.meigwclr[index as usize - 1].set(0);
230 self.registers.meie[index as usize - 1].write(MEIE::INTEN::ENABLE);
232
233 let offset = if index < 32 {
234 0
235 } else if index < 64 {
236 1
237 } else {
238 2
239 };
240 let irq = index % 32;
241
242 let new_saved = self.saved[offset].get().get() & !(1 << irq);
244
245 self.saved[offset].set(LocalRegisterCopy::new(new_saved));
247 }
248}