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, ®Addr, 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, ®Addr, 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, ®Addr, 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, ®Addr, 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