1use core::error::Error;
2
3use alloc::boxed::Box;
4use rdif_intc::*;
5use tock_registers::{interfaces::*, register_bitfields, register_structs, registers::*};
6use v3::IROUTER;
7
8pub mod v2;
9pub mod v3;
10
11use crate::define::*;
12
13register_structs! {
14 #[allow(non_snake_case)]
15 pub Distributor {
16 (0x0000 => pub CTLR: ReadWrite<u32, CTLR::Register>),
18 (0x0004 => TYPER: ReadOnly<u32, TYPER::Register>),
20 (0x0008 => IIDR: ReadOnly<u32, IIDR::Register>),
22 (0x000c => _rsv1),
23 (0x0080 => IGROUPR: [ReadWrite<u32>; 0x20]),
25 (0x0100 => ISENABLER: [ReadWrite<u32>; 0x20]),
27 (0x0180 => ICENABLER: [ReadWrite<u32>; 0x20]),
29 (0x0200 => ISPENDR: [ReadWrite<u32>; 0x20]),
31 (0x0280 => ICPENDR: [ReadWrite<u32>; 0x20]),
33 (0x0300 => ISACTIVER: [ReadWrite<u32>; 0x20]),
35 (0x0380 => ICACTIVER: [ReadWrite<u32>; 0x20]),
37 (0x0400 => IPRIORITYR: [ReadWrite<u8>; 1024]),
39 (0x0800 => ITARGETSR: [ReadWrite<u8>; 1024]),
41 (0x0c00 => pub ICFGR: [ReadWrite<u32>; 0x40]),
43 (0x0d00 => pub IGRPMODR: [ReadWrite<u32>; 32]),
44 (0x0d80 => _rsv2),
45 (0x0f00 => SGIR: WriteOnly<u32, SGIR::Register>),
47 (0x0f04 => _rsv3),
48 (0x0f10 => CPENDSGIR: [ReadWrite<u32>; 0x4]),
49 (0x0f20 => SPENDSGIR: [ReadWrite<u32>; 0x4]),
50 (0x0f30 => _rsv4),
51 (0x0fe8 => ICPIDR2 : ReadOnly<u32, PIDR2::Register>),
52 (0x0fec => _rsv5),
53 (0x6000 => IROUTER: [ReadWrite<u64, IROUTER::Register>; 1019]),
56 (0x7FD8 => _rsv6),
57 (0xFFE8 => PIDR2 : ReadOnly<u32, PIDR2::Register>),
58 (0xFFEC => _rsv7),
59 (0xFFFC => @END),
60 }
61}
62register_bitfields! [
63 u32,
64 pub CTLR [
65 EnableGrp0 OFFSET(0) NUMBITS(1) [],
66 EnableGrp1NS OFFSET(1) NUMBITS(1) [],
67 EnableGrp1S OFFSET(2) NUMBITS(1) [],
68 ARE_S OFFSET(4) NUMBITS(1) [],
69 ARE_NS OFFSET(5) NUMBITS(1) [],
70 DS OFFSET(6) NUMBITS(1) [],
71 RWP OFFSET(31) NUMBITS(1) [],
72 ],
73 TYPER [
74 ITLinesNumber OFFSET(0) NUMBITS(5) [],
75 CPUNumber OFFSET(5) NUMBITS(3) []
76 ],
77 IIDR [
78 Implementer OFFSET(0) NUMBITS(12) [],
79 Revision OFFSET(12) NUMBITS(4) [],
80 Variant OFFSET(16) NUMBITS(4) [],
81 ProductId OFFSET(24) NUMBITS(8) []
82 ],
83 SGIR [
84 SGIINTID OFFSET(0) NUMBITS(4) [],
85 NSATT OFFSET(15) NUMBITS(1) [],
86 CPUTargetList OFFSET(16) NUMBITS(8) [],
87 TargetListFilter OFFSET(24) NUMBITS(2) [
88 TargetList=0,
89 AllOther=0b01,
90 Current=0b10,
91 ],
92 ],
93 IAR [
94 INTID OFFSET(0) NUMBITS(10) [],
95 CPUID OFFSET(10) NUMBITS(3) []
96 ],
97 pub PIDR2 [
98 ArchRev OFFSET(4) NUMBITS(4) [],
99 ],
100
101
102];
103
104#[allow(unused)]
105impl Distributor {
106 pub fn version(&self) -> u32 {
107 let v = self.ICPIDR2.read(PIDR2::ArchRev);
108 if v == 1 || v == 2 {
109 return v;
110 }
111 self.PIDR2.read(PIDR2::ArchRev)
112 }
113
114 pub fn implementer(&self) -> u32 {
115 self.IIDR.read(IIDR::Implementer)
116 }
117
118 pub fn irq_line_max(&self) -> u32 {
119 (self.TYPER.read(TYPER::ITLinesNumber) + 1) * 32
120 }
121
122 pub fn max_spi_num(&self) -> usize {
123 let max_line = self.irq_line_max() as usize;
124 ((max_line + 1) << 5) - 1
125 }
126
127 pub fn set_enable_interrupt(&self, irq: IntId, enable: bool) {
128 let int_id: u32 = irq.into();
129 let index = (int_id / 32) as usize;
130 let bit = 1 << (int_id % 32);
131 if enable {
132 self.ISENABLER[index].set(bit);
133 } else {
134 self.ICENABLER[index].set(bit);
135 }
136 }
137
138 pub fn set_priority(&self, intid: IntId, priority: u8) {
139 self.IPRIORITYR[u32::from(intid) as usize].set(priority)
140 }
141
142 pub fn set_bind_cpu(&self, intid: IntId, target_list: u8) {
143 self.ITARGETSR[u32::from(intid) as usize].set(target_list)
144 }
145
146 pub fn disable_all_interrupts(&self) {
147 for reg in &self.ICENABLER {
148 reg.set(u32::MAX);
149 }
150 for reg in &self.ICPENDR {
151 reg.set(u32::MAX);
152 }
153 }
154
155 pub fn sgi(&self, intid: IntId, target: SGITarget) {
156 assert!(intid.is_sgi());
157
158 let mut val = SGIR::SGIINTID.val(intid.into());
159
160 match target {
161 SGITarget::AllOther => {
162 val += SGIR::TargetListFilter::AllOther;
163 }
164 SGITarget::Targets(list) => {
165 if list.is_empty() {
166 return;
167 }
168
169 let target_list = list
170 .iter()
171 .fold(0, |acc, &target| acc | target.cpu_target_list());
172
173 val += SGIR::TargetListFilter::TargetList
174 + SGIR::CPUTargetList.val(target_list as u32);
175 }
176 }
177
178 self.SGIR.write(val);
179 }
180
181 pub fn set_all_group1(&self) {
182 for i in 0..32 {
183 self.IGROUPR[i].set(u32::MAX);
184 }
185 }
186
187 pub fn set_route(&self, intid: IntId, target: CPUTarget) {
188 self.IROUTER[u32::from(intid) as usize].write(
189 IROUTER::InterruptRoutingMode::Aff
190 + IROUTER::AFF0.val(target.aff0 as _)
191 + IROUTER::AFF1.val(target.aff1 as _)
192 + IROUTER::AFF2.val(target.aff2 as _)
193 + IROUTER::AFF3.val(target.aff3 as _),
194 );
195 }
196
197 fn set_cfgr(&self, intid: IntId, trigger: Trigger) {
198 let val = u32::from(intid);
199
200 let index = (val / 16) as usize;
201 let bit = 1 << (((val % 16) * 2) + 1);
202
203 let v = self.ICFGR[index].get();
204 self.ICFGR[index].set(match trigger {
205 Trigger::EdgeBoth => v | bit,
206 Trigger::EdgeRising => v | bit,
207 Trigger::EdgeFailling => v | bit,
208 Trigger::LevelHigh => v & !bit,
209 Trigger::LevelLow => v & !bit,
210 })
211 }
212
213 }
217
218bitflags::bitflags! {
220 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
222 struct TriggerFlag: usize {
223 const NONE = 0;
224 const EDGE_RISING = 1;
225 const EDGE_FALLING = 2;
226 const EDGE_BOTH = Self::EDGE_RISING.bits()| Self::EDGE_FALLING.bits();
227 const LEVEL_HIGH = 4;
228 const LEVEL_LOW = 8;
229 }
230}
231pub fn fdt_parse_irq_config(itr: &[u32]) -> Result<IrqConfig, Box<dyn Error>> {
232 const SPI: u32 = 0;
233 const PPI: u32 = 1;
234
235 let num = itr[1];
236
237 let irq_id: u32 = match itr[0] {
238 SPI => IntId::spi(num),
239 PPI => IntId::ppi(num),
240 _ => panic!("Invalid irq type {}", itr[0]),
241 }
242 .into();
243
244 let flag = TriggerFlag::from_bits_truncate(itr[2] as _);
245
246 let trigger = if flag.contains(TriggerFlag::EDGE_BOTH) {
247 Trigger::EdgeBoth
248 } else if flag.contains(TriggerFlag::EDGE_RISING) {
249 Trigger::EdgeRising
250 } else if flag.contains(TriggerFlag::EDGE_FALLING) {
251 Trigger::EdgeFailling
252 } else if flag.contains(TriggerFlag::LEVEL_HIGH) {
253 Trigger::LevelHigh
254 } else if flag.contains(TriggerFlag::LEVEL_LOW) {
255 Trigger::LevelLow
256 } else {
257 panic!("Invalid irq type {}", itr[2])
258 };
259
260 Ok(IrqConfig {
261 irq: (irq_id as usize).into(),
262 trigger,
263 })
264}