Skip to content

Commit 32615e5

Browse files
committed
update
1 parent 00d0a3f commit 32615e5

6 files changed

Lines changed: 540 additions & 267 deletions

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Generated by Cargo
22
# will have compiled files and executables
3-
debug/
43
target/
54

65
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries

gic-driver/src/version/v2/mod.rs

Lines changed: 124 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
mod reg;
2+
23
use core::ptr::NonNull;
4+
use tock_registers::interfaces::*;
35

46
use reg::*;
57

6-
78
/// GICv2 driver. (support GICv1)
89
pub struct Gic {
9-
gicd: NonNull<Distributor>,
10-
gicc: NonNull<CpuInterface>,
10+
gicd: NonNull<DistributorReg>,
11+
gicc: NonNull<CpuInterfaceReg>,
1112
}
1213

1314
unsafe impl Send for Gic {}
@@ -25,7 +26,125 @@ impl Gic {
2526
}
2627
}
2728

28-
fn gicd(&self) -> &Distributor {
29+
fn gicd(&self) -> &DistributorReg {
2930
unsafe { self.gicd.as_ref() }
3031
}
31-
}
32+
33+
pub fn init_cpu_interface(&self) -> CpuInterface {
34+
let mut c = CpuInterface {
35+
gicc: self.gicc,
36+
};
37+
c.init();
38+
c
39+
}
40+
41+
/// Initialize the GIC according to GICv2 specification
42+
/// This includes both Distributor and CPU Interface initialization
43+
pub fn init(&self) {
44+
// Initialize the Distributor
45+
self.gicd().init();
46+
}
47+
48+
/// Enable a specific interrupt
49+
pub fn enable_interrupt(&self, interrupt_id: u32) {
50+
self.gicd().enable_interrupt(interrupt_id);
51+
}
52+
53+
/// Disable a specific interrupt
54+
pub fn disable_interrupt(&self, interrupt_id: u32) {
55+
self.gicd().disable_interrupt(interrupt_id);
56+
}
57+
58+
/// Set interrupt priority (0 = highest priority, 255 = lowest priority)
59+
pub fn set_interrupt_priority(&self, interrupt_id: u32, priority: u8) {
60+
self.gicd().set_interrupt_priority(interrupt_id, priority);
61+
}
62+
63+
/// Set interrupt target CPU for SPIs (bit mask, bit 0 = CPU 0, etc.)
64+
pub fn set_interrupt_target(&self, interrupt_id: u32, target_cpu_mask: u8) {
65+
self.gicd().set_interrupt_target(interrupt_id, target_cpu_mask);
66+
}
67+
68+
/// Configure interrupt as Group 0 (Secure) or Group 1 (Non-secure)
69+
pub fn set_interrupt_group(&self, interrupt_id: u32, group1: bool) {
70+
self.gicd().set_interrupt_group(interrupt_id, group1);
71+
}
72+
73+
/// Send a Software Generated Interrupt (SGI) to target CPUs
74+
///
75+
/// # Arguments
76+
/// * `sgi_id` - SGI interrupt ID (0-15)
77+
/// * `target_list` - Target CPU list (bit mask)
78+
/// * `filter` - Target list filter:
79+
/// - 0: Forward to CPUs listed in target_list
80+
/// - 1: Forward to all CPUs except requesting CPU
81+
/// - 2: Forward only to requesting CPU
82+
pub fn send_sgi(&self, sgi_id: u32, target_list: u8, filter: u32) {
83+
self.gicd().send_sgi(sgi_id, target_list, filter);
84+
}
85+
}
86+
87+
pub struct CpuInterface{
88+
gicc: NonNull<CpuInterfaceReg>,
89+
}
90+
91+
impl CpuInterface {
92+
fn gicc(&self) -> &CpuInterfaceReg {
93+
unsafe { self.gicc.as_ref() }
94+
}
95+
96+
fn init(&mut self) {
97+
let gicc = self.gicc();
98+
99+
// 1. Disable CPU interface first
100+
gicc.CTLR.set(0);
101+
102+
// 2. Set priority mask to allow all interrupts (lowest priority)
103+
gicc.PMR.write(PMR::Priority.val(0xFF));
104+
105+
// 3. Set binary point to default value (no preemption)
106+
gicc.BPR.write(BPR::BinaryPoint.val(0x2));
107+
108+
// 4. Set aliased binary point for Group 1 interrupts
109+
gicc.ABPR.write(ABPR::BinaryPoint.val(0x3));
110+
111+
// 5. Enable CPU interface for both Group 0 and Group 1 interrupts
112+
gicc.CTLR.write(
113+
GICC_CTLR::EnableGrp0::SET +
114+
GICC_CTLR::EnableGrp1::SET +
115+
GICC_CTLR::FIQEn::CLEAR + // Use IRQ for Group 0 interrupts
116+
GICC_CTLR::AckCtl::CLEAR // Separate acknowledge for groups
117+
);
118+
}
119+
120+
/// Acknowledge an interrupt and return the interrupt ID
121+
/// Returns the interrupt ID and source CPU ID (for SGIs)
122+
pub fn acknowledge_interrupt(&self) -> (u32, u32) {
123+
let iar = self.gicc().IAR.get();
124+
let interrupt_id = iar & 0x3FF; // Bits [9:0]
125+
let cpu_id = (iar >> 10) & 0x7; // Bits [12:10]
126+
(interrupt_id, cpu_id)
127+
}
128+
129+
/// Signal end of interrupt processing
130+
pub fn end_of_interrupt(&self, interrupt_id: u32, cpu_id: u32) {
131+
let eoir_val = interrupt_id | (cpu_id << 10);
132+
self.gicc().EOIR.set(eoir_val);
133+
}
134+
135+
/// Get the highest priority pending interrupt ID
136+
pub fn get_highest_priority_pending(&self) -> u32 {
137+
let hppir = self.gicc().HPPIR.get();
138+
hppir & 0x3FF // Bits [9:0]
139+
}
140+
141+
/// Get the current running priority
142+
pub fn get_running_priority(&self) -> u8 {
143+
(self.gicc().RPR.get() & 0xFF) as u8
144+
}
145+
146+
/// Set the priority mask (interrupts with priority >= mask will be masked)
147+
pub fn set_priority_mask(&self, mask: u8) {
148+
self.gicc().PMR.write(PMR::Priority.val(mask as u32));
149+
}
150+
}

0 commit comments

Comments
 (0)