• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * rtc_adapter.c
3  *
4  * rtc driver adapter of linux
5  *
6  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  */
18 
19 #include <linux/rtc.h>
20 #include "device_resource_if.h"
21 #include "hdf_device_desc.h"
22 #include "hdf_log.h"
23 #include "rtc_core.h"
24 
25 #define HDF_LOG_TAG RTC_ADAPTER
26 #define MONTH_DIFF 1
27 #define YEAR_BASE 1900
28 
HdfTimeToLinuxTime(const struct RtcTime * hdfTime,struct rtc_time * linuxTime)29 static inline void HdfTimeToLinuxTime(const struct RtcTime *hdfTime, struct rtc_time *linuxTime)
30 {
31     linuxTime->tm_sec = hdfTime->second;
32     linuxTime->tm_min = hdfTime->minute;
33     linuxTime->tm_hour = hdfTime->hour;
34     linuxTime->tm_mday = hdfTime->day;
35     linuxTime->tm_mon = hdfTime->month - MONTH_DIFF;
36     linuxTime->tm_year = hdfTime->year - YEAR_BASE;
37     linuxTime->tm_wday = hdfTime->weekday;
38     linuxTime->tm_yday = rtc_year_days(linuxTime->tm_mday, linuxTime->tm_mon, linuxTime->tm_year);
39 }
40 
LinuxTimeToHdfTime(struct RtcTime * hdfTime,const struct rtc_time * linuxTime)41 static inline void LinuxTimeToHdfTime(struct RtcTime *hdfTime, const struct rtc_time *linuxTime)
42 {
43     hdfTime->second = linuxTime->tm_sec;
44     hdfTime->minute = linuxTime->tm_min;
45     hdfTime->hour = linuxTime->tm_hour;
46     hdfTime->day = linuxTime->tm_mday;
47     hdfTime->month = linuxTime->tm_mon + MONTH_DIFF;
48     hdfTime->year = linuxTime->tm_year + YEAR_BASE;
49     hdfTime->weekday = linuxTime->tm_wday;
50 }
51 
HdfGetRtcDevice(void)52 static inline struct rtc_device *HdfGetRtcDevice(void)
53 {
54     struct rtc_device *dev = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
55 
56     if (dev == NULL) {
57         HDF_LOGE("%s: failed to get rtc device", __func__);
58     }
59     return dev;
60 }
61 
HdfPutRtcDevice(struct rtc_device * dev)62 static inline void HdfPutRtcDevice(struct rtc_device *dev)
63 {
64     rtc_class_close(dev);
65 }
66 
HiRtcReadTime(struct RtcHost * host,struct RtcTime * hdfTime)67 static int32_t HiRtcReadTime(struct RtcHost *host, struct RtcTime *hdfTime)
68 {
69     int32_t ret;
70     struct rtc_time linuxTime = {0};
71     struct rtc_device *dev = HdfGetRtcDevice();
72 
73     (void)host;
74     if (dev == NULL) {
75         return HDF_FAILURE;
76     }
77     ret = rtc_read_time(dev, &linuxTime);
78     if (ret < 0) {
79         HDF_LOGE("%s: rtc_read_time error, ret is %d", __func__, ret);
80         return ret;
81     }
82     HdfPutRtcDevice(dev);
83     LinuxTimeToHdfTime(hdfTime, &linuxTime);
84     return HDF_SUCCESS;
85 }
86 
HiRtcWriteTime(struct RtcHost * host,const struct RtcTime * hdfTime)87 static int32_t HiRtcWriteTime(struct RtcHost *host, const struct RtcTime *hdfTime)
88 {
89     int32_t ret;
90     struct rtc_time linuxTime = {0};
91     struct rtc_device *dev = HdfGetRtcDevice();
92 
93     (void)host;
94     if (dev == NULL) {
95         return HDF_FAILURE;
96     }
97     HdfTimeToLinuxTime(hdfTime, &linuxTime);
98     ret = rtc_set_time(dev, &linuxTime);
99     if (ret < 0) {
100         HDF_LOGE("%s: rtc_set_time error, ret is %d", __func__, ret);
101         return ret;
102     }
103 
104     HdfPutRtcDevice(dev);
105     return HDF_SUCCESS;
106 }
107 
HiReadAlarm(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,struct RtcTime * hdfTime)108 static int32_t HiReadAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *hdfTime)
109 {
110     int32_t ret;
111     struct rtc_wkalrm alarm = {0};
112     struct rtc_device *dev = HdfGetRtcDevice();
113 
114     (void)host;
115     (void)alarmIndex;
116     if (dev == NULL) {
117         return HDF_FAILURE;
118     }
119     ret = rtc_read_alarm(dev, &alarm);
120     if (ret < 0) {
121         HDF_LOGE("%s: rtc_read_alarm error, ret is %d", __func__, ret);
122         return ret;
123     }
124 
125     LinuxTimeToHdfTime(hdfTime, &(alarm.time));
126     HdfPutRtcDevice(dev);
127     return HDF_SUCCESS;
128 }
129 
HiWriteAlarm(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,const struct RtcTime * hdfTime)130 static int32_t HiWriteAlarm(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *hdfTime)
131 {
132     int32_t ret;
133     struct rtc_wkalrm alarm = {0};
134     struct rtc_device *dev = HdfGetRtcDevice();
135 
136     (void)host;
137     (void)alarmIndex;
138     if (dev == NULL) {
139         return HDF_FAILURE;
140     }
141 
142     HdfTimeToLinuxTime(hdfTime, &(alarm.time));
143     alarm.enabled = 0;
144     ret = rtc_set_alarm(dev, &alarm);
145     if (ret < 0) {
146         HDF_LOGE("%s: rtc_read_alarm error, ret is %d", __func__, ret);
147         return ret;
148     }
149 
150     HdfPutRtcDevice(dev);
151     return HDF_SUCCESS;
152 }
153 
HiAlarmInterruptEnable(struct RtcHost * host,enum RtcAlarmIndex alarmIndex,uint8_t enable)154 static int32_t HiAlarmInterruptEnable(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable)
155 {
156     int32_t ret;
157     struct rtc_device *dev = HdfGetRtcDevice();
158 
159     (void)host;
160     (void)alarmIndex;
161     if (dev == NULL) {
162         return HDF_FAILURE;
163     }
164     ret = rtc_alarm_irq_enable(dev, enable);
165     if (ret < 0) {
166         HDF_LOGE("%s: rtc_read_alarm error, ret is %d", __func__, ret);
167         return ret;
168     }
169 
170     HdfPutRtcDevice(dev);
171     return HDF_SUCCESS;
172 }
173 
174 static struct RtcMethod g_method = {
175     .ReadTime = HiRtcReadTime,
176     .WriteTime = HiRtcWriteTime,
177     .ReadAlarm = HiReadAlarm,
178     .WriteAlarm = HiWriteAlarm,
179     .RegisterAlarmCallback = NULL,
180     .AlarmInterruptEnable = HiAlarmInterruptEnable,
181     .GetFreq = NULL,
182     .SetFreq = NULL,
183     .Reset = NULL,
184     .ReadReg = NULL,
185     .WriteReg = NULL,
186 };
187 
HiRtcBind(struct HdfDeviceObject * device)188 static int32_t HiRtcBind(struct HdfDeviceObject *device)
189 {
190     struct RtcHost *host = NULL;
191 
192     host = RtcHostCreate(device);
193     if (host == NULL) {
194         HDF_LOGE("%s: create host fail", __func__);
195         return HDF_ERR_INVALID_OBJECT;
196     }
197 
198     host->device = device;
199     device->service = &host->service;
200     return HDF_SUCCESS;
201 }
202 
HiRtcInit(struct HdfDeviceObject * device)203 static int32_t HiRtcInit(struct HdfDeviceObject *device)
204 {
205     struct RtcHost *host = NULL;
206 
207     if (device == NULL) {
208         HDF_LOGE("%s: err, device is null", __func__);
209         return HDF_ERR_INVALID_OBJECT;
210     }
211     host = RtcHostFromDevice(device);
212     host->method = &g_method;
213     HDF_LOGI("%s: Hdf dev service:%s init success", __func__, HdfDeviceGetServiceName(device));
214     return HDF_SUCCESS;
215 }
216 
HiRtcRelease(struct HdfDeviceObject * device)217 static void HiRtcRelease(struct HdfDeviceObject *device)
218 {
219     struct RtcHost *host = NULL;
220 
221     if (device == NULL) {
222         return;
223     }
224 
225     host = RtcHostFromDevice(device);
226     RtcHostDestroy(host);
227 }
228 
229 struct HdfDriverEntry g_rtcDriverEntry = {
230     .moduleVersion = 1,
231     .Bind = HiRtcBind,
232     .Init = HiRtcInit,
233     .Release = HiRtcRelease,
234     .moduleName = "HDF_PLATFORM_RTC",
235 };
236 
237 HDF_INIT(g_rtcDriverEntry);
238