Skip to content

Commit 0227bda

Browse files
committed
irq
1 parent a5a3c2f commit 0227bda

File tree

7 files changed

+133
-59
lines changed

7 files changed

+133
-59
lines changed

axplat/src/time.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub trait TimeIf {
4141
/// deadline (in nanoseconds).
4242
#[cfg(feature = "irq")]
4343
fn set_oneshot_timer(deadline_ns: u64);
44+
45+
#[cfg(feature = "irq")]
46+
fn irq_num()->usize;
4447
}
4548

4649
/// Returns nanoseconds elapsed since system boot.

platforms/axplat-aarch64-dyn/Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,22 @@ version = "0.1.0"
1010

1111
[features]
1212
fp-simd = ["axcpu/fp-simd"]
13+
hv = []
14+
irq = ["axplat/irq"]
1315
smp = ["axplat/smp"]
1416

1517
[dependencies]
1618
aarch64-cpu = "10"
1719
any-uart = "0.2.11"
1820
axconfig-macros = "0.2"
1921
axcpu = {workspace = true}
20-
axplat = {workspace = true, features = ["irq"]}
22+
axplat = {workspace = true}
2123
fdt-parser = "0.4"
2224
heapless = "0.8"
25+
lazyinit = "0.2"
2326
log = "0.4"
2427
memory_addr = "0.3"
2528
pie-boot = {version = "0.2.9"}
2629
rdrive = "0.15"
2730
smccc = "0.2"
2831
spin = "0.10"
29-
lazyinit = "0.2"

platforms/axplat-aarch64-dyn/src/init.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,23 @@ impl InitIf for InitIfImpl {
7070
/// * Other platform devices are initialized.
7171
fn init_later(cpu_id: usize, arg: usize) {
7272
driver::setup();
73-
crate::irq::init();
74-
crate::irq::init_current_cpu();
73+
#[cfg(feature = "irq")]
74+
{
75+
crate::irq::init();
76+
crate::irq::init_current_cpu();
77+
crate::time::enable_irqs();
78+
}
7579
}
7680

7781
/// Initializes the platform at the later stage for secondary cores.
7882
///
7983
/// See [`init_later`] for details.
8084
#[cfg(feature = "smp")]
8185
fn init_later_secondary(cpu_id: usize) {
82-
crate::irq::init_current_cpu();
86+
#[cfg(feature = "irq")]
87+
{
88+
crate::irq::init_current_cpu();
89+
crate::time::enable_irqs();
90+
}
8391
}
8492
}

