1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 * Description: Provides rtc driver source \n
16 *
17 * History: \n
18 * 2023-03-06, Create file. \n
19 */
20 #include <stdbool.h>
21 #include <limits.h>
22 #include "securec.h"
23 #include "common_def.h"
24 #include "interrupt/osal_interrupt.h"
25 #include "tcxo.h"
26 #include "rtc_porting.h"
27 #include "rtc.h"
28
29 #ifndef UINT64_MAX
30 #define UINT64_MAX (0xFFFFFFFFFFFFFFFFUL)
31 #endif
32
33 #if defined(CONFIG_RTC_USING_OLD_VERSION)
34 #define RTC_OLD_VERSION_LOAD_COUNT_MASK (uint64_t)0x0F
35 #endif
36
37 #ifdef CONFIG_RTC_MAX_RTCS_NUM
38 #ifndef CONFIG_RTC_MAX_RTCS_NUM_0
39 #define CONFIG_RTC_MAX_RTCS_NUM_0 CONFIG_RTC_MAX_RTCS_NUM
40 #endif
41 #ifndef CONFIG_RTC_MAX_RTCS_NUM_1
42 #define CONFIG_RTC_MAX_RTCS_NUM_1 CONFIG_RTC_MAX_RTCS_NUM
43 #endif
44 #ifndef CONFIG_RTC_MAX_RTCS_NUM_2
45 #define CONFIG_RTC_MAX_RTCS_NUM_2 CONFIG_RTC_MAX_RTCS_NUM
46 #endif
47 #ifndef CONFIG_RTC_MAX_RTCS_NUM_3
48 #define CONFIG_RTC_MAX_RTCS_NUM_3 CONFIG_RTC_MAX_RTCS_NUM
49 #endif
50 #ifndef CONFIG_RTC_MAX_RTCS_NUM_EXTRA
51 #define CONFIG_RTC_MAX_RTCS_NUM_EXTRA CONFIG_RTC_MAX_RTCS_NUM
52 #endif
53 #endif
54
55 typedef enum rtc_flag {
56 RTC_FLAG_NORMAL,
57 RTC_FLAG_PERMANENT
58 } rtc_flag_t;
59
60 typedef struct rtc_info {
61 rtc_handle_t key;
62 rtc_index_t index;
63 bool enable;
64 bool is_run;
65 rtc_flag_t flag;
66 uint64_t cycle;
67 rtc_callback_t callback;
68 uintptr_t data;
69 } rtc_info_t;
70
71 typedef struct soft_rtc_cfg {
72 uintptr_t rtc_addr;
73 uint8_t rtc_num;
74 } soft_rtc_cfg_t;
75
76 #define CUR_MAX_HARDWARE_RTC_NUM 4
77 #define RTC_SIZE_0 0
78 #define RTC_SIZE_1 1
79 #define RTC_SIZE_2 2
80 #define RTC_SIZE_3 3
81 #define RTC_SIZE_4 4
82
83 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_0)
84 static rtc_info_t g_rtclist_0[CONFIG_RTC_MAX_RTCS_NUM_0];
85 #endif
86 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_1)
87 static rtc_info_t g_rtclist_1[CONFIG_RTC_MAX_RTCS_NUM_1];
88 #endif
89 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_2)
90 static rtc_info_t g_rtclist_2[CONFIG_RTC_MAX_RTCS_NUM_2];
91 #endif
92 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_3)
93 static rtc_info_t g_rtclist_3[CONFIG_RTC_MAX_RTCS_NUM_3];
94 #endif
95 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_4)
96 static rtc_info_t g_rtclist_extra[CONFIG_RTC_MAX_NUM - CUR_MAX_HARDWARE_RTC_NUM][CONFIG_RTC_MAX_RTCS_NUM_EXTRA];
97 #endif
98 typedef struct rtcs_manager {
99 uint64_t last_rtc_load_cycle;
100 rtc_info_t *rtcs;
101 uint32_t rtc_irq_id;
102 uint16_t rtc_int_priority;
103 bool in_rtc_irq;
104 uint8_t soft_rtc_num;
105 #if defined(CONFIG_RTC_USING_OLD_VERSION)
106 int32_t rtc_load_cycle_deviation;
107 #endif
108 } rtcs_manager_t;
109
110 static bool g_rtc_inited = false;
111 static bool g_rtc_adapted[CONFIG_RTC_MAX_NUM];
112 rtcs_manager_t g_rtcs_manager[CONFIG_RTC_MAX_NUM] = { 0 };
113
114
115 /* 计算对齐后的cycle和偏差值 */
rtc_get_cycle_with_mask(rtc_index_t index,uint64_t cycle,int32_t * cycle_deviation)116 STATIC uint64_t rtc_get_cycle_with_mask(rtc_index_t index, uint64_t cycle, int32_t *cycle_deviation)
117 {
118 #if defined(CONFIG_RTC_USING_OLD_VERSION)
119 /* 内部函数, 不进行空指针检查 */
120 int32_t rtc_load_cycle_deviation = g_rtcs_manager[index].rtc_load_cycle_deviation;
121
122 /* cycle值小于等于0xF, 或当前累积偏差值不到0xF时, cycle向上对齐到0xF */
123 if (cycle <= RTC_OLD_VERSION_LOAD_COUNT_MASK
124 || rtc_load_cycle_deviation <= (int32_t)RTC_OLD_VERSION_LOAD_COUNT_MASK) {
125 *cycle_deviation =
126 (int32_t)RTC_OLD_VERSION_LOAD_COUNT_MASK - (int32_t)(cycle & RTC_OLD_VERSION_LOAD_COUNT_MASK);
127 return (cycle | RTC_OLD_VERSION_LOAD_COUNT_MASK);
128 }
129
130 /* 当前累积偏差值超过0xF时, cycle向下对齐到(0xF - 0x10) */
131 *cycle_deviation = -1 - (int32_t)(cycle & RTC_OLD_VERSION_LOAD_COUNT_MASK);
132 return (cycle | RTC_OLD_VERSION_LOAD_COUNT_MASK) - (RTC_OLD_VERSION_LOAD_COUNT_MASK + 1);
133 #else
134 unused(index);
135 unused(cycle_deviation);
136 return cycle;
137 #endif
138 }
139
140 /* load对齐后的cycle和偏差值 */
rtc_load_cycle_with_mask(rtc_index_t index,uint64_t cycle_with_mask,int32_t cycle_deviation)141 STATIC void rtc_load_cycle_with_mask(rtc_index_t index, uint64_t cycle_with_mask, int32_t cycle_deviation)
142 {
143 #if defined(CONFIG_RTC_USING_OLD_VERSION)
144 g_rtcs_manager[index].rtc_load_cycle_deviation += cycle_deviation;
145 #else
146 unused(index);
147 unused(cycle_deviation);
148 #endif
149 hal_rtc_config_load(index, cycle_with_mask);
150 }
151
152 /* Reduces the rtc left for all the rtcs by rtc us amount */
rtc_update_rtcs_rtc(rtc_index_t index,uint64_t update_amount_cycle)153 STATIC bool rtc_update_rtcs_rtc(rtc_index_t index, uint64_t update_amount_cycle)
154 {
155 bool has_new_rtc = false;
156 uint32_t irq_sts = osal_irq_lock();
157 uint8_t soft_rtc_num = g_rtcs_manager[index].soft_rtc_num;
158 for (uint32_t i = 0; i < soft_rtc_num; i++) {
159 if (g_rtcs_manager[index].rtcs[i].cycle <= update_amount_cycle) {
160 g_rtcs_manager[index].rtcs[i].cycle = 0;
161 if (g_rtcs_manager[index].rtcs[i].is_run == true) {
162 has_new_rtc = true;
163 }
164 } else {
165 g_rtcs_manager[index].rtcs[i].cycle -= update_amount_cycle;
166 }
167 }
168 osal_irq_restore(irq_sts);
169 return has_new_rtc;
170 }
171
172 /*
173 * Loops through the rtcs to see if any need to be processed
174 */
rtc_process_rtcs(rtc_index_t index)175 STATIC bool rtc_process_rtcs(rtc_index_t index)
176 {
177 bool re_run = false;
178 uint64_t start_rtc = uapi_tcxo_get_count();
179 uint8_t soft_rtc_num = g_rtcs_manager[index].soft_rtc_num;
180 for (uint32_t i = 0; i < soft_rtc_num; i++) {
181 if (g_rtcs_manager[index].rtcs[i].enable &&
182 g_rtcs_manager[index].rtcs[i].cycle == 0 &&
183 g_rtcs_manager[index].rtcs[i].is_run) {
184 g_rtcs_manager[index].rtcs[i].is_run = false;
185 if (g_rtcs_manager[index].rtcs[i].callback) {
186 g_rtcs_manager[index].rtcs[i].callback(g_rtcs_manager[index].rtcs[i].data);
187 }
188 re_run = true;
189 }
190 }
191
192 if (re_run) {
193 uint64_t end_rtc = uapi_tcxo_get_count();
194 uint64_t diff = end_rtc - start_rtc;
195 uint64_t cycle = 0;
196 cycle = rtc_porting_compensat_by_tcxo(diff);
197 re_run = rtc_update_rtcs_rtc(index, cycle);
198 }
199
200 return re_run;
201 }
202
203 /*
204 * Gets the index of the next rtc to expire
205 */
rtc_get_next_rtc(rtc_index_t index)206 STATIC uint32_t rtc_get_next_rtc(rtc_index_t index)
207 {
208 uint64_t shortest_rtc_found = UINT64_MAX;
209 uint8_t soft_rtc_num = g_rtcs_manager[index].soft_rtc_num;
210 uint32_t rtc_found = soft_rtc_num;
211 for (uint8_t i = 0; i < soft_rtc_num; i++) {
212 if (g_rtcs_manager[index].rtcs[i].enable &&
213 g_rtcs_manager[index].rtcs[i].cycle <= shortest_rtc_found &&
214 g_rtcs_manager[index].rtcs[i].is_run) {
215 shortest_rtc_found = g_rtcs_manager[index].rtcs[i].cycle;
216 rtc_found = i;
217 }
218 }
219 return rtc_found;
220 }
221
222 /*
223 * Gets the rtc in us till the next interrupt, MAX_UINT32 indicates that no rtc is set
224 */
rtc_get_rtc_till_interrupt(rtc_index_t index)225 STATIC uint64_t rtc_get_rtc_till_interrupt(rtc_index_t index)
226 {
227 uint64_t current_value = hal_rtc_get_current_value(index);
228 if (current_value != 0) {
229 return current_value;
230 }
231
232 uint32_t next_rtc = rtc_get_next_rtc(index);
233 if (next_rtc >= g_rtcs_manager[index].soft_rtc_num) {
234 return UINT64_MAX;
235 }
236
237 uint64_t cycle_with_mask;
238 int32_t cycle_deviation = 0;
239 cycle_with_mask = rtc_get_cycle_with_mask(index, g_rtcs_manager[index].rtcs[next_rtc].cycle, &cycle_deviation);
240 if (g_rtcs_manager[index].in_rtc_irq) {
241 return cycle_with_mask;
242 }
243
244 hal_rtc_stop(index);
245 rtc_load_cycle_with_mask(index, cycle_with_mask, cycle_deviation);
246 hal_rtc_start(index);
247 return cycle_with_mask;
248 }
249
250 /*
251 * Searches through the rtcs to find the one with the lowest callback rtc
252 */
rtc_set_next_rtc_interrupt(rtc_index_t index)253 STATIC void rtc_set_next_rtc_interrupt(rtc_index_t index)
254 {
255 uint32_t irq_sts = osal_irq_lock();
256 hal_rtc_stop(index);
257 uint32_t rtc_found = rtc_get_next_rtc(index);
258 if (rtc_found < g_rtcs_manager[index].soft_rtc_num) {
259 uint64_t cycle_with_mask;
260 int32_t cycle_deviation = 0;
261 cycle_with_mask =
262 rtc_get_cycle_with_mask(index, g_rtcs_manager[index].rtcs[rtc_found].cycle, &cycle_deviation);
263 rtc_load_cycle_with_mask(index, cycle_with_mask, cycle_deviation);
264 hal_rtc_start(index);
265 g_rtcs_manager[index].last_rtc_load_cycle = cycle_with_mask;
266 }
267 osal_irq_restore(irq_sts);
268 }
269
rtc_int_callback(rtc_index_t index)270 STATIC void rtc_int_callback(rtc_index_t index)
271 {
272 uint32_t irq_sts = osal_irq_lock();
273 g_rtcs_manager[index].in_rtc_irq = true;
274 rtc_update_rtcs_rtc(index, g_rtcs_manager[index].last_rtc_load_cycle);
275 g_rtcs_manager[index].last_rtc_load_cycle = 0;
276 osal_irq_restore(irq_sts);
277
278 while (rtc_process_rtcs(index)) {
279 }
280
281 rtc_set_next_rtc_interrupt(index);
282 g_rtcs_manager[index].in_rtc_irq = false;
283 }
284
soft_rtc_list_cfg_get(uint32_t index,soft_rtc_cfg_t * rtc_info)285 STATIC errcode_t soft_rtc_list_cfg_get(uint32_t index, soft_rtc_cfg_t *rtc_info)
286 {
287 switch (index) {
288 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_0)
289 case RTC_SIZE_0:
290 rtc_info->rtc_num = CONFIG_RTC_MAX_RTCS_NUM_0;
291 rtc_info->rtc_addr = (uintptr_t)g_rtclist_0;
292 break;
293 #endif
294 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_1)
295 case RTC_SIZE_1:
296 rtc_info->rtc_num = CONFIG_RTC_MAX_RTCS_NUM_1;
297 rtc_info->rtc_addr = (uintptr_t)g_rtclist_1;
298 break;
299 #endif
300 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_2)
301 case RTC_SIZE_2:
302 rtc_info->rtc_num = CONFIG_RTC_MAX_RTCS_NUM_2;
303 rtc_info->rtc_addr = (uintptr_t)g_rtclist_2;
304 break;
305 #endif
306 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_3)
307 case RTC_SIZE_3:
308 rtc_info->rtc_num = CONFIG_RTC_MAX_RTCS_NUM_3;
309 rtc_info->rtc_addr = (uintptr_t)g_rtclist_3;
310 break;
311 #endif
312 default:
313 #if defined(CONFIG_RTC_MAX_NUM) && (CONFIG_RTC_MAX_NUM > RTC_SIZE_4)
314 rtc_info->rtc_num = CONFIG_RTC_MAX_RTCS_NUM_EXTRA;
315 rtc_info->rtc_addr = (uintptr_t)&g_rtclist_extra[index - CUR_MAX_HARDWARE_RTC_NUM];
316 #endif
317 break;
318 }
319 if (memset_s((uint8_t *)rtc_info->rtc_addr, sizeof(rtc_info_t) * rtc_info->rtc_num, 0,
320 sizeof(rtc_info_t) * rtc_info->rtc_num) != EOK) {
321 return ERRCODE_MEMSET;
322 }
323 return ERRCODE_SUCC;
324 }
325
uapi_rtc_init(void)326 errcode_t uapi_rtc_init(void)
327 {
328 uint32_t irq_sts = osal_irq_lock();
329 if (unlikely(g_rtc_inited)) {
330 osal_irq_restore(irq_sts);
331 return ERRCODE_SUCC;
332 }
333
334 if (unlikely(memset_s(&g_rtcs_manager, sizeof(g_rtcs_manager), 0, sizeof(g_rtcs_manager)) != EOK)) {
335 osal_irq_restore(irq_sts);
336 return ERRCODE_MEMSET;
337 }
338
339 for (uint32_t i = 0; i < CONFIG_RTC_MAX_NUM; i++) {
340 soft_rtc_cfg_t rtc_info;
341 uint32_t ret;
342 g_rtc_adapted[i] = false;
343 ret = soft_rtc_list_cfg_get(i, &rtc_info);
344 if (unlikely(ret != ERRCODE_SUCC)) {
345 osal_irq_restore(irq_sts);
346 return ret;
347 }
348 g_rtcs_manager[i].soft_rtc_num = rtc_info.rtc_num;
349 g_rtcs_manager[i].rtcs = (rtc_info_t *)rtc_info.rtc_addr;
350 }
351
352 g_rtc_inited = true;
353 osal_irq_restore(irq_sts);
354 return ERRCODE_SUCC;
355 }
356
uapi_rtc_adapter(rtc_index_t index,uint32_t int_id,uint16_t int_priority)357 errcode_t uapi_rtc_adapter(rtc_index_t index, uint32_t int_id, uint16_t int_priority)
358 {
359 if (unlikely(index >= RTC_MAX_NUM)) {
360 return ERRCODE_INVALID_PARAM;
361 }
362
363 uint32_t irq_sts = osal_irq_lock();
364 if (unlikely(g_rtc_inited == 0)) {
365 osal_irq_restore(irq_sts);
366 return ERRCODE_RTC_NOT_INITED;
367 }
368
369 if (unlikely(g_rtc_adapted[index] != 0)) {
370 osal_irq_restore(irq_sts);
371 return ERRCODE_SUCC;
372 }
373
374 errcode_t ret = hal_rtc_init(index, rtc_int_callback);
375 if (ret != ERRCODE_SUCC) {
376 osal_irq_restore(irq_sts);
377 return ret;
378 }
379
380 rtc_port_register_irq(index, int_id, int_priority);
381
382 g_rtcs_manager[index].rtc_irq_id = int_id;
383 g_rtcs_manager[index].rtc_int_priority = int_priority;
384
385 g_rtc_adapted[index] = true;
386 osal_irq_restore(irq_sts);
387
388 return ERRCODE_SUCC;
389 }
390
uapi_rtc_deinit(void)391 errcode_t uapi_rtc_deinit(void)
392 {
393 uint32_t irq_sts = osal_irq_lock();
394 if (unlikely(!g_rtc_inited)) {
395 osal_irq_restore(irq_sts);
396 return ERRCODE_SUCC;
397 }
398
399 for (uint32_t i = 0; i < CONFIG_RTC_MAX_NUM; i++) {
400 if (g_rtc_adapted[i]) {
401 hal_rtc_stop(i);
402 rtc_port_unregister_irq(i, g_rtcs_manager[i].rtc_irq_id);
403 }
404 }
405
406 if (unlikely(memset_s(&g_rtcs_manager, sizeof(g_rtcs_manager), 0, sizeof(g_rtcs_manager)) != EOK)) {
407 osal_irq_restore(irq_sts);
408 return ERRCODE_MEMSET;
409 }
410
411 for (uint32_t i = 0; i < CONFIG_RTC_MAX_NUM; i++) {
412 if (g_rtc_adapted[i]) {
413 hal_rtc_deinit(i);
414 }
415 }
416
417 g_rtc_inited = false;
418 for (uint32_t i = 0; i < CONFIG_RTC_MAX_NUM; i++) {
419 g_rtc_adapted[i] = false;
420 }
421 osal_irq_restore(irq_sts);
422 return ERRCODE_SUCC;
423 }
424
uapi_rtc_create(rtc_index_t index,rtc_handle_t * rtc)425 errcode_t uapi_rtc_create(rtc_index_t index, rtc_handle_t *rtc)
426 {
427 if (unlikely(index >= RTC_MAX_NUM || rtc == NULL)) {
428 return ERRCODE_INVALID_PARAM;
429 }
430
431 uint32_t irq_sts = osal_irq_lock();
432 for (uint32_t i = 0; i < g_rtcs_manager[index].soft_rtc_num; i++) {
433 if (g_rtcs_manager[index].rtcs[i].enable == false) {
434 g_rtcs_manager[index].rtcs[i].enable = true;
435 g_rtcs_manager[index].rtcs[i].is_run = false;
436 g_rtcs_manager[index].rtcs[i].index = index;
437 g_rtcs_manager[index].rtcs[i].key = &g_rtcs_manager[index].rtcs[i];
438
439 *rtc = g_rtcs_manager[index].rtcs[i].key;
440 osal_irq_restore(irq_sts);
441 return ERRCODE_SUCC;
442 }
443 }
444
445 *rtc = NULL;
446 osal_irq_restore(irq_sts);
447 return ERRCODE_RTC_NO_ENOUGH;
448 }
449
uapi_rtc_delete(rtc_handle_t rtc)450 errcode_t uapi_rtc_delete(rtc_handle_t rtc)
451 {
452 if (unlikely(rtc == NULL)) {
453 return ERRCODE_INVALID_PARAM;
454 }
455
456 rtc_info_t *rtc_info = (rtc_info_t *)rtc;
457 uint32_t irq_sts = osal_irq_lock();
458 rtc_info->enable = false;
459 osal_irq_restore(irq_sts);
460 return ERRCODE_SUCC;
461 }
462
uapi_rtc_get_max_ms(void)463 uint32_t uapi_rtc_get_max_ms(void)
464 {
465 return RTC_MAX_MS;
466 }
467
uapi_rtc_start(rtc_handle_t rtc,uint32_t rtc_ms,rtc_callback_t callback,uintptr_t data)468 errcode_t uapi_rtc_start(rtc_handle_t rtc, uint32_t rtc_ms, rtc_callback_t callback, uintptr_t data)
469 {
470 rtc_index_t index;
471 uint32_t rtc_max_ms = RTC_MAX_MS;
472 if (unlikely(rtc == NULL) || unlikely(callback == NULL) || unlikely(rtc_ms == 0) || unlikely(rtc_ms > rtc_max_ms)) {
473 return ERRCODE_INVALID_PARAM;
474 }
475
476 rtc_info_t *rtc_info = (rtc_info_t *)rtc;
477 uint32_t irq_sts = osal_irq_lock();
478 if (unlikely(rtc_info->enable == false)) {
479 osal_irq_restore(irq_sts);
480 return ERRCODE_RTC_NOT_CREATED;
481 }
482
483 uint64_t cycle;
484 int32_t cycle_deviation = 0;
485 index = rtc_info->index;
486 cycle = rtc_get_cycle_with_mask(index, rtc_porting_ms_2_cycle(rtc_ms), &cycle_deviation);
487 rtc_info->cycle = cycle;
488 rtc_info->callback = callback;
489 rtc_info->data = data;
490
491 uint64_t remain_rtc_cycle = rtc_get_rtc_till_interrupt(index);
492 if (cycle <= remain_rtc_cycle) {
493 if (remain_rtc_cycle != UINT64_MAX && g_rtcs_manager[index].last_rtc_load_cycle != 0) {
494 rtc_update_rtcs_rtc(index, g_rtcs_manager[index].last_rtc_load_cycle - remain_rtc_cycle);
495 }
496 g_rtcs_manager[index].last_rtc_load_cycle = cycle;
497 hal_rtc_stop(index);
498 rtc_load_cycle_with_mask(index, cycle, cycle_deviation);
499 hal_rtc_start(index);
500 } else {
501 rtc_info->cycle += (g_rtcs_manager[index].last_rtc_load_cycle - remain_rtc_cycle);
502 }
503
504 rtc_info->is_run = true;
505 osal_irq_restore(irq_sts);
506 return ERRCODE_SUCC;
507 }
508
uapi_rtc_stop(rtc_handle_t rtc)509 errcode_t uapi_rtc_stop(rtc_handle_t rtc)
510 {
511 if (unlikely(rtc == NULL)) {
512 return ERRCODE_INVALID_PARAM;
513 }
514
515 rtc_info_t *rtc_info = (rtc_info_t *)rtc;
516
517 uint32_t irq_sts = osal_irq_lock();
518 if (unlikely(rtc_info->enable == false)) {
519 osal_irq_restore(irq_sts);
520 return ERRCODE_RTC_NOT_CREATED;
521 }
522
523 if (unlikely(rtc_info->is_run == false)) {
524 osal_irq_restore(irq_sts);
525 return ERRCODE_SUCC;
526 }
527
528 rtc_info->is_run = false;
529 rtc_info->cycle = 0;
530 rtc_info->callback = NULL;
531 rtc_info->data = 0;
532
533 /* 检查当前是否还有在运行的定时器, 若没有定时器则停止硬件计时 */
534 rtc_index_t index = rtc_info->index;
535 uint32_t rtc_found = rtc_get_next_rtc(index);
536 if (rtc_found >= g_rtcs_manager[index].soft_rtc_num) {
537 hal_rtc_stop(index);
538 }
539 osal_irq_restore(irq_sts);
540 return ERRCODE_SUCC;
541 }
542
uapi_rtc_int_cnt_record_get(rtc_index_t index)543 uint32_t uapi_rtc_int_cnt_record_get(rtc_index_t index)
544 {
545 if (unlikely(index >= RTC_MAX_NUM)) {
546 return 0;
547 }
548
549 uint32_t int_cnt_record = hal_rtc_get_int_cnt_record();
550 return int_cnt_record;
551 }
552
uapi_rtc_get_current_time_count(rtc_index_t index,uint64_t * current_time_count)553 errcode_t uapi_rtc_get_current_time_count(rtc_index_t index, uint64_t *current_time_count)
554 {
555 if (unlikely(index >= RTC_MAX_NUM || current_time_count == NULL)) {
556 return ERRCODE_INVALID_PARAM;
557 }
558
559 uint32_t irq_sts = osal_irq_lock();
560 uint64_t current_value = hal_rtc_get_current_value(index);
561 osal_irq_restore(irq_sts);
562 *current_time_count = current_value;
563 return ERRCODE_SUCC;
564 }
565
uapi_rtc_get_current_time_us(rtc_index_t index,uint32_t * current_time_us)566 errcode_t uapi_rtc_get_current_time_us(rtc_index_t index, uint32_t *current_time_us)
567 {
568 if (unlikely(index >= RTC_MAX_NUM || current_time_us == NULL)) {
569 return ERRCODE_INVALID_PARAM;
570 }
571
572 uint32_t irq_sts = osal_irq_lock();
573 uint64_t current_value = hal_rtc_get_current_value(index);
574 osal_irq_restore(irq_sts);
575 *current_time_us = rtc_porting_cycle_2_us(current_value);
576 return ERRCODE_SUCC;
577 }
578
uapi_rtc_start_hw_rtc(rtc_index_t index,uint64_t rtc_ms)579 errcode_t uapi_rtc_start_hw_rtc(rtc_index_t index, uint64_t rtc_ms)
580 {
581 if (unlikely(index >= RTC_MAX_NUM)) {
582 return ERRCODE_INVALID_PARAM;
583 }
584
585 uint64_t rtc_max_ms = RTC_HW_MAX_MS;
586 if (unlikely(rtc_ms == 0) || unlikely(rtc_ms > rtc_max_ms)) {
587 return ERRCODE_INVALID_PARAM;
588 }
589
590 uint32_t irq_sts = osal_irq_lock();
591 hal_rtc_stop(index);
592 #if defined(CONFIG_RTC_USING_OLD_VERSION)
593 hal_rtc_config_load(index, rtc_hw_porting_ms_2_cycle(rtc_ms) | RTC_OLD_VERSION_LOAD_COUNT_MASK);
594 #else
595 hal_rtc_config_load(index, rtc_hw_porting_ms_2_cycle(rtc_ms));
596 #endif
597 hal_rtc_start(index);
598 osal_irq_restore(irq_sts);
599
600 return ERRCODE_SUCC;
601 }
602
uapi_rtc_stop_hw_rtc(rtc_index_t index)603 errcode_t uapi_rtc_stop_hw_rtc(rtc_index_t index)
604 {
605 if (unlikely(index >= RTC_MAX_NUM)) {
606 return ERRCODE_INVALID_PARAM;
607 }
608
609 uint32_t irq_sts = osal_irq_lock();
610 hal_rtc_stop(index);
611 osal_irq_restore(irq_sts);
612
613 return ERRCODE_SUCC;
614 }
615
616 #if defined(CONFIG_RTC_SUPPORT_LPM)
uapi_rtc_get_latest_timeout(void)617 uint32_t uapi_rtc_get_latest_timeout(void)
618 {
619 uint64_t nxt_count = UINT64_MAX;
620 uint64_t cur_count = UINT64_MAX;
621 for (uint32_t index = 0; index < RTC_MAX_NUM; index++) {
622 if (g_rtc_adapted[index] == false) {
623 continue;
624 }
625 cur_count = hal_rtc_get_current_value(index);
626 /* 值为0分为两种情况:timer已全部过期或在功耗调度中到期,可通过中断状态区分。前者视为超时时间为U64最大值 */
627 if (cur_count == 0 && hal_rtc_get_int_status(index) == 0) {
628 cur_count = UINT64_MAX;
629 }
630 nxt_count = cur_count < nxt_count ? cur_count : nxt_count;
631 }
632 uint32_t nxt_ms = rtc_porting_cycle_2_ms(nxt_count);
633 return nxt_ms;
634 }
635
uapi_rtc_suspend(uintptr_t val)636 errcode_t uapi_rtc_suspend(uintptr_t val)
637 {
638 unused(val);
639 uint32_t int_sts = osal_irq_lock();
640 for (uint32_t index = 0; index < RTC_MAX_NUM; index++) {
641 if (g_rtc_adapted[index] == false) {
642 continue;
643 }
644 rtc_update_rtcs_rtc(index,
645 g_rtcs_manager[index].last_rtc_load_cycle - hal_rtc_get_current_value(index));
646 g_rtcs_manager[index].last_rtc_load_cycle = 0;
647 rtc_set_next_rtc_interrupt(index);
648 }
649 osal_irq_restore(int_sts);
650 return ERRCODE_SUCC;
651 }
652
uapi_rtc_resume(uintptr_t val)653 errcode_t uapi_rtc_resume(uintptr_t val)
654 {
655 uint32_t int_sts = osal_irq_lock();
656 uint64_t compansation_count = *(uint64_t *)val;
657 for (uint32_t index = 0; index < RTC_MAX_NUM; index++) {
658 if (g_rtc_adapted[index] == false) {
659 continue;
660 }
661 g_rtcs_manager[index].last_rtc_load_cycle = compansation_count;
662 hal_rtc_stop(index);
663 hal_rtc_config_load(index, rtc_porting_ms_2_cycle(1));
664 hal_rtc_start(index);
665 }
666 osal_irq_restore(int_sts);
667 return ERRCODE_SUCC;
668 }
669 #endif /* CONFIG_RTC_SUPPORT_LPM */