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 9*e2841179SLoGin use crate::{ 10*e2841179SLoGin libs::{cpumask::CpuMask, spinlock::SpinLock}, 11*e2841179SLoGin mm::VirtAddr, 12*e2841179SLoGin }; 13ce5850adSLoGin 14ce5850adSLoGin use super::{ 15ce5850adSLoGin irqdata::{IrqData, IrqLineStatus}, 16ce5850adSLoGin irqdomain::IrqDomain, 17*e2841179SLoGin manage::IrqManager, 18ce5850adSLoGin msi::MsiMsg, 19ce5850adSLoGin }; 20ce5850adSLoGin 21ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506 22ce5850adSLoGin pub trait IrqChip: Sync + Send + Any + Debug { 23ce5850adSLoGin fn name(&self) -> &'static str; 24ce5850adSLoGin /// start up the interrupt (defaults to ->enable if ENOSYS) 25ce5850adSLoGin fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 26ce5850adSLoGin Err(SystemError::ENOSYS) 27ce5850adSLoGin } 28ce5850adSLoGin 29ce5850adSLoGin /// shut down the interrupt (defaults to ->disable if ENOSYS) 30ce5850adSLoGin fn irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 31ce5850adSLoGin Err(SystemError::ENOSYS) 32ce5850adSLoGin } 33ce5850adSLoGin 34ce5850adSLoGin /// enable the interrupt 35ce5850adSLoGin /// 36ce5850adSLoGin /// (defaults to ->unmask if ENOSYS) 37ce5850adSLoGin fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 38ce5850adSLoGin Err(SystemError::ENOSYS) 39ce5850adSLoGin } 40ce5850adSLoGin 41ce5850adSLoGin /// disable the interrupt 42ce5850adSLoGin fn irq_disable(&self, irq: &Arc<IrqData>); 43ce5850adSLoGin 44ce5850adSLoGin /// start of a new interrupt 45ce5850adSLoGin fn irq_ack(&self, irq: &Arc<IrqData>); 46ce5850adSLoGin 47ce5850adSLoGin /// mask an interrupt source 48*e2841179SLoGin /// 49*e2841179SLoGin /// 用于屏蔽中断 50*e2841179SLoGin /// 51*e2841179SLoGin /// 如果返回ENOSYS,则表明irq_mask()不支持. 52*e2841179SLoGin /// 53*e2841179SLoGin /// 如果返回错误,那么中断的屏蔽状态将不会改变。 54*e2841179SLoGin fn irq_mask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 55*e2841179SLoGin Err(SystemError::ENOSYS) 56*e2841179SLoGin } 57*e2841179SLoGin 58*e2841179SLoGin /// 指示当前芯片是否实现了`irq_mask_ack`函数 59*e2841179SLoGin fn can_mask_ack(&self) -> bool; 60*e2841179SLoGin 61ce5850adSLoGin /// ack and mask an interrupt source 623bc96fa4SLoGin fn irq_mask_ack(&self, _irq: &Arc<IrqData>) {} 63*e2841179SLoGin 64ce5850adSLoGin /// unmask an interrupt source 65*e2841179SLoGin /// 66*e2841179SLoGin /// 用于取消屏蔽中断 67*e2841179SLoGin /// 68*e2841179SLoGin /// 如果返回ENOSYS,则表明irq_unmask()不支持. 69*e2841179SLoGin fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 70*e2841179SLoGin Err(SystemError::ENOSYS) 71*e2841179SLoGin } 72ce5850adSLoGin /// end of interrupt 733bc96fa4SLoGin fn irq_eoi(&self, _irq: &Arc<IrqData>) {} 74ce5850adSLoGin 75*e2841179SLoGin /// 指示当前芯片是否可以设置中断亲和性。 76*e2841179SLoGin fn can_set_affinity(&self) -> bool; 77*e2841179SLoGin 78*e2841179SLoGin /// 在SMP机器上设置CPU亲和性。 79*e2841179SLoGin /// 80*e2841179SLoGin /// 如果force参数为真,它告诉驱动程序无条件地应用亲和性设置。 81*e2841179SLoGin /// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔,其中目标CPU尚未在cpu_online_mask中设置。 82*e2841179SLoGin fn irq_set_affinity( 83*e2841179SLoGin &self, 84*e2841179SLoGin _irq: &Arc<IrqData>, 85*e2841179SLoGin _cpu: &CpuMask, 86*e2841179SLoGin _force: bool, 87*e2841179SLoGin ) -> Result<IrqChipSetMaskResult, SystemError> { 88*e2841179SLoGin Err(SystemError::ENOSYS) 89*e2841179SLoGin } 90ce5850adSLoGin 91ce5850adSLoGin /// retrigger an IRQ to the CPU 92*e2841179SLoGin fn retrigger(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 93*e2841179SLoGin Err(SystemError::ENOSYS) 94*e2841179SLoGin } 95*e2841179SLoGin 96*e2841179SLoGin /// 指示当前芯片是否可以设置中断流类型。 97*e2841179SLoGin /// 98*e2841179SLoGin /// 如果返回true,则可以调用irq_set_type()。 99*e2841179SLoGin fn can_set_flow_type(&self) -> bool; 100ce5850adSLoGin 101ce5850adSLoGin /// set the flow type of an interrupt 102ce5850adSLoGin /// 103ce5850adSLoGin /// flow_type: the flow type to set 104ce5850adSLoGin /// 105ce5850adSLoGin fn irq_set_type( 106ce5850adSLoGin &self, 107ce5850adSLoGin _irq: &Arc<IrqData>, 108ce5850adSLoGin _flow_type: IrqLineStatus, 109*e2841179SLoGin ) -> Result<IrqChipSetMaskResult, SystemError> { 110ce5850adSLoGin Err(SystemError::ENOSYS) 111ce5850adSLoGin } 112ce5850adSLoGin 113ce5850adSLoGin /// enable/disable power management wake-on of an interrupt 114ce5850adSLoGin fn irq_set_wake(&self, _irq: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> { 115ce5850adSLoGin Err(SystemError::ENOSYS) 116ce5850adSLoGin } 117ce5850adSLoGin 118ce5850adSLoGin /// function to lock access to slow bus (i2c) chips 119ce5850adSLoGin fn irq_bus_lock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 120ce5850adSLoGin Ok(()) 121ce5850adSLoGin } 122ce5850adSLoGin 123ce5850adSLoGin /// function to sync and unlock slow bus (i2c) chips 124ce5850adSLoGin fn irq_bus_sync_unlock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 125ce5850adSLoGin Ok(()) 126ce5850adSLoGin } 127ce5850adSLoGin 128ce5850adSLoGin /// function called from core code on suspend once per 129ce5850adSLoGin /// chip, when one or more interrupts are installed 1303bc96fa4SLoGin fn irq_suspend(&self, _irq: &Arc<IrqData>) {} 131ce5850adSLoGin 132ce5850adSLoGin /// function called from core code on resume once per chip, 133ce5850adSLoGin /// when one ore more interrupts are installed 1343bc96fa4SLoGin fn irq_resume(&self, _irq: &Arc<IrqData>) {} 135ce5850adSLoGin 136ce5850adSLoGin /// function called from core code on shutdown once per chip 1373bc96fa4SLoGin fn irq_pm_shutdown(&self, _irq: &Arc<IrqData>) {} 138ce5850adSLoGin 139ce5850adSLoGin /// Optional function to set irq_data.mask for special cases 140ce5850adSLoGin fn irq_calc_mask(&self, _irq: &Arc<IrqData>) {} 141ce5850adSLoGin 142ce5850adSLoGin // todo: print chip 143ce5850adSLoGin 144ce5850adSLoGin /// optional to request resources before calling 145ce5850adSLoGin /// any other callback related to this irq 146ce5850adSLoGin fn irq_request_resources(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 147ce5850adSLoGin Ok(()) 148ce5850adSLoGin } 149ce5850adSLoGin 150ce5850adSLoGin /// optional to release resources acquired with 151ce5850adSLoGin /// irq_request_resources 152ce5850adSLoGin fn irq_release_resources(&self, _irq: &Arc<IrqData>) {} 153ce5850adSLoGin 154ce5850adSLoGin /// optional to compose message content for MSI 155*e2841179SLoGin /// 156*e2841179SLoGin /// 组装MSI消息并返回到msg中 157ce5850adSLoGin fn irq_compose_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &mut MsiMsg) {} 158ce5850adSLoGin 159ce5850adSLoGin /// optional to write message content for MSI 160ce5850adSLoGin fn irq_write_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &MsiMsg) {} 161ce5850adSLoGin 162ce5850adSLoGin /// return the internal state of an interrupt 163ce5850adSLoGin fn irqchip_state( 164ce5850adSLoGin &self, 165ce5850adSLoGin _irq: &Arc<IrqData>, 166ce5850adSLoGin _which: IrqChipState, 167ce5850adSLoGin ) -> Result<bool, SystemError> { 168ce5850adSLoGin Err(SystemError::ENOSYS) 169ce5850adSLoGin } 170ce5850adSLoGin 171ce5850adSLoGin /// set the internal state of an interrupt 172ce5850adSLoGin fn set_irqchip_state( 173ce5850adSLoGin &self, 174ce5850adSLoGin _irq: &Arc<IrqData>, 175ce5850adSLoGin _which: IrqChipState, 176ce5850adSLoGin _state: bool, 177ce5850adSLoGin ) -> Result<(), SystemError> { 178ce5850adSLoGin Err(SystemError::ENOSYS) 179ce5850adSLoGin } 180ce5850adSLoGin 181ce5850adSLoGin // todo: set vcpu affinity 182ce5850adSLoGin 183ce5850adSLoGin /// send a single IPI to destination cpus 1843bc96fa4SLoGin fn send_single_ipi(&self, _irq: &Arc<IrqData>, _cpu: u32) {} 185ce5850adSLoGin 186ce5850adSLoGin // todo: send ipi with cpu mask 187ce5850adSLoGin 188ce5850adSLoGin /// function called from core code before enabling an NMI 189ce5850adSLoGin fn irq_nmi_setup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 190ce5850adSLoGin Err(SystemError::ENOSYS) 191ce5850adSLoGin } 192ce5850adSLoGin 193ce5850adSLoGin /// function called from core code after disabling an NMI 1943bc96fa4SLoGin fn irq_nmi_teardown(&self, _irq: &Arc<IrqData>) {} 1953bc96fa4SLoGin 1963bc96fa4SLoGin fn flags(&self) -> IrqChipFlags; 197ce5850adSLoGin } 198ce5850adSLoGin 199ce5850adSLoGin #[allow(dead_code)] 200ce5850adSLoGin #[derive(Debug, Clone, Copy)] 201ce5850adSLoGin pub enum IrqChipState { 202ce5850adSLoGin /// Is the interrupt pending? 203ce5850adSLoGin Pending, 204ce5850adSLoGin /// Is the interrupt in progress? 205ce5850adSLoGin Active, 206ce5850adSLoGin /// Is the interrupt masked? 207ce5850adSLoGin Masked, 208ce5850adSLoGin /// Is Irq line high? 209ce5850adSLoGin LineLevel, 210ce5850adSLoGin } 211ce5850adSLoGin 212*e2841179SLoGin /// 中断芯片的数据(per-irq的) 213*e2841179SLoGin pub trait IrqChipData: Sync + Send + Any + Debug { 214*e2841179SLoGin fn as_any_ref(&self) -> &dyn Any; 215*e2841179SLoGin } 216ce5850adSLoGin 217ce5850adSLoGin bitflags! { 218ce5850adSLoGin /// 定义 IrqGcFlags 位标志 219ce5850adSLoGin pub struct IrqGcFlags: u32 { 220ce5850adSLoGin /// 通过读取mask reg来初始化mask_cache 221ce5850adSLoGin const IRQ_GC_INIT_MASK_CACHE = 1 << 0; 222ce5850adSLoGin /// 对于需要在父irq上调用irq_set_wake()的irq芯片, 将irqs的锁类设置为嵌套。Usually GPIO implementations 223ce5850adSLoGin const IRQ_GC_INIT_NESTED_LOCK = 1 << 1; 224ce5850adSLoGin /// Mask cache是芯片类型私有的 225ce5850adSLoGin const IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2; 226ce5850adSLoGin /// 不计算irqData->mask 227ce5850adSLoGin const IRQ_GC_NO_MASK = 1 << 3; 228ce5850adSLoGin /// 使用大端字节序的寄存器访问(默认:小端LE) 229ce5850adSLoGin const IRQ_GC_BE_IO = 1 << 4; 230ce5850adSLoGin } 231ce5850adSLoGin } 232ce5850adSLoGin 233ce5850adSLoGin #[allow(dead_code)] 234ce5850adSLoGin #[derive(Debug)] 235ce5850adSLoGin pub struct IrqChipGeneric { 236ce5850adSLoGin inner: SpinLock<InnerIrqChipGeneric>, 237ce5850adSLoGin } 238ce5850adSLoGin 239ce5850adSLoGin #[allow(dead_code)] 240ce5850adSLoGin #[derive(Debug)] 241ce5850adSLoGin struct InnerIrqChipGeneric { 242ce5850adSLoGin /// Register base address 243ce5850adSLoGin reg_base: VirtAddr, 244ce5850adSLoGin ops: &'static dyn IrqChipGenericOps, 245ce5850adSLoGin /// Interrupt base num for this chip 246ce5850adSLoGin irq_base: u32, 247ce5850adSLoGin /// Number of interrupts handled by this chip 248ce5850adSLoGin irq_cnt: u32, 249ce5850adSLoGin /// Cached mask register shared between all chip types 250ce5850adSLoGin mask_cache: u32, 251ce5850adSLoGin /// Cached type register 252ce5850adSLoGin type_cache: u32, 253ce5850adSLoGin /// Cached polarity register 254ce5850adSLoGin polarity_cache: u32, 255ce5850adSLoGin /// Interrupt can wakeup from suspend 256ce5850adSLoGin wake_enabled: bool, 257ce5850adSLoGin /// Interrupt is marked as an wakeup from suspend source 258ce5850adSLoGin wake_active: bool, 259ce5850adSLoGin /// Number of available irq_chip_type instances (usually 1) 260ce5850adSLoGin num_chip_type: u32, 261ce5850adSLoGin private_data: Option<Arc<dyn IrqChipGenericPrivateData>>, 262ce5850adSLoGin installed: u64, 263ce5850adSLoGin unused: u64, 264ce5850adSLoGin domain: Weak<IrqDomain>, 265ce5850adSLoGin chip_types: Vec<IrqChipType>, 266ce5850adSLoGin } 267ce5850adSLoGin 2683bc96fa4SLoGin pub trait IrqChipGenericOps: Debug + Send + Sync { 269ce5850adSLoGin /// Alternate I/O accessor (defaults to readl if NULL) 270ce5850adSLoGin unsafe fn reg_readl(&self, addr: VirtAddr) -> u32; 271ce5850adSLoGin 272ce5850adSLoGin /// Alternate I/O accessor (defaults to writel if NULL) 273ce5850adSLoGin unsafe fn reg_writel(&self, addr: VirtAddr, val: u32); 274ce5850adSLoGin 275ce5850adSLoGin /// Function called from core code on suspend once per 276ce5850adSLoGin /// chip; can be useful instead of irq_chip::suspend to 277ce5850adSLoGin /// handle chip details even when no interrupts are in use 278ce5850adSLoGin fn suspend(&self, gc: &Arc<IrqChipGeneric>); 279ce5850adSLoGin /// Function called from core code on resume once per chip; 280ce5850adSLoGin /// can be useful instead of irq_chip::resume to handle chip 281ce5850adSLoGin /// details even when no interrupts are in use 282ce5850adSLoGin fn resume(&self, gc: &Arc<IrqChipGeneric>); 283ce5850adSLoGin } 284ce5850adSLoGin 285ce5850adSLoGin pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {} 286ce5850adSLoGin 287ce5850adSLoGin #[derive(Debug)] 288ce5850adSLoGin pub struct IrqChipType { 289ce5850adSLoGin // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024 290ce5850adSLoGin } 2913bc96fa4SLoGin 292*e2841179SLoGin #[allow(dead_code)] 293*e2841179SLoGin #[derive(Debug)] 294*e2841179SLoGin pub enum IrqChipSetMaskResult { 295*e2841179SLoGin /// core updates mask ok. 296*e2841179SLoGin SetMaskOk, 297*e2841179SLoGin /// core updates mask ok. No change. 298*e2841179SLoGin SetMaskOkNoChange, 299*e2841179SLoGin /// core updates mask ok. Done.(same as SetMaskOk) 300*e2841179SLoGin /// 301*e2841179SLoGin /// 支持堆叠irq芯片的特殊代码, 表示跳过所有子irq芯片。 302*e2841179SLoGin SetMaskOkDone, 303*e2841179SLoGin } 304*e2841179SLoGin 3053bc96fa4SLoGin bitflags! { 3063bc96fa4SLoGin /// IrqChip specific flags 3073bc96fa4SLoGin pub struct IrqChipFlags: u32 { 308*e2841179SLoGin /// 在调用chip.irq_set_type()之前屏蔽中断 3093bc96fa4SLoGin const IRQCHIP_SET_TYPE_MASKED = 1 << 0; 3103bc96fa4SLoGin /// 只有在irq被处理时才发出irq_eoi() 3113bc96fa4SLoGin const IRQCHIP_EOI_IF_HANDLED = 1 << 1; 3123bc96fa4SLoGin /// 在挂起路径中屏蔽非唤醒irq 3133bc96fa4SLoGin const IRQCHIP_MASK_ON_SUSPEND = 1 << 2; 3143bc96fa4SLoGin /// 只有在irq启用时才调用irq_on/off_line回调 3153bc96fa4SLoGin const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3; 3163bc96fa4SLoGin /// 跳过chip.irq_set_wake(),对于这个irq芯片 3173bc96fa4SLoGin const IRQCHIP_SKIP_SET_WAKE = 1 << 4; 3183bc96fa4SLoGin /// 单次触发不需要屏蔽/取消屏蔽 3193bc96fa4SLoGin const IRQCHIP_ONESHOT_SAFE = 1 << 5; 3203bc96fa4SLoGin /// 芯片在线程模式下需要在取消屏蔽时eoi() 3213bc96fa4SLoGin const IRQCHIP_EOI_THREADED = 1 << 6; 3223bc96fa4SLoGin /// 芯片可以为Level MSIs提供两个门铃 3233bc96fa4SLoGin const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7; 3243bc96fa4SLoGin /// 芯片可以传递NMIs,仅适用于根irqchips 3253bc96fa4SLoGin const IRQCHIP_SUPPORTS_NMI = 1 << 8; 3263bc96fa4SLoGin /// 在挂起路径中,如果它们处于禁用状态,则调用__enable_irq()/__disable_irq()以唤醒irq 3273bc96fa4SLoGin const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9; 3283bc96fa4SLoGin /// 在启动前更新默认亲和性 3293bc96fa4SLoGin const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10; 3303bc96fa4SLoGin /// 不要在这个芯片中改变任何东西 3313bc96fa4SLoGin const IRQCHIP_IMMUTABLE = 1 << 11; 3323bc96fa4SLoGin } 3333bc96fa4SLoGin } 334*e2841179SLoGin 335*e2841179SLoGin impl IrqManager { 336*e2841179SLoGin /// Acknowledge the parent interrupt 337*e2841179SLoGin #[allow(dead_code)] 338*e2841179SLoGin pub fn irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>) { 339*e2841179SLoGin let parent_data = irq_data.parent_data().map(|p| p.upgrade()).flatten(); 340*e2841179SLoGin 341*e2841179SLoGin if let Some(parent_data) = parent_data { 342*e2841179SLoGin let parent_chip = parent_data.chip_info_read_irqsave().chip(); 343*e2841179SLoGin parent_chip.irq_ack(&parent_data); 344*e2841179SLoGin } 345*e2841179SLoGin } 346*e2841179SLoGin 347*e2841179SLoGin /// 在硬件中重新触发中断 348*e2841179SLoGin /// 349*e2841179SLoGin /// 遍历中断域的层次结构,并检查是否存在一个硬件重新触发函数。如果存在则调用它 350*e2841179SLoGin pub fn irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> { 351*e2841179SLoGin let mut data: Option<Arc<IrqData>> = Some(irq_data.clone()); 352*e2841179SLoGin loop { 353*e2841179SLoGin if let Some(d) = data { 354*e2841179SLoGin if let Err(e) = d.chip_info_read_irqsave().chip().retrigger(&d) { 355*e2841179SLoGin if e == SystemError::ENOSYS { 356*e2841179SLoGin data = d.parent_data().map(|p| p.upgrade()).flatten(); 357*e2841179SLoGin } else { 358*e2841179SLoGin return Err(e); 359*e2841179SLoGin } 360*e2841179SLoGin } else { 361*e2841179SLoGin return Ok(()); 362*e2841179SLoGin } 363*e2841179SLoGin } else { 364*e2841179SLoGin break; 365*e2841179SLoGin } 366*e2841179SLoGin } 367*e2841179SLoGin 368*e2841179SLoGin return Ok(()); 369*e2841179SLoGin } 370*e2841179SLoGin } 371