xref: /DragonOS/kernel/src/exception/irqchip.rs (revision 3bc96fa4a9c01d91cddeb152fe78d6408351c29f)
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