1use kernel::utilities::registers::interfaces::{Readable, Writeable};
8use kernel::utilities::registers::{register_bitfields, ReadWrite};
9use kernel::utilities::StaticRef;
10
11#[repr(C)]
13struct ClicRegisters {
14 clicintip: IntPendRegisters,
16 clicintie: IntEnableRegisters,
18 clicintcfg: IntConfigRegisters,
20 cliccfg: ConfigRegisters,
22}
23
24#[repr(C)]
26struct IntPendRegisters {
27 _reserved0: [u8; 3],
28 msip: ReadWrite<u8, intpend::Register>,
30 _reserved1: [u8; 3],
31 mtip: ReadWrite<u8, intpend::Register>,
33 _reserved2: [u8; 3],
34 meip: ReadWrite<u8, intpend::Register>,
36 csip: ReadWrite<u8, intpend::Register>,
38 _reserved3: [u8; 3],
39 localintpend: [ReadWrite<u8, intpend::Register>; 128],
41 _reserved4: [u8; 880],
42}
43
44#[repr(C)]
46struct IntEnableRegisters {
47 _reserved0: [u8; 3],
48 msip: ReadWrite<u8, inten::Register>,
50 _reserved1: [u8; 3],
51 mtip: ReadWrite<u8, inten::Register>,
53 _reserved2: [u8; 3],
54 meip: ReadWrite<u8, inten::Register>,
56 csip: ReadWrite<u8, inten::Register>,
58 _reserved3: [u8; 3],
59 localint: [ReadWrite<u8, inten::Register>; 128],
61 _reserved4: [u8; 880],
62}
63
64#[repr(C)]
66struct IntConfigRegisters {
67 _reserved0: [u8; 3],
68 msip: ReadWrite<u8, intcon::Register>,
70 _reserved1: [u8; 3],
71 mtip: ReadWrite<u8, intcon::Register>,
73 _reserved2: [u8; 3],
74 meip: ReadWrite<u8, intcon::Register>,
76 csip: ReadWrite<u8, intcon::Register>,
78 _reserved3: [u8; 3],
79 localint: [ReadWrite<u8, intcon::Register>; 128],
81 _reserved4: [u8; 880],
82}
83
84#[repr(C)]
86struct ConfigRegisters {
87 cliccfg: ReadWrite<u8, conreg::Register>,
88}
89
90register_bitfields![u8,
91 intpend [
92 IntPend OFFSET(0) NUMBITS(1) []
93 ]
94];
95
96register_bitfields![u8,
97 inten [
98 IntEn OFFSET(0) NUMBITS(1) []
99 ]
100];
101
102register_bitfields![u8,
106 intcon [
107 IntCon OFFSET(4) NUMBITS(4) []
108 ]
109];
110
111register_bitfields![u8,
112 conreg [
113 nvbits OFFSET(0) NUMBITS(1) [],
114 nlbits OFFSET(1) NUMBITS(4) [],
115 nmbits OFFSET(5) NUMBITS(2) []
116 ]
117];
118
119const CLIC_BASE: StaticRef<ClicRegisters> =
120 unsafe { StaticRef::new(0x0280_0000 as *const ClicRegisters) };
121
122pub struct Clic {
123 registers: StaticRef<ClicRegisters>,
124
125 in_use_interrupts: u64,
136}
137
138impl Clic {
139 pub const fn new(in_use_interrupts: u64) -> Clic {
140 Clic {
141 registers: CLIC_BASE,
142 in_use_interrupts,
143 }
144 }
145
146 pub fn clear_all_pending(&self) {
148 self.registers.clicintip.msip.write(intpend::IntPend::CLEAR);
149 self.registers.clicintip.mtip.write(intpend::IntPend::CLEAR);
150 self.registers.clicintip.meip.write(intpend::IntPend::CLEAR);
151 self.registers.clicintip.csip.write(intpend::IntPend::CLEAR);
152
153 for pending in self.registers.clicintip.localintpend.iter() {
154 pending.write(intpend::IntPend::CLEAR);
155 }
156 }
157
158 pub fn enable_all(&self) {
163 if self.in_use_interrupts & (1 << 3) > 0 {
164 self.registers.clicintie.msip.write(inten::IntEn::SET);
165 } else if self.in_use_interrupts & (1 << 7) > 0 {
166 self.registers.clicintie.mtip.write(inten::IntEn::SET);
167 } else if self.in_use_interrupts & (1 << 11) > 0 {
168 self.registers.clicintie.meip.write(inten::IntEn::SET);
169 } else if self.in_use_interrupts & (1 << 12) > 0 {
170 self.registers.clicintie.csip.write(inten::IntEn::SET);
171 }
172
173 for (i, enable) in self.registers.clicintie.localint.iter().enumerate() {
174 if self.in_use_interrupts & (1 << (i + 16)) > 0 {
175 enable.write(inten::IntEn::SET);
176 }
177 }
178 }
179
180 pub fn disable_pending(&self) {
184 if self.registers.clicintip.msip.is_set(intpend::IntPend) {
186 self.registers.clicintie.msip.write(inten::IntEn::CLEAR);
187 } else if self.registers.clicintip.mtip.is_set(intpend::IntPend) {
188 self.registers.clicintie.mtip.write(inten::IntEn::CLEAR);
189 } else if self.registers.clicintip.meip.is_set(intpend::IntPend) {
190 self.registers.clicintie.meip.write(inten::IntEn::CLEAR);
191 } else if self.registers.clicintip.csip.is_set(intpend::IntPend) {
192 self.registers.clicintie.csip.write(inten::IntEn::CLEAR);
193 }
194
195 for (i, pending) in self.registers.clicintip.localintpend.iter().enumerate() {
198 if pending.is_set(intpend::IntPend)
199 && self.registers.clicintie.localint[i].is_set(inten::IntEn)
200 {
201 self.registers.clicintie.localint[i].write(inten::IntEn::CLEAR);
202 }
203 }
204 }
205
206 pub fn disable_all(&self) {
208 self.registers.clicintie.msip.write(inten::IntEn::CLEAR);
209 self.registers.clicintie.mtip.write(inten::IntEn::CLEAR);
210 self.registers.clicintie.meip.write(inten::IntEn::CLEAR);
211 self.registers.clicintie.csip.write(inten::IntEn::CLEAR);
212
213 for enable in self.registers.clicintie.localint.iter() {
214 enable.write(inten::IntEn::CLEAR);
215 }
216 }
217
218 pub fn next_pending(&self) -> Option<u32> {
221 if self.in_use_interrupts & (1 << 3) > 0
222 && self.registers.clicintip.msip.is_set(intpend::IntPend)
223 {
224 return Some(3);
225 } else if self.in_use_interrupts & (1 << 7) > 0
226 && self.registers.clicintip.mtip.is_set(intpend::IntPend)
227 {
228 return Some(7);
229 } else if self.in_use_interrupts & (1 << 11) > 0
230 && self.registers.clicintip.meip.is_set(intpend::IntPend)
231 {
232 return Some(11);
233 } else if self.in_use_interrupts & (1 << 12) > 0
234 && self.registers.clicintip.csip.is_set(intpend::IntPend)
235 {
236 return Some(12);
237 }
238
239 for (i, pending) in self.registers.clicintip.localintpend.iter().enumerate() {
240 if self.in_use_interrupts & (1 << (i + 16)) > 0 && pending.is_set(intpend::IntPend) {
241 return Some((i + 16) as u32);
242 }
243 }
244 None
245 }
246
247 pub fn complete(&self, index: u32) {
251 match index {
252 3 => {
253 self.registers.clicintip.msip.write(intpend::IntPend::CLEAR);
254 self.registers.clicintie.msip.write(inten::IntEn::SET);
255 }
256 7 => {
257 self.registers.clicintip.mtip.write(intpend::IntPend::CLEAR);
258 self.registers.clicintie.mtip.write(inten::IntEn::SET);
259 }
260 11 => {
261 self.registers.clicintip.meip.write(intpend::IntPend::CLEAR);
262 self.registers.clicintie.meip.write(inten::IntEn::SET);
263 }
264 12 => {
265 self.registers.clicintip.csip.write(intpend::IntPend::CLEAR);
266 self.registers.clicintie.csip.write(inten::IntEn::SET);
267 }
268 16..=144 => {
269 self.registers.clicintip.localintpend[(index as usize) - 16]
270 .write(intpend::IntPend::CLEAR);
271 self.registers.clicintie.localint[(index as usize) - 16].write(inten::IntEn::SET);
272 }
273 _ => {}
274 }
275 }
276
277 pub fn has_pending(&self) -> bool {
280 self.next_pending().is_some()
281 }
282}
283
284pub unsafe fn disable_interrupt(index: u32) {
289 let regs: &ClicRegisters = &CLIC_BASE;
290
291 match index {
292 3 => regs.clicintie.msip.write(inten::IntEn::CLEAR),
293 7 => regs.clicintie.mtip.write(inten::IntEn::CLEAR),
294 11 => regs.clicintie.meip.write(inten::IntEn::CLEAR),
295 12 => regs.clicintie.csip.write(inten::IntEn::CLEAR),
296 16..=144 => regs.clicintie.localint[(index as usize) - 16].write(inten::IntEn::CLEAR),
297 _ => {}
298 }
299}