arm_gic_driver/version/
mod.rs

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        /// Distributor Control Register.
17        (0x0000 => pub CTLR: ReadWrite<u32, CTLR::Register>),
18        /// Interrupt Controller Type Register.
19        (0x0004 => TYPER: ReadOnly<u32, TYPER::Register>),
20        /// Distributor Implementer Identification Register.
21        (0x0008 => IIDR: ReadOnly<u32, IIDR::Register>),
22        (0x000c => _rsv1),
23        /// Interrupt Group Registers.
24        (0x0080 => IGROUPR: [ReadWrite<u32>; 0x20]),
25        /// Interrupt Set-Enable Registers.
26        (0x0100 => ISENABLER: [ReadWrite<u32>; 0x20]),
27        /// Interrupt Clear-Enable Registers.
28        (0x0180 => ICENABLER: [ReadWrite<u32>; 0x20]),
29        /// Interrupt Set-Pending Registers.
30        (0x0200 => ISPENDR: [ReadWrite<u32>; 0x20]),
31        /// Interrupt Clear-Pending Registers.
32        (0x0280 => ICPENDR: [ReadWrite<u32>; 0x20]),
33        /// Interrupt Set-Active Registers.
34        (0x0300 => ISACTIVER: [ReadWrite<u32>; 0x20]),
35        /// Interrupt Clear-Active Registers.
36        (0x0380 => ICACTIVER: [ReadWrite<u32>; 0x20]),
37        /// Interrupt Priority Registers.
38        (0x0400 => IPRIORITYR: [ReadWrite<u8>; 1024]),
39        /// Interrupt Processor Targets Registers.
40        (0x0800 => ITARGETSR: [ReadWrite<u8>; 1024]),
41        /// Interrupt Configuration Registers.
42        (0x0c00 => pub ICFGR: [ReadWrite<u32>; 0x40]),
43        (0x0d00 => pub IGRPMODR: [ReadWrite<u32>; 32]),
44        (0x0d80 => _rsv2),
45        /// Software Generated Interrupt Register.
46        (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        /// v3
54
55        (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    // pub fn cpu_num(&self) -> u32 {
214    //     self.TYPER.read(TYPER::CPUNumber) + 1
215    // }
216}
217
218// The `bitflags!` macro generates `struct`s that manage a set of flags.
219bitflags::bitflags! {
220    /// Represents a set of flags.
221    #[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}