• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &regAddr, 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, &regAddr, 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, &regAddr, 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, &regAddr, 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