xref: /DragonOS/kernel/src/driver/irqchip/riscv_intc.rs (revision 338f6903262c5031abad3c8e361813355a27fcdb)
1*338f6903SLoGin use alloc::{string::ToString, sync::Arc};
2*338f6903SLoGin use system_error::SystemError;
3*338f6903SLoGin 
4*338f6903SLoGin use crate::exception::{
5*338f6903SLoGin     handle::PerCpuDevIdIrqHandler,
6*338f6903SLoGin     irqchip::{IrqChip, IrqChipFlags},
7*338f6903SLoGin     irqdata::IrqData,
8*338f6903SLoGin     irqdesc::irq_desc_manager,
9*338f6903SLoGin     irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
10*338f6903SLoGin     HardwareIrqNumber, IrqNumber,
11*338f6903SLoGin };
12*338f6903SLoGin 
13*338f6903SLoGin static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None;
14*338f6903SLoGin static mut RISCV_INTC_CHIP: Option<Arc<RiscvIntcChip>> = None;
15*338f6903SLoGin 
16*338f6903SLoGin #[inline(always)]
17*338f6903SLoGin pub fn riscv_intc_domain() -> &'static Option<Arc<IrqDomain>> {
18*338f6903SLoGin     unsafe { &RISCV_INTC_DOMAIN }
19*338f6903SLoGin }
20*338f6903SLoGin 
21*338f6903SLoGin #[inline(always)]
22*338f6903SLoGin fn riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>> {
23*338f6903SLoGin     unsafe { RISCV_INTC_CHIP.as_ref() }
24*338f6903SLoGin }
25*338f6903SLoGin 
26*338f6903SLoGin #[derive(Debug)]
27*338f6903SLoGin struct RiscvIntcChip;
28*338f6903SLoGin 
29*338f6903SLoGin impl IrqChip for RiscvIntcChip {
30*338f6903SLoGin     fn name(&self) -> &'static str {
31*338f6903SLoGin         "RISC-V INTC"
32*338f6903SLoGin     }
33*338f6903SLoGin 
34*338f6903SLoGin     fn irq_disable(&self, _irq: &Arc<IrqData>) {}
35*338f6903SLoGin 
36*338f6903SLoGin     fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
37*338f6903SLoGin         unsafe { riscv::register::sie::clear_bits(1 << irq.hardware_irq().data()) };
38*338f6903SLoGin         Ok(())
39*338f6903SLoGin     }
40*338f6903SLoGin 
41*338f6903SLoGin     fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
42*338f6903SLoGin         unsafe { riscv::register::sie::set_bits(1 << irq.hardware_irq().data()) };
43*338f6903SLoGin         Ok(())
44*338f6903SLoGin     }
45*338f6903SLoGin 
46*338f6903SLoGin     fn irq_ack(&self, irq: &Arc<IrqData>) {
47*338f6903SLoGin         todo!()
48*338f6903SLoGin     }
49*338f6903SLoGin 
50*338f6903SLoGin     fn can_mask_ack(&self) -> bool {
51*338f6903SLoGin         false
52*338f6903SLoGin     }
53*338f6903SLoGin 
54*338f6903SLoGin     fn irq_eoi(&self, _irq: &Arc<IrqData>) {
55*338f6903SLoGin         /*
56*338f6903SLoGin          * The RISC-V INTC driver uses handle_percpu_devid_irq() flow
57*338f6903SLoGin          * for the per-HART local interrupts and child irqchip drivers
58*338f6903SLoGin          * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement
59*338f6903SLoGin          * chained handlers for the per-HART local interrupts.
60*338f6903SLoGin          *
61*338f6903SLoGin          * In the absence of irq_eoi(), the chained_irq_enter() and
62*338f6903SLoGin          * chained_irq_exit() functions (used by child irqchip drivers)
63*338f6903SLoGin          * will do unnecessary mask/unmask of per-HART local interrupts
64*338f6903SLoGin          * at the time of handling interrupts. To avoid this, we provide
65*338f6903SLoGin          * an empty irq_eoi() callback for RISC-V INTC irqchip.
66*338f6903SLoGin          */
67*338f6903SLoGin     }
68*338f6903SLoGin 
69*338f6903SLoGin     fn can_set_affinity(&self) -> bool {
70*338f6903SLoGin         false
71*338f6903SLoGin     }
72*338f6903SLoGin 
73*338f6903SLoGin     fn can_set_flow_type(&self) -> bool {
74*338f6903SLoGin         false
75*338f6903SLoGin     }
76*338f6903SLoGin 
77*338f6903SLoGin     fn flags(&self) -> IrqChipFlags {
78*338f6903SLoGin         todo!()
79*338f6903SLoGin     }
80*338f6903SLoGin }
81*338f6903SLoGin 
82*338f6903SLoGin #[derive(Debug)]
83*338f6903SLoGin struct RiscvIntcDomainOps;
84*338f6903SLoGin 
85*338f6903SLoGin impl IrqDomainOps for RiscvIntcDomainOps {
86*338f6903SLoGin     fn map(
87*338f6903SLoGin         &self,
88*338f6903SLoGin         irq_domain: &Arc<IrqDomain>,
89*338f6903SLoGin         hwirq: HardwareIrqNumber,
90*338f6903SLoGin         virq: IrqNumber,
91*338f6903SLoGin     ) -> Result<(), SystemError> {
92*338f6903SLoGin         irq_desc_manager().set_percpu_devid_all(virq)?;
93*338f6903SLoGin         irq_domain_manager().domain_set_info(
94*338f6903SLoGin             irq_domain,
95*338f6903SLoGin             virq,
96*338f6903SLoGin             hwirq,
97*338f6903SLoGin             riscv_intc_chip().unwrap().clone() as Arc<dyn IrqChip>,
98*338f6903SLoGin             irq_domain.host_data(),
99*338f6903SLoGin             &PerCpuDevIdIrqHandler,
100*338f6903SLoGin             None,
101*338f6903SLoGin             None,
102*338f6903SLoGin         );
103*338f6903SLoGin 
104*338f6903SLoGin         return Ok(());
105*338f6903SLoGin     }
106*338f6903SLoGin 
107*338f6903SLoGin     fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber) {
108*338f6903SLoGin         todo!("riscv_intc_domain_ops::unmap");
109*338f6903SLoGin     }
110*338f6903SLoGin }
111*338f6903SLoGin 
112*338f6903SLoGin #[inline(never)]
113*338f6903SLoGin pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
114*338f6903SLoGin     let intc_chip = Arc::new(RiscvIntcChip);
115*338f6903SLoGin 
116*338f6903SLoGin     unsafe {
117*338f6903SLoGin         RISCV_INTC_CHIP = Some(intc_chip);
118*338f6903SLoGin     }
119*338f6903SLoGin 
120*338f6903SLoGin     let intc_domain = irq_domain_manager()
121*338f6903SLoGin         .create_and_add_linear("riscv-intc".to_string(), &RiscvIntcDomainOps, 64)
122*338f6903SLoGin         .ok_or_else(|| {
123*338f6903SLoGin             kerror!("Failed to create riscv-intc domain");
124*338f6903SLoGin             SystemError::ENXIO
125*338f6903SLoGin         })?;
126*338f6903SLoGin 
127*338f6903SLoGin     irq_domain_manager().set_default_domain(intc_domain.clone());
128*338f6903SLoGin 
129*338f6903SLoGin     unsafe {
130*338f6903SLoGin         RISCV_INTC_DOMAIN = Some(intc_domain);
131*338f6903SLoGin     }
132*338f6903SLoGin 
133*338f6903SLoGin     return Ok(());
134*338f6903SLoGin }
135