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
16 #include "device_resource_if.h"
17 #include "hdf_device_desc.h"
18 #include "hdf_log.h"
19 #include "osal_io.h"
20 #include "osal_irq.h"
21 #include "osal_mem.h"
22 #include "osal_time.h"
23 #include "rtc_base.h"
24 #include "rtc_core.h"
25 #include "rtc_hi35xx.h"
26
27 #define HDF_LOG_TAG rtc_hi35xx
28
29 static uint8_t g_usrRegAddr[REG_INDEX_MAX_VAL] = {
30 RTC_USER_REG1, RTC_USER_REG2, RTC_USER_REG3, RTC_USER_REG4,
31 RTC_USER_REG5, RTC_USER_REG6, RTC_USER_REG7, RTC_USER_REG8,
32 };
33
HiSpiRead(struct RtcConfigInfo * rtcInfo,uint8_t regAdd,uint8_t * value)34 static uint32_t HiSpiRead(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t *value)
35 {
36 uint16_t cnt = RETRY_CNT;
37 union RtcSpiConfig readConfig;
38 union RtcSpiConfig writeConfig;
39
40 readConfig.data = 0;
41 writeConfig.data = 0;
42 writeConfig.bits.spiAddr = regAdd;
43 writeConfig.bits.spiOperateType = RTC_SPI_READ;
44 writeConfig.bits.spiStart = RTC_TRUE;
45 OSAL_WRITEL(writeConfig.data, RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
46
47 do {
48 readConfig.data = OSAL_READL(RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
49 --cnt;
50 } while ((readConfig.bits.spiBusy == RTC_TRUE) && (cnt != 0));
51
52 if (readConfig.bits.spiBusy == RTC_TRUE) {
53 HDF_LOGE("HiRtcSpiRead: spi busy!");
54 return RTC_ERROR_READ_BUSY;
55 }
56
57 *value = readConfig.bits.spiReadData;
58 return HDF_SUCCESS;
59 }
60
HiRtcSpiRead(struct RtcConfigInfo * rtcInfo,uint8_t regAdd,uint8_t * value)61 static uint32_t HiRtcSpiRead(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t *value)
62 {
63 uint32_t ret;
64 OsalMutexLock(&rtcInfo->mutex);
65 ret = HiSpiRead(rtcInfo, regAdd, value);
66 OsalMutexUnlock(&rtcInfo->mutex);
67 return ret;
68 }
69
HiSpiWrite(struct RtcConfigInfo * rtcInfo,uint8_t regAdd,uint8_t value)70 static uint32_t HiSpiWrite(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t value)
71 {
72 uint16_t cnt = RETRY_CNT;
73 union RtcSpiConfig readConfig;
74 union RtcSpiConfig writeConfig;
75
76 readConfig.data = 0;
77 writeConfig.data = 0;
78 writeConfig.bits.spiWriteData = value;
79 writeConfig.bits.spiAddr = regAdd;
80 writeConfig.bits.spiOperateType = RTC_SPI_WRITE;
81 writeConfig.bits.spiStart = RTC_TRUE;
82 OSAL_WRITEL(writeConfig.data, RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
83
84 do {
85 readConfig.data = OSAL_READL(RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
86 --cnt;
87 } while ((readConfig.bits.spiBusy == RTC_TRUE) && (cnt != 0));
88
89 if (readConfig.bits.spiBusy == RTC_TRUE) {
90 HDF_LOGE("HiRtcSpiWrite: spi busy!");
91 return RTC_ERROR_WRITE_BUSY;
92 }
93
94 return HDF_SUCCESS;
95 }
96
HiRtcSpiWrite(struct RtcConfigInfo * rtcInfo,uint8_t regAdd,uint8_t value)97 static uint32_t HiRtcSpiWrite(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t value)
98 {
99 uint32_t ret;
100 OsalMutexLock(&rtcInfo->mutex);
101 ret = HiSpiWrite(rtcInfo, regAdd, value);
102 OsalMutexUnlock(&rtcInfo->mutex);
103 return ret;
104 }
105
HiRtcReadTimeData(struct RtcConfigInfo * rtcInfo,struct RtcTimeReg * regAddr,struct RtcTime * time)106 static int32_t HiRtcReadTimeData(struct RtcConfigInfo *rtcInfo, struct RtcTimeReg *regAddr, struct RtcTime *time)
107 {
108 uint64_t seconds;
109 uint32_t ret;
110 uint8_t millisecond = 0;
111 uint8_t dayLow;
112 uint8_t dayHigh;
113 uint8_t second;
114 uint8_t minute;
115 uint8_t hour;
116 uint16_t day;
117
118 if (regAddr == NULL || time == NULL) {
119 HDF_LOGE("HiRtcReadTimeData: para is null!");
120 return HDF_ERR_INVALID_OBJECT;
121 }
122
123 ret = HiRtcSpiRead(rtcInfo, regAddr->millisecondAddr, &millisecond);
124 if (ret != 0) {
125 return HDF_FAILURE;
126 }
127 time->millisecond = millisecond * MS_OF_ACCURACY;
128 ret = HiRtcSpiRead(rtcInfo, regAddr->secondAddr, &second);
129 if (ret != 0) {
130 return HDF_FAILURE;
131 }
132 ret = HiRtcSpiRead(rtcInfo, regAddr->minuteAddr, &minute);
133 if (ret != 0) {
134 return HDF_FAILURE;
135 }
136 ret = HiRtcSpiRead(rtcInfo, regAddr->hourAddr, &hour);
137 if (ret != 0) {
138 return HDF_FAILURE;
139 }
140 ret = HiRtcSpiRead(rtcInfo, regAddr->dayLowAddr, &dayLow);
141 if (ret != 0) {
142 return HDF_FAILURE;
143 }
144 ret = HiRtcSpiRead(rtcInfo, regAddr->dayHighAddr, &dayHigh);
145 if (ret != 0) {
146 return HDF_FAILURE;
147 }
148
149 day = (uint16_t)(dayLow | (dayHigh << SHIFT_BYTE)); /* 8:[15:8] for day high bit */
150 seconds = (uint64_t)second + (uint64_t)minute * RTC_TIME_UNIT + (uint64_t)hour * RTC_TIME_UNIT * RTC_TIME_UNIT +
151 (uint64_t)day * RTC_DAY_SECONDS;
152 TimestampToRtcTime(time, seconds);
153
154 return HDF_SUCCESS;
155 }
156
HiRtcReadPreviousConfig(struct RtcConfigInfo * rtcInfo)157 static uint32_t HiRtcReadPreviousConfig(struct RtcConfigInfo *rtcInfo)
158 {
159 uint32_t ret;
160 uint8_t value = 0;
161
162 ret = HiRtcSpiRead(rtcInfo, RTC_INT_RAW, &value);
163 if (ret != HDF_SUCCESS) {
164 HDF_LOGE("HiRtcReadPreviousConfig: read fail!");
165 return ret;
166 }
167
168 if (value & RTC_INT_RAW_MASK) {
169 HDF_LOGW("low voltage detected, date/time is not reliable");
170 }
171
172 ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
173 if (ret != HDF_SUCCESS) {
174 return ret;
175 }
176
177 if (value & RTC_LOCK_BYPASS_MASK) {
178 ret = HiRtcSpiWrite(rtcInfo, RTC_LORD, (~(RTC_LOCK_BYPASS_MASK)) & value);
179 if (ret != HDF_SUCCESS) {
180 return ret;
181 }
182 }
183
184 ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
185 if (ret != HDF_SUCCESS) {
186 return ret;
187 }
188
189 ret = HiRtcSpiWrite(rtcInfo, RTC_LORD, (value | RTC_LOCK_MASK));
190 if (ret != HDF_SUCCESS) {
191 HDF_LOGE("HiRtcReadPreviousConfig: write fail!");
192 return ret;
193 }
194 return HDF_SUCCESS;
195 }
196
HiRtcReadTime(struct RtcHost * host,struct RtcTime * time)197 static int32_t HiRtcReadTime(struct RtcHost *host, struct RtcTime *time)
198 {
199 uint32_t ret;
200 uint16_t cnt = RETRY_CNT;
201 uint8_t value;
202 struct RtcTimeReg regAddr;
203 struct RtcConfigInfo *rtcInfo = NULL;
204
205 if (host == NULL || host->data == NULL) {
206 HDF_LOGE("HiRtcReadTime: host is null!");
207 return HDF_ERR_INVALID_OBJECT;
208 }
209
210 rtcInfo = (struct RtcConfigInfo *)host->data;
211 ret = HiRtcReadPreviousConfig(rtcInfo);
212 if (ret != HDF_SUCCESS) {
213 HDF_LOGE("HiRtcReadTime: previous config fail!");
214 return HDF_FAILURE;
215 }
216
217 do {
218 ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
219 OsalMSleep(1);
220 --cnt;
221 } while (((ret != HDF_SUCCESS) || ((value & RTC_LOCK_MASK) == RTC_LOCK_MASK)) && (cnt != 0));
222
223 if ((ret == HDF_SUCCESS) && ((value & RTC_LOCK_MASK) == RTC_LOCK_MASK)) {
224 return HDF_ERR_DEVICE_BUSY;
225 }
226
227 regAddr.millisecondAddr = RTC_10MS_COUN;
228 regAddr.secondAddr = RTC_S_COUNT;
229 regAddr.minuteAddr = RTC_M_COUNT;
230 regAddr.hourAddr = RTC_H_COUNT;
231 regAddr.dayLowAddr = RTC_D_COUNT_L;
232 regAddr.dayHighAddr = RTC_D_COUNT_H;
233 return HiRtcReadTimeData(rtcInfo, ®Addr, time);
234 }
235
HiRtcWriteTimeData(struct RtcConfigInfo * rtcInfo,struct RtcTimeReg * regAddr,const struct RtcTime * time)236 static int32_t HiRtcWriteTimeData(struct RtcConfigInfo *rtcInfo, struct RtcTimeReg *regAddr, const struct RtcTime *time)
237 {
238 uint64_t seconds;
239 uint32_t ret;
240 uint16_t day;
241 uint16_t millisecond;
242
243 if (regAddr == NULL || time == NULL) {
244 HDF_LOGE("HiRtcWriteTimeData: para is null!");
245 return HDF_ERR_INVALID_OBJECT;
246 }
247
248 seconds = RtcTimeToTimestamp(time);
249 day = (uint16_t)(seconds / RTC_DAY_SECONDS);
250 millisecond = time->millisecond / MS_OF_ACCURACY;
251
252 ret = HiRtcSpiWrite(rtcInfo, regAddr->millisecondAddr, millisecond);
253 if (ret != 0) {
254 return HDF_FAILURE;
255 }
256 ret = HiRtcSpiWrite(rtcInfo, regAddr->secondAddr, time->second);
257 if (ret != 0) {
258 return HDF_FAILURE;
259 }
260 ret = HiRtcSpiWrite(rtcInfo, regAddr->minuteAddr, time->minute);
261 if (ret != 0) {
262 return HDF_FAILURE;
263 }
264 ret = HiRtcSpiWrite(rtcInfo, regAddr->hourAddr, time->hour);
265 if (ret != 0) {
266 return HDF_FAILURE;
267 }
268 ret = HiRtcSpiWrite(rtcInfo, regAddr->dayLowAddr, (day & 0xFF)); /* 0xFF:mask */
269 if (ret != 0) {
270 return HDF_FAILURE;
271 }
272 ret = HiRtcSpiWrite(rtcInfo, regAddr->dayHighAddr, (day >> SHIFT_BYTE)); /* 8:[15:8] for day high bit */
273 if (ret != 0) {
274 return HDF_FAILURE;
275 }
276
277 return HDF_SUCCESS;
278 }
279
HiRtcWriteTime(struct RtcHost * host,const struct RtcTime * time)280 static int32_t HiRtcWriteTime(struct RtcHost *host, const struct RtcTime *time)
281 {
282 uint32_t ret;
283 uint16_t cnt = RETRY_CNT;
284 uint8_t value = 0;
285 struct RtcTimeReg regAddr;
286 struct RtcConfigInfo *rtcInfo = NULL;
287
288 if (host == NULL || host->data == NULL) {
289 HDF_LOGE("HiRtcWriteTime: host is null!");
290 return HDF_ERR_INVALID_OBJECT;
291 }
292
293 rtcInfo = (struct RtcConfigInfo *)host->data;
294 regAddr.millisecondAddr = RTC_LR_10MS;
295 regAddr.secondAddr = RTC_LR_S;
296 regAddr.minuteAddr = RTC_LR_M;
297 regAddr.hourAddr = RTC_LR_H;
298 regAddr.dayLowAddr = RTC_LR_D_L;
299 regAddr.dayHighAddr = RTC_LR_D_H;
300
301 if (HiRtcWriteTimeData(rtcInfo, ®Addr, time) != HDF_SUCCESS) {
302 HDF_LOGE("HiRtcWriteTime: write time data fail!");
303 return HDF_FAILURE;
304 }
305
306 ret = HiRtcSpiWrite(rtcInfo, RTC_LORD, (value | RTC_LOAD_MASK));
307 if (ret != HDF_SUCCESS) {
308 HDF_LOGE("HiRtcWriteTime: write fail!");
309 return HDF_FAILURE;
310 }
311
312 do {
313 ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
314 OsalMSleep(RTC_WAIT_TIME);
315 --cnt;
316 } while (((ret != HDF_SUCCESS) || ((value & RTC_LOAD_MASK) == RTC_LOAD_MASK)) && (cnt != 0));
317
318 OsalMSleep(RTC_WAIT_TIME);
319
320 if ((ret == HDF_SUCCESS) && ((value & RTC_LOAD_MASK) == RTC_LOAD_MASK)) {
321 HDF_LOGE("HiRtcWriteTime: fail!ret[%d], value[%d]", ret, value);
322 return HDF_ERR_DEVICE_BUSY;
323 }
324
325 return HDF_SUCCESS;
326 }
327
HiReadAlarm(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,struct RtcTime * time)328 static int32_t HiReadAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *time)
329 {
330 struct RtcConfigInfo *rtcInfo = NULL;
331 struct RtcTimeReg regAddr;
332
333 if (host == NULL || host->data == NULL) {
334 HDF_LOGE("HiReadAlarm: host is null!");
335 return HDF_ERR_INVALID_OBJECT;
336 }
337
338 rtcInfo = (struct RtcConfigInfo *)host->data;
339 if (alarmIndex != rtcInfo->alarmIndex) {
340 HDF_LOGE("HiReadAlarm: alarmIndex para error!");
341 return HDF_FAILURE;
342 }
343
344 regAddr.millisecondAddr = RTC_MR_10MS;
345 regAddr.secondAddr = RTC_MR_S;
346 regAddr.minuteAddr = RTC_MR_M;
347 regAddr.hourAddr = RTC_MR_H;
348 regAddr.dayLowAddr = RTC_MR_D_L;
349 regAddr.dayHighAddr = RTC_MR_D_H;
350
351 return HiRtcReadTimeData(rtcInfo, ®Addr, time);
352 }
353
HiWriteAlarm(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,const struct RtcTime * time)354 static int32_t HiWriteAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *time)
355 {
356 struct RtcConfigInfo *rtcInfo = NULL;
357 struct RtcTimeReg regAddr;
358
359 if (host == NULL || host->data == NULL) {
360 HDF_LOGE("WriteAlarm: host is null!");
361 return HDF_ERR_INVALID_OBJECT;
362 }
363
364 rtcInfo = (struct RtcConfigInfo *)host->data;
365 if (alarmIndex != rtcInfo->alarmIndex) {
366 HDF_LOGE("WriteAlarm: alarmIndex para error!");
367 return HDF_ERR_INVALID_PARAM;
368 }
369
370 regAddr.millisecondAddr = RTC_MR_10MS;
371 regAddr.secondAddr = RTC_MR_S;
372 regAddr.minuteAddr = RTC_MR_M;
373 regAddr.hourAddr = RTC_MR_H;
374 regAddr.dayLowAddr = RTC_MR_D_L;
375 regAddr.dayHighAddr = RTC_MR_D_H;
376
377 return HiRtcWriteTimeData(rtcInfo, ®Addr, time);
378 }
379
HiRegisterAlarmCallback(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,RtcAlarmCallback cb)380 static int32_t HiRegisterAlarmCallback(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb)
381 {
382 struct RtcConfigInfo *rtcInfo = NULL;
383
384 if (host == NULL || host->data == NULL || cb == NULL) {
385 HDF_LOGE("HiRegisterAlarmCallback: pointer is null!");
386 return HDF_ERR_INVALID_OBJECT;
387 }
388
389 rtcInfo = (struct RtcConfigInfo *)host->data;
390 if (alarmIndex != rtcInfo->alarmIndex) {
391 HDF_LOGE("HiRegisterAlarmCallback: alarmIndex para error!");
392 return HDF_ERR_INVALID_PARAM;
393 }
394 rtcInfo->cb = cb;
395 return HDF_SUCCESS;
396 }
397
HiAlarmInterruptEnable(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,uint8_t enable)398 static int32_t HiAlarmInterruptEnable(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable)
399 {
400 uint32_t ret;
401 uint8_t value = 0;
402 struct RtcConfigInfo *rtcInfo = NULL;
403
404 if (host == NULL || host->data == NULL || alarmIndex != RTC_ALARM_INDEX_A) {
405 HDF_LOGE("HiAlarmInterruptEnable: para invalid!");
406 return HDF_ERR_INVALID_OBJECT;
407 }
408
409 rtcInfo = (struct RtcConfigInfo *)host->data;
410 if ((enable != RTC_TRUE) && (enable != RTC_FALSE)) {
411 HDF_LOGE("HiAlarmInterruptEnable: enable para error!");
412 return HDF_ERR_INVALID_PARAM;
413 }
414
415 ret = HiRtcSpiRead(rtcInfo, RTC_MSC, &value);
416 if (ret != HDF_SUCCESS) {
417 return ret;
418 }
419
420 if (enable == RTC_TRUE) {
421 ret = HiRtcSpiWrite(rtcInfo, RTC_MSC, (value | RTC_MSC_TIME_MASK));
422 } else {
423 ret = HiRtcSpiWrite(rtcInfo, RTC_MSC, (value & (~RTC_MSC_TIME_MASK)));
424 }
425 if (ret != HDF_SUCCESS) {
426 return HDF_FAILURE;
427 }
428
429 return HDF_SUCCESS;
430 }
431
HiGetFreq(struct RtcHost * host,uint32_t * freq)432 static int32_t HiGetFreq(struct RtcHost *host, uint32_t *freq)
433 {
434 uint32_t ret;
435 uint16_t value;
436 uint8_t lowFreq = 0;
437 uint8_t highFreq = 0;
438 struct RtcConfigInfo *rtcInfo = NULL;
439
440 if (host == NULL || host->data == NULL || freq == NULL) {
441 HDF_LOGE("HiReadFreq: host is null!");
442 return HDF_ERR_INVALID_OBJECT;
443 }
444
445 rtcInfo = (struct RtcConfigInfo *)host->data;
446 ret = HiRtcSpiRead(rtcInfo, RTC_FREQ_H, &highFreq);
447 ret |= HiRtcSpiRead(rtcInfo, RTC_FREQ_L, &lowFreq);
448 if (ret != HDF_SUCCESS) {
449 return HDF_FAILURE;
450 }
451
452 value = ((highFreq & 0x0f) << SHIFT_BYTE) + lowFreq; /* 8:[12:8] for freq_h bit */
453 *freq = FREQ_DIFF + (value * FREQ_UNIT) / FREQ_COEFFICIENT; /* freq convert: 3270000+(freq*10000)/3052 */
454 return HDF_SUCCESS;
455 }
456
HiSetFreq(struct RtcHost * host,uint32_t freq)457 static int32_t HiSetFreq(struct RtcHost *host, uint32_t freq)
458 {
459 uint32_t ret;
460 uint8_t lowFreq;
461 uint8_t highFreq;
462 struct RtcConfigInfo *rtcInfo = NULL;
463
464 if (host == NULL || host->data == NULL) {
465 HDF_LOGE("HiWriteFreq: host is null!");
466 return HDF_ERR_INVALID_OBJECT;
467 }
468
469 freq *= FREQ_ROUND_OFF_NUMBER;
470 if (freq > FREQ_MAX_VAL || freq < FREQ_MIN_VAL) {
471 HDF_LOGE("HiWriteFreq: para error!");
472 return HDF_ERR_INVALID_PARAM;
473 }
474
475 freq = (freq - FREQ_DIFF) * FREQ_COEFFICIENT / FREQ_UNIT; /* freq convert: (freq-3270000)*3052/10000 */
476 lowFreq = (freq & 0xff); /* 8:[7:0] for freq low */
477 highFreq = ((freq >> SHIFT_BYTE) & 0xf); /* 8:[12:8] for freq high */
478
479 rtcInfo = (struct RtcConfigInfo *)host->data;
480 ret = HiRtcSpiWrite(rtcInfo, RTC_FREQ_H, highFreq);
481 ret |= HiRtcSpiWrite(rtcInfo, RTC_FREQ_L, lowFreq);
482 if (ret != HDF_SUCCESS) {
483 return HDF_FAILURE;
484 }
485
486 return HDF_SUCCESS;
487 }
488
HiReset(struct RtcHost * host)489 static int32_t HiReset(struct RtcHost *host)
490 {
491 uint32_t ret;
492 struct RtcConfigInfo *rtcInfo = NULL;
493
494 if (host == NULL || host->data == NULL) {
495 HDF_LOGE("HiReset: host is null!");
496 return HDF_ERR_INVALID_OBJECT;
497 }
498
499 rtcInfo = (struct RtcConfigInfo *)host->data;
500 ret = HiRtcSpiWrite(rtcInfo, RTC_POR_N, 0);
501 if (ret != HDF_SUCCESS) {
502 HDF_LOGE("HiReset: write por fail!");
503 return HDF_FAILURE;
504 }
505
506 ret = HiRtcSpiWrite(rtcInfo, RTC_CLK, RTC_CLK_OUT_SEL);
507 if (ret != HDF_SUCCESS) {
508 HDF_LOGE("HiReset: write clk fail!");
509 return HDF_FAILURE;
510 }
511 return HDF_SUCCESS;
512 }
513
HiReadReg(struct RtcHost * host,uint8_t usrDefIndex,uint8_t * value)514 static int32_t HiReadReg(struct RtcHost *host, uint8_t usrDefIndex, uint8_t *value)
515 {
516 struct RtcConfigInfo *rtcInfo = NULL;
517
518 if (host == NULL || host->data == NULL || value == NULL) {
519 HDF_LOGE("HiReadReg: host is null!");
520 return HDF_ERR_INVALID_OBJECT;
521 }
522
523 if (usrDefIndex >= REG_INDEX_MAX_VAL) {
524 HDF_LOGE("HiReadReg: index error!");
525 return HDF_ERR_INVALID_PARAM;
526 }
527
528 rtcInfo = (struct RtcConfigInfo *)host->data;
529 return HiRtcSpiRead(rtcInfo, g_usrRegAddr[usrDefIndex], value);
530 }
531
HiWriteReg(struct RtcHost * host,uint8_t usrDefIndex,uint8_t value)532 static int32_t HiWriteReg(struct RtcHost *host, uint8_t usrDefIndex, uint8_t value)
533 {
534 struct RtcConfigInfo *rtcInfo = NULL;
535
536 if (host == NULL || host->data == NULL) {
537 HDF_LOGE("HiWriteReg: host is null!");
538 return HDF_ERR_INVALID_OBJECT;
539 }
540
541 if (usrDefIndex >= REG_INDEX_MAX_VAL) {
542 HDF_LOGE("HiWriteReg: index error!");
543 return HDF_ERR_INVALID_PARAM;
544 }
545
546 rtcInfo = (struct RtcConfigInfo *)host->data;
547 return HiRtcSpiWrite(rtcInfo, g_usrRegAddr[usrDefIndex], value);
548 }
549
550 static struct RtcMethod g_method = {
551 .ReadTime = HiRtcReadTime,
552 .WriteTime = HiRtcWriteTime,
553 .ReadAlarm = HiReadAlarm,
554 .WriteAlarm = HiWriteAlarm,
555 .RegisterAlarmCallback = HiRegisterAlarmCallback,
556 .AlarmInterruptEnable = HiAlarmInterruptEnable,
557 .GetFreq = HiGetFreq,
558 .SetFreq = HiSetFreq,
559 .Reset = HiReset,
560 .ReadReg = HiReadReg,
561 .WriteReg = HiWriteReg,
562 };
563
HiRtcAttachConfigData(struct RtcConfigInfo * rtcInfo,const struct DeviceResourceNode * node)564 static int32_t HiRtcAttachConfigData(struct RtcConfigInfo *rtcInfo, const struct DeviceResourceNode *node)
565 {
566 int32_t ret;
567 uint32_t value;
568 struct DeviceResourceIface *drsOps = NULL;
569
570 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
571 if (node == NULL || drsOps == NULL || drsOps->GetUint32 == NULL) {
572 HDF_LOGE("%s: node null!", __func__);
573 return HDF_FAILURE;
574 }
575
576 if (rtcInfo->supportAnaCtrl == RTC_FEATURE_SUPPORT) {
577 ret = drsOps->GetUint32(node, "anaCtrlAddr", &value, 0);
578 if (ret != HDF_SUCCESS) {
579 HDF_LOGE("%s: read anaCtrlAddr fail!", __func__);
580 return ret;
581 }
582 rtcInfo->anaCtrlAddr = (uint8_t)value;
583 }
584
585 if (rtcInfo->supportLock == RTC_FEATURE_SUPPORT) {
586 ret = drsOps->GetUint32(node, "lock0Addr", &value, 0);
587 if (ret != HDF_SUCCESS) {
588 return ret;
589 }
590 rtcInfo->lockAddr.lock0Addr = (uint8_t)value;
591 ret = drsOps->GetUint32(node, "lock1Addr", &value, 0);
592 if (ret != HDF_SUCCESS) {
593 return ret;
594 }
595 rtcInfo->lockAddr.lock1Addr = (uint8_t)value;
596 ret = drsOps->GetUint32(node, "lock2Addr", &value, 0);
597 if (ret != HDF_SUCCESS) {
598 return ret;
599 }
600 rtcInfo->lockAddr.lock2Addr = (uint8_t)value;
601 ret = drsOps->GetUint32(node, "lock3Addr", &value, 0);
602 if (ret != HDF_SUCCESS) {
603 return ret;
604 }
605 rtcInfo->lockAddr.lock3Addr = (uint8_t)value;
606 }
607 return HDF_SUCCESS;
608 }
609
HiRtcConfigData(struct RtcConfigInfo * rtcInfo,const struct DeviceResourceNode * node)610 static int32_t HiRtcConfigData(struct RtcConfigInfo *rtcInfo, const struct DeviceResourceNode *node)
611 {
612 int32_t ret;
613 uint32_t value;
614 struct DeviceResourceIface *drsOps = NULL;
615
616 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
617 if (drsOps == NULL || drsOps->GetBool == NULL || drsOps->GetUint32 == NULL) {
618 HDF_LOGE("%s: invalid drs ops fail!", __func__);
619 return HDF_FAILURE;
620 }
621
622 rtcInfo->supportAnaCtrl = drsOps->GetBool(node, "supportAnaCtrl");
623 rtcInfo->supportLock = drsOps->GetBool(node, "supportLock");
624
625 ret = drsOps->GetUint32(node, "rtcSpiBaseAddr", &rtcInfo->spiBaseAddr, 0);
626 if (ret != HDF_SUCCESS) {
627 HDF_LOGE("%s: read regBase fail!", __func__);
628 return ret;
629 }
630
631 ret = drsOps->GetUint32(node, "regAddrLength", &value, 0);
632 if (ret != HDF_SUCCESS) {
633 HDF_LOGE("%s: read Length fail!", __func__);
634 return ret;
635 }
636 rtcInfo->regAddrLength = (uint16_t)value;
637
638 ret = drsOps->GetUint32(node, "irq", &value, 0);
639 if (ret != HDF_SUCCESS) {
640 HDF_LOGE("%s: read irq fail!", __func__);
641 return ret;
642 }
643 rtcInfo->irq = (uint8_t)value;
644 ret = HiRtcAttachConfigData(rtcInfo, node);
645 if (ret != HDF_SUCCESS) {
646 HDF_LOGE("%s: read config data fail!", __func__);
647 return ret;
648 }
649
650 rtcInfo->alarmIndex = RTC_ALARM_INDEX_A;
651 rtcInfo->remapBaseAddr = NULL;
652 return HDF_SUCCESS;
653 }
654
HiRtcIrqHandle(uint32_t irqId,void * data)655 static uint32_t HiRtcIrqHandle(uint32_t irqId, void *data)
656 {
657 uint8_t value = 0;
658 uint32_t ret;
659 struct RtcConfigInfo *rtcInfo = NULL;
660
661 UNUSED(irqId);
662 rtcInfo = (struct RtcConfigInfo *)data;
663 if (rtcInfo == NULL) {
664 return RTC_ERROR_NULL;
665 }
666
667 ret = HiSpiRead(rtcInfo, RTC_INT, &value);
668 if (ret != HDF_SUCCESS) {
669 return RTC_ERROR_READ_FAIL;
670 }
671
672 ret = HiSpiWrite(rtcInfo, RTC_INT_CLR, RTC_INT_CLR_MASK);
673 if (ret != HDF_SUCCESS) {
674 return RTC_ERROR_WRITE_FAIL;
675 }
676 if (rtcInfo->cb == NULL) {
677 return RTC_ERROR_NULL;
678 }
679
680 if (value & RTC_INT_MASK) {
681 return rtcInfo->cb(rtcInfo->alarmIndex);
682 }
683
684 if (value & RTC_INT_UV_MASK) {
685 HiSpiRead(rtcInfo, RTC_MSC, &value);
686 HiSpiWrite(rtcInfo, RTC_MSC, value & (~RTC_INT_UV_MASK)); /* close low voltage int */
687 }
688 return HDF_SUCCESS;
689 }
690
HiRtcSwInit(struct RtcConfigInfo * rtcInfo)691 static int32_t HiRtcSwInit(struct RtcConfigInfo *rtcInfo)
692 {
693 bool ret = false;
694
695 if (rtcInfo->spiBaseAddr == 0 || (rtcInfo->regAddrLength == 0)) {
696 HDF_LOGE("HiRtcSwInit: para invalid!");
697 return HDF_ERR_INVALID_PARAM;
698 }
699
700 if (OsalMutexInit(&rtcInfo->mutex) != HDF_SUCCESS) {
701 HDF_LOGE("HiRtcSwInit: create mutex fail!");
702 return HDF_FAILURE;
703 }
704
705 if (rtcInfo->remapBaseAddr == NULL) {
706 rtcInfo->remapBaseAddr = (volatile void *)OsalIoRemap((uintptr_t)rtcInfo->spiBaseAddr,
707 rtcInfo->regAddrLength);
708 }
709
710 ret = OsalRegisterIrq(rtcInfo->irq, 0, HiRtcIrqHandle, "rtc_alarm", (void*)rtcInfo);
711 if (ret != 0) {
712 HDF_LOGE("HiRtcSwInit: register irq(%d) fail!", rtcInfo->irq);
713 (void)OsalMutexDestroy(&rtcInfo->mutex);
714 OsalIoUnmap((void*)rtcInfo->remapBaseAddr);
715 rtcInfo->remapBaseAddr = NULL;
716 return HDF_FAILURE;
717 }
718
719 return HDF_SUCCESS;
720 }
721
HiRtcSwExit(struct RtcConfigInfo * rtcInfo)722 static void HiRtcSwExit(struct RtcConfigInfo *rtcInfo)
723 {
724 (void)OsalUnregisterIrq(rtcInfo->irq, (void *)rtcInfo);
725 (void)OsalMutexDestroy(&rtcInfo->mutex);
726
727 if (rtcInfo->remapBaseAddr != NULL) {
728 OsalIoUnmap((void*)rtcInfo->remapBaseAddr);
729 rtcInfo->remapBaseAddr = NULL;
730 }
731 }
732
HiRtcHwAttachInit(struct RtcConfigInfo * rtcInfo)733 static uint32_t HiRtcHwAttachInit(struct RtcConfigInfo *rtcInfo)
734 {
735 uint32_t ret = 0;
736
737 if (rtcInfo->supportAnaCtrl == RTC_FEATURE_SUPPORT) {
738 ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->anaCtrlAddr, RTC_ANA_CTRL_ENABLE);
739 }
740
741 /* Unlock First, Then modify to the default driver capability */
742 if (rtcInfo->supportLock == RTC_FEATURE_SUPPORT) {
743 ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock3Addr, RTC_LOCK_ORDER2);
744 ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock2Addr, RTC_LOCK_ORDER2);
745 ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock1Addr, RTC_LOCK_ORDER1);
746 ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock0Addr, RTC_LOCK_ORDER0);
747 ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->anaCtrlAddr, RTC_ANA_CTRL_ORDER);
748 }
749
750 if (ret != HDF_SUCCESS) {
751 HDF_LOGE("HiRtcHwAttachInit: write config fail");
752 return ret;
753 }
754 return ret;
755 }
756
HiRtcHwInit(struct RtcConfigInfo * rtcInfo)757 static int32_t HiRtcHwInit(struct RtcConfigInfo *rtcInfo)
758 {
759 uint32_t ret = 0;
760 uint8_t value = 0;
761
762 /* clk div value is (apb_clk/spi_clk)/2-1, for asic, apb clk(100MHz), spi_clk(10MHz), so value is 0x4 */
763 OSAL_WRITEL(RTC_CLK_DIV_VALUE, RTC_SPI_CLK_DIV((uintptr_t)rtcInfo->remapBaseAddr));
764 ret |= HiRtcSpiWrite(rtcInfo, RTC_MSC, RTC_MSC_ENABLE);
765 ret |= HiRtcSpiWrite(rtcInfo, RTC_SAR_CTRL, RTC_UV_CTRL_ENABLE);
766 ret |= HiRtcHwAttachInit(rtcInfo);
767 ret |= HiRtcSpiWrite(rtcInfo, RTC_FREQ_H, FREQ_H_DEFAULT);
768 ret |= HiRtcSpiWrite(rtcInfo, RTC_FREQ_L, FREQ_L_DEFAULT);
769 if (ret != HDF_SUCCESS) {
770 HDF_LOGE("RtcHwInit: init fail");
771 return HDF_FAILURE;
772 }
773
774 if (HiRtcSpiRead(rtcInfo, RTC_INT_RAW, &value) != 0) {
775 HDF_LOGW("RtcHwInit: spi read fail");
776 return HDF_FAILURE;
777 }
778
779 if (value & RTC_INT_RAW_MASK) {
780 HDF_LOGW("HiRtcHwInit: low voltage detected, date/time is not reliable");
781 }
782 return HDF_SUCCESS;
783 }
784
HiRtcBind(struct HdfDeviceObject * device)785 static int32_t HiRtcBind(struct HdfDeviceObject *device)
786 {
787 struct RtcHost *host = NULL;
788
789 host = RtcHostCreate(device);
790 if (host == NULL) {
791 HDF_LOGE("HiRtcBind: create host fail!");
792 return HDF_ERR_INVALID_OBJECT;
793 }
794
795 host->device = device;
796 device->service = &host->service;
797 return HDF_SUCCESS;
798 }
799
HiRtcInit(struct HdfDeviceObject * device)800 static int32_t HiRtcInit(struct HdfDeviceObject *device)
801 {
802 struct RtcHost *host = NULL;
803 struct RtcConfigInfo *rtcInfo = NULL;
804
805 if (device == NULL || device->property == NULL) {
806 return HDF_ERR_INVALID_OBJECT;
807 }
808 host = RtcHostFromDevice(device);
809 rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
810 if (rtcInfo == NULL) {
811 HDF_LOGE("HiRtcInit: malloc info fail!");
812 return HDF_ERR_MALLOC_FAIL;
813 }
814
815 if (HiRtcConfigData(rtcInfo, device->property) != 0) {
816 HDF_LOGE("HiRtcInit: hcs config fail!");
817 OsalMemFree(rtcInfo);
818 return HDF_ERR_INVALID_OBJECT;
819 }
820
821 if (HiRtcSwInit(rtcInfo) != 0) {
822 HDF_LOGE("HiRtcInit: sw init fail!");
823 OsalMemFree(rtcInfo);
824 return HDF_DEV_ERR_DEV_INIT_FAIL;
825 }
826
827 if (HiRtcHwInit(rtcInfo) != 0) {
828 HDF_LOGE("HiRtcInit: hw init fail!");
829 HiRtcSwExit(rtcInfo);
830 OsalMemFree(rtcInfo);
831 return HDF_DEV_ERR_DEV_INIT_FAIL;
832 }
833
834 host->method = &g_method;
835 host->data = rtcInfo;
836 HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
837 return HDF_SUCCESS;
838 }
839
HiRtcRelease(struct HdfDeviceObject * device)840 static void HiRtcRelease(struct HdfDeviceObject *device)
841 {
842 struct RtcHost *host = NULL;
843 struct RtcConfigInfo *rtcInfo = NULL;
844
845 if (device == NULL) {
846 return;
847 }
848
849 host = RtcHostFromDevice(device);
850 rtcInfo = (struct RtcConfigInfo *)host->data;
851 if (rtcInfo != NULL) {
852 HiRtcSwExit(rtcInfo);
853 OsalMemFree(rtcInfo);
854 host->data = NULL;
855 }
856 RtcHostDestroy(host);
857 }
858
859 struct HdfDriverEntry g_rtcDriverEntry = {
860 .moduleVersion = 1,
861 .Bind = HiRtcBind,
862 .Init = HiRtcInit,
863 .Release = HiRtcRelease,
864 .moduleName = "HDF_PLATFORM_RTC",
865 };
866
867 HDF_INIT(g_rtcDriverEntry);
868