rp2040/
rtc.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//! Real Time Clock (RTC) driver for RP2040.
6//!
7//! Author: Irina Bradu <irinabradu.a@gmail.com>
8//!         Remus Rughinis <remus.rughinis.007@gmail.com>
9//!
10//! # Hardware Interface Layer (HIL)
11//!
12//! The driver implements Date_Time HIL. The following features are available when using
13//! the driver through HIL:
14//!
15//! + Set time from which real time clock should start counting
16//! + Read current time from the RTC registers
17//!
18
19use crate::clocks;
20use core::cell::Cell;
21use kernel::deferred_call::{DeferredCall, DeferredCallClient};
22use kernel::hil::date_time;
23use kernel::hil::date_time::{DateTimeClient, DateTimeValues, DayOfWeek, Month};
24use kernel::utilities::cells::OptionalCell;
25use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
26use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
27use kernel::utilities::StaticRef;
28use kernel::ErrorCode;
29
30register_structs! {
31    /// Register block to control RTC
32    RtcRegisters {
33        /// Divider minus 1 for the 1 second counter. Safe to change the value when RTC is n
34        (0x000 => clkdiv_m1: ReadWrite<u32, CLKDIV_M1::Register>),
35        /// RTC setup register 0
36        (0x004 => setup_0: ReadWrite<u32, SETUP_0::Register>),
37        /// RTC setup register 1
38        (0x008 => setup_1: ReadWrite<u32, SETUP_1::Register>),
39        /// RTC Control and status
40        (0x00C => ctrl: ReadWrite<u32, CTRL::Register>),
41        /// Interrupt setup register 0
42        (0x010 => irq_setup_0: ReadWrite<u32, IRQ_SETUP_0::Register>),
43        /// Interrupt setup register 1
44        (0x014 => irq_setup_1: ReadWrite<u32, IRQ_SETUP_1::Register>),
45        /// RTC register 1.
46        (0x018 => rtc_1: ReadWrite<u32, RTC_1::Register>),
47        /// RTC register 0\n
48        /// Read this before RTC 1!
49        (0x01C => rtc_0: ReadWrite<u32, RTC_0::Register>),
50        /// Raw Interrupts
51        (0x020 => intr: ReadWrite<u32>),
52        /// Interrupt Enable
53        (0x024 => inte: ReadWrite<u32, INTE::Register>),
54        /// Interrupt Force
55        (0x028 => intf: ReadWrite<u32, INTF::Register>),
56        /// Interrupt status after masking & forcing
57        (0x02C => ints: ReadWrite<u32>),
58        (0x030 => @END),
59    }
60}
61register_bitfields![u32,
62CLKDIV_M1 [
63    CLKDIV_M OFFSET(0) NUMBITS(16) []
64],
65SETUP_0 [
66    /// Year
67    YEAR OFFSET(12) NUMBITS(12) [],
68    /// Month (1..12)
69    MONTH OFFSET(8) NUMBITS(4) [],
70    /// Day of the month (1..31)
71    DAY OFFSET(0) NUMBITS(5) []
72],
73SETUP_1 [
74    /// Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7
75    DOTW OFFSET(24) NUMBITS(3) [],
76    /// Hours
77    HOUR OFFSET(16) NUMBITS(5) [],
78    /// Minutes
79    MIN OFFSET(8) NUMBITS(6) [],
80    /// Seconds
81    SEC OFFSET(0) NUMBITS(6) []
82],
83CTRL [
84    /// If set, leapyear is forced off.\n
85    /// Useful for years divisible by 100 but not by 400
86    FORCE_NOTLEAPYEAR OFFSET(8) NUMBITS(1) [],
87    /// Load RTC
88    LOAD OFFSET(4) NUMBITS(1) [],
89    /// RTC enabled (running)
90    RTC_ACTIVE OFFSET(1) NUMBITS(1) [],
91    /// Enable RTC
92    RTC_ENABLE OFFSET(0) NUMBITS(1) []
93],
94IRQ_SETUP_0 [
95    MATCH_ACTIVE OFFSET(29) NUMBITS(1) [],
96    /// Global match enable. Don't change any other value while this one is enabled
97    MATCH_ENA OFFSET(28) NUMBITS(1) [],
98    /// Enable year matching
99    YEAR_ENA OFFSET(26) NUMBITS(1) [],
100    /// Enable month matching
101    MONTH_ENA OFFSET(25) NUMBITS(1) [],
102    /// Enable day matching
103    DAY_ENA OFFSET(24) NUMBITS(1) [],
104    /// Year
105    YEAR OFFSET(12) NUMBITS(12) [],
106    /// Month (1..12)
107    MONTH OFFSET(8) NUMBITS(4) [],
108    /// Day of the month (1..31)
109    DAY OFFSET(0) NUMBITS(5) []
110],
111IRQ_SETUP_1 [
112    /// Enable day of the week matching
113    DOTW_ENA OFFSET(31) NUMBITS(1) [],
114    /// Enable hour matching
115    HOUR_ENA OFFSET(30) NUMBITS(1) [],
116    /// Enable minute matching
117    MIN_ENA OFFSET(29) NUMBITS(1) [],
118    /// Enable second matching
119    SEC_ENA OFFSET(28) NUMBITS(1) [],
120    /// Day of the week
121    DOTW OFFSET(24) NUMBITS(3) [],
122    /// Hours
123    HOUR OFFSET(16) NUMBITS(5) [],
124    /// Minutes
125    MIN OFFSET(8) NUMBITS(6) [],
126    /// Seconds
127    SEC OFFSET(0) NUMBITS(6) []
128],
129RTC_1 [
130    /// Year
131    YEAR OFFSET(12) NUMBITS(12) [],
132    /// Month (1..12)
133    MONTH OFFSET(8) NUMBITS(4) [],
134    /// Day of the month (1..31)
135    DAY OFFSET(0) NUMBITS(5) []
136],
137RTC_0 [
138    /// Day of the week
139    DOTW OFFSET(24) NUMBITS(3) [],
140    /// Hours
141    HOUR OFFSET(16) NUMBITS(5) [],
142    /// Minutes
143    MIN OFFSET(8) NUMBITS(6) [],
144    /// Seconds
145    SEC OFFSET(0) NUMBITS(6) []
146],
147INTR [
148
149    RTC OFFSET(0) NUMBITS(1) []
150],
151INTE [
152
153    RTC OFFSET(0) NUMBITS(1) []
154],
155INTF [
156
157    RTC OFFSET(0) NUMBITS(1) []
158],
159INTS [
160
161    RTC OFFSET(0) NUMBITS(1) []
162]
163];
164
165const RTC_BASE: StaticRef<RtcRegisters> =
166    unsafe { StaticRef::new(0x4005C000 as *const RtcRegisters) };
167
168pub struct Rtc<'a> {
169    registers: StaticRef<RtcRegisters>,
170    client: OptionalCell<&'a dyn date_time::DateTimeClient>,
171    clocks: OptionalCell<&'a clocks::Clocks>,
172    time: Cell<DateTimeValues>,
173
174    deferred_call: DeferredCall,
175    deferred_call_task: OptionalCell<DeferredCallTask>,
176}
177
178#[derive(Clone, Copy)]
179enum DeferredCallTask {
180    Get,
181    Set,
182}
183
184impl DeferredCallClient for Rtc<'_> {
185    fn handle_deferred_call(&self) {
186        self.deferred_call_task.take().map(|value| match value {
187            DeferredCallTask::Get => self
188                .client
189                .map(|client| client.get_date_time_done(Ok(self.time.get()))),
190            DeferredCallTask::Set => self.client.map(|client| client.set_date_time_done(Ok(()))),
191        });
192    }
193    fn register(&'static self) {
194        self.deferred_call.register(self);
195    }
196}
197
198impl<'a> Rtc<'a> {
199    pub fn new() -> Rtc<'a> {
200        Rtc {
201            registers: RTC_BASE,
202            client: OptionalCell::empty(),
203            clocks: OptionalCell::empty(),
204            time: Cell::new(DateTimeValues {
205                year: 0,
206                month: Month::January,
207                day: 1,
208                day_of_week: DayOfWeek::Sunday,
209                hour: 0,
210                minute: 0,
211                seconds: 0,
212            }),
213
214            deferred_call: DeferredCall::new(),
215            deferred_call_task: OptionalCell::empty(),
216        }
217    }
218
219    fn dotw_try_from_u32(&self, dotw: u32) -> Result<DayOfWeek, ErrorCode> {
220        match dotw {
221            0 => Ok(DayOfWeek::Sunday),
222            1 => Ok(DayOfWeek::Monday),
223            2 => Ok(DayOfWeek::Tuesday),
224            3 => Ok(DayOfWeek::Wednesday),
225            4 => Ok(DayOfWeek::Thursday),
226            5 => Ok(DayOfWeek::Friday),
227            6 => Ok(DayOfWeek::Saturday),
228            _ => Err(ErrorCode::INVAL),
229        }
230    }
231
232    fn dotw_into_u32(&self, dotw: DayOfWeek) -> u32 {
233        match dotw {
234            DayOfWeek::Sunday => 0,
235            DayOfWeek::Monday => 1,
236            DayOfWeek::Tuesday => 2,
237            DayOfWeek::Wednesday => 3,
238            DayOfWeek::Thursday => 4,
239            DayOfWeek::Friday => 5,
240            DayOfWeek::Saturday => 6,
241        }
242    }
243
244    fn month_try_from_u32(&self, month_num: u32) -> Result<Month, ErrorCode> {
245        match month_num {
246            1 => Ok(Month::January),
247            2 => Ok(Month::February),
248            3 => Ok(Month::March),
249            4 => Ok(Month::April),
250            5 => Ok(Month::May),
251            6 => Ok(Month::June),
252            7 => Ok(Month::July),
253            8 => Ok(Month::August),
254            9 => Ok(Month::September),
255            10 => Ok(Month::October),
256            11 => Ok(Month::November),
257            12 => Ok(Month::December),
258            _ => Err(ErrorCode::INVAL),
259        }
260    }
261
262    fn month_into_u32(&self, month: Month) -> u32 {
263        match month {
264            Month::January => 1,
265            Month::February => 2,
266            Month::March => 3,
267            Month::April => 4,
268            Month::May => 5,
269            Month::June => 6,
270            Month::July => 7,
271            Month::August => 8,
272            Month::September => 9,
273            Month::October => 10,
274            Month::November => 11,
275            Month::December => 12,
276        }
277    }
278
279    pub fn handle_set_interrupt(&self) {
280        self.client.map(|client| client.set_date_time_done(Ok(())));
281    }
282
283    pub fn handle_get_interrupt(&self) {
284        self.client
285            .map(|client| client.get_date_time_done(Ok(self.time.get())));
286    }
287
288    pub fn set_clocks(&self, clocks: &'a clocks::Clocks) {
289        self.clocks.replace(clocks);
290    }
291
292    fn date_time_setup(&self, datetime: date_time::DateTimeValues) -> Result<(), ErrorCode> {
293        let month_val: u32 = self.month_into_u32(datetime.month);
294        let day_val: u32 = self.dotw_into_u32(datetime.day_of_week);
295
296        if !(datetime.year <= 4095) {
297            return Err(ErrorCode::INVAL);
298        }
299
300        if !(datetime.day >= 1 && datetime.day <= 31) {
301            return Err(ErrorCode::INVAL);
302        }
303
304        if !(datetime.hour <= 23) {
305            return Err(ErrorCode::INVAL);
306        }
307        if !(datetime.minute <= 59) {
308            return Err(ErrorCode::INVAL);
309        }
310        if !(datetime.seconds <= 59) {
311            return Err(ErrorCode::INVAL);
312        }
313
314        self.registers
315            .setup_0
316            .modify(SETUP_0::YEAR.val(datetime.year as u32));
317        self.registers.setup_0.modify(SETUP_0::MONTH.val(month_val));
318        self.registers
319            .setup_0
320            .modify(SETUP_0::DAY.val(datetime.day as u32));
321
322        self.registers.setup_1.modify(SETUP_1::DOTW.val(day_val));
323        self.registers
324            .setup_1
325            .modify(SETUP_1::HOUR.val(datetime.hour as u32));
326        self.registers
327            .setup_1
328            .modify(SETUP_1::MIN.val(datetime.minute as u32));
329        self.registers
330            .setup_1
331            .modify(SETUP_1::SEC.val(datetime.seconds as u32));
332
333        self.registers.ctrl.modify(CTRL::LOAD::SET);
334
335        Ok(())
336    }
337
338    fn set_initial(&self) -> Result<(), ErrorCode> {
339        let mut hw_ctrl: u32;
340
341        self.registers.ctrl.modify(CTRL::RTC_ENABLE.val(0));
342        hw_ctrl = self.registers.ctrl.read(CTRL::RTC_ENABLE);
343
344        while hw_ctrl & self.registers.ctrl.read(CTRL::RTC_ACTIVE) > 0 {}
345
346        let datetime = date_time::DateTimeValues {
347            year: 1970,
348            month: Month::January,
349            day: 1,
350            day_of_week: DayOfWeek::Sunday,
351            hour: 0,
352            minute: 0,
353            seconds: 0,
354        };
355
356        self.date_time_setup(datetime)?;
357        self.registers.ctrl.modify(CTRL::LOAD::SET);
358        self.registers.ctrl.modify(CTRL::RTC_ENABLE.val(1));
359        hw_ctrl = self.registers.ctrl.read(CTRL::RTC_ENABLE);
360
361        while !((hw_ctrl & self.registers.ctrl.read(CTRL::RTC_ACTIVE)) > 0) {
362            // wait until rtc starts
363        }
364
365        Ok(())
366    }
367
368    pub fn rtc_init(&self) -> Result<(), ErrorCode> {
369        let mut rtc_freq = self
370            .clocks
371            .map_or(46875, |clocks| clocks.get_frequency(clocks::Clock::Rtc));
372
373        rtc_freq -= rtc_freq;
374
375        self.registers
376            .clkdiv_m1
377            .modify(CLKDIV_M1::CLKDIV_M.val(rtc_freq));
378
379        self.set_initial()
380    }
381}
382
383impl<'a> date_time::DateTime<'a> for Rtc<'a> {
384    fn get_date_time(&self) -> Result<(), ErrorCode> {
385        match self.deferred_call_task.take() {
386            Some(DeferredCallTask::Set) => {
387                self.deferred_call_task.insert(Some(DeferredCallTask::Set));
388                return Err(ErrorCode::BUSY);
389            }
390            Some(DeferredCallTask::Get) => {
391                self.deferred_call_task.insert(Some(DeferredCallTask::Get));
392                return Err(ErrorCode::ALREADY);
393            }
394            _ => (),
395        }
396
397        let month_num: u32 = self.registers.setup_0.read(SETUP_0::MONTH);
398        let month_name: Month = match self.month_try_from_u32(month_num) {
399            Result::Ok(t) => t,
400            Result::Err(e) => {
401                return Err(e);
402            }
403        };
404        let dotw_num = self.registers.setup_1.read(SETUP_1::DOTW);
405        let dotw = match self.dotw_try_from_u32(dotw_num) {
406            Result::Ok(t) => t,
407            Result::Err(e) => {
408                return Err(e);
409            }
410        };
411
412        let datetime = date_time::DateTimeValues {
413            hour: self.registers.rtc_0.read(RTC_0::HOUR) as u8,
414            minute: self.registers.rtc_0.read(RTC_0::MIN) as u8,
415            seconds: self.registers.rtc_0.read(RTC_0::SEC) as u8,
416
417            year: self.registers.rtc_1.read(RTC_1::YEAR) as u16,
418            month: month_name,
419            day: self.registers.rtc_1.read(RTC_1::DAY) as u8,
420            day_of_week: dotw,
421        };
422
423        self.time.replace(datetime);
424
425        self.deferred_call_task.insert(Some(DeferredCallTask::Get));
426        self.deferred_call.set();
427
428        Ok(())
429    }
430
431    fn set_date_time(&self, date_time: date_time::DateTimeValues) -> Result<(), ErrorCode> {
432        match self.deferred_call_task.take() {
433            Some(DeferredCallTask::Set) => {
434                self.deferred_call_task.insert(Some(DeferredCallTask::Set));
435                return Err(ErrorCode::ALREADY);
436            }
437            Some(DeferredCallTask::Get) => {
438                self.deferred_call_task.insert(Some(DeferredCallTask::Get));
439                return Err(ErrorCode::BUSY);
440            }
441            _ => (),
442        }
443
444        self.date_time_setup(date_time)?;
445
446        self.deferred_call_task.insert(Some(DeferredCallTask::Set));
447        self.deferred_call.set();
448        Ok(())
449    }
450
451    fn set_client(&self, client: &'a dyn DateTimeClient) {
452        self.client.set(client);
453    }
454}