arm_gic_driver/version/
v2.rs1use core::ptr::NonNull;
2
3use rdif_intc::*;
4use tock_registers::{register_structs, registers::*};
5
6use super::*;
7
8pub struct Gic {
10 gicd: NonNull<Distributor>,
11 gicc: NonNull<CpuInterface>,
12}
13
14unsafe impl Send for Gic {}
15
16impl Gic {
17 pub fn new(gicd: NonNull<u8>, gicc: NonNull<u8>) -> Self {
19 Self {
20 gicd: gicd.cast(),
21 gicc: gicc.cast(),
22 }
23 }
24
25 fn gicd(&self) -> &Distributor {
26 unsafe { self.gicd.as_ref() }
27 }
28 fn gicc(&self) -> &CpuInterface {
29 unsafe { self.gicc.as_ref() }
30 }
31}
32
33impl DriverGeneric for Gic {
34 fn open(&mut self) -> DriverResult {
35 self.gicd().disable_all_interrupts();
36 self.gicd().CTLR.write(CTLR::EnableGrp0::SET);
37 Ok(())
38 }
39
40 fn close(&mut self) -> DriverResult {
41 Ok(())
42 }
43}
44
45impl Interface for Gic {
46 fn current_cpu_setup(&self) -> HardwareCPU {
47 self.gicc().enable();
48 self.gicc().set_priority_mask(0xff);
49 Box::new(GicCpu { ptr: self.gicc })
50 }
51
52 fn irq_enable(&mut self, irq: IrqId) {
53 self.gicd().set_enable_interrupt(irq.into(), true);
54 }
55
56 fn irq_disable(&mut self, irq: IrqId) {
57 self.gicd().set_enable_interrupt(irq.into(), false);
58 }
59
60 fn set_priority(&mut self, irq: IrqId, priority: usize) {
61 self.gicd().set_priority(irq.into(), priority as _);
62 }
63
64 fn set_trigger(&mut self, irq: IrqId, trigger: Trigger) {
65 self.gicd().set_cfgr(irq.into(), trigger);
66 }
67
68 fn set_target_cpu(&mut self, irq: IrqId, cpu: CpuId) {
69 let target_list = 1u8 << usize::from(cpu);
70 self.gicd().set_bind_cpu(irq.into(), target_list);
71 }
72}
73
74pub struct GicCpu {
75 ptr: NonNull<CpuInterface>,
76}
77
78unsafe impl Sync for GicCpu {}
79unsafe impl Send for GicCpu {}
80
81impl GicCpu {
82 fn gicc(&self) -> &CpuInterface {
83 unsafe { self.ptr.as_ref() }
84 }
85}
86
87impl InterfaceCPU for GicCpu {
88 fn get_and_acknowledge_interrupt(&self) -> Option<IrqId> {
89 self.gicc()
90 .get_and_acknowledge_interrupt()
91 .map(|i| (u32::from(i) as usize).into())
92 }
93
94 fn end_interrupt(&self, irq: IrqId) {
95 self.gicc().end_interrupt(IntId::from(irq))
96 }
97}
98
99register_structs! {
100 #[allow(non_snake_case)]
102 pub CpuInterface {
103 (0x0000 => CTLR: ReadWrite<u32>),
105 (0x0004 => PMR: ReadWrite<u32>),
107 (0x0008 => BPR: ReadWrite<u32>),
109 (0x000c => IAR: ReadOnly<u32, IAR::Register>),
111 (0x0010 => EOIR: WriteOnly<u32>),
113 (0x0014 => RPR: ReadOnly<u32>),
115 (0x0018 => HPPIR: ReadOnly<u32>),
117 (0x001c => _reserved_1),
118 (0x00fc => IIDR: ReadOnly<u32>),
120 (0x0100 => _reserved_2),
121 (0x1000 => DIR: WriteOnly<u32>),
123 (0x1004 => @END),
124 }
125}
126
127impl CpuInterface {
128 pub fn set_priority_mask(&self, priority: u8) {
129 self.PMR.set(priority as u32);
130 }
131
132 pub fn enable(&self) {
133 self.CTLR.set(1);
134 }
135
136 pub fn get_and_acknowledge_interrupt(&self) -> Option<IntId> {
137 let id = self.IAR.read(IAR::INTID);
138 if id == 1023 {
139 None
140 } else {
141 unsafe { Some(IntId::raw(id)) }
142 }
143 }
144
145 pub fn end_interrupt(&self, intid: IntId) {
146 self.EOIR.set(intid.into())
147 }
148}