x86-64: keep HPET enabled even without interrupts
This commit is contained in:
parent
9c419115e7
commit
9b9a1f68b5
@ -107,6 +107,9 @@ pub struct Hpet {
|
||||
|
||||
impl Inner {
|
||||
unsafe fn new(base: usize) -> Result<Self, Error> {
|
||||
// Femtoseconds in a millisecond
|
||||
const FS_IN_MS: u64 = 1000000000000;
|
||||
|
||||
let regs = DeviceMemoryIo::<Regs>::map("hpet", base)?;
|
||||
|
||||
// Disable the counter first
|
||||
@ -127,9 +130,29 @@ impl Inner {
|
||||
.modify(TimerConfigurationCapablities::TM_INT_ENB_CNF::InterruptDisabled);
|
||||
}
|
||||
|
||||
// Calculate the interrupt period
|
||||
let clk_period = regs
|
||||
.GeneralCapabilities
|
||||
.read(GeneralCapabilities::COUNTER_CLK_PERIOD);
|
||||
|
||||
// Will give an interrupt interval of 1ms
|
||||
let tim0_period = FS_IN_MS / clk_period;
|
||||
|
||||
// if tim0_period > 0x100000000
|
||||
// && !tim0
|
||||
// .ConfigurationCapability
|
||||
// .matches_all(TimerConfigurationCapablities::TM_SIZE_CAP::Timer64Bit)
|
||||
// {
|
||||
// panic!("Period is too large and timer doesn't support 64-bit");
|
||||
// }
|
||||
|
||||
// Enable the main counter
|
||||
regs.GeneralConfiguration
|
||||
.modify(GeneralConfiguration::ENABLE_CNF::SET);
|
||||
|
||||
Ok(Self {
|
||||
regs,
|
||||
tim0_period: 0,
|
||||
tim0_period,
|
||||
tim0_counter: 0,
|
||||
})
|
||||
}
|
||||
@ -138,7 +161,9 @@ impl Inner {
|
||||
impl MonotonicTimestampProviderDevice for Hpet {
|
||||
fn monotonic_timestamp(&self) -> Result<Duration, Error> {
|
||||
let inner = self.inner.lock();
|
||||
Ok(Duration::from_millis(inner.tim0_counter))
|
||||
let counter = inner.regs.MainCounter.get();
|
||||
let period = inner.tim0_period;
|
||||
Ok(Duration::from_millis(counter / period))
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,38 +190,22 @@ impl Device for Hpet {
|
||||
}
|
||||
|
||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
||||
// Femtoseconds in a millisecond
|
||||
const FS_IN_MS: u64 = 1000000000000;
|
||||
|
||||
// Configure timer 0
|
||||
let intc = ARCHITECTURE.external_interrupt_controller();
|
||||
let mut inner = self.inner.lock();
|
||||
|
||||
// Calculate the interrupt period
|
||||
let clk_period = inner
|
||||
.regs
|
||||
.GeneralCapabilities
|
||||
.read(GeneralCapabilities::COUNTER_CLK_PERIOD);
|
||||
|
||||
// Will give an interrupt interval of 1ms
|
||||
let period = FS_IN_MS / clk_period;
|
||||
|
||||
inner.tim0_period = period;
|
||||
|
||||
let tim0 = &inner.regs.Timers[0];
|
||||
|
||||
// Temporarily disable the main counter
|
||||
inner
|
||||
.regs
|
||||
.GeneralConfiguration
|
||||
.modify(GeneralConfiguration::ENABLE_CNF::CLEAR);
|
||||
|
||||
assert!(tim0
|
||||
.ConfigurationCapability
|
||||
.matches_all(TimerConfigurationCapablities::TM_PER_INT_CAP::SupportsPeriodic));
|
||||
|
||||
if period > 0x100000000
|
||||
&& !tim0
|
||||
.ConfigurationCapability
|
||||
.matches_all(TimerConfigurationCapablities::TM_SIZE_CAP::Timer64Bit)
|
||||
{
|
||||
panic!("Period is too large and timer doesn't support 64-bit");
|
||||
}
|
||||
|
||||
let mut tim0_irq = None;
|
||||
let tim0_irqs = tim0
|
||||
.ConfigurationCapability
|
||||
@ -247,7 +256,7 @@ impl Device for Hpet {
|
||||
tim0.ConfigurationCapability
|
||||
.modify(TimerConfigurationCapablities::TM_INT_ENB_CNF::InterruptEnabled);
|
||||
|
||||
// Enable the main counter
|
||||
// Reenable the main counter
|
||||
inner
|
||||
.regs
|
||||
.GeneralConfiguration
|
||||
|
Loading…
x
Reference in New Issue
Block a user