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