1ce5850adSLoGin use core::{any::Any, fmt::Debug}; 2ce5850adSLoGin 3ce5850adSLoGin use alloc::{ 4ce5850adSLoGin sync::{Arc, Weak}, 5ce5850adSLoGin vec::Vec, 6ce5850adSLoGin }; 7ce5850adSLoGin use system_error::SystemError; 8ce5850adSLoGin 9ce5850adSLoGin use crate::{libs::spinlock::SpinLock, mm::VirtAddr}; 10ce5850adSLoGin 11ce5850adSLoGin use super::{ 12ce5850adSLoGin irqdata::{IrqData, IrqLineStatus}, 13ce5850adSLoGin irqdomain::IrqDomain, 14ce5850adSLoGin msi::MsiMsg, 15ce5850adSLoGin }; 16ce5850adSLoGin 17ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506 18ce5850adSLoGin pub trait IrqChip: Sync + Send + Any + Debug { 19ce5850adSLoGin fn name(&self) -> &'static str; 20ce5850adSLoGin /// start up the interrupt (defaults to ->enable if ENOSYS) 21ce5850adSLoGin fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 22ce5850adSLoGin Err(SystemError::ENOSYS) 23ce5850adSLoGin } 24ce5850adSLoGin 25ce5850adSLoGin /// shut down the interrupt (defaults to ->disable if ENOSYS) 26ce5850adSLoGin fn irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 27ce5850adSLoGin Err(SystemError::ENOSYS) 28ce5850adSLoGin } 29ce5850adSLoGin 30ce5850adSLoGin /// enable the interrupt 31ce5850adSLoGin /// 32ce5850adSLoGin /// (defaults to ->unmask if ENOSYS) 33ce5850adSLoGin fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 34ce5850adSLoGin Err(SystemError::ENOSYS) 35ce5850adSLoGin } 36ce5850adSLoGin 37ce5850adSLoGin /// disable the interrupt 38ce5850adSLoGin fn irq_disable(&self, irq: &Arc<IrqData>); 39ce5850adSLoGin 40ce5850adSLoGin /// start of a new interrupt 41ce5850adSLoGin fn irq_ack(&self, irq: &Arc<IrqData>); 42ce5850adSLoGin 43ce5850adSLoGin /// mask an interrupt source 44*3bc96fa4SLoGin fn irq_mask(&self, _irq: &Arc<IrqData>) {} 45ce5850adSLoGin /// ack and mask an interrupt source 46*3bc96fa4SLoGin fn irq_mask_ack(&self, _irq: &Arc<IrqData>) {} 47ce5850adSLoGin /// unmask an interrupt source 48*3bc96fa4SLoGin fn irq_unmask(&self, _irq: &Arc<IrqData>) {} 49ce5850adSLoGin /// end of interrupt 50*3bc96fa4SLoGin fn irq_eoi(&self, _irq: &Arc<IrqData>) {} 51ce5850adSLoGin 52ce5850adSLoGin // todo: set affinity 53ce5850adSLoGin 54ce5850adSLoGin /// retrigger an IRQ to the CPU 55*3bc96fa4SLoGin fn retrigger(&self, _irq: &Arc<IrqData>) {} 56ce5850adSLoGin 57ce5850adSLoGin /// set the flow type of an interrupt 58ce5850adSLoGin /// 59ce5850adSLoGin /// flow_type: the flow type to set 60ce5850adSLoGin /// 61ce5850adSLoGin fn irq_set_type( 62ce5850adSLoGin &self, 63ce5850adSLoGin _irq: &Arc<IrqData>, 64ce5850adSLoGin _flow_type: IrqLineStatus, 65ce5850adSLoGin ) -> Result<(), SystemError> { 66ce5850adSLoGin Err(SystemError::ENOSYS) 67ce5850adSLoGin } 68ce5850adSLoGin 69ce5850adSLoGin /// enable/disable power management wake-on of an interrupt 70ce5850adSLoGin fn irq_set_wake(&self, _irq: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> { 71ce5850adSLoGin Err(SystemError::ENOSYS) 72ce5850adSLoGin } 73ce5850adSLoGin 74ce5850adSLoGin /// function to lock access to slow bus (i2c) chips 75ce5850adSLoGin fn irq_bus_lock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 76ce5850adSLoGin Ok(()) 77ce5850adSLoGin } 78ce5850adSLoGin 79ce5850adSLoGin /// function to sync and unlock slow bus (i2c) chips 80ce5850adSLoGin fn irq_bus_sync_unlock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 81ce5850adSLoGin Ok(()) 82ce5850adSLoGin } 83ce5850adSLoGin 84ce5850adSLoGin /// function called from core code on suspend once per 85ce5850adSLoGin /// chip, when one or more interrupts are installed 86*3bc96fa4SLoGin fn irq_suspend(&self, _irq: &Arc<IrqData>) {} 87ce5850adSLoGin 88ce5850adSLoGin /// function called from core code on resume once per chip, 89ce5850adSLoGin /// when one ore more interrupts are installed 90*3bc96fa4SLoGin fn irq_resume(&self, _irq: &Arc<IrqData>) {} 91ce5850adSLoGin 92ce5850adSLoGin /// function called from core code on shutdown once per chip 93*3bc96fa4SLoGin fn irq_pm_shutdown(&self, _irq: &Arc<IrqData>) {} 94ce5850adSLoGin 95ce5850adSLoGin /// Optional function to set irq_data.mask for special cases 96ce5850adSLoGin fn irq_calc_mask(&self, _irq: &Arc<IrqData>) {} 97ce5850adSLoGin 98ce5850adSLoGin // todo: print chip 99ce5850adSLoGin 100ce5850adSLoGin /// optional to request resources before calling 101ce5850adSLoGin /// any other callback related to this irq 102ce5850adSLoGin fn irq_request_resources(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 103ce5850adSLoGin Ok(()) 104ce5850adSLoGin } 105ce5850adSLoGin 106ce5850adSLoGin /// optional to release resources acquired with 107ce5850adSLoGin /// irq_request_resources 108ce5850adSLoGin fn irq_release_resources(&self, _irq: &Arc<IrqData>) {} 109ce5850adSLoGin 110ce5850adSLoGin /// optional to compose message content for MSI 111ce5850adSLoGin fn irq_compose_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &mut MsiMsg) {} 112ce5850adSLoGin 113ce5850adSLoGin /// optional to write message content for MSI 114ce5850adSLoGin fn irq_write_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &MsiMsg) {} 115ce5850adSLoGin 116ce5850adSLoGin /// return the internal state of an interrupt 117ce5850adSLoGin fn irqchip_state( 118ce5850adSLoGin &self, 119ce5850adSLoGin _irq: &Arc<IrqData>, 120ce5850adSLoGin _which: IrqChipState, 121ce5850adSLoGin ) -> Result<bool, SystemError> { 122ce5850adSLoGin Err(SystemError::ENOSYS) 123ce5850adSLoGin } 124ce5850adSLoGin 125ce5850adSLoGin /// set the internal state of an interrupt 126ce5850adSLoGin fn set_irqchip_state( 127ce5850adSLoGin &self, 128ce5850adSLoGin _irq: &Arc<IrqData>, 129ce5850adSLoGin _which: IrqChipState, 130ce5850adSLoGin _state: bool, 131ce5850adSLoGin ) -> Result<(), SystemError> { 132ce5850adSLoGin Err(SystemError::ENOSYS) 133ce5850adSLoGin } 134ce5850adSLoGin 135ce5850adSLoGin // todo: set vcpu affinity 136ce5850adSLoGin 137ce5850adSLoGin /// send a single IPI to destination cpus 138*3bc96fa4SLoGin fn send_single_ipi(&self, _irq: &Arc<IrqData>, _cpu: u32) {} 139ce5850adSLoGin 140ce5850adSLoGin // todo: send ipi with cpu mask 141ce5850adSLoGin 142ce5850adSLoGin /// function called from core code before enabling an NMI 143ce5850adSLoGin fn irq_nmi_setup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 144ce5850adSLoGin Err(SystemError::ENOSYS) 145ce5850adSLoGin } 146ce5850adSLoGin 147ce5850adSLoGin /// function called from core code after disabling an NMI 148*3bc96fa4SLoGin fn irq_nmi_teardown(&self, _irq: &Arc<IrqData>) {} 149*3bc96fa4SLoGin 150*3bc96fa4SLoGin fn flags(&self) -> IrqChipFlags; 151ce5850adSLoGin } 152ce5850adSLoGin 153ce5850adSLoGin #[allow(dead_code)] 154ce5850adSLoGin #[derive(Debug, Clone, Copy)] 155ce5850adSLoGin pub enum IrqChipState { 156ce5850adSLoGin /// Is the interrupt pending? 157ce5850adSLoGin Pending, 158ce5850adSLoGin /// Is the interrupt in progress? 159ce5850adSLoGin Active, 160ce5850adSLoGin /// Is the interrupt masked? 161ce5850adSLoGin Masked, 162ce5850adSLoGin /// Is Irq line high? 163ce5850adSLoGin LineLevel, 164ce5850adSLoGin } 165ce5850adSLoGin 166ce5850adSLoGin pub trait IrqChipData: Sync + Send + Any + Debug {} 167ce5850adSLoGin 168ce5850adSLoGin bitflags! { 169ce5850adSLoGin /// 定义 IrqGcFlags 位标志 170ce5850adSLoGin pub struct IrqGcFlags: u32 { 171ce5850adSLoGin /// 通过读取mask reg来初始化mask_cache 172ce5850adSLoGin const IRQ_GC_INIT_MASK_CACHE = 1 << 0; 173ce5850adSLoGin /// 对于需要在父irq上调用irq_set_wake()的irq芯片, 将irqs的锁类设置为嵌套。Usually GPIO implementations 174ce5850adSLoGin const IRQ_GC_INIT_NESTED_LOCK = 1 << 1; 175ce5850adSLoGin /// Mask cache是芯片类型私有的 176ce5850adSLoGin const IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2; 177ce5850adSLoGin /// 不计算irqData->mask 178ce5850adSLoGin const IRQ_GC_NO_MASK = 1 << 3; 179ce5850adSLoGin /// 使用大端字节序的寄存器访问(默认:小端LE) 180ce5850adSLoGin const IRQ_GC_BE_IO = 1 << 4; 181ce5850adSLoGin } 182ce5850adSLoGin } 183ce5850adSLoGin 184ce5850adSLoGin #[allow(dead_code)] 185ce5850adSLoGin #[derive(Debug)] 186ce5850adSLoGin pub struct IrqChipGeneric { 187ce5850adSLoGin inner: SpinLock<InnerIrqChipGeneric>, 188ce5850adSLoGin } 189ce5850adSLoGin 190ce5850adSLoGin #[allow(dead_code)] 191ce5850adSLoGin #[derive(Debug)] 192ce5850adSLoGin struct InnerIrqChipGeneric { 193ce5850adSLoGin /// Register base address 194ce5850adSLoGin reg_base: VirtAddr, 195ce5850adSLoGin ops: &'static dyn IrqChipGenericOps, 196ce5850adSLoGin /// Interrupt base num for this chip 197ce5850adSLoGin irq_base: u32, 198ce5850adSLoGin /// Number of interrupts handled by this chip 199ce5850adSLoGin irq_cnt: u32, 200ce5850adSLoGin /// Cached mask register shared between all chip types 201ce5850adSLoGin mask_cache: u32, 202ce5850adSLoGin /// Cached type register 203ce5850adSLoGin type_cache: u32, 204ce5850adSLoGin /// Cached polarity register 205ce5850adSLoGin polarity_cache: u32, 206ce5850adSLoGin /// Interrupt can wakeup from suspend 207ce5850adSLoGin wake_enabled: bool, 208ce5850adSLoGin /// Interrupt is marked as an wakeup from suspend source 209ce5850adSLoGin wake_active: bool, 210ce5850adSLoGin /// Number of available irq_chip_type instances (usually 1) 211ce5850adSLoGin num_chip_type: u32, 212ce5850adSLoGin private_data: Option<Arc<dyn IrqChipGenericPrivateData>>, 213ce5850adSLoGin installed: u64, 214ce5850adSLoGin unused: u64, 215ce5850adSLoGin domain: Weak<IrqDomain>, 216ce5850adSLoGin chip_types: Vec<IrqChipType>, 217ce5850adSLoGin } 218ce5850adSLoGin 219*3bc96fa4SLoGin pub trait IrqChipGenericOps: Debug + Send + Sync { 220ce5850adSLoGin /// Alternate I/O accessor (defaults to readl if NULL) 221ce5850adSLoGin unsafe fn reg_readl(&self, addr: VirtAddr) -> u32; 222ce5850adSLoGin 223ce5850adSLoGin /// Alternate I/O accessor (defaults to writel if NULL) 224ce5850adSLoGin unsafe fn reg_writel(&self, addr: VirtAddr, val: u32); 225ce5850adSLoGin 226ce5850adSLoGin /// Function called from core code on suspend once per 227ce5850adSLoGin /// chip; can be useful instead of irq_chip::suspend to 228ce5850adSLoGin /// handle chip details even when no interrupts are in use 229ce5850adSLoGin fn suspend(&self, gc: &Arc<IrqChipGeneric>); 230ce5850adSLoGin /// Function called from core code on resume once per chip; 231ce5850adSLoGin /// can be useful instead of irq_chip::resume to handle chip 232ce5850adSLoGin /// details even when no interrupts are in use 233ce5850adSLoGin fn resume(&self, gc: &Arc<IrqChipGeneric>); 234ce5850adSLoGin } 235ce5850adSLoGin 236ce5850adSLoGin pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {} 237ce5850adSLoGin 238ce5850adSLoGin #[derive(Debug)] 239ce5850adSLoGin pub struct IrqChipType { 240ce5850adSLoGin // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024 241ce5850adSLoGin } 242*3bc96fa4SLoGin 243*3bc96fa4SLoGin bitflags! { 244*3bc96fa4SLoGin /// IrqChip specific flags 245*3bc96fa4SLoGin pub struct IrqChipFlags: u32 { 246*3bc96fa4SLoGin /// 在调用chip.irq_set_type()之前屏蔽 247*3bc96fa4SLoGin const IRQCHIP_SET_TYPE_MASKED = 1 << 0; 248*3bc96fa4SLoGin /// 只有在irq被处理时才发出irq_eoi() 249*3bc96fa4SLoGin const IRQCHIP_EOI_IF_HANDLED = 1 << 1; 250*3bc96fa4SLoGin /// 在挂起路径中屏蔽非唤醒irq 251*3bc96fa4SLoGin const IRQCHIP_MASK_ON_SUSPEND = 1 << 2; 252*3bc96fa4SLoGin /// 只有在irq启用时才调用irq_on/off_line回调 253*3bc96fa4SLoGin const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3; 254*3bc96fa4SLoGin /// 跳过chip.irq_set_wake(),对于这个irq芯片 255*3bc96fa4SLoGin const IRQCHIP_SKIP_SET_WAKE = 1 << 4; 256*3bc96fa4SLoGin /// 单次触发不需要屏蔽/取消屏蔽 257*3bc96fa4SLoGin const IRQCHIP_ONESHOT_SAFE = 1 << 5; 258*3bc96fa4SLoGin /// 芯片在线程模式下需要在取消屏蔽时eoi() 259*3bc96fa4SLoGin const IRQCHIP_EOI_THREADED = 1 << 6; 260*3bc96fa4SLoGin /// 芯片可以为Level MSIs提供两个门铃 261*3bc96fa4SLoGin const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7; 262*3bc96fa4SLoGin /// 芯片可以传递NMIs,仅适用于根irqchips 263*3bc96fa4SLoGin const IRQCHIP_SUPPORTS_NMI = 1 << 8; 264*3bc96fa4SLoGin /// 在挂起路径中,如果它们处于禁用状态,则调用__enable_irq()/__disable_irq()以唤醒irq 265*3bc96fa4SLoGin const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9; 266*3bc96fa4SLoGin /// 在启动前更新默认亲和性 267*3bc96fa4SLoGin const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10; 268*3bc96fa4SLoGin /// 不要在这个芯片中改变任何东西 269*3bc96fa4SLoGin const IRQCHIP_IMMUTABLE = 1 << 11; 270*3bc96fa4SLoGin } 271*3bc96fa4SLoGin } 272