platforms/axplat-aarch64-dyn/src/irq.rs

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use aarch64_cpu::registers::*;
2+
use alloc::{format, string::String};
3+
24
use axplat::irq::{HandlerTable, IrqHandler, IrqIf};
35
use lazyinit::LazyInit;
46
use log::{debug, trace, warn};
@@ -22,30 +24,7 @@ struct IrqIfImpl;
2224
impl IrqIf for IrqIfImpl {
2325
/// Enables or disables the given IRQ.
2426
fn set_enable(irq_raw: usize, enabled: bool) {
25-
trace!("IRQ set enable: {:#x} {}", irq_raw, enabled);
26-
let irq: IrqId = irq_raw.into();
27-
if is_irq_private(irq_raw)
28-
&& let local::Capability::ConfigLocalIrq(c) = CPU_IF.capability()
29-
{
30-
if enabled {
31-
c.irq_enable(irq).expect("failed to enable local IRQ");
32-
} else {
33-
c.irq_disable(irq).expect("failed to disable local IRQ");
34-
}
35-
} else {
36-
let mut intc = get_gicd().lock().unwrap();
37-
if enabled {
38-
intc.irq_enable(irq).expect("failed to enable IRQ");
39-
} else {
40-
intc.irq_disable(irq).expect("failed to disable IRQ");
41-
}
42-
43-
if !is_irq_private(irq_raw) {
44-
// For private IRQs, we need to acknowledge the interrupt
45-
// controller.
46-
intc.set_target_cpu(irq, current_cpu().into());
47-
}
48-
}
27+
set_enable(irq_raw, is_irq_private(irq_raw), None, enabled);
4928
}
5029

5130
/// Registers an IRQ handler for the given IRQ.
@@ -96,13 +75,15 @@ impl IrqIf for IrqIfImpl {
9675

9776
pub(crate) fn init() {
9877
let intc = get_gicd();
78+
debug!("Initializing GICD...");
9979
intc.lock().unwrap().open().unwrap();
10080
debug!("GICD initialized");
10181
}
10282

10383
pub(crate) fn init_current_cpu() {
10484
let intc = rdrive::get_one::<Intc>().expect("no interrupt controller found");
105-
let cpu_if = intc.lock().unwrap().cpu_local().unwrap();
85+
let mut cpu_if = intc.lock().unwrap().cpu_local().unwrap();
86+
cpu_if.open().unwrap();
10687
cpu_if.set_eoi_mode(true);
10788
CPU_IF.init_once(cpu_if);
10889
debug!("GIC initialized for current CPU");
@@ -115,3 +96,51 @@ fn get_gicd() -> Device<Intc> {
11596
fn current_cpu() -> usize {
11697
MPIDR_EL1.get() as usize & 0xffffff
11798
}
99+
100+
pub(crate) fn set_enable(
101+
irq_raw: usize,
102+
is_private: bool,
103+
trigger: Option<Trigger>,
104+
enabled: bool,
105+
) {
106+
debug!(
107+
"IRQ({:#x}) set enable: {}, {}",
108+
irq_raw,
109+
enabled,
110+
match trigger {
111+
Some(t) => format!("trigger: {:?}", t),
112+
None => String::new(),
113+
}
114+
);
115+
let irq: IrqId = irq_raw.into();
116+
if is_irq_private(irq_raw)
117+
&& let local::Capability::ConfigLocalIrq(c) = CPU_IF.capability()
118+
{
119+
if enabled {
120+
c.irq_enable(irq).expect("failed to enable local IRQ");
121+
} else {
122+
c.irq_disable(irq).expect("failed to disable local IRQ");
123+
}
124+
if let Some(t) = trigger {
125+
c.set_trigger(irq, t)
126+
.expect("failed to set local IRQ trigger");
127+
}
128+
} else {
129+
let mut intc = get_gicd().lock().unwrap();
130+
if enabled {
131+
intc.irq_enable(irq).expect("failed to enable IRQ");
132+
if !is_irq_private(irq_raw) {
133+
// For private IRQs, we need to acknowledge the interrupt
134+
// controller.
135+
intc.set_target_cpu(irq, current_cpu().into());
136+
}
137+
138+
if let Some(t) = trigger {
139+
intc.set_trigger(irq, t).expect("failed to set IRQ trigger");
140+
}
141+
} else {
142+
intc.irq_disable(irq).expect("failed to disable IRQ");
143+
}
144+
}
145+
debug!("IRQ({:#x}) set enable done", irq_raw);
146+
}

platforms/axplat-aarch64-dyn/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use pie_boot::BootInfo;
1010
mod console;
1111
mod driver;
1212
mod init;
13+
#[cfg(feature = "irq")]
1314
mod irq;
1415
mod mem;
1516
mod power;

platforms/axplat-aarch64-dyn/src/power.rs

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ use aarch64_cpu::asm::wfi;
44
use alloc::{boxed::Box, format};
55
use axplat::power::PowerIf;
66
use log::{debug, error};
7-
use rdrive::{
8-
DriverGeneric, KError, PlatformDevice, driver::power::Interface, module_driver,
9-
probe::OnProbeError, register::FdtInfo,
10-
};
7+
use rdrive::{PlatformDevice, module_driver, probe::OnProbeError, register::FdtInfo};
118
use smccc::{Hvc, Smc, psci};
129
use spin::Once;
1310

@@ -71,31 +68,6 @@ impl TryFrom<&str> for Method {
7168
}
7269
}
7370

74-
struct Psci {
75-
method: Method,
76-
}
77-
78-
impl DriverGeneric for Psci {
79-
fn open(&mut self) -> Result<(), KError> {
80-
Ok(())
81-
}
82-
83-
fn close(&mut self) -> Result<(), KError> {
84-
Ok(())
85-
}
86-
}
87-
88-
impl Interface for Psci {
89-
fn shutdown(&mut self) {
90-
if let Err(e) = match self.method {
91-
Method::Smc => psci::system_off::<Smc>(),
92-
Method::Hvc => psci::system_off::<Hvc>(),
93-
} {
94-
error!("shutdown failed: {}", e);
95-
}
96-
}
97-
}
98-
9971
fn probe(fdt: FdtInfo<'_>, _dev: PlatformDevice) -> Result<(), OnProbeError> {
10072
let method = fdt
10173
.node

platforms/axplat-aarch64-dyn/src/time.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
use aarch64_cpu::registers::*;
22
use axplat::time::TimeIf;
3+
use lazyinit::LazyInit;
4+
#[cfg(not(feature = "irq"))]
5+
use rdrive::driver::intc::Trigger;
6+
use rdrive::{IrqConfig, PlatformDevice, module_driver, probe::OnProbeError, register::FdtInfo};
7+
8+
static TIMER_IRQ_CONFIG: LazyInit<IrqConfig> = LazyInit::new();
39

410
struct TimeIfImpl;
511

@@ -34,6 +40,7 @@ impl TimeIf for TimeIfImpl {
3440
///
3541
/// A timer interrupt will be triggered at the specified monotonic time
3642
/// deadline (in nanoseconds).
43+
#[cfg(feature = "irq")]
3744
fn set_oneshot_timer(deadline_ns: u64) {
3845
let cnptct = CNTPCT_EL0.get();
3946
let cnptct_deadline = Self::nanos_to_ticks(deadline_ns);
@@ -45,4 +52,56 @@ impl TimeIf for TimeIfImpl {
4552
CNTP_TVAL_EL0.set(0);
4653
}
4754
}
55+
56+
#[cfg(feature = "irq")]
57+
fn irq_num() -> usize {
58+
TIMER_IRQ_CONFIG.irq.into()
59+
}
60+
}
61+
62+
#[cfg(feature = "irq")]
63+
/// Enable timer interrupts.
64+
///
65+
/// It should be called on all CPUs, as the timer interrupt is a PPI (Private
66+
/// Peripheral Interrupt).
67+
pub fn enable_irqs() {
68+
CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET);
69+
CNTP_TVAL_EL0.set(0);
70+
crate::irq::set_enable(
71+
TIMER_IRQ_CONFIG.irq.into(),
72+
true,
73+
Some(TIMER_IRQ_CONFIG.trigger),
74+
false,
75+
);
76+
}
77+
78+
module_driver!(
79+
name: "ARMv8 Timer",
80+
level: ProbeLevel::PreKernel,
81+
priority: ProbePriority::DEFAULT,
82+
probe_kinds: &[
83+
ProbeKind::Fdt {
84+
compatibles: &["arm,armv8-timer"],
85+
on_probe: probe
86+
}
87+
],
88+
);
89+
90+
fn probe(_fdt: FdtInfo<'_>, _dev: PlatformDevice) -> Result<(), OnProbeError> {
91+
#[cfg(not(feature = "irq"))]
92+
let irq = IrqConfig {
93+
irq: 0.into(),
94+
trigger: Trigger::EdgeBoth,
95+
is_private: true,
96+
};
97+
#[cfg(feature = "irq")]
98+
let irq = {
99+
#[cfg(not(feature = "hv"))]
100+
let irq_idx = 1;
101+
#[cfg(feature = "hv")]
102+
let irq_idx = 3;
103+
_dev.descriptor.irqs[irq_idx].clone()
104+
};
105+
TIMER_IRQ_CONFIG.call_once(|| irq);
106+
Ok(())
48107
}

0 commit comments

Comments
 (0)