axplat_aarch64_peripherals/
gic.rs1use arm_gicv2::{GicCpuInterface, GicDistributor};
4use axplat::irq::{HandlerTable, IrqHandler};
5use axplat::mem::VirtAddr;
6use kspin::SpinNoIrq;
7use lazyinit::LazyInit;
8
9const MAX_IRQ_COUNT: usize = 1024;
11
12static GICD: LazyInit<SpinNoIrq<GicDistributor>> = LazyInit::new();
13
14static GICC: LazyInit<GicCpuInterface> = LazyInit::new();
16
17static IRQ_HANDLER_TABLE: HandlerTable<MAX_IRQ_COUNT> = HandlerTable::new();
18
19pub fn set_enable(irq_num: usize, enabled: bool) {
21 trace!("GICD set enable: {} {}", irq_num, enabled);
22 GICD.lock().set_enable(irq_num as _, enabled);
23}
24
25pub fn register_handler(irq_num: usize, handler: IrqHandler) -> bool {
30 trace!("register handler IRQ {}", irq_num);
31 if IRQ_HANDLER_TABLE.register_handler(irq_num, handler) {
32 set_enable(irq_num, true);
33 return true;
34 }
35 warn!("register handler for IRQ {} failed", irq_num);
36 false
37}
38
39pub fn unregister_handler(irq_num: usize) -> Option<IrqHandler> {
44 trace!("unregister handler IRQ {}", irq_num);
45 set_enable(irq_num, false);
46 IRQ_HANDLER_TABLE.unregister_handler(irq_num)
47}
48
49pub fn handle_irq(_unused: usize) {
55 GICC.handle_irq(|irq_num| {
56 trace!("IRQ {}", irq_num);
57 if !IRQ_HANDLER_TABLE.handle(irq_num as _) {
58 warn!("Unhandled IRQ {}", irq_num);
59 }
60 });
61}
62
63pub fn init_gicd(gicd_base: VirtAddr, gicc_base: VirtAddr) {
65 info!("Initialize GICv2...");
66 GICD.init_once(SpinNoIrq::new(GicDistributor::new(gicd_base.as_mut_ptr())));
67 GICC.init_once(GicCpuInterface::new(gicc_base.as_mut_ptr()));
68 GICD.lock().init();
69}
70
71pub fn init_gicc() {
75 GICC.init();
76}
77
78#[macro_export]
80macro_rules! irq_if_impl {
81 ($name:ident) => {
82 struct $name;
83
84 #[impl_plat_interface]
85 impl axplat::irq::IrqIf for $name {
86 fn set_enable(irq: usize, enabled: bool) {
88 $crate::gic::set_enable(irq, enabled);
89 }
90
91 fn register(irq: usize, handler: axplat::irq::IrqHandler) -> bool {
96 $crate::gic::register_handler(irq, handler)
97 }
98
99 fn unregister(irq: usize) -> Option<axplat::irq::IrqHandler> {
104 $crate::gic::unregister_handler(irq)
105 }
106
107 fn handle(irq: usize) {
113 $crate::gic::handle_irq(irq)
114 }
115 }
116 };
117}