1use 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 RtcRegisters {
33 (0x000 => clkdiv_m1: ReadWrite<u32, CLKDIV_M1::Register>),
35 (0x004 => setup_0: ReadWrite<u32, SETUP_0::Register>),
37 (0x008 => setup_1: ReadWrite<u32, SETUP_1::Register>),
39 (0x00C => ctrl: ReadWrite<u32, CTRL::Register>),
41 (0x010 => irq_setup_0: ReadWrite<u32, IRQ_SETUP_0::Register>),
43 (0x014 => irq_setup_1: ReadWrite<u32, IRQ_SETUP_1::Register>),
45 (0x018 => rtc_1: ReadWrite<u32, RTC_1::Register>),
47 (0x01C => rtc_0: ReadWrite<u32, RTC_0::Register>),
50 (0x020 => intr: ReadWrite<u32>),
52 (0x024 => inte: ReadWrite<u32, INTE::Register>),
54 (0x028 => intf: ReadWrite<u32, INTF::Register>),
56 (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 OFFSET(12) NUMBITS(12) [],
68 MONTH OFFSET(8) NUMBITS(4) [],
70 DAY OFFSET(0) NUMBITS(5) []
72],
73SETUP_1 [
74 DOTW OFFSET(24) NUMBITS(3) [],
76 HOUR OFFSET(16) NUMBITS(5) [],
78 MIN OFFSET(8) NUMBITS(6) [],
80 SEC OFFSET(0) NUMBITS(6) []
82],
83CTRL [
84 FORCE_NOTLEAPYEAR OFFSET(8) NUMBITS(1) [],
87 LOAD OFFSET(4) NUMBITS(1) [],
89 RTC_ACTIVE OFFSET(1) NUMBITS(1) [],
91 RTC_ENABLE OFFSET(0) NUMBITS(1) []
93],
94IRQ_SETUP_0 [
95 MATCH_ACTIVE OFFSET(29) NUMBITS(1) [],
96 MATCH_ENA OFFSET(28) NUMBITS(1) [],
98 YEAR_ENA OFFSET(26) NUMBITS(1) [],
100 MONTH_ENA OFFSET(25) NUMBITS(1) [],
102 DAY_ENA OFFSET(24) NUMBITS(1) [],
104 YEAR OFFSET(12) NUMBITS(12) [],
106 MONTH OFFSET(8) NUMBITS(4) [],
108 DAY OFFSET(0) NUMBITS(5) []
110],
111IRQ_SETUP_1 [
112 DOTW_ENA OFFSET(31) NUMBITS(1) [],
114 HOUR_ENA OFFSET(30) NUMBITS(1) [],
116 MIN_ENA OFFSET(29) NUMBITS(1) [],
118 SEC_ENA OFFSET(28) NUMBITS(1) [],
120 DOTW OFFSET(24) NUMBITS(3) [],
122 HOUR OFFSET(16) NUMBITS(5) [],
124 MIN OFFSET(8) NUMBITS(6) [],
126 SEC OFFSET(0) NUMBITS(6) []
128],
129RTC_1 [
130 YEAR OFFSET(12) NUMBITS(12) [],
132 MONTH OFFSET(8) NUMBITS(4) [],
134 DAY OFFSET(0) NUMBITS(5) []
136],
137RTC_0 [
138 DOTW OFFSET(24) NUMBITS(3) [],
140 HOUR OFFSET(16) NUMBITS(5) [],
142 MIN OFFSET(8) NUMBITS(6) [],
144 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 }
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}