11bd4fe43Sopenharmony_ci/*
21bd4fe43Sopenharmony_ci * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
31bd4fe43Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41bd4fe43Sopenharmony_ci * you may not use this file except in compliance with the License.
51bd4fe43Sopenharmony_ci * You may obtain a copy of the License at
61bd4fe43Sopenharmony_ci *
71bd4fe43Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81bd4fe43Sopenharmony_ci *
91bd4fe43Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101bd4fe43Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111bd4fe43Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121bd4fe43Sopenharmony_ci * See the License for the specific language governing permissions and
131bd4fe43Sopenharmony_ci * limitations under the License.
141bd4fe43Sopenharmony_ci */
151bd4fe43Sopenharmony_ci
161bd4fe43Sopenharmony_ci#include "device_resource_if.h"
171bd4fe43Sopenharmony_ci#include "hdf_device_desc.h"
181bd4fe43Sopenharmony_ci#include "hdf_log.h"
191bd4fe43Sopenharmony_ci#include "osal_io.h"
201bd4fe43Sopenharmony_ci#include "osal_irq.h"
211bd4fe43Sopenharmony_ci#include "osal_mem.h"
221bd4fe43Sopenharmony_ci#include "osal_time.h"
231bd4fe43Sopenharmony_ci#include "rtc_base.h"
241bd4fe43Sopenharmony_ci#include "rtc_core.h"
251bd4fe43Sopenharmony_ci#include "rtc_hi35xx.h"
261bd4fe43Sopenharmony_ci
271bd4fe43Sopenharmony_ci#define HDF_LOG_TAG rtc_hi35xx
281bd4fe43Sopenharmony_ci
291bd4fe43Sopenharmony_cistatic uint8_t g_usrRegAddr[REG_INDEX_MAX_VAL] = {
301bd4fe43Sopenharmony_ci    RTC_USER_REG1, RTC_USER_REG2, RTC_USER_REG3, RTC_USER_REG4,
311bd4fe43Sopenharmony_ci    RTC_USER_REG5, RTC_USER_REG6, RTC_USER_REG7, RTC_USER_REG8,
321bd4fe43Sopenharmony_ci};
331bd4fe43Sopenharmony_ci
341bd4fe43Sopenharmony_cistatic uint32_t HiSpiRead(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t *value)
351bd4fe43Sopenharmony_ci{
361bd4fe43Sopenharmony_ci    uint16_t cnt = RETRY_CNT;
371bd4fe43Sopenharmony_ci    union RtcSpiConfig readConfig;
381bd4fe43Sopenharmony_ci    union RtcSpiConfig writeConfig;
391bd4fe43Sopenharmony_ci
401bd4fe43Sopenharmony_ci    readConfig.data = 0;
411bd4fe43Sopenharmony_ci    writeConfig.data = 0;
421bd4fe43Sopenharmony_ci    writeConfig.bits.spiAddr = regAdd;
431bd4fe43Sopenharmony_ci    writeConfig.bits.spiOperateType = RTC_SPI_READ;
441bd4fe43Sopenharmony_ci    writeConfig.bits.spiStart = RTC_TRUE;
451bd4fe43Sopenharmony_ci    OSAL_WRITEL(writeConfig.data, RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
461bd4fe43Sopenharmony_ci
471bd4fe43Sopenharmony_ci    do {
481bd4fe43Sopenharmony_ci        readConfig.data = OSAL_READL(RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
491bd4fe43Sopenharmony_ci        --cnt;
501bd4fe43Sopenharmony_ci    } while ((readConfig.bits.spiBusy == RTC_TRUE) && (cnt != 0));
511bd4fe43Sopenharmony_ci
521bd4fe43Sopenharmony_ci    if (readConfig.bits.spiBusy == RTC_TRUE) {
531bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcSpiRead: spi busy!");
541bd4fe43Sopenharmony_ci        return RTC_ERROR_READ_BUSY;
551bd4fe43Sopenharmony_ci    }
561bd4fe43Sopenharmony_ci
571bd4fe43Sopenharmony_ci    *value = readConfig.bits.spiReadData;
581bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
591bd4fe43Sopenharmony_ci}
601bd4fe43Sopenharmony_ci
611bd4fe43Sopenharmony_cistatic uint32_t HiRtcSpiRead(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t *value)
621bd4fe43Sopenharmony_ci{
631bd4fe43Sopenharmony_ci    uint32_t ret;
641bd4fe43Sopenharmony_ci    OsalMutexLock(&rtcInfo->mutex);
651bd4fe43Sopenharmony_ci    ret = HiSpiRead(rtcInfo, regAdd, value);
661bd4fe43Sopenharmony_ci    OsalMutexUnlock(&rtcInfo->mutex);
671bd4fe43Sopenharmony_ci    return ret;
681bd4fe43Sopenharmony_ci}
691bd4fe43Sopenharmony_ci
701bd4fe43Sopenharmony_cistatic uint32_t HiSpiWrite(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t value)
711bd4fe43Sopenharmony_ci{
721bd4fe43Sopenharmony_ci    uint16_t cnt = RETRY_CNT;
731bd4fe43Sopenharmony_ci    union RtcSpiConfig readConfig;
741bd4fe43Sopenharmony_ci    union RtcSpiConfig writeConfig;
751bd4fe43Sopenharmony_ci
761bd4fe43Sopenharmony_ci    readConfig.data = 0;
771bd4fe43Sopenharmony_ci    writeConfig.data = 0;
781bd4fe43Sopenharmony_ci    writeConfig.bits.spiWriteData = value;
791bd4fe43Sopenharmony_ci    writeConfig.bits.spiAddr = regAdd;
801bd4fe43Sopenharmony_ci    writeConfig.bits.spiOperateType = RTC_SPI_WRITE;
811bd4fe43Sopenharmony_ci    writeConfig.bits.spiStart = RTC_TRUE;
821bd4fe43Sopenharmony_ci    OSAL_WRITEL(writeConfig.data, RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
831bd4fe43Sopenharmony_ci
841bd4fe43Sopenharmony_ci    do {
851bd4fe43Sopenharmony_ci        readConfig.data = OSAL_READL(RTC_SPI_RW((uintptr_t)rtcInfo->remapBaseAddr));
861bd4fe43Sopenharmony_ci        --cnt;
871bd4fe43Sopenharmony_ci    } while ((readConfig.bits.spiBusy == RTC_TRUE) && (cnt != 0));
881bd4fe43Sopenharmony_ci
891bd4fe43Sopenharmony_ci    if (readConfig.bits.spiBusy == RTC_TRUE) {
901bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcSpiWrite: spi busy!");
911bd4fe43Sopenharmony_ci        return RTC_ERROR_WRITE_BUSY;
921bd4fe43Sopenharmony_ci    }
931bd4fe43Sopenharmony_ci
941bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
951bd4fe43Sopenharmony_ci}
961bd4fe43Sopenharmony_ci
971bd4fe43Sopenharmony_cistatic uint32_t HiRtcSpiWrite(struct RtcConfigInfo *rtcInfo, uint8_t regAdd, uint8_t value)
981bd4fe43Sopenharmony_ci{
991bd4fe43Sopenharmony_ci    uint32_t ret;
1001bd4fe43Sopenharmony_ci    OsalMutexLock(&rtcInfo->mutex);
1011bd4fe43Sopenharmony_ci    ret = HiSpiWrite(rtcInfo, regAdd, value);
1021bd4fe43Sopenharmony_ci    OsalMutexUnlock(&rtcInfo->mutex);
1031bd4fe43Sopenharmony_ci    return ret;
1041bd4fe43Sopenharmony_ci}
1051bd4fe43Sopenharmony_ci
1061bd4fe43Sopenharmony_cistatic int32_t HiRtcReadTimeData(struct RtcConfigInfo *rtcInfo, struct RtcTimeReg *regAddr, struct RtcTime *time)
1071bd4fe43Sopenharmony_ci{
1081bd4fe43Sopenharmony_ci    uint64_t seconds;
1091bd4fe43Sopenharmony_ci    uint32_t ret;
1101bd4fe43Sopenharmony_ci    uint8_t millisecond = 0;
1111bd4fe43Sopenharmony_ci    uint8_t dayLow;
1121bd4fe43Sopenharmony_ci    uint8_t dayHigh;
1131bd4fe43Sopenharmony_ci    uint8_t second;
1141bd4fe43Sopenharmony_ci    uint8_t minute;
1151bd4fe43Sopenharmony_ci    uint8_t hour;
1161bd4fe43Sopenharmony_ci    uint16_t day;
1171bd4fe43Sopenharmony_ci
1181bd4fe43Sopenharmony_ci    if (regAddr == NULL || time == NULL) {
1191bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcReadTimeData: para is null!");
1201bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
1211bd4fe43Sopenharmony_ci    }
1221bd4fe43Sopenharmony_ci
1231bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, regAddr->millisecondAddr, &millisecond);
1241bd4fe43Sopenharmony_ci    if (ret != 0) {
1251bd4fe43Sopenharmony_ci        return HDF_FAILURE;
1261bd4fe43Sopenharmony_ci    }
1271bd4fe43Sopenharmony_ci    time->millisecond = millisecond * MS_OF_ACCURACY;
1281bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, regAddr->secondAddr, &second);
1291bd4fe43Sopenharmony_ci    if (ret != 0) {
1301bd4fe43Sopenharmony_ci        return HDF_FAILURE;
1311bd4fe43Sopenharmony_ci    }
1321bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, regAddr->minuteAddr, &minute);
1331bd4fe43Sopenharmony_ci    if (ret != 0) {
1341bd4fe43Sopenharmony_ci        return HDF_FAILURE;
1351bd4fe43Sopenharmony_ci    }
1361bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, regAddr->hourAddr, &hour);
1371bd4fe43Sopenharmony_ci    if (ret != 0) {
1381bd4fe43Sopenharmony_ci        return HDF_FAILURE;
1391bd4fe43Sopenharmony_ci    }
1401bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, regAddr->dayLowAddr, &dayLow);
1411bd4fe43Sopenharmony_ci    if (ret != 0) {
1421bd4fe43Sopenharmony_ci        return HDF_FAILURE;
1431bd4fe43Sopenharmony_ci    }
1441bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, regAddr->dayHighAddr, &dayHigh);
1451bd4fe43Sopenharmony_ci    if (ret != 0) {
1461bd4fe43Sopenharmony_ci        return HDF_FAILURE;
1471bd4fe43Sopenharmony_ci    }
1481bd4fe43Sopenharmony_ci
1491bd4fe43Sopenharmony_ci    day = (uint16_t)(dayLow | (dayHigh << SHIFT_BYTE)); /* 8:[15:8] for day high bit */
1501bd4fe43Sopenharmony_ci    seconds = (uint64_t)second + (uint64_t)minute * RTC_TIME_UNIT + (uint64_t)hour * RTC_TIME_UNIT * RTC_TIME_UNIT +
1511bd4fe43Sopenharmony_ci        (uint64_t)day * RTC_DAY_SECONDS;
1521bd4fe43Sopenharmony_ci    TimestampToRtcTime(time, seconds);
1531bd4fe43Sopenharmony_ci
1541bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
1551bd4fe43Sopenharmony_ci}
1561bd4fe43Sopenharmony_ci
1571bd4fe43Sopenharmony_cistatic uint32_t HiRtcReadPreviousConfig(struct RtcConfigInfo *rtcInfo)
1581bd4fe43Sopenharmony_ci{
1591bd4fe43Sopenharmony_ci    uint32_t ret;
1601bd4fe43Sopenharmony_ci    uint8_t value = 0;
1611bd4fe43Sopenharmony_ci
1621bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, RTC_INT_RAW, &value);
1631bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1641bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcReadPreviousConfig: read fail!");
1651bd4fe43Sopenharmony_ci        return ret;
1661bd4fe43Sopenharmony_ci    }
1671bd4fe43Sopenharmony_ci
1681bd4fe43Sopenharmony_ci    if (value & RTC_INT_RAW_MASK) {
1691bd4fe43Sopenharmony_ci        HDF_LOGW("low voltage detected, date/time is not reliable");
1701bd4fe43Sopenharmony_ci    }
1711bd4fe43Sopenharmony_ci
1721bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
1731bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1741bd4fe43Sopenharmony_ci        return ret;
1751bd4fe43Sopenharmony_ci    }
1761bd4fe43Sopenharmony_ci
1771bd4fe43Sopenharmony_ci    if (value & RTC_LOCK_BYPASS_MASK) {
1781bd4fe43Sopenharmony_ci        ret = HiRtcSpiWrite(rtcInfo, RTC_LORD, (~(RTC_LOCK_BYPASS_MASK)) & value);
1791bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
1801bd4fe43Sopenharmony_ci            return ret;
1811bd4fe43Sopenharmony_ci        }
1821bd4fe43Sopenharmony_ci    }
1831bd4fe43Sopenharmony_ci
1841bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
1851bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1861bd4fe43Sopenharmony_ci        return ret;
1871bd4fe43Sopenharmony_ci    }
1881bd4fe43Sopenharmony_ci
1891bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, RTC_LORD, (value | RTC_LOCK_MASK));
1901bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1911bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcReadPreviousConfig: write fail!");
1921bd4fe43Sopenharmony_ci        return ret;
1931bd4fe43Sopenharmony_ci    }
1941bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
1951bd4fe43Sopenharmony_ci}
1961bd4fe43Sopenharmony_ci
1971bd4fe43Sopenharmony_cistatic int32_t HiRtcReadTime(struct RtcHost *host, struct RtcTime *time)
1981bd4fe43Sopenharmony_ci{
1991bd4fe43Sopenharmony_ci    uint32_t ret;
2001bd4fe43Sopenharmony_ci    uint16_t cnt = RETRY_CNT;
2011bd4fe43Sopenharmony_ci    uint8_t value;
2021bd4fe43Sopenharmony_ci    struct RtcTimeReg regAddr;
2031bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
2041bd4fe43Sopenharmony_ci
2051bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
2061bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcReadTime: host is null!");
2071bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
2081bd4fe43Sopenharmony_ci    }
2091bd4fe43Sopenharmony_ci
2101bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
2111bd4fe43Sopenharmony_ci    ret = HiRtcReadPreviousConfig(rtcInfo);
2121bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
2131bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcReadTime: previous config fail!");
2141bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2151bd4fe43Sopenharmony_ci    }
2161bd4fe43Sopenharmony_ci
2171bd4fe43Sopenharmony_ci    do {
2181bd4fe43Sopenharmony_ci        ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
2191bd4fe43Sopenharmony_ci        OsalMSleep(1);
2201bd4fe43Sopenharmony_ci        --cnt;
2211bd4fe43Sopenharmony_ci    } while (((ret != HDF_SUCCESS) || ((value & RTC_LOCK_MASK) == RTC_LOCK_MASK)) && (cnt != 0));
2221bd4fe43Sopenharmony_ci
2231bd4fe43Sopenharmony_ci    if ((ret == HDF_SUCCESS) && ((value & RTC_LOCK_MASK) == RTC_LOCK_MASK)) {
2241bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
2251bd4fe43Sopenharmony_ci    }
2261bd4fe43Sopenharmony_ci
2271bd4fe43Sopenharmony_ci    regAddr.millisecondAddr = RTC_10MS_COUN;
2281bd4fe43Sopenharmony_ci    regAddr.secondAddr = RTC_S_COUNT;
2291bd4fe43Sopenharmony_ci    regAddr.minuteAddr = RTC_M_COUNT;
2301bd4fe43Sopenharmony_ci    regAddr.hourAddr = RTC_H_COUNT;
2311bd4fe43Sopenharmony_ci    regAddr.dayLowAddr = RTC_D_COUNT_L;
2321bd4fe43Sopenharmony_ci    regAddr.dayHighAddr = RTC_D_COUNT_H;
2331bd4fe43Sopenharmony_ci    return HiRtcReadTimeData(rtcInfo, &regAddr, time);
2341bd4fe43Sopenharmony_ci}
2351bd4fe43Sopenharmony_ci
2361bd4fe43Sopenharmony_cistatic int32_t HiRtcWriteTimeData(struct RtcConfigInfo *rtcInfo, struct RtcTimeReg *regAddr, const struct RtcTime *time)
2371bd4fe43Sopenharmony_ci{
2381bd4fe43Sopenharmony_ci    uint64_t seconds;
2391bd4fe43Sopenharmony_ci    uint32_t ret;
2401bd4fe43Sopenharmony_ci    uint16_t day;
2411bd4fe43Sopenharmony_ci    uint16_t millisecond;
2421bd4fe43Sopenharmony_ci
2431bd4fe43Sopenharmony_ci    if (regAddr == NULL || time == NULL) {
2441bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcWriteTimeData: para is null!");
2451bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
2461bd4fe43Sopenharmony_ci    }
2471bd4fe43Sopenharmony_ci
2481bd4fe43Sopenharmony_ci    seconds = RtcTimeToTimestamp(time);
2491bd4fe43Sopenharmony_ci    day = (uint16_t)(seconds / RTC_DAY_SECONDS);
2501bd4fe43Sopenharmony_ci    millisecond = time->millisecond / MS_OF_ACCURACY;
2511bd4fe43Sopenharmony_ci
2521bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, regAddr->millisecondAddr, millisecond);
2531bd4fe43Sopenharmony_ci    if (ret != 0) {
2541bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2551bd4fe43Sopenharmony_ci    }
2561bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, regAddr->secondAddr, time->second);
2571bd4fe43Sopenharmony_ci    if (ret != 0) {
2581bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2591bd4fe43Sopenharmony_ci    }
2601bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, regAddr->minuteAddr, time->minute);
2611bd4fe43Sopenharmony_ci    if (ret != 0) {
2621bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2631bd4fe43Sopenharmony_ci    }
2641bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, regAddr->hourAddr, time->hour);
2651bd4fe43Sopenharmony_ci    if (ret != 0) {
2661bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2671bd4fe43Sopenharmony_ci    }
2681bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, regAddr->dayLowAddr, (day & 0xFF)); /* 0xFF:mask */
2691bd4fe43Sopenharmony_ci    if (ret != 0) {
2701bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2711bd4fe43Sopenharmony_ci    }
2721bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, regAddr->dayHighAddr, (day >> SHIFT_BYTE)); /* 8:[15:8] for day high bit */
2731bd4fe43Sopenharmony_ci    if (ret != 0) {
2741bd4fe43Sopenharmony_ci        return HDF_FAILURE;
2751bd4fe43Sopenharmony_ci    }
2761bd4fe43Sopenharmony_ci
2771bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
2781bd4fe43Sopenharmony_ci}
2791bd4fe43Sopenharmony_ci
2801bd4fe43Sopenharmony_cistatic int32_t HiRtcWriteTime(struct RtcHost *host, const struct RtcTime *time)
2811bd4fe43Sopenharmony_ci{
2821bd4fe43Sopenharmony_ci    uint32_t ret;
2831bd4fe43Sopenharmony_ci    uint16_t cnt = RETRY_CNT;
2841bd4fe43Sopenharmony_ci    uint8_t value = 0;
2851bd4fe43Sopenharmony_ci    struct RtcTimeReg regAddr;
2861bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
2871bd4fe43Sopenharmony_ci
2881bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
2891bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcWriteTime: host is null!");
2901bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
2911bd4fe43Sopenharmony_ci    }
2921bd4fe43Sopenharmony_ci
2931bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
2941bd4fe43Sopenharmony_ci    regAddr.millisecondAddr = RTC_LR_10MS;
2951bd4fe43Sopenharmony_ci    regAddr.secondAddr = RTC_LR_S;
2961bd4fe43Sopenharmony_ci    regAddr.minuteAddr = RTC_LR_M;
2971bd4fe43Sopenharmony_ci    regAddr.hourAddr = RTC_LR_H;
2981bd4fe43Sopenharmony_ci    regAddr.dayLowAddr = RTC_LR_D_L;
2991bd4fe43Sopenharmony_ci    regAddr.dayHighAddr = RTC_LR_D_H;
3001bd4fe43Sopenharmony_ci
3011bd4fe43Sopenharmony_ci    if (HiRtcWriteTimeData(rtcInfo, &regAddr, time) != HDF_SUCCESS) {
3021bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcWriteTime: write time data fail!");
3031bd4fe43Sopenharmony_ci        return HDF_FAILURE;
3041bd4fe43Sopenharmony_ci    }
3051bd4fe43Sopenharmony_ci
3061bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, RTC_LORD, (value | RTC_LOAD_MASK));
3071bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
3081bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcWriteTime: write fail!");
3091bd4fe43Sopenharmony_ci        return HDF_FAILURE;
3101bd4fe43Sopenharmony_ci    }
3111bd4fe43Sopenharmony_ci
3121bd4fe43Sopenharmony_ci    do {
3131bd4fe43Sopenharmony_ci        ret = HiRtcSpiRead(rtcInfo, RTC_LORD, &value);
3141bd4fe43Sopenharmony_ci        OsalMSleep(RTC_WAIT_TIME);
3151bd4fe43Sopenharmony_ci        --cnt;
3161bd4fe43Sopenharmony_ci    } while (((ret != HDF_SUCCESS) || ((value & RTC_LOAD_MASK) == RTC_LOAD_MASK)) && (cnt != 0));
3171bd4fe43Sopenharmony_ci
3181bd4fe43Sopenharmony_ci    OsalMSleep(RTC_WAIT_TIME);
3191bd4fe43Sopenharmony_ci
3201bd4fe43Sopenharmony_ci    if ((ret == HDF_SUCCESS) && ((value & RTC_LOAD_MASK) == RTC_LOAD_MASK)) {
3211bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcWriteTime: fail!ret[%u], value[%hhu]", ret, value);
3221bd4fe43Sopenharmony_ci        return HDF_ERR_DEVICE_BUSY;
3231bd4fe43Sopenharmony_ci    }
3241bd4fe43Sopenharmony_ci
3251bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
3261bd4fe43Sopenharmony_ci}
3271bd4fe43Sopenharmony_ci
3281bd4fe43Sopenharmony_cistatic int32_t HiReadAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *time)
3291bd4fe43Sopenharmony_ci{
3301bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
3311bd4fe43Sopenharmony_ci    struct RtcTimeReg regAddr;
3321bd4fe43Sopenharmony_ci
3331bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
3341bd4fe43Sopenharmony_ci        HDF_LOGE("HiReadAlarm: host is null!");
3351bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
3361bd4fe43Sopenharmony_ci    }
3371bd4fe43Sopenharmony_ci
3381bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
3391bd4fe43Sopenharmony_ci    if (alarmIndex != rtcInfo->alarmIndex) {
3401bd4fe43Sopenharmony_ci        HDF_LOGE("HiReadAlarm: alarmIndex para error!");
3411bd4fe43Sopenharmony_ci        return HDF_FAILURE;
3421bd4fe43Sopenharmony_ci    }
3431bd4fe43Sopenharmony_ci
3441bd4fe43Sopenharmony_ci    regAddr.millisecondAddr = RTC_MR_10MS;
3451bd4fe43Sopenharmony_ci    regAddr.secondAddr = RTC_MR_S;
3461bd4fe43Sopenharmony_ci    regAddr.minuteAddr = RTC_MR_M;
3471bd4fe43Sopenharmony_ci    regAddr.hourAddr = RTC_MR_H;
3481bd4fe43Sopenharmony_ci    regAddr.dayLowAddr = RTC_MR_D_L;
3491bd4fe43Sopenharmony_ci    regAddr.dayHighAddr = RTC_MR_D_H;
3501bd4fe43Sopenharmony_ci
3511bd4fe43Sopenharmony_ci    return HiRtcReadTimeData(rtcInfo, &regAddr, time);
3521bd4fe43Sopenharmony_ci}
3531bd4fe43Sopenharmony_ci
3541bd4fe43Sopenharmony_cistatic int32_t HiWriteAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *time)
3551bd4fe43Sopenharmony_ci{
3561bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
3571bd4fe43Sopenharmony_ci    struct RtcTimeReg regAddr;
3581bd4fe43Sopenharmony_ci
3591bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
3601bd4fe43Sopenharmony_ci        HDF_LOGE("WriteAlarm: host is null!");
3611bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
3621bd4fe43Sopenharmony_ci    }
3631bd4fe43Sopenharmony_ci
3641bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
3651bd4fe43Sopenharmony_ci    if (alarmIndex != rtcInfo->alarmIndex) {
3661bd4fe43Sopenharmony_ci        HDF_LOGE("WriteAlarm: alarmIndex para error!");
3671bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
3681bd4fe43Sopenharmony_ci    }
3691bd4fe43Sopenharmony_ci
3701bd4fe43Sopenharmony_ci    regAddr.millisecondAddr = RTC_MR_10MS;
3711bd4fe43Sopenharmony_ci    regAddr.secondAddr = RTC_MR_S;
3721bd4fe43Sopenharmony_ci    regAddr.minuteAddr = RTC_MR_M;
3731bd4fe43Sopenharmony_ci    regAddr.hourAddr = RTC_MR_H;
3741bd4fe43Sopenharmony_ci    regAddr.dayLowAddr = RTC_MR_D_L;
3751bd4fe43Sopenharmony_ci    regAddr.dayHighAddr = RTC_MR_D_H;
3761bd4fe43Sopenharmony_ci
3771bd4fe43Sopenharmony_ci    return HiRtcWriteTimeData(rtcInfo, &regAddr, time);
3781bd4fe43Sopenharmony_ci}
3791bd4fe43Sopenharmony_ci
3801bd4fe43Sopenharmony_cistatic int32_t HiRegisterAlarmCallback(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb)
3811bd4fe43Sopenharmony_ci{
3821bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
3831bd4fe43Sopenharmony_ci
3841bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL || cb == NULL) {
3851bd4fe43Sopenharmony_ci        HDF_LOGE("HiRegisterAlarmCallback: pointer is null!");
3861bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
3871bd4fe43Sopenharmony_ci    }
3881bd4fe43Sopenharmony_ci
3891bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
3901bd4fe43Sopenharmony_ci    if (alarmIndex != rtcInfo->alarmIndex) {
3911bd4fe43Sopenharmony_ci        HDF_LOGE("HiRegisterAlarmCallback: alarmIndex para error!");
3921bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
3931bd4fe43Sopenharmony_ci    }
3941bd4fe43Sopenharmony_ci    rtcInfo->cb = cb;
3951bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
3961bd4fe43Sopenharmony_ci}
3971bd4fe43Sopenharmony_ci
3981bd4fe43Sopenharmony_cistatic int32_t HiAlarmInterruptEnable(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable)
3991bd4fe43Sopenharmony_ci{
4001bd4fe43Sopenharmony_ci    uint32_t ret;
4011bd4fe43Sopenharmony_ci    uint8_t value = 0;
4021bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
4031bd4fe43Sopenharmony_ci
4041bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL || alarmIndex != RTC_ALARM_INDEX_A) {
4051bd4fe43Sopenharmony_ci        HDF_LOGE("HiAlarmInterruptEnable: para invalid!");
4061bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
4071bd4fe43Sopenharmony_ci    }
4081bd4fe43Sopenharmony_ci
4091bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
4101bd4fe43Sopenharmony_ci    if ((enable != RTC_TRUE) && (enable != RTC_FALSE)) {
4111bd4fe43Sopenharmony_ci        HDF_LOGE("HiAlarmInterruptEnable: enable para error!");
4121bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
4131bd4fe43Sopenharmony_ci    }
4141bd4fe43Sopenharmony_ci
4151bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, RTC_MSC, &value);
4161bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
4171bd4fe43Sopenharmony_ci        return ret;
4181bd4fe43Sopenharmony_ci    }
4191bd4fe43Sopenharmony_ci
4201bd4fe43Sopenharmony_ci    if (enable == RTC_TRUE) {
4211bd4fe43Sopenharmony_ci        ret = HiRtcSpiWrite(rtcInfo, RTC_MSC, (value | RTC_MSC_TIME_MASK));
4221bd4fe43Sopenharmony_ci    } else {
4231bd4fe43Sopenharmony_ci        ret = HiRtcSpiWrite(rtcInfo, RTC_MSC, (value & (~RTC_MSC_TIME_MASK)));
4241bd4fe43Sopenharmony_ci    }
4251bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
4261bd4fe43Sopenharmony_ci        return HDF_FAILURE;
4271bd4fe43Sopenharmony_ci    }
4281bd4fe43Sopenharmony_ci
4291bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4301bd4fe43Sopenharmony_ci}
4311bd4fe43Sopenharmony_ci
4321bd4fe43Sopenharmony_cistatic int32_t HiGetFreq(struct RtcHost *host, uint32_t *freq)
4331bd4fe43Sopenharmony_ci{
4341bd4fe43Sopenharmony_ci    uint32_t ret;
4351bd4fe43Sopenharmony_ci    uint16_t value;
4361bd4fe43Sopenharmony_ci    uint8_t lowFreq = 0;
4371bd4fe43Sopenharmony_ci    uint8_t highFreq = 0;
4381bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
4391bd4fe43Sopenharmony_ci
4401bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL || freq == NULL) {
4411bd4fe43Sopenharmony_ci        HDF_LOGE("HiReadFreq: host is null!");
4421bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
4431bd4fe43Sopenharmony_ci    }
4441bd4fe43Sopenharmony_ci
4451bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
4461bd4fe43Sopenharmony_ci    ret = HiRtcSpiRead(rtcInfo, RTC_FREQ_H, &highFreq);
4471bd4fe43Sopenharmony_ci    ret |= HiRtcSpiRead(rtcInfo, RTC_FREQ_L, &lowFreq);
4481bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
4491bd4fe43Sopenharmony_ci        return HDF_FAILURE;
4501bd4fe43Sopenharmony_ci    }
4511bd4fe43Sopenharmony_ci
4521bd4fe43Sopenharmony_ci    value = ((highFreq & 0x0f) << SHIFT_BYTE) + lowFreq; /* 8:[12:8] for freq_h bit */
4531bd4fe43Sopenharmony_ci    *freq = FREQ_DIFF + (value * FREQ_UNIT) / FREQ_COEFFICIENT; /* freq convert: 3270000+(freq*10000)/3052 */
4541bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4551bd4fe43Sopenharmony_ci}
4561bd4fe43Sopenharmony_ci
4571bd4fe43Sopenharmony_cistatic int32_t HiSetFreq(struct RtcHost *host, uint32_t freq)
4581bd4fe43Sopenharmony_ci{
4591bd4fe43Sopenharmony_ci    uint32_t ret;
4601bd4fe43Sopenharmony_ci    uint8_t lowFreq;
4611bd4fe43Sopenharmony_ci    uint8_t highFreq;
4621bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
4631bd4fe43Sopenharmony_ci
4641bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
4651bd4fe43Sopenharmony_ci        HDF_LOGE("HiWriteFreq: host is null!");
4661bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
4671bd4fe43Sopenharmony_ci    }
4681bd4fe43Sopenharmony_ci
4691bd4fe43Sopenharmony_ci    freq *= FREQ_ROUND_OFF_NUMBER;
4701bd4fe43Sopenharmony_ci    if (freq > FREQ_MAX_VAL || freq < FREQ_MIN_VAL) {
4711bd4fe43Sopenharmony_ci        HDF_LOGE("HiWriteFreq: para error!");
4721bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
4731bd4fe43Sopenharmony_ci    }
4741bd4fe43Sopenharmony_ci
4751bd4fe43Sopenharmony_ci    freq = (freq - FREQ_DIFF) * FREQ_COEFFICIENT / FREQ_UNIT; /* freq convert: (freq-3270000)*3052/10000 */
4761bd4fe43Sopenharmony_ci    lowFreq = (freq & 0xff); /* 8:[7:0] for freq low */
4771bd4fe43Sopenharmony_ci    highFreq = ((freq >> SHIFT_BYTE) & 0xf); /* 8:[12:8] for freq high */
4781bd4fe43Sopenharmony_ci
4791bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
4801bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, RTC_FREQ_H, highFreq);
4811bd4fe43Sopenharmony_ci    ret |= HiRtcSpiWrite(rtcInfo, RTC_FREQ_L, lowFreq);
4821bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
4831bd4fe43Sopenharmony_ci        return HDF_FAILURE;
4841bd4fe43Sopenharmony_ci    }
4851bd4fe43Sopenharmony_ci
4861bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4871bd4fe43Sopenharmony_ci}
4881bd4fe43Sopenharmony_ci
4891bd4fe43Sopenharmony_cistatic int32_t HiReset(struct RtcHost *host)
4901bd4fe43Sopenharmony_ci{
4911bd4fe43Sopenharmony_ci    uint32_t ret;
4921bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
4931bd4fe43Sopenharmony_ci
4941bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
4951bd4fe43Sopenharmony_ci        HDF_LOGE("HiReset: host is null!");
4961bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
4971bd4fe43Sopenharmony_ci    }
4981bd4fe43Sopenharmony_ci
4991bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
5001bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, RTC_POR_N, 0);
5011bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5021bd4fe43Sopenharmony_ci        HDF_LOGE("HiReset: write por fail!");
5031bd4fe43Sopenharmony_ci        return HDF_FAILURE;
5041bd4fe43Sopenharmony_ci    }
5051bd4fe43Sopenharmony_ci
5061bd4fe43Sopenharmony_ci    ret = HiRtcSpiWrite(rtcInfo, RTC_CLK, RTC_CLK_OUT_SEL);
5071bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
5081bd4fe43Sopenharmony_ci        HDF_LOGE("HiReset: write clk fail!");
5091bd4fe43Sopenharmony_ci        return HDF_FAILURE;
5101bd4fe43Sopenharmony_ci    }
5111bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
5121bd4fe43Sopenharmony_ci}
5131bd4fe43Sopenharmony_ci
5141bd4fe43Sopenharmony_cistatic int32_t HiReadReg(struct RtcHost *host, uint8_t usrDefIndex, uint8_t *value)
5151bd4fe43Sopenharmony_ci{
5161bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
5171bd4fe43Sopenharmony_ci
5181bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL || value == NULL) {
5191bd4fe43Sopenharmony_ci        HDF_LOGE("HiReadReg: host is null!");
5201bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
5211bd4fe43Sopenharmony_ci    }
5221bd4fe43Sopenharmony_ci
5231bd4fe43Sopenharmony_ci    if (usrDefIndex >= REG_INDEX_MAX_VAL) {
5241bd4fe43Sopenharmony_ci        HDF_LOGE("HiReadReg: index error!");
5251bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
5261bd4fe43Sopenharmony_ci    }
5271bd4fe43Sopenharmony_ci
5281bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
5291bd4fe43Sopenharmony_ci    return HiRtcSpiRead(rtcInfo, g_usrRegAddr[usrDefIndex], value);
5301bd4fe43Sopenharmony_ci}
5311bd4fe43Sopenharmony_ci
5321bd4fe43Sopenharmony_cistatic int32_t HiWriteReg(struct RtcHost *host, uint8_t usrDefIndex, uint8_t value)
5331bd4fe43Sopenharmony_ci{
5341bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
5351bd4fe43Sopenharmony_ci
5361bd4fe43Sopenharmony_ci    if (host == NULL || host->data == NULL) {
5371bd4fe43Sopenharmony_ci        HDF_LOGE("HiWriteReg: host is null!");
5381bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
5391bd4fe43Sopenharmony_ci    }
5401bd4fe43Sopenharmony_ci
5411bd4fe43Sopenharmony_ci    if (usrDefIndex >= REG_INDEX_MAX_VAL) {
5421bd4fe43Sopenharmony_ci        HDF_LOGE("HiWriteReg: index error!");
5431bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
5441bd4fe43Sopenharmony_ci    }
5451bd4fe43Sopenharmony_ci
5461bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
5471bd4fe43Sopenharmony_ci    return HiRtcSpiWrite(rtcInfo, g_usrRegAddr[usrDefIndex], value);
5481bd4fe43Sopenharmony_ci}
5491bd4fe43Sopenharmony_ci
5501bd4fe43Sopenharmony_cistatic struct RtcMethod g_method = {
5511bd4fe43Sopenharmony_ci    .ReadTime = HiRtcReadTime,
5521bd4fe43Sopenharmony_ci    .WriteTime = HiRtcWriteTime,
5531bd4fe43Sopenharmony_ci    .ReadAlarm = HiReadAlarm,
5541bd4fe43Sopenharmony_ci    .WriteAlarm = HiWriteAlarm,
5551bd4fe43Sopenharmony_ci    .RegisterAlarmCallback = HiRegisterAlarmCallback,
5561bd4fe43Sopenharmony_ci    .AlarmInterruptEnable = HiAlarmInterruptEnable,
5571bd4fe43Sopenharmony_ci    .GetFreq = HiGetFreq,
5581bd4fe43Sopenharmony_ci    .SetFreq = HiSetFreq,
5591bd4fe43Sopenharmony_ci    .Reset = HiReset,
5601bd4fe43Sopenharmony_ci    .ReadReg = HiReadReg,
5611bd4fe43Sopenharmony_ci    .WriteReg = HiWriteReg,
5621bd4fe43Sopenharmony_ci};
5631bd4fe43Sopenharmony_ci
5641bd4fe43Sopenharmony_cistatic int32_t HiRtcAttachConfigData(struct RtcConfigInfo *rtcInfo, const struct DeviceResourceNode *node)
5651bd4fe43Sopenharmony_ci{
5661bd4fe43Sopenharmony_ci    int32_t ret;
5671bd4fe43Sopenharmony_ci    uint32_t value;
5681bd4fe43Sopenharmony_ci    struct DeviceResourceIface *drsOps = NULL;
5691bd4fe43Sopenharmony_ci
5701bd4fe43Sopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
5711bd4fe43Sopenharmony_ci    if (node == NULL || drsOps == NULL || drsOps->GetUint32 == NULL) {
5721bd4fe43Sopenharmony_ci        HDF_LOGE("%s: node null!", __func__);
5731bd4fe43Sopenharmony_ci        return HDF_FAILURE;
5741bd4fe43Sopenharmony_ci    }
5751bd4fe43Sopenharmony_ci
5761bd4fe43Sopenharmony_ci    if (rtcInfo->supportAnaCtrl == RTC_FEATURE_SUPPORT) {
5771bd4fe43Sopenharmony_ci        ret = drsOps->GetUint32(node, "anaCtrlAddr", &value, 0);
5781bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
5791bd4fe43Sopenharmony_ci            HDF_LOGE("%s: read anaCtrlAddr fail!", __func__);
5801bd4fe43Sopenharmony_ci            return ret;
5811bd4fe43Sopenharmony_ci        }
5821bd4fe43Sopenharmony_ci        rtcInfo->anaCtrlAddr = (uint8_t)value;
5831bd4fe43Sopenharmony_ci    }
5841bd4fe43Sopenharmony_ci
5851bd4fe43Sopenharmony_ci    if (rtcInfo->supportLock == RTC_FEATURE_SUPPORT) {
5861bd4fe43Sopenharmony_ci        ret = drsOps->GetUint32(node, "lock0Addr", &value, 0);
5871bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
5881bd4fe43Sopenharmony_ci            return ret;
5891bd4fe43Sopenharmony_ci        }
5901bd4fe43Sopenharmony_ci        rtcInfo->lockAddr.lock0Addr = (uint8_t)value;
5911bd4fe43Sopenharmony_ci        ret = drsOps->GetUint32(node, "lock1Addr", &value, 0);
5921bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
5931bd4fe43Sopenharmony_ci            return ret;
5941bd4fe43Sopenharmony_ci        }
5951bd4fe43Sopenharmony_ci        rtcInfo->lockAddr.lock1Addr = (uint8_t)value;
5961bd4fe43Sopenharmony_ci        ret = drsOps->GetUint32(node, "lock2Addr", &value, 0);
5971bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
5981bd4fe43Sopenharmony_ci            return ret;
5991bd4fe43Sopenharmony_ci        }
6001bd4fe43Sopenharmony_ci        rtcInfo->lockAddr.lock2Addr = (uint8_t)value;
6011bd4fe43Sopenharmony_ci        ret = drsOps->GetUint32(node, "lock3Addr", &value, 0);
6021bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
6031bd4fe43Sopenharmony_ci            return ret;
6041bd4fe43Sopenharmony_ci        }
6051bd4fe43Sopenharmony_ci        rtcInfo->lockAddr.lock3Addr = (uint8_t)value;
6061bd4fe43Sopenharmony_ci    }
6071bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6081bd4fe43Sopenharmony_ci}
6091bd4fe43Sopenharmony_ci
6101bd4fe43Sopenharmony_cistatic int32_t HiRtcConfigData(struct RtcConfigInfo *rtcInfo, const struct DeviceResourceNode *node)
6111bd4fe43Sopenharmony_ci{
6121bd4fe43Sopenharmony_ci    int32_t ret;
6131bd4fe43Sopenharmony_ci    uint32_t value;
6141bd4fe43Sopenharmony_ci    struct DeviceResourceIface *drsOps = NULL;
6151bd4fe43Sopenharmony_ci
6161bd4fe43Sopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
6171bd4fe43Sopenharmony_ci    if (drsOps == NULL || drsOps->GetBool == NULL || drsOps->GetUint32 == NULL) {
6181bd4fe43Sopenharmony_ci        HDF_LOGE("%s: invalid drs ops fail!", __func__);
6191bd4fe43Sopenharmony_ci        return HDF_FAILURE;
6201bd4fe43Sopenharmony_ci    }
6211bd4fe43Sopenharmony_ci
6221bd4fe43Sopenharmony_ci    rtcInfo->supportAnaCtrl = drsOps->GetBool(node, "supportAnaCtrl");
6231bd4fe43Sopenharmony_ci    rtcInfo->supportLock = drsOps->GetBool(node, "supportLock");
6241bd4fe43Sopenharmony_ci
6251bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "rtcSpiBaseAddr", &rtcInfo->spiBaseAddr, 0);
6261bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6271bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read regBase fail!", __func__);
6281bd4fe43Sopenharmony_ci        return ret;
6291bd4fe43Sopenharmony_ci    }
6301bd4fe43Sopenharmony_ci
6311bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "regAddrLength", &value, 0);
6321bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6331bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read Length fail!", __func__);
6341bd4fe43Sopenharmony_ci        return ret;
6351bd4fe43Sopenharmony_ci    }
6361bd4fe43Sopenharmony_ci    rtcInfo->regAddrLength = (uint16_t)value;
6371bd4fe43Sopenharmony_ci
6381bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "irq", &value, 0);
6391bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6401bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read irq fail!", __func__);
6411bd4fe43Sopenharmony_ci        return ret;
6421bd4fe43Sopenharmony_ci    }
6431bd4fe43Sopenharmony_ci    rtcInfo->irq = (uint8_t)value;
6441bd4fe43Sopenharmony_ci    ret = HiRtcAttachConfigData(rtcInfo, node);
6451bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6461bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read config data fail!", __func__);
6471bd4fe43Sopenharmony_ci        return ret;
6481bd4fe43Sopenharmony_ci    }
6491bd4fe43Sopenharmony_ci
6501bd4fe43Sopenharmony_ci    rtcInfo->alarmIndex = RTC_ALARM_INDEX_A;
6511bd4fe43Sopenharmony_ci    rtcInfo->remapBaseAddr = NULL;
6521bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6531bd4fe43Sopenharmony_ci}
6541bd4fe43Sopenharmony_ci
6551bd4fe43Sopenharmony_cistatic uint32_t HiRtcIrqHandle(uint32_t irqId, void *data)
6561bd4fe43Sopenharmony_ci{
6571bd4fe43Sopenharmony_ci    uint8_t value = 0;
6581bd4fe43Sopenharmony_ci    uint32_t ret;
6591bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
6601bd4fe43Sopenharmony_ci
6611bd4fe43Sopenharmony_ci    UNUSED(irqId);
6621bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)data;
6631bd4fe43Sopenharmony_ci    if (rtcInfo == NULL) {
6641bd4fe43Sopenharmony_ci        return RTC_ERROR_NULL;
6651bd4fe43Sopenharmony_ci    }
6661bd4fe43Sopenharmony_ci
6671bd4fe43Sopenharmony_ci    ret = HiSpiRead(rtcInfo, RTC_INT, &value);
6681bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6691bd4fe43Sopenharmony_ci        return RTC_ERROR_READ_FAIL;
6701bd4fe43Sopenharmony_ci    }
6711bd4fe43Sopenharmony_ci
6721bd4fe43Sopenharmony_ci    ret = HiSpiWrite(rtcInfo, RTC_INT_CLR, RTC_INT_CLR_MASK);
6731bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6741bd4fe43Sopenharmony_ci        return RTC_ERROR_WRITE_FAIL;
6751bd4fe43Sopenharmony_ci    }
6761bd4fe43Sopenharmony_ci    if (rtcInfo->cb == NULL) {
6771bd4fe43Sopenharmony_ci        return RTC_ERROR_NULL;
6781bd4fe43Sopenharmony_ci    }
6791bd4fe43Sopenharmony_ci
6801bd4fe43Sopenharmony_ci    if (value & RTC_INT_MASK) {
6811bd4fe43Sopenharmony_ci        return rtcInfo->cb(rtcInfo->alarmIndex);
6821bd4fe43Sopenharmony_ci    }
6831bd4fe43Sopenharmony_ci
6841bd4fe43Sopenharmony_ci    if (value & RTC_INT_UV_MASK) {
6851bd4fe43Sopenharmony_ci        HiSpiRead(rtcInfo, RTC_MSC, &value);
6861bd4fe43Sopenharmony_ci        HiSpiWrite(rtcInfo, RTC_MSC, value & (~RTC_INT_UV_MASK)); /* close low voltage int */
6871bd4fe43Sopenharmony_ci    }
6881bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6891bd4fe43Sopenharmony_ci}
6901bd4fe43Sopenharmony_ci
6911bd4fe43Sopenharmony_cistatic int32_t HiRtcSwInit(struct RtcConfigInfo *rtcInfo)
6921bd4fe43Sopenharmony_ci{
6931bd4fe43Sopenharmony_ci    bool ret = false;
6941bd4fe43Sopenharmony_ci
6951bd4fe43Sopenharmony_ci    if (rtcInfo->spiBaseAddr == 0 || (rtcInfo->regAddrLength == 0)) {
6961bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcSwInit: para invalid!");
6971bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
6981bd4fe43Sopenharmony_ci    }
6991bd4fe43Sopenharmony_ci
7001bd4fe43Sopenharmony_ci    if (OsalMutexInit(&rtcInfo->mutex) != HDF_SUCCESS) {
7011bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcSwInit: create mutex fail!");
7021bd4fe43Sopenharmony_ci        return HDF_FAILURE;
7031bd4fe43Sopenharmony_ci    }
7041bd4fe43Sopenharmony_ci
7051bd4fe43Sopenharmony_ci    if (rtcInfo->remapBaseAddr == NULL) {
7061bd4fe43Sopenharmony_ci        rtcInfo->remapBaseAddr = (volatile void *)OsalIoRemap((uintptr_t)rtcInfo->spiBaseAddr,
7071bd4fe43Sopenharmony_ci            rtcInfo->regAddrLength);
7081bd4fe43Sopenharmony_ci    }
7091bd4fe43Sopenharmony_ci
7101bd4fe43Sopenharmony_ci    ret = OsalRegisterIrq(rtcInfo->irq, 0, HiRtcIrqHandle, "rtc_alarm", (void*)rtcInfo);
7111bd4fe43Sopenharmony_ci    if (ret != 0) {
7121bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcSwInit: register irq(%hhu) fail!", rtcInfo->irq);
7131bd4fe43Sopenharmony_ci        (void)OsalMutexDestroy(&rtcInfo->mutex);
7141bd4fe43Sopenharmony_ci        OsalIoUnmap((void*)rtcInfo->remapBaseAddr);
7151bd4fe43Sopenharmony_ci        rtcInfo->remapBaseAddr = NULL;
7161bd4fe43Sopenharmony_ci        return HDF_FAILURE;
7171bd4fe43Sopenharmony_ci    }
7181bd4fe43Sopenharmony_ci
7191bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
7201bd4fe43Sopenharmony_ci}
7211bd4fe43Sopenharmony_ci
7221bd4fe43Sopenharmony_cistatic void HiRtcSwExit(struct RtcConfigInfo *rtcInfo)
7231bd4fe43Sopenharmony_ci{
7241bd4fe43Sopenharmony_ci    (void)OsalUnregisterIrq(rtcInfo->irq, (void *)rtcInfo);
7251bd4fe43Sopenharmony_ci    (void)OsalMutexDestroy(&rtcInfo->mutex);
7261bd4fe43Sopenharmony_ci
7271bd4fe43Sopenharmony_ci    if (rtcInfo->remapBaseAddr != NULL) {
7281bd4fe43Sopenharmony_ci        OsalIoUnmap((void*)rtcInfo->remapBaseAddr);
7291bd4fe43Sopenharmony_ci        rtcInfo->remapBaseAddr = NULL;
7301bd4fe43Sopenharmony_ci    }
7311bd4fe43Sopenharmony_ci}
7321bd4fe43Sopenharmony_ci
7331bd4fe43Sopenharmony_cistatic uint32_t HiRtcHwAttachInit(struct RtcConfigInfo *rtcInfo)
7341bd4fe43Sopenharmony_ci{
7351bd4fe43Sopenharmony_ci    uint32_t ret = 0;
7361bd4fe43Sopenharmony_ci
7371bd4fe43Sopenharmony_ci    if (rtcInfo->supportAnaCtrl == RTC_FEATURE_SUPPORT) {
7381bd4fe43Sopenharmony_ci        ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->anaCtrlAddr, RTC_ANA_CTRL_ENABLE);
7391bd4fe43Sopenharmony_ci    }
7401bd4fe43Sopenharmony_ci
7411bd4fe43Sopenharmony_ci    /* Unlock First, Then modify to the default driver capability */
7421bd4fe43Sopenharmony_ci    if (rtcInfo->supportLock == RTC_FEATURE_SUPPORT) {
7431bd4fe43Sopenharmony_ci        ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock3Addr, RTC_LOCK_ORDER2);
7441bd4fe43Sopenharmony_ci        ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock2Addr, RTC_LOCK_ORDER2);
7451bd4fe43Sopenharmony_ci        ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock1Addr, RTC_LOCK_ORDER1);
7461bd4fe43Sopenharmony_ci        ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->lockAddr.lock0Addr, RTC_LOCK_ORDER0);
7471bd4fe43Sopenharmony_ci        ret |= HiRtcSpiWrite(rtcInfo, rtcInfo->anaCtrlAddr, RTC_ANA_CTRL_ORDER);
7481bd4fe43Sopenharmony_ci    }
7491bd4fe43Sopenharmony_ci
7501bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
7511bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcHwAttachInit: write config fail");
7521bd4fe43Sopenharmony_ci        return ret;
7531bd4fe43Sopenharmony_ci    }
7541bd4fe43Sopenharmony_ci    return ret;
7551bd4fe43Sopenharmony_ci}
7561bd4fe43Sopenharmony_ci
7571bd4fe43Sopenharmony_cistatic int32_t HiRtcHwInit(struct RtcConfigInfo *rtcInfo)
7581bd4fe43Sopenharmony_ci{
7591bd4fe43Sopenharmony_ci    uint32_t ret = 0;
7601bd4fe43Sopenharmony_ci    uint8_t value = 0;
7611bd4fe43Sopenharmony_ci
7621bd4fe43Sopenharmony_ci    /* clk div value is (apb_clk/spi_clk)/2-1, for asic, apb clk(100MHz), spi_clk(10MHz), so value is 0x4 */
7631bd4fe43Sopenharmony_ci    OSAL_WRITEL(RTC_CLK_DIV_VALUE, RTC_SPI_CLK_DIV((uintptr_t)rtcInfo->remapBaseAddr));
7641bd4fe43Sopenharmony_ci    ret |= HiRtcSpiWrite(rtcInfo, RTC_MSC, RTC_MSC_ENABLE);
7651bd4fe43Sopenharmony_ci    ret |= HiRtcSpiWrite(rtcInfo, RTC_SAR_CTRL, RTC_UV_CTRL_ENABLE);
7661bd4fe43Sopenharmony_ci    ret |= HiRtcHwAttachInit(rtcInfo);
7671bd4fe43Sopenharmony_ci    ret |= HiRtcSpiWrite(rtcInfo, RTC_FREQ_H, FREQ_H_DEFAULT);
7681bd4fe43Sopenharmony_ci    ret |= HiRtcSpiWrite(rtcInfo, RTC_FREQ_L, FREQ_L_DEFAULT);
7691bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
7701bd4fe43Sopenharmony_ci        HDF_LOGE("RtcHwInit: init fail");
7711bd4fe43Sopenharmony_ci        return HDF_FAILURE;
7721bd4fe43Sopenharmony_ci    }
7731bd4fe43Sopenharmony_ci
7741bd4fe43Sopenharmony_ci    if (HiRtcSpiRead(rtcInfo, RTC_INT_RAW, &value) != 0) {
7751bd4fe43Sopenharmony_ci        HDF_LOGW("RtcHwInit: spi read fail");
7761bd4fe43Sopenharmony_ci        return HDF_FAILURE;
7771bd4fe43Sopenharmony_ci    }
7781bd4fe43Sopenharmony_ci
7791bd4fe43Sopenharmony_ci    if (value & RTC_INT_RAW_MASK) {
7801bd4fe43Sopenharmony_ci        HDF_LOGW("HiRtcHwInit: low voltage detected, date/time is not reliable");
7811bd4fe43Sopenharmony_ci    }
7821bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
7831bd4fe43Sopenharmony_ci}
7841bd4fe43Sopenharmony_ci
7851bd4fe43Sopenharmony_cistatic int32_t HiRtcBind(struct HdfDeviceObject *device)
7861bd4fe43Sopenharmony_ci{
7871bd4fe43Sopenharmony_ci    struct RtcHost *host = NULL;
7881bd4fe43Sopenharmony_ci
7891bd4fe43Sopenharmony_ci    host = RtcHostCreate(device);
7901bd4fe43Sopenharmony_ci    if (host == NULL) {
7911bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcBind: create host fail!");
7921bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
7931bd4fe43Sopenharmony_ci    }
7941bd4fe43Sopenharmony_ci
7951bd4fe43Sopenharmony_ci    host->device = device;
7961bd4fe43Sopenharmony_ci    device->service = &host->service;
7971bd4fe43Sopenharmony_ci    HDF_LOGI("%s: rtc bind success.", __func__);
7981bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
7991bd4fe43Sopenharmony_ci}
8001bd4fe43Sopenharmony_ci
8011bd4fe43Sopenharmony_cistatic int32_t HiRtcInit(struct HdfDeviceObject *device)
8021bd4fe43Sopenharmony_ci{
8031bd4fe43Sopenharmony_ci    struct RtcHost *host = NULL;
8041bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
8051bd4fe43Sopenharmony_ci
8061bd4fe43Sopenharmony_ci    if (device == NULL || device->property == NULL) {
8071bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
8081bd4fe43Sopenharmony_ci    }
8091bd4fe43Sopenharmony_ci    host = RtcHostFromDevice(device);
8101bd4fe43Sopenharmony_ci    rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
8111bd4fe43Sopenharmony_ci    if (rtcInfo == NULL) {
8121bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcInit: malloc info fail!");
8131bd4fe43Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
8141bd4fe43Sopenharmony_ci    }
8151bd4fe43Sopenharmony_ci
8161bd4fe43Sopenharmony_ci    if (HiRtcConfigData(rtcInfo, device->property) != 0) {
8171bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcInit: hcs config fail!");
8181bd4fe43Sopenharmony_ci        OsalMemFree(rtcInfo);
8191bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
8201bd4fe43Sopenharmony_ci    }
8211bd4fe43Sopenharmony_ci
8221bd4fe43Sopenharmony_ci    if (HiRtcSwInit(rtcInfo) != 0) {
8231bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcInit: sw init fail!");
8241bd4fe43Sopenharmony_ci        OsalMemFree(rtcInfo);
8251bd4fe43Sopenharmony_ci        return HDF_DEV_ERR_DEV_INIT_FAIL;
8261bd4fe43Sopenharmony_ci    }
8271bd4fe43Sopenharmony_ci
8281bd4fe43Sopenharmony_ci    if (HiRtcHwInit(rtcInfo) != 0) {
8291bd4fe43Sopenharmony_ci        HDF_LOGE("HiRtcInit: hw init fail!");
8301bd4fe43Sopenharmony_ci        HiRtcSwExit(rtcInfo);
8311bd4fe43Sopenharmony_ci        OsalMemFree(rtcInfo);
8321bd4fe43Sopenharmony_ci        return HDF_DEV_ERR_DEV_INIT_FAIL;
8331bd4fe43Sopenharmony_ci    }
8341bd4fe43Sopenharmony_ci
8351bd4fe43Sopenharmony_ci    host->method = &g_method;
8361bd4fe43Sopenharmony_ci    host->data = rtcInfo;
8371bd4fe43Sopenharmony_ci    HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
8381bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
8391bd4fe43Sopenharmony_ci}
8401bd4fe43Sopenharmony_ci
8411bd4fe43Sopenharmony_cistatic void HiRtcRelease(struct HdfDeviceObject *device)
8421bd4fe43Sopenharmony_ci{
8431bd4fe43Sopenharmony_ci    struct RtcHost *host = NULL;
8441bd4fe43Sopenharmony_ci    struct RtcConfigInfo *rtcInfo = NULL;
8451bd4fe43Sopenharmony_ci
8461bd4fe43Sopenharmony_ci    HDF_LOGI("%s: enter", __func__);
8471bd4fe43Sopenharmony_ci    if (device == NULL) {
8481bd4fe43Sopenharmony_ci        return;
8491bd4fe43Sopenharmony_ci    }
8501bd4fe43Sopenharmony_ci
8511bd4fe43Sopenharmony_ci    host = RtcHostFromDevice(device);
8521bd4fe43Sopenharmony_ci    rtcInfo = (struct RtcConfigInfo *)host->data;
8531bd4fe43Sopenharmony_ci    if (rtcInfo != NULL) {
8541bd4fe43Sopenharmony_ci        HiRtcSwExit(rtcInfo);
8551bd4fe43Sopenharmony_ci        OsalMemFree(rtcInfo);
8561bd4fe43Sopenharmony_ci        host->data = NULL;
8571bd4fe43Sopenharmony_ci    }
8581bd4fe43Sopenharmony_ci    RtcHostDestroy(host);
8591bd4fe43Sopenharmony_ci}
8601bd4fe43Sopenharmony_ci
8611bd4fe43Sopenharmony_cistruct HdfDriverEntry g_rtcDriverEntry = {
8621bd4fe43Sopenharmony_ci    .moduleVersion = 1,
8631bd4fe43Sopenharmony_ci    .Bind = HiRtcBind,
8641bd4fe43Sopenharmony_ci    .Init = HiRtcInit,
8651bd4fe43Sopenharmony_ci    .Release = HiRtcRelease,
8661bd4fe43Sopenharmony_ci    .moduleName = "HDF_PLATFORM_RTC",
8671bd4fe43Sopenharmony_ci};
8681bd4fe43Sopenharmony_ci
8691bd4fe43Sopenharmony_ciHDF_INIT(g_rtcDriverEntry);
870