1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <common/bk_include.h>
16 #include <os/mem.h>
17 #include <driver/calendar.h>
18 #include "calendar_driver.h"
19 #include "calendar_hal.h"
20
21 typedef struct {
22 calendar_hal_t hal;
23 } calendar_driver_t;
24
25 #define CALENDAR_SRC_CLOCK_FREQ 32000
26 #define CALENDAR_CLOCKS_PER_SECOND CALENDAR_SRC_CLOCK_FREQ
27 #define CALENDAR_PERIOD_US_PER_CLOCK 31.25f /* (1 / CALENDAR_SRC_CLOCK_FREQ) * 1000000 us */
28
29 #define CALENDAR_RETURN_ON_NOT_INIT() do {\
30 if (!s_calendar_driver_is_init) {\
31 return BK_ERR_CALENDAR_NOT_INIT;\
32 }\
33 } while(0)
34
35 static calendar_driver_t s_calendar = {0};
36 static bool s_calendar_driver_is_init = false;
37
calendar_deinit_common(void)38 static void calendar_deinit_common(void)
39 {
40 calendar_hal_disable(&s_calendar.hal);
41 calendar_hal_reset_config_to_default(&s_calendar.hal);
42 }
43
bk_calendar_driver_init(void)44 bk_err_t bk_calendar_driver_init(void)
45 {
46 if (s_calendar_driver_is_init) {
47 return BK_OK;
48 }
49
50 os_memset(&s_calendar, 0, sizeof(s_calendar));
51 calendar_hal_init(&s_calendar.hal);
52 s_calendar_driver_is_init = true;
53
54 return BK_OK;
55 }
56
bk_calendar_driver_deinit(void)57 bk_err_t bk_calendar_driver_deinit(void)
58 {
59 if (!s_calendar_driver_is_init) {
60 return BK_OK;
61 }
62
63 calendar_deinit_common();
64 s_calendar_driver_is_init = false;
65
66 return BK_OK;
67 }
68
bk_calendar_set_init_value(uint32_t init_val)69 bk_err_t bk_calendar_set_init_value(uint32_t init_val)
70 {
71 CALENDAR_RETURN_ON_NOT_INIT();
72 calendar_hal_set_init_value(&s_calendar.hal, init_val);
73
74 return BK_OK;
75 }
76
bk_calendar_get_time_us(void)77 uint64_t bk_calendar_get_time_us(void)
78 {
79 uint64_t total_us_since_calendar_init = 0;
80 uint32_t seconds, pre_seconds = 0;
81 uint32_t clocks_of_us_part, pre_clocks_of_us_part = 0;
82 uint32_t diff_s, diff_us = 0;
83
84 while (1) {
85 seconds = calendar_hal_get_second_cnt(&s_calendar.hal);
86 clocks_of_us_part = calendar_hal_get_us_cnt(&s_calendar.hal);
87 diff_s = seconds - pre_seconds;
88 diff_us = clocks_of_us_part - pre_clocks_of_us_part;
89 if ((0 == diff_s) && (0 == diff_us)) {
90 break;
91 }
92
93 pre_seconds = seconds;
94 pre_clocks_of_us_part = clocks_of_us_part;
95 }
96
97 /* The calendar source clock is lpo_clk(default 32k).
98 * notice:
99 * Please check lpo_clk_mux(sys_ctrl REG_0x40[0:1]) is whether rosc clock,
100 * If lpo_clk_mux select rosc clock, please check whether the rosc_clk is calibrated to 32k(sys_ctrl REG_0x4D[2])
101 * Please ensure the rosc_clk is calibrated to 32k if lpo_clk_mux select rosc_clk,
102 * otherwise the following formula is wrong if rosc_clk is calibrated to 31.25k.
103 */
104 total_us_since_calendar_init = (seconds * CALENDAR_CLOCKS_PER_SECOND + clocks_of_us_part) * CALENDAR_PERIOD_US_PER_CLOCK;
105
106 return total_us_since_calendar_init;
107 }
108
109