/* * rtc_adapter.c * * rtc driver adapter of linux * * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include "device_resource_if.h" #include "hdf_device_desc.h" #include "hdf_log.h" #include "rtc_core.h" #define HDF_LOG_TAG RTC_ADAPTER #define MONTH_DIFF 1 #define YEAR_BASE 1900 static inline void HdfTimeToLinuxTime(const struct RtcTime *hdfTime, struct rtc_time *linuxTime) { linuxTime->tm_sec = hdfTime->second; linuxTime->tm_min = hdfTime->minute; linuxTime->tm_hour = hdfTime->hour; linuxTime->tm_mday = hdfTime->day; linuxTime->tm_mon = hdfTime->month - MONTH_DIFF; linuxTime->tm_year = hdfTime->year - YEAR_BASE; linuxTime->tm_wday = hdfTime->weekday; linuxTime->tm_yday = rtc_year_days(linuxTime->tm_mday, linuxTime->tm_mon, linuxTime->tm_year); } static inline void LinuxTimeToHdfTime(struct RtcTime *hdfTime, const struct rtc_time *linuxTime) { hdfTime->second = linuxTime->tm_sec; hdfTime->minute = linuxTime->tm_min; hdfTime->hour = linuxTime->tm_hour; hdfTime->day = linuxTime->tm_mday; hdfTime->month = linuxTime->tm_mon + MONTH_DIFF; hdfTime->year = linuxTime->tm_year + YEAR_BASE; hdfTime->weekday = linuxTime->tm_wday; } static inline struct rtc_device *HdfGetRtcDevice(void) { struct rtc_device *dev = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE); if (dev == NULL) { HDF_LOGE("%s: failed to get rtc device", __func__); } return dev; } static inline void HdfPutRtcDevice(struct rtc_device *dev) { rtc_class_close(dev); } static int32_t HiRtcReadTime(struct RtcHost *host, struct RtcTime *hdfTime) { int32_t ret; struct rtc_time linuxTime = {0}; struct rtc_device *dev = HdfGetRtcDevice(); (void)host; if (dev == NULL) { return HDF_FAILURE; } ret = rtc_read_time(dev, &linuxTime); if (ret < 0) { HDF_LOGE("%s: rtc_read_time error, ret is %d", __func__, ret); return ret; } HdfPutRtcDevice(dev); LinuxTimeToHdfTime(hdfTime, &linuxTime); return HDF_SUCCESS; } static int32_t HiRtcWriteTime(struct RtcHost *host, const struct RtcTime *hdfTime) { int32_t ret; struct rtc_time linuxTime = {0}; struct rtc_device *dev = HdfGetRtcDevice(); (void)host; if (dev == NULL) { return HDF_FAILURE; } HdfTimeToLinuxTime(hdfTime, &linuxTime); ret = rtc_set_time(dev, &linuxTime); if (ret < 0) { HDF_LOGE("%s: rtc_set_time error, ret is %d", __func__, ret); return ret; } HdfPutRtcDevice(dev); return HDF_SUCCESS; } static int32_t HiReadAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *hdfTime) { int32_t ret; struct rtc_wkalrm alarm = {0}; struct rtc_device *dev = HdfGetRtcDevice(); (void)host; (void)alarmIndex; if (dev == NULL) { return HDF_FAILURE; } ret = rtc_read_alarm(dev, &alarm); if (ret < 0) { HDF_LOGE("%s: rtc_read_alarm error, ret is %d", __func__, ret); return ret; } LinuxTimeToHdfTime(hdfTime, &(alarm.time)); HdfPutRtcDevice(dev); return HDF_SUCCESS; } static int32_t HiWriteAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *hdfTime) { int32_t ret; struct rtc_wkalrm alarm = {0}; struct rtc_device *dev = HdfGetRtcDevice(); (void)host; (void)alarmIndex; if (dev == NULL) { return HDF_FAILURE; } HdfTimeToLinuxTime(hdfTime, &(alarm.time)); alarm.enabled = 0; ret = rtc_set_alarm(dev, &alarm); if (ret < 0) { HDF_LOGE("%s: rtc_read_alarm error, ret is %d", __func__, ret); return ret; } HdfPutRtcDevice(dev); return HDF_SUCCESS; } static int32_t HiAlarmInterruptEnable(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable) { int32_t ret; struct rtc_device *dev = HdfGetRtcDevice(); (void)host; (void)alarmIndex; if (dev == NULL) { return HDF_FAILURE; } ret = rtc_alarm_irq_enable(dev, enable); if (ret < 0) { HDF_LOGE("%s: rtc_read_alarm error, ret is %d", __func__, ret); return ret; } HdfPutRtcDevice(dev); return HDF_SUCCESS; } static struct RtcMethod g_method = { .ReadTime = HiRtcReadTime, .WriteTime = HiRtcWriteTime, .ReadAlarm = HiReadAlarm, .WriteAlarm = HiWriteAlarm, .RegisterAlarmCallback = NULL, .AlarmInterruptEnable = HiAlarmInterruptEnable, .GetFreq = NULL, .SetFreq = NULL, .Reset = NULL, .ReadReg = NULL, .WriteReg = NULL, }; static int32_t HiRtcBind(struct HdfDeviceObject *device) { struct RtcHost *host = NULL; host = RtcHostCreate(device); if (host == NULL) { HDF_LOGE("%s: create host fail", __func__); return HDF_ERR_INVALID_OBJECT; } host->device = device; device->service = &host->service; return HDF_SUCCESS; } static int32_t HiRtcInit(struct HdfDeviceObject *device) { struct RtcHost *host = NULL; if (device == NULL) { HDF_LOGE("%s: err, device is null", __func__); return HDF_ERR_INVALID_OBJECT; } host = RtcHostFromDevice(device); host->method = &g_method; HDF_LOGI("%s: Hdf dev service:%s init success", __func__, HdfDeviceGetServiceName(device)); return HDF_SUCCESS; } static void HiRtcRelease(struct HdfDeviceObject *device) { struct RtcHost *host = NULL; if (device == NULL) { return; } host = RtcHostFromDevice(device); RtcHostDestroy(host); } struct HdfDriverEntry g_rtcDriverEntry = { .moduleVersion = 1, .Bind = HiRtcBind, .Init = HiRtcInit, .Release = HiRtcRelease, .moduleName = "HDF_PLATFORM_RTC", }; HDF_INIT(g_rtcDriverEntry);