1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PoalrFire SoC Microprocessor Subsystem RTC bare metal driver implementation.
7 */
8 #include <string.h>
9 #include "mpfs_hal/mss_hal.h"
10 #include "mss_rtc_regs.h"
11 #include "mss_rtc.h"
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16
17 /*-------------------------------------------------------------------------*//**
18 * CONTROL_REG register masks.
19 */
20 #define CONTROL_RUNNING_MASK 0x00000001u
21 #define CONTROL_RTC_START_MASK 0x00000001u
22 #define CONTROL_RTC_STOP_MASK 0x00000002u
23 #define CONTROL_ALARM_ON_MASK 0x00000004u
24 #define CONTROL_ALARM_OFF_MASK 0x00000008u
25 #define CONTROL_RESET_MASK 0x00000010u
26 #define CONTROL_UPLOAD_MASK 0x00000020u
27 #define CONTROL_WAKEUP_CLR_MASK 0x00000100u
28 #define CONTROL_UPDATED_MASK 0x00000400u
29
30 /*-------------------------------------------------------------------------*//**
31 * MODE_REG register masks.
32 */
33 #define MODE_CLK_MODE_MASK 0x00000001u
34 #define MODE_WAKEUP_EN_MASK 0x00000002u
35 #define MODE_WAKEUP_RESET_MASK 0x00000004u
36 #define MODE_WAKEUP_CONTINUE_MASK 0x00000008u
37
38 /*-------------------------------------------------------------------------*//**
39 * Other masks.
40 */
41 #define MAX_BINARY_HIGHER_COUNT 0x7FFu
42 #define MASK_32_BIT 0xFFFFFFFFu
43 #define MAX_PRESCALAR_COUNT 0x03FFFFFFu
44 #define CALENDAR_SHIFT 8u
45
46 /*-------------------------------------------------------------------------*//**
47 * Index into look-up table.
48 */
49 #define SECONDS 0
50 #define MINUTES 1
51 #define HOURS 2
52 #define DAYS 3
53 #define MONTHS 4
54 #define YEARS 5
55 #define WEEKDAYS 6
56 #define WEEKS 7
57
58 /*-------------------------------------------------------------------------*//**
59 * A pointer to the RTC_TypeDef structure is used to configure the user selected
60 * RTC. This pointer is used by all the mss RTC driver function to carry out the
61 * required functionality.
62 */
63 RTC_TypeDef * mss_rtc;
64
65 static uint8_t
66 get_clock_mode
67 (
68 void
69 );
70
71 static void
72 set_rtc_mode
73 (
74 uint8_t requested_mode
75 );
76
77 static void add_alarm_cfg_values
78 (
79 uint8_t calendar_item,
80 uint32_t * p_calendar_value,
81 uint32_t * p_compare_mask
82 );
83
84 /*-------------------------------------------------------------------------*//**
85 * See "mss_rtc.h" for details of how to use this function.
86 */
87 void
MSS_RTC_init(RTC_TypeDef * base_address,uint8_t mode,uint32_t prescaler)88 MSS_RTC_init
89 (
90 RTC_TypeDef *base_address,
91 uint8_t mode,
92 uint32_t prescaler
93 )
94 {
95 ASSERT(prescaler <= MAX_PRESCALAR_COUNT);
96
97 /* Assigning the user selected MSS RTC base address to global RTC structure
98 * pointer so that the other driver functions can use it.
99 */
100 mss_rtc = base_address;
101
102 if (prescaler <= MAX_PRESCALAR_COUNT)
103 {
104 /* Stop the RTC. */
105 MSS_RTC_stop();
106
107 /* Disable alarm. */
108 mss_rtc->CONTROL_REG = CONTROL_ALARM_OFF_MASK;
109
110 /* Disable Interrupt */
111 MSS_RTC_disable_irq();
112
113 /* Clear RTC wake up interrupt signal */
114 MSS_RTC_clear_irq();
115
116 /* Select mode of operation, including the wake configuration. */
117 if (MSS_RTC_CALENDAR_MODE == mode)
118 {
119 mss_rtc->MODE_REG = MODE_CLK_MODE_MASK;
120 }
121 else
122 {
123 mss_rtc->MODE_REG = 0u;
124 }
125
126 /* Reset the alarm and compare registers to a known value. */
127 mss_rtc->ALARM_LOWER_REG = 0u;
128 mss_rtc->ALARM_UPPER_REG = 0u;
129 mss_rtc->COMPARE_LOWER_REG = 0u;
130 mss_rtc->COMPARE_UPPER_REG = 0u;
131
132 /* Reset the calendar counters */
133 MSS_RTC_reset_counter();
134
135 /* Set new Prescaler value */
136 mss_rtc->PRESCALER_REG = prescaler;
137 }
138 }
139
140 /*-------------------------------------------------------------------------*//**
141 See "mss_rtc.h" for details of how to use this function.
142 */
143 void
MSS_RTC_set_calendar_count(const mss_rtc_calender_t * new_rtc_value)144 MSS_RTC_set_calendar_count
145 (
146 const mss_rtc_calender_t *new_rtc_value
147 )
148 {
149 uint8_t error = 0u;
150 uint8_t clock_mode;
151
152 const uint8_t g_rtc_max_count_lut[] =
153 {
154 /* Calendar mode */
155 59u, /* Seconds */
156 59u, /* Minutes */
157 23u, /* Hours */
158 31u, /* Days */
159 12u, /* Months */
160 254u, /* Years */
161 7u, /* Weekdays */
162 52u /* Week */
163 };
164
165 const uint8_t g_rtc_min_count_lut[] =
166 {
167 /* Calendar mode */
168 0u, /* Seconds */
169 0u, /* Minutes */
170 0u, /* Hours */
171 1u, /* Days */
172 1u, /* Months */
173 0u, /* Years */
174 1u, /* Weekdays */
175 1u /* Week */
176 };
177
178 /* Assert if the values cross the limit */
179 ASSERT(new_rtc_value->second >= g_rtc_min_count_lut[SECONDS]);
180 ASSERT(new_rtc_value->second <= g_rtc_max_count_lut[SECONDS]);
181 ASSERT(new_rtc_value->minute >= g_rtc_min_count_lut[MINUTES]);
182 ASSERT(new_rtc_value->minute <= g_rtc_max_count_lut[MINUTES]);
183 ASSERT(new_rtc_value->hour >= g_rtc_min_count_lut[HOURS]);
184 ASSERT(new_rtc_value->hour <= g_rtc_max_count_lut[HOURS]);
185 ASSERT(new_rtc_value->day >= g_rtc_min_count_lut[DAYS]);
186 ASSERT(new_rtc_value->day <= g_rtc_max_count_lut[DAYS]);
187 ASSERT(new_rtc_value->month >= g_rtc_min_count_lut[MONTHS]);
188 ASSERT(new_rtc_value->month <= g_rtc_max_count_lut[MONTHS]);
189 ASSERT(new_rtc_value->year >= g_rtc_min_count_lut[YEARS]);
190 ASSERT(new_rtc_value->year <= g_rtc_max_count_lut[YEARS]);
191 ASSERT(new_rtc_value->weekday >= g_rtc_min_count_lut[WEEKDAYS]);
192 ASSERT(new_rtc_value->weekday <= g_rtc_max_count_lut[WEEKDAYS]);
193 ASSERT(new_rtc_value->week >= g_rtc_min_count_lut[WEEKS]);
194 ASSERT(new_rtc_value->week <= g_rtc_max_count_lut[WEEKS]);
195
196 if (new_rtc_value->second < g_rtc_min_count_lut[SECONDS]) {error = 1u;}
197 if (new_rtc_value->second > g_rtc_max_count_lut[SECONDS]) {error = 1u;}
198 if (new_rtc_value->minute < g_rtc_min_count_lut[MINUTES]) {error = 1u;}
199 if (new_rtc_value->minute > g_rtc_max_count_lut[MINUTES]) {error = 1u;}
200 if (new_rtc_value->hour < g_rtc_min_count_lut[HOURS]) {error = 1u;}
201 if (new_rtc_value->hour > g_rtc_max_count_lut[HOURS]) {error = 1u;}
202 if (new_rtc_value->day < g_rtc_min_count_lut[DAYS]) {error = 1u;}
203 if (new_rtc_value->day > g_rtc_max_count_lut[DAYS]) {error = 1u;}
204 if (new_rtc_value->month < g_rtc_min_count_lut[MONTHS]) {error = 1u;}
205 if (new_rtc_value->month > g_rtc_max_count_lut[MONTHS]) {error = 1u;}
206 if (new_rtc_value->year < g_rtc_min_count_lut[YEARS]) {error = 1u;}
207 if (new_rtc_value->year > g_rtc_max_count_lut[YEARS]) {error = 1u;}
208 if (new_rtc_value->weekday < g_rtc_min_count_lut[WEEKDAYS]) {error = 1u;}
209 if (new_rtc_value->weekday > g_rtc_max_count_lut[WEEKDAYS]) {error = 1u;}
210 if (new_rtc_value->week < g_rtc_min_count_lut[WEEKS]) {error = 1u;}
211 if (new_rtc_value->week > g_rtc_max_count_lut[WEEKS]) {error = 1u;}
212
213 /* This function can only be used when the RTC is configured to operate in
214 * calendar counter mode. */
215 clock_mode = get_clock_mode();
216 ASSERT(MSS_RTC_CALENDAR_MODE == clock_mode);
217
218 if ((0u == error) && (MSS_RTC_CALENDAR_MODE == clock_mode))
219 {
220 uint32_t upload_in_progress;
221
222 /* Write the RTC new value. */
223 mss_rtc->SECONDS_REG = new_rtc_value->second;
224 mss_rtc->MINUTES_REG = new_rtc_value->minute;
225 mss_rtc->HOURS_REG = new_rtc_value->hour;
226 mss_rtc->DAY_REG = new_rtc_value->day;
227 mss_rtc->MONTH_REG = new_rtc_value->month;
228 mss_rtc->YEAR_REG = new_rtc_value->year;
229 mss_rtc->WEEKDAY_REG = new_rtc_value->weekday;
230 mss_rtc->WEEK_REG = new_rtc_value->week;
231
232 /* Data is copied, now issue upload command */
233 mss_rtc->CONTROL_REG = CONTROL_UPLOAD_MASK ;
234
235 /* Wait for the upload to complete. */
236 do {
237 upload_in_progress = mss_rtc->CONTROL_REG & CONTROL_UPLOAD_MASK;
238 } while (upload_in_progress);
239 }
240 }
241
242 /*-------------------------------------------------------------------------*//**
243 * See "mss_rtc.h" for details of how to use this function.
244 */
245 void
MSS_RTC_set_binary_count(uint64_t new_rtc_value)246 MSS_RTC_set_binary_count
247 (
248 uint64_t new_rtc_value
249 )
250 {
251 uint8_t clock_mode;
252
253 /* This function can only be used when the RTC is configured to operate in
254 * binary counter mode. */
255 clock_mode = get_clock_mode();
256 ASSERT(MSS_RTC_BINARY_MODE == clock_mode);
257
258 if (MSS_RTC_BINARY_MODE == clock_mode)
259 {
260 uint32_t rtc_upper_32_bit_value;
261
262 rtc_upper_32_bit_value = (uint32_t)(new_rtc_value >> 32u) & MASK_32_BIT;
263
264 /* Assert if the values cross the limit */
265 ASSERT(rtc_upper_32_bit_value <= MAX_BINARY_HIGHER_COUNT);
266
267 if (rtc_upper_32_bit_value <= MAX_BINARY_HIGHER_COUNT)
268 {
269 uint32_t upload_in_progress;
270
271 /* Write the RTC new value. */
272 mss_rtc->DATE_TIME_LOWER_REG = (uint32_t)new_rtc_value;
273 mss_rtc->DATE_TIME_UPPER_REG =
274 (uint32_t)(( new_rtc_value >> 32u) & MAX_BINARY_HIGHER_COUNT);
275
276 /* Data is copied, now issue upload command */
277 mss_rtc->CONTROL_REG = CONTROL_UPLOAD_MASK;
278
279 /* Wait for the upload to complete. */
280 do {
281 upload_in_progress = mss_rtc->CONTROL_REG & CONTROL_UPLOAD_MASK;
282 } while (upload_in_progress);
283 }
284 }
285 }
286
287 /*-------------------------------------------------------------------------*//**
288 * See "mss_rtc.h" for details of how to use this function.
289 */
290 void
MSS_RTC_get_calendar_count(mss_rtc_calender_t * p_rtc_calendar)291 MSS_RTC_get_calendar_count
292 (
293 mss_rtc_calender_t *p_rtc_calendar
294 )
295 {
296 uint8_t clock_mode;
297 /* This function can only be used when the RTC is configured to operate in
298 * calendar counter mode. */
299 clock_mode = get_clock_mode();
300 ASSERT(MSS_RTC_CALENDAR_MODE == clock_mode);
301
302 if (MSS_RTC_CALENDAR_MODE == clock_mode)
303 {
304 p_rtc_calendar->second = (uint8_t)mss_rtc->SECONDS_REG;
305 p_rtc_calendar->minute = (uint8_t)mss_rtc->MINUTES_REG;
306 p_rtc_calendar->hour = (uint8_t)mss_rtc->HOURS_REG;
307 p_rtc_calendar->day = (uint8_t)mss_rtc->DAY_REG;
308 p_rtc_calendar->month = (uint8_t)mss_rtc->MONTH_REG;
309 p_rtc_calendar->year = (uint8_t)mss_rtc->YEAR_REG;
310 p_rtc_calendar->weekday = (uint8_t)mss_rtc->WEEKDAY_REG;
311 p_rtc_calendar->week = (uint8_t)mss_rtc->WEEK_REG;
312 }
313 else
314 {
315 /* Set returned calendar count to zero if the RTC is not configured for
316 * calendar counter mode. This should make incorrect release application
317 * code behave consistently and help application debugging. */
318 memset(p_rtc_calendar, 0, sizeof(mss_rtc_calender_t));
319 }
320 }
321
322 /*-------------------------------------------------------------------------*//**
323 * See "mss_rtc.h" for details of how to use this function.
324 */
325 uint64_t
MSS_RTC_get_binary_count(void)326 MSS_RTC_get_binary_count
327 (
328 void
329 )
330 {
331 uint64_t rtc_count;
332 uint8_t clock_mode;
333
334 /* This function can only be used when the RTC is configured to operate in
335 * binary counter mode. */
336 clock_mode = get_clock_mode();
337 ASSERT(MSS_RTC_BINARY_MODE == clock_mode);
338
339 if (MSS_RTC_BINARY_MODE == clock_mode)
340 {
341 rtc_count = mss_rtc->DATE_TIME_LOWER_REG;
342 rtc_count = rtc_count | ((uint64_t)mss_rtc->DATE_TIME_UPPER_REG << 32u);
343 }
344 else
345 {
346 /* Set returned binary count to zero if the RTC is not configured for
347 * binary counter mode. This should make incorrect release application
348 * code behave consistently and help application debugging. */
349 rtc_count = 0u;
350 }
351
352 return rtc_count;
353 }
354
add_alarm_cfg_values(uint8_t calendar_item,uint32_t * p_calendar_value,uint32_t * p_compare_mask)355 static void add_alarm_cfg_values
356 (
357 uint8_t calendar_item,
358 uint32_t * p_calendar_value,
359 uint32_t * p_compare_mask
360 )
361 {
362 if (MSS_RTC_CALENDAR_DONT_CARE == calendar_item)
363 {
364 *p_calendar_value = (uint32_t)(*p_calendar_value << CALENDAR_SHIFT);
365 *p_compare_mask = (uint32_t)(*p_compare_mask << CALENDAR_SHIFT);
366 }
367 else
368 {
369 *p_calendar_value = (uint32_t)((*p_calendar_value << CALENDAR_SHIFT) |
370 (uint32_t)calendar_item);
371 *p_compare_mask = (uint32_t)((*p_compare_mask << CALENDAR_SHIFT) |
372 (uint32_t)0xFFu);
373 }
374 }
375
376 /*-------------------------------------------------------------------------*//**
377 * See "mss_rtc.h" for details of how to use this function.
378 */
MSS_RTC_set_calendar_count_alarm(const mss_rtc_calender_t * alarm_value)379 void MSS_RTC_set_calendar_count_alarm
380 (
381 const mss_rtc_calender_t * alarm_value
382 )
383 {
384 uint32_t calendar_value;
385 uint32_t compare_mask;
386 uint8_t mode;
387
388 mode = (uint8_t)(mss_rtc->MODE_REG & MODE_CLK_MODE_MASK);
389
390 /* This function can only be used with the RTC set to operate in calendar
391 * mode. */
392 ASSERT(MSS_RTC_CALENDAR_MODE == mode);
393
394 if (MSS_RTC_CALENDAR_MODE == mode)
395 {
396 uint8_t required_mode_reg;
397
398 /* Disable the alarm before updating */
399 mss_rtc->CONTROL_REG = CONTROL_ALARM_OFF_MASK;
400
401 /* Set alarm and compare lower registers. */
402 calendar_value = 0u;
403 compare_mask = 0u;
404
405 add_alarm_cfg_values(alarm_value->day, &calendar_value, &compare_mask);
406 add_alarm_cfg_values(alarm_value->hour, &calendar_value, &compare_mask);
407 add_alarm_cfg_values(alarm_value->minute, &calendar_value, &compare_mask);
408 add_alarm_cfg_values(alarm_value->second, &calendar_value, &compare_mask);
409
410 mss_rtc->ALARM_LOWER_REG = calendar_value;
411 mss_rtc->COMPARE_LOWER_REG = compare_mask;
412
413 /* Set alarm and compare upper registers. */
414 calendar_value = 0u;
415 compare_mask = 0u;
416
417 add_alarm_cfg_values(alarm_value->week, &calendar_value, &compare_mask);
418 add_alarm_cfg_values(alarm_value->weekday, &calendar_value, &compare_mask);
419 add_alarm_cfg_values(alarm_value->year, &calendar_value, &compare_mask);
420 add_alarm_cfg_values(alarm_value->month, &calendar_value, &compare_mask);
421
422 mss_rtc->ALARM_UPPER_REG = calendar_value;
423 mss_rtc->COMPARE_UPPER_REG = compare_mask;
424
425 /* Configure the RTC to enable the alarm. */
426 required_mode_reg = mode | MODE_WAKEUP_EN_MASK | MODE_WAKEUP_CONTINUE_MASK;
427 set_rtc_mode(required_mode_reg);
428
429 /* Enable the alarm */
430 mss_rtc->CONTROL_REG = CONTROL_ALARM_ON_MASK ;
431 }
432 }
433
434 /*-------------------------------------------------------------------------*//**
435 We only write the RTC mode register if really required because the RTC needs
436 to be stopped for the mode register to be written. Stopping the RTC every time
437 the wake-up alarm configuration is set might induce drift on the RTC time.
438 This function is intended to be used when setting alarms.
439 */
440 static void
set_rtc_mode(uint8_t requested_mode)441 set_rtc_mode
442 (
443 uint8_t requested_mode
444 )
445 {
446 if (mss_rtc->MODE_REG != requested_mode)
447 {
448 uint32_t rtc_running;
449 rtc_running = mss_rtc->CONTROL_REG & CONTROL_RUNNING_MASK;
450 if (rtc_running)
451 {
452 /* Stop the RTC in order to change the mode register content. */
453 MSS_RTC_stop();
454 mss_rtc->MODE_REG = requested_mode;
455 MSS_RTC_start();
456 }
457 else
458 {
459 mss_rtc->MODE_REG = requested_mode;
460 }
461 }
462 }
463
464 /*-------------------------------------------------------------------------*//**
465 * See "mss_rtc.h" for details of how to use this function.
466 */
467 void
MSS_RTC_set_binary_count_alarm(uint64_t alarm_value,mss_rtc_alarm_type_t alarm_type)468 MSS_RTC_set_binary_count_alarm
469 (
470 uint64_t alarm_value,
471 mss_rtc_alarm_type_t alarm_type
472 )
473 {
474 uint8_t mode;
475
476 mode = (uint8_t)(mss_rtc->MODE_REG & MODE_CLK_MODE_MASK);
477
478 /* This function can only be used with the RTC set to operate in binary
479 * counter mode. */
480 ASSERT(MSS_RTC_BINARY_MODE == mode);
481 if (MSS_RTC_BINARY_MODE == mode)
482 {
483 uint8_t required_mode_reg;
484
485 /* Disable the alarm before updating */
486 mss_rtc->CONTROL_REG = CONTROL_ALARM_OFF_MASK;
487
488 /* Set the alarm value. */
489 mss_rtc->COMPARE_LOWER_REG = COMPARE_ALL_BITS;
490 mss_rtc->COMPARE_UPPER_REG = COMPARE_ALL_BITS;
491 mss_rtc->ALARM_LOWER_REG = (uint32_t)alarm_value;
492 mss_rtc->ALARM_UPPER_REG = (uint32_t)(alarm_value >> 32u);
493
494 /* Configure the RTC to enable the alarm. */
495 required_mode_reg = mode | MODE_WAKEUP_EN_MASK | MODE_WAKEUP_CONTINUE_MASK;
496 if (MSS_RTC_PERIODIC_ALARM == alarm_type)
497 {
498 /* The RTC binary counter will be fully reset when the alarm occurs.
499 * The counter will continue counting while the wake-up interrupt is
500 * active. */
501 required_mode_reg |= MODE_WAKEUP_RESET_MASK;
502 }
503 set_rtc_mode(required_mode_reg);
504
505 /* Enable the alarm */
506 mss_rtc->CONTROL_REG = CONTROL_ALARM_ON_MASK;
507
508 uint8_t test = get_clock_mode();
509 }
510 }
511
512 /*-------------------------------------------------------------------------*//**
513 * See "mss_rtc.h" for details of how to use this function.
514 */
515 void
MSS_RTC_start(void)516 MSS_RTC_start
517 (
518 void
519 )
520 {
521 mss_rtc->CONTROL_REG = CONTROL_RTC_START_MASK;
522 }
523
524 /*-------------------------------------------------------------------------*//**
525 * See "mss_rtc.h" for details of how to use this function.
526 */
527 void
MSS_RTC_stop(void)528 MSS_RTC_stop
529 (
530 void
531 )
532 {
533 uint32_t rtc_running;
534
535 /* Send command to stop RTC. */
536 mss_rtc->CONTROL_REG = CONTROL_RTC_STOP_MASK;
537
538 /* Wait for RTC internal synchronization to take place and RTC to actually
539 * stop. */
540 do {
541 rtc_running = mss_rtc->CONTROL_REG & CONTROL_RUNNING_MASK;
542 } while(rtc_running);
543 }
544
545 /*-------------------------------------------------------------------------*//**
546 * See "mss_rtc.h" for details of how to use this function.
547 */
548 void
MSS_RTC_reset_counter(void)549 MSS_RTC_reset_counter
550 (
551 void
552 )
553 {
554 uint32_t upload_in_progress;
555
556 mss_rtc->CONTROL_REG = CONTROL_RESET_MASK;
557
558 /* Wait for the upload to complete. */
559 do {
560 upload_in_progress = mss_rtc->CONTROL_REG & CONTROL_UPLOAD_MASK;
561 } while (upload_in_progress);
562 }
563
564 /*-------------------------------------------------------------------------*//**
565 * See "mss_rtc.h" for details of how to use this function.
566 */
567 uint32_t
MSS_RTC_get_update_flag(void)568 MSS_RTC_get_update_flag
569 (
570 void
571 )
572 {
573 uint32_t updated;
574 updated = mss_rtc->CONTROL_REG & CONTROL_UPDATED_MASK;
575 return updated;
576 }
577
578 /*-------------------------------------------------------------------------*//**
579 * See "mss_rtc.h" for details of how to use this function.
580 */
581 void
MSS_RTC_clear_update_flag(void)582 MSS_RTC_clear_update_flag
583 (
584 void
585 )
586 {
587 /* Clear the "updated" control bit. */
588 mss_rtc->CONTROL_REG = CONTROL_UPDATED_MASK;
589 }
590
591 /*-------------------------------------------------------------------------*//**
592 * See "mss_rtc.h" for details of how to use this function.
593 */
594 void
MSS_RTC_enable_irq(void)595 MSS_RTC_enable_irq
596 (
597 void
598 )
599 {
600 /* Only the PLIC level interrupt enable is performed within this function.
601 * The RTC level interrupt enable is performed within the alarm setting
602 * functions.
603 * This avoid the MODE register being modified whenever RTC
604 * interrupts are enabled/disabled. */
605 PLIC_EnableIRQ(RTC_WAKEUP_PLIC);
606 }
607
608 /*-------------------------------------------------------------------------*//**
609 * See "mss_rtc.h" for details of how to use this function.
610 */
611 void
MSS_RTC_disable_irq(void)612 MSS_RTC_disable_irq
613 (
614 void
615 )
616 {
617 /* Only the PLIC level interrupt disable is performed within this function.
618 * This avoid the MODE register being modified whenever RTC
619 * interrupts are enabled/disabled. */
620 PLIC_DisableIRQ(RTC_WAKEUP_PLIC);
621 }
622
623 /*-------------------------------------------------------------------------*//**
624 * See "mss_rtc.h" for details of how to use this function.
625 */
626 void
MSS_RTC_clear_irq(void)627 MSS_RTC_clear_irq
628 (
629 void
630 )
631 {
632 volatile uint32_t dummy_read;
633
634 /* Clear wake up interrupt signal */
635 mss_rtc->CONTROL_REG = CONTROL_WAKEUP_CLR_MASK;
636
637 /* Ensure that the posted write to the CONTROL_REG register completed before
638 * returning from this function. Not doing this may result in the interrupt
639 * only being cleared some time after this function returns. */
640 dummy_read = mss_rtc->CONTROL_REG;
641
642 /* Dummy operation to avoid warning message */
643 ++dummy_read;
644 }
645
646 /*-------------------------------------------------------------------------*//**
647 The get_clock_mode() function gets the clock mode of RTC hardware.
648 Possible clock modes are:
649 MSS_RTC_CALENDAR_MODE
650 MSS_RTC_BINARY_MODE
651 */
652 static uint8_t
get_clock_mode(void)653 get_clock_mode
654 (
655 void
656 )
657 {
658 uint8_t clock_mode;
659
660 clock_mode = (uint8_t)(mss_rtc->MODE_REG & MODE_CLK_MODE_MASK);
661
662 return(clock_mode);
663 }
664
665 #ifdef __cplusplus
666 }
667 #endif
668