• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Talkweb Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include <stdlib.h>
10 #include <stdio.h>
11 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
12 #include "hcs_macro.h"
13 #include "hdf_config_macro.h"
14 #else
15 #include "device_resource_if.h"
16 #endif
17 #include "hdf_device_desc.h"
18 #include "hdf_log.h"
19 #include "watchdog_core.h"
20 #include "watchdog_if.h"
21 
22 #define WATCHDOG_MIN_TIMEOUT    1
23 #define WATCHDOG_MAX_TIMEOUT    4096
24 #define WATCHDOG_UPDATE_TIME    (((6UL * 256UL * 1000UL) / LSI_VALUE) + ((LSI_STARTUP_TIME / 1000UL) + 1UL))
25 
26 typedef struct {
27     int watchdogId;
28     int timeout;    // Maximum interval between watchdog feeding, unit: ms
29 } WatchdogDeviceInfo;
30 
31 static IWDG_TypeDef *hdf_iwdg = NULL;
32 static int g_watchdogStart = 0;
33 static int g_watchdogTimeout = 0;
34 
35 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr);
36 static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr);
37 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds);
38 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds);
39 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status);
40 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr);
41 
42 struct WatchdogMethod g_WatchdogCntlrMethod = {
43     .getStatus = WatchdogDevGetStatus,
44     .setTimeout = WatchdogDevSetTimeout,
45     .getTimeout = WatchdogDevGetTimeout,
46     .start  = WatchdogDevStart,
47     .stop   = WatchdogDevStop,
48     .feed   = WatchdogDevFeed,
49     .getPriv = NULL,
50     .releasePriv = NULL,
51 };
52 
InitWatchdogDeviceInfo(const WatchdogDeviceInfo * watchdogdeviceinfo)53 static int InitWatchdogDeviceInfo(const WatchdogDeviceInfo *watchdogdeviceinfo)
54 {
55     if (watchdogdeviceinfo == NULL) {
56         HDF_LOGE("%s: invaild parameter\r\n", __func__);
57         return HDF_ERR_INVALID_PARAM;
58     }
59     return HDF_SUCCESS;
60 }
61 
62 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
63 #define WATCHDOG_FIND_CONFIG(node, name, device) \
64     do { \
65         if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
66             device->watchdogId = HCS_PROP(node, id); \
67             device->timeout = HCS_PROP(node, timeout); \
68             result = HDF_SUCCESS; \
69         } \
70     } while (0)
71 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
72 #define PLATFORM_WATCHDOG_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), watchdog_config)
GetWatchdogDeviceInfoResource(WatchdogDeviceInfo * device,const char * deviceMatchAttr)73 static uint32_t GetWatchdogDeviceInfoResource(WatchdogDeviceInfo *device, const char *deviceMatchAttr)
74 {
75     int32_t result = HDF_FAILURE;
76     if (device == NULL || deviceMatchAttr == NULL) {
77         HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
78         return HDF_ERR_INVALID_PARAM;
79     }
80 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, watchdog_config)
81     HCS_FOREACH_CHILD_VARGS(PLATFORM_WATCHDOG_CONFIG, WATCHDOG_FIND_CONFIG, deviceMatchAttr, device);
82 #endif
83     if (result != HDF_SUCCESS) {
84         HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
85         return result;
86     }
87 
88     return HDF_SUCCESS;
89 }
90 #else
GetWatchdogDeviceInfoResource(WatchdogDeviceInfo * device,const struct DeviceResourceNode * resourceNode)91 static uint32_t GetWatchdogDeviceInfoResource(WatchdogDeviceInfo *device, const struct DeviceResourceNode *resourceNode)
92 {
93     struct DeviceResourceIface *dri = NULL;
94     if (device == NULL || resourceNode == NULL) {
95         HDF_LOGE("resource or device is NULL\r\n");
96         return HDF_ERR_INVALID_PARAM;
97     }
98 
99     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
100     if (dri == NULL || dri->GetUint32 == NULL) {
101         HDF_LOGE("DeviceResourceIface is invalid\r\n");
102         return HDF_ERR_INVALID_OBJECT;
103     }
104 
105     if (dri->GetUint32(resourceNode, "id", &device->watchdogId, 0) != HDF_SUCCESS) {
106         HDF_LOGE("read watchdogId fail\r\n");
107         return HDF_FAILURE;
108     }
109     if (dri->GetUint32(resourceNode, "timeout", &device->timeout, 0) != HDF_SUCCESS) {
110         HDF_LOGE("read watchdogId fail\r\n");
111         return HDF_FAILURE;
112     }
113 
114     HDF_LOGI("watchdogId = %d\n", device->watchdogId);
115     HDF_LOGI("timeout = %dms\n", device->timeout);
116 
117     return HDF_SUCCESS;
118 }
119 #endif
120 
AttachWatchdogDeviceInfo(struct WatchdogCntlr * watchdogCntlr,struct HdfDeviceObject * device)121 static int32_t AttachWatchdogDeviceInfo(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device)
122 {
123     int32_t ret;
124     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
125 
126 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
127     if (device == NULL || device->deviceMatchAttr == NULL) {
128 #else
129     if (device == NULL || device->property == NULL) {
130 #endif
131         HDF_LOGE("%s: param is NULL\r\n", __func__);
132         return HDF_FAILURE;
133     }
134 
135     watchdogdeviceinfo = (WatchdogDeviceInfo *)OsalMemAlloc(sizeof(WatchdogDeviceInfo));
136     if (watchdogdeviceinfo == NULL) {
137         HDF_LOGE("%s: OsalMemAlloc WatchdogDeviceInfo error\r\n", __func__);
138         return HDF_ERR_MALLOC_FAIL;
139     }
140 
141 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
142     ret = GetWatchdogDeviceInfoResource(watchdogdeviceinfo, device->deviceMatchAttr);
143 #else
144     ret = GetWatchdogDeviceInfoResource(watchdogdeviceinfo, device->property);
145 #endif
146     if (ret != HDF_SUCCESS) {
147         (void)OsalMemFree(watchdogdeviceinfo);
148         return HDF_FAILURE;
149     }
150 
151     (void)OsalMutexInit(&watchdogCntlr->lock);
152 
153     watchdogCntlr->priv = watchdogdeviceinfo;
154     watchdogCntlr->wdtId = watchdogdeviceinfo->watchdogId;
155 
156     return InitWatchdogDeviceInfo(watchdogdeviceinfo);
157 }
158 /* HdfDriverEntry method definitions */
159 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device);
160 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device);
161 static void WatchdogDriverRelease(struct HdfDeviceObject *device);
162 
163 /* HdfDriverEntry definitions */
164 struct HdfDriverEntry g_watchdogDriverEntry = {
165     .moduleVersion = 1,
166     .moduleName = "ST_WATCHDOG_MODULE_HDF",
167     .Bind = WatchdogDriverBind,
168     .Init = WatchdogDriverInit,
169     .Release = WatchdogDriverRelease,
170 };
171 
172 // Initialize HdfDriverEntry
173 HDF_INIT(g_watchdogDriverEntry);
174 
175 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device)
176 {
177     struct WatchdogCntlr *watchdogCntlr = NULL;
178 
179     if (device == NULL) {
180         HDF_LOGE("hdfDevice object is null!\r\n");
181         return HDF_FAILURE;
182     }
183 
184     watchdogCntlr = (struct WatchdogCntlr *)OsalMemAlloc(sizeof(struct WatchdogCntlr));
185     if (watchdogCntlr == NULL) {
186         HDF_LOGE("%s: OsalMemAlloc watchdogCntlr error\r\n", __func__);
187         return HDF_ERR_MALLOC_FAIL;
188     }
189 
190     HDF_LOGI("Enter %s\r\n", __func__);
191     device->service = &watchdogCntlr->service;
192     watchdogCntlr->device = device;
193     watchdogCntlr->priv = NULL;
194     return HDF_SUCCESS;
195 }
196 
197 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device)
198 {
199     int32_t ret;
200     struct WatchdogCntlr *watchdogCntlr = NULL;
201 
202     if (device == NULL) {
203         HDF_LOGE("%s: device is NULL\r\n", __func__);
204         return HDF_ERR_INVALID_OBJECT;
205     }
206 
207     HDF_LOGI("Enter %s:\r\n", __func__);
208 
209     watchdogCntlr = WatchdogCntlrFromDevice(device);
210     if (watchdogCntlr == NULL) {
211         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
212         return HDF_ERR_INVALID_PARAM;
213     }
214 
215     ret = AttachWatchdogDeviceInfo(watchdogCntlr, device);
216     if (ret != HDF_SUCCESS) {
217         OsalMemFree(watchdogCntlr);
218         HDF_LOGE("%s:attach error\r\n", __func__);
219         return HDF_ERR_INVALID_PARAM;
220     }
221 
222     watchdogCntlr->ops = &g_WatchdogCntlrMethod;
223 
224     HDF_LOGI("WatchdogDriverInit success!\r\n");
225     return ret;
226 }
227 
228 static void WatchdogDriverRelease(struct HdfDeviceObject *device)
229 {
230     struct WatchdogCntlr *watchdogCntlr = NULL;
231     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
232 
233     if (device == NULL) {
234         HDF_LOGE("device is null\r\n");
235         return;
236     }
237 
238     watchdogCntlr = WatchdogCntlrFromDevice(device);
239     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
240         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
241         return;
242     }
243 
244     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
245     OsalMemFree(watchdogdeviceinfo);
246     return;
247 }
248 
249 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr)
250 {
251     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
252     int32_t watchdogId = 0;
253     int32_t timeout = 0;
254     unsigned long long tickstart = 0;
255 
256     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
257         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
258         return HDF_ERR_INVALID_PARAM;
259     }
260 
261     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
262     watchdogId = watchdogdeviceinfo->watchdogId;
263     timeout = watchdogdeviceinfo->timeout;
264 
265     if (timeout < WATCHDOG_MIN_TIMEOUT) {
266         HDF_LOGW("%s: watchdog timeout must >= 1, set the timeout to 1ms\r\n", __func__);
267         timeout = WATCHDOG_MIN_TIMEOUT;
268     }
269     if (timeout > WATCHDOG_MAX_TIMEOUT) {
270         HDF_LOGW("%s: watchdog timeout must <= 1, set the timeout to 4096ms\r\n", __func__);
271         timeout = WATCHDOG_MAX_TIMEOUT;
272     }
273 
274     HDF_LOGI("%s: watchdog Started! timeout: %dms\r\n", __func__, timeout);
275 
276     hdf_iwdg = IWDG;  // Point to watchdog register
277     hdf_iwdg->KR = IWDG_KEY_ENABLE;
278     hdf_iwdg->KR = IWDG_KEY_WRITE_ACCESS_ENABLE;
279     hdf_iwdg->PR = IWDG_PRESCALER_32;   // 32 frequency division
280     hdf_iwdg->RLR = timeout - 1;        // 32K crystal oscillator corresponds to 1-4096ms under 32 prescaled frequency
281 
282     tickstart = (unsigned long long)LOS_TickCountGet();
283     // Wait for the register value to be updated and confirm that the watchdog is started successfully
284     while ((hdf_iwdg->SR & (IWDG_SR_RVU | IWDG_SR_PVU)) != 0x00u) {
285         if ((LOS_TickCountGet() - tickstart) > WATCHDOG_UPDATE_TIME) {
286             if ((hdf_iwdg->SR & (IWDG_SR_RVU | IWDG_SR_PVU)) != 0x00u) {
287                 return HDF_FAILURE;
288             }
289         }
290     }
291     hdf_iwdg->KR = IWDG_KEY_RELOAD;  // Reload initial value
292 
293     g_watchdogStart = 1;
294     return HDF_SUCCESS;
295 }
296 
297 static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr)
298 {
299     HDF_LOGW("%s: WatchdogDevStop fail,because of soc not support!!\r\n", __func__);
300     return HDF_FAILURE;
301 }
302 
303 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds)
304 {
305     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
306 
307     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
308         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
309         return HDF_ERR_INVALID_PARAM;
310     }
311 
312     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
313     watchdogdeviceinfo->timeout = seconds;
314     return HDF_SUCCESS;
315 }
316 
317 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds)
318 {
319     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
320 
321     if (watchdogCntlr == NULL || seconds == NULL) {
322         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
323         return HDF_ERR_INVALID_PARAM;
324     }
325 
326     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
327     if (watchdogdeviceinfo == NULL) {
328         HDF_LOGE("%s: OBJECT is NULL\r\n", __func__);
329         return HDF_ERR_INVALID_OBJECT;
330     }
331 
332     *seconds = watchdogdeviceinfo->timeout;
333     return HDF_SUCCESS;
334 }
335 
336 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status)
337 {
338     if (watchdogCntlr == NULL || status == NULL) {
339         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
340         return HDF_ERR_INVALID_PARAM;
341     }
342     if (g_watchdogStart == 1) {
343         *status = WATCHDOG_START;
344     } else {
345         *status = WATCHDOG_STOP;
346     }
347     return HDF_SUCCESS;
348 }
349 
350 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr)
351 {
352     (void)watchdogCntlr;
353     if (hdf_iwdg != NULL)
354         hdf_iwdg->KR = IWDG_KEY_RELOAD;  // Reload initial value
355     return HDF_SUCCESS;
356 }
357 
358 static int32_t WatchdogDevGetPriv(struct WatchdogCntlr *watchdogCntlr)
359 {
360     (void)watchdogCntlr;
361     return HDF_SUCCESS;
362 }
363 
364 static int32_t WatchdogDevReleasePriv(struct WatchdogCntlr *watchdogCntlr)
365 {
366     (void)watchdogCntlr;
367     return HDF_SUCCESS;
368 }