earlgrey/
timer.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Timer driver.
6
7use crate::chip_config::EarlGreyConfig;
8use crate::registers::top_earlgrey::RV_TIMER_BASE_ADDR;
9use core::marker::PhantomData;
10use kernel::hil::time::{self, Ticks64};
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::registers::interfaces::{Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
14use kernel::utilities::StaticRef;
15use kernel::ErrorCode;
16use rv32i::machine_timer::MachineTimer;
17
18/// 10KHz `Frequency`
19#[derive(Debug)]
20pub struct Freq10KHz;
21impl time::Frequency for Freq10KHz {
22    fn frequency() -> u32 {
23        10_000
24    }
25}
26
27register_structs! {
28    pub TimerRegisters {
29        (0x000 => alert_test: WriteOnly<u32>),
30        (0x004 => ctrl: ReadWrite<u32, ctrl::Register>),
31        (0x008 => _reserved),
32        (0x100 => intr_enable: ReadWrite<u32, intr::Register>),
33        (0x104 => intr_state: ReadWrite<u32, intr::Register>),
34        (0x108 => intr_test: WriteOnly<u32, intr::Register>),
35        (0x10C => config: ReadWrite<u32, config::Register>),
36        (0x110 => value_low: ReadWrite<u32>),
37        (0x114 => value_high: ReadWrite<u32>),
38        (0x118 => compare_low: ReadWrite<u32>),
39        (0x11C => compare_high: ReadWrite<u32>),
40        (0x120 => @END),
41    }
42}
43
44register_bitfields![u32,
45    ctrl [
46        enable OFFSET(0) NUMBITS(1) []
47    ],
48    intr [
49        timer0 OFFSET(0) NUMBITS(1) []
50    ],
51    config [
52        prescale OFFSET(0) NUMBITS(12) [],
53        step OFFSET(16) NUMBITS(8) []
54    ],
55];
56
57pub struct RvTimer<'a, CFG: EarlGreyConfig> {
58    registers: StaticRef<TimerRegisters>,
59    alarm_client: OptionalCell<&'a dyn time::AlarmClient>,
60    overflow_client: OptionalCell<&'a dyn time::OverflowClient>,
61    mtimer: MachineTimer<'a>,
62    _cfg: PhantomData<CFG>,
63}
64
65impl<CFG: EarlGreyConfig> RvTimer<'_, CFG> {
66    pub fn new() -> Self {
67        Self {
68            registers: TIMER_BASE,
69            alarm_client: OptionalCell::empty(),
70            overflow_client: OptionalCell::empty(),
71            mtimer: MachineTimer::new(
72                &TIMER_BASE.compare_low,
73                &TIMER_BASE.compare_high,
74                &TIMER_BASE.value_low,
75                &TIMER_BASE.value_high,
76            ),
77            _cfg: PhantomData,
78        }
79    }
80
81    pub fn setup(&self) {
82        let prescale: u16 = ((CFG::CPU_FREQ / 10_000) - 1) as u16; // 10Khz
83
84        let regs = self.registers;
85        // Set proper prescaler and the like
86        regs.config
87            .write(config::prescale.val(prescale as u32) + config::step.val(1u32));
88        regs.compare_high.set(0);
89        regs.value_low.set(0xFFFF_0000);
90        regs.intr_enable.write(intr::timer0::CLEAR);
91        regs.ctrl.write(ctrl::enable::SET);
92    }
93
94    pub fn service_interrupt(&self) {
95        let regs = self.registers;
96        regs.intr_enable.write(intr::timer0::CLEAR);
97        regs.intr_state.write(intr::timer0::SET);
98        self.alarm_client.map(|client| {
99            client.alarm();
100        });
101    }
102}
103
104impl<CFG: EarlGreyConfig> time::Time for RvTimer<'_, CFG> {
105    type Frequency = Freq10KHz;
106    type Ticks = Ticks64;
107
108    fn now(&self) -> Ticks64 {
109        self.mtimer.now()
110    }
111}
112
113impl<'a, CFG: EarlGreyConfig> time::Counter<'a> for RvTimer<'a, CFG> {
114    fn set_overflow_client(&self, client: &'a dyn time::OverflowClient) {
115        self.overflow_client.set(client);
116    }
117
118    fn start(&self) -> Result<(), ErrorCode> {
119        Ok(())
120    }
121
122    fn stop(&self) -> Result<(), ErrorCode> {
123        // RISCV counter can't be stopped...
124        Err(ErrorCode::BUSY)
125    }
126
127    fn reset(&self) -> Result<(), ErrorCode> {
128        // RISCV counter can't be reset
129        Err(ErrorCode::FAIL)
130    }
131
132    fn is_running(&self) -> bool {
133        true
134    }
135}
136
137impl<'a, CFG: EarlGreyConfig> time::Alarm<'a> for RvTimer<'a, CFG> {
138    fn set_alarm_client(&self, client: &'a dyn time::AlarmClient) {
139        self.alarm_client.set(client);
140    }
141
142    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
143        self.registers.intr_enable.write(intr::timer0::SET);
144
145        self.mtimer.set_alarm(reference, dt)
146    }
147
148    fn get_alarm(&self) -> Self::Ticks {
149        self.mtimer.get_alarm()
150    }
151
152    fn disarm(&self) -> Result<(), ErrorCode> {
153        self.registers.intr_enable.write(intr::timer0::CLEAR);
154
155        self.mtimer.disarm()
156    }
157
158    fn is_armed(&self) -> bool {
159        self.registers.intr_enable.is_set(intr::timer0)
160    }
161
162    fn minimum_dt(&self) -> Self::Ticks {
163        self.mtimer.minimum_dt()
164    }
165}
166
167const TIMER_BASE: StaticRef<TimerRegisters> =
168    unsafe { StaticRef::new(RV_TIMER_BASE_ADDR as *const TimerRegisters) };