1 /*
2  * Copyright (c) 2021-2022 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3  *
4  * This file 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 "watchdog_bes.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "device_resource_if.h"
13 #include "hdf_device_desc.h"
14 #include "hdf_log.h"
15 #include "hal_trace.h"
16 #include "hal_sleep.h"
17 #include "watchdog_if.h"
18 
19 static int g_watchdogStart;
20 static int g_watchdogTimeout;
21 
22 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr);
23 static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr);
24 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds);
25 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds);
26 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status);
27 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr);
28 
29 struct WatchdogMethod g_WatchdogCntlrMethod = {
30     .getStatus = WatchdogDevGetStatus,
31     .setTimeout = WatchdogDevSetTimeout,
32     .getTimeout = WatchdogDevGetTimeout,
33     .start  = WatchdogDevStart,
34     .stop   = WatchdogDevStop,
35     .feed   = WatchdogDevFeed,
36     .getPriv = NULL, // WatchdogDevGetPriv
37     .releasePriv = NULL, // WatchdogDevReleasePriv
38 };
39 
WatchdogIrqHandler(enum HAL_WDT_ID_T id,enum HAL_WDT_EVENT_T event)40 static void WatchdogIrqHandler(enum HAL_WDT_ID_T id, enum HAL_WDT_EVENT_T event)
41 {
42     HDF_LOGD("%s: id %d event %d\r\n", __func__, id, event);
43 }
44 
InitWatchdogDevice(const struct WatchdogDevice * watchdogDevice)45 static int InitWatchdogDevice(const struct WatchdogDevice *watchdogDevice)
46 {
47     struct WatchdogResource *resource = NULL;
48     int32_t watchdogId;
49     if (watchdogDevice == NULL) {
50         HDF_LOGE("%s: invalid parameter\r\n", __func__);
51         return HDF_ERR_INVALID_PARAM;
52     }
53 
54     resource = &watchdogDevice->resource;
55     if (resource == NULL) {
56         HDF_LOGE("resource is NULL\r\n");
57         return HDF_ERR_INVALID_OBJECT;
58     }
59 
60     watchdogId = resource->watchdogId;
61     hal_wdt_set_irq_callback(watchdogId, WatchdogIrqHandler);
62     return HDF_SUCCESS;
63 }
64 
GetWatchdogDeviceResource(struct WatchdogDevice * device,const struct DeviceResourceNode * resourceNode)65 static uint32_t GetWatchdogDeviceResource(
66     struct WatchdogDevice *device, const struct DeviceResourceNode *resourceNode)
67 {
68     struct WatchdogResource *resource = NULL;
69     struct DeviceResourceIface *dri = NULL;
70     if (device == NULL || resourceNode == NULL) {
71         HDF_LOGE("resource or device is NULL\r\n");
72         return HDF_ERR_INVALID_PARAM;
73     }
74 
75     resource = &device->resource;
76     if (resource == NULL) {
77         HDF_LOGE("resource is NULL\r\n");
78         return HDF_ERR_INVALID_OBJECT;
79     }
80 
81     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
82     if (dri == NULL || dri->GetUint32 == NULL) {
83         HDF_LOGE("DeviceResourceIface is invalid\r\n");
84         return HDF_ERR_INVALID_OBJECT;
85     }
86     if (dri->GetUint32(resourceNode, "watchdogId", &resource->watchdogId, 0) != HDF_SUCCESS) {
87         HDF_LOGE("read watchdogId fail\r\n");
88         return HDF_FAILURE;
89     }
90     return HDF_SUCCESS;
91 }
92 
AttachWatchdogDevice(struct WatchdogCntlr * watchdogCntlr,struct HdfDeviceObject * device)93 static int32_t AttachWatchdogDevice(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device)
94 {
95     int32_t ret;
96     struct WatchdogDevice *watchdogDevice = NULL;
97 
98     if (device == NULL || device->property == NULL) {
99         HDF_LOGE("%s: param is NULL\r\n", __func__);
100         return HDF_FAILURE;
101     }
102 
103     watchdogDevice = (struct WatchdogDevice *)OsalMemAlloc(sizeof(struct WatchdogDevice));
104     if (watchdogDevice == NULL) {
105         HDF_LOGE("%s: OsalMemAlloc watchdogDevice error\r\n", __func__);
106         return HDF_ERR_MALLOC_FAIL;
107     }
108 
109     ret = GetWatchdogDeviceResource(watchdogDevice, device->property);
110     if (ret != HDF_SUCCESS) {
111         (void)OsalMemFree(watchdogDevice);
112         return HDF_FAILURE;
113     }
114 
115     watchdogCntlr->priv = watchdogDevice;
116     watchdogCntlr->wdtId = watchdogDevice->resource.watchdogId;
117 
118     return InitWatchdogDevice(watchdogDevice);
119 }
120 /* HdfDriverEntry method definitions */
121 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device);
122 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device);
123 static void WatchdogDriverRelease(struct HdfDeviceObject *device);
124 
125 /* HdfDriverEntry definitions */
126 struct HdfDriverEntry g_watchdogDriverEntry = {
127     .moduleVersion = 1,
128     .moduleName = "BES_WATCHDOG_MODULE_HDF",
129     .Bind = WatchdogDriverBind,
130     .Init = WatchdogDriverInit,
131     .Release = WatchdogDriverRelease,
132 };
133 
134 // Initialize HdfDriverEntry
135 HDF_INIT(g_watchdogDriverEntry);
136 
WatchdogDriverBind(struct HdfDeviceObject * device)137 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device)
138 {
139     struct WatchdogCntlr *watchdogCntlr = NULL;
140 
141     if (device == NULL) {
142         HDF_LOGE("hdfDevice object is null!\r\n");
143         return HDF_FAILURE;
144     }
145 
146     watchdogCntlr = (struct WatchdogCntlr *)OsalMemAlloc(sizeof(struct WatchdogCntlr));
147     if (watchdogCntlr == NULL) {
148         HDF_LOGE("%s: OsalMemAlloc watchdogCntlr error\r\n", __func__);
149         return HDF_ERR_MALLOC_FAIL;
150     }
151 
152     HDF_LOGI("Enter %s\r\n", __func__);
153     device->service = &watchdogCntlr->service;
154     watchdogCntlr->device = device;
155     watchdogCntlr->priv = NULL;
156     return HDF_SUCCESS;
157 }
158 
WatchdogDriverInit(struct HdfDeviceObject * device)159 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device)
160 {
161     int32_t ret;
162     struct WatchdogCntlr *watchdogCntlr = NULL;
163 
164     if (device == NULL) {
165         HDF_LOGE("%s: device is NULL\r\n", __func__);
166         return HDF_ERR_INVALID_OBJECT;
167     }
168 
169     HDF_LOGI("Enter %s:\r\n", __func__);
170 
171     watchdogCntlr = WatchdogCntlrFromDevice(device);
172     if (watchdogCntlr == NULL) {
173         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
174         return HDF_ERR_INVALID_PARAM;
175     }
176 
177     ret = AttachWatchdogDevice(watchdogCntlr, device);
178     if (ret != HDF_SUCCESS) {
179         OsalMemFree(watchdogCntlr);
180         HDF_LOGE("%s:attach error\r\n", __func__);
181         return HDF_ERR_INVALID_PARAM;
182     }
183 
184     watchdogCntlr->ops = &g_WatchdogCntlrMethod;
185 
186     HDF_LOGE("WatchdogDriverInit success!\r\n");
187     return ret;
188 }
189 
WatchdogDriverRelease(struct HdfDeviceObject * device)190 static void WatchdogDriverRelease(struct HdfDeviceObject *device)
191 {
192     struct WatchdogCntlr *watchdogCntlr = NULL;
193     struct WatchdogDevice *watchdogDevice = NULL;
194 
195     if (device == NULL) {
196         HDF_LOGE("device is null\r\n");
197         return;
198     }
199 
200     watchdogCntlr = WatchdogCntlrFromDevice(device);
201     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
202         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
203         return HDF_ERR_INVALID_PARAM;
204     }
205 
206     watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv;
207     OsalMemFree(watchdogDevice);
208     return;
209 }
210 
WatchdogDevStart(struct WatchdogCntlr * watchdogCntlr)211 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr)
212 {
213     struct WatchdogDevice *watchdogDevice = NULL;
214     int32_t watchdogId;
215 
216     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
217         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
218         return HDF_ERR_INVALID_PARAM;
219     }
220 
221     watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv;
222     watchdogId = watchdogDevice->resource.watchdogId;
223     hal_wdt_start(watchdogId);
224     g_watchdogStart = 1;
225     return HDF_SUCCESS;
226 }
227 
WatchdogDevStop(struct WatchdogCntlr * watchdogCntlr)228 static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr)
229 {
230     int32_t watchdogId;
231     struct WatchdogDevice *watchdogDevice = NULL;
232 
233     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
234         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
235         return HDF_FAILURE;
236     }
237 
238     watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv;
239     watchdogId = watchdogDevice->resource.watchdogId;
240     hal_wdt_stop(watchdogId);
241     g_watchdogStart = 0;
242     return HDF_SUCCESS;
243 }
244 
WatchdogDevSetTimeout(struct WatchdogCntlr * watchdogCntlr,uint32_t seconds)245 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds)
246 {
247     int32_t watchdogId;
248     struct WatchdogDevice *watchdogDevice = NULL;
249 
250     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
251         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
252         return HDF_ERR_INVALID_PARAM;
253     }
254     g_watchdogTimeout = seconds;
255     watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv;
256     watchdogId = watchdogDevice->resource.watchdogId;
257     hal_wdt_set_timeout(watchdogId, seconds);
258     return HDF_SUCCESS;
259 }
260 
WatchdogDevGetTimeout(struct WatchdogCntlr * watchdogCntlr,uint32_t * seconds)261 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds)
262 {
263     if (watchdogCntlr == NULL || seconds == NULL) {
264         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
265         return HDF_ERR_INVALID_PARAM;
266     }
267     *seconds = g_watchdogTimeout;
268     return HDF_SUCCESS;
269 }
270 
WatchdogDevGetStatus(struct WatchdogCntlr * watchdogCntlr,uint32_t * status)271 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status)
272 {
273     if (watchdogCntlr == NULL || status == NULL) {
274         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
275         return HDF_ERR_INVALID_PARAM;
276     }
277     if (g_watchdogStart == 1) {
278         *status = WATCHDOG_START;
279     } else {
280         *status = WATCHDOG_STOP;
281     }
282     return HDF_SUCCESS;
283 }
284 
WatchdogDevFeed(struct WatchdogCntlr * watchdogCntlr)285 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr)
286 {
287     struct WatchdogDevice *watchdogDevice = NULL;
288 
289     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
290         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
291         return HDF_ERR_INVALID_PARAM;
292     }
293 
294     watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv;
295     int32_t watchdogId = watchdogDevice->resource.watchdogId;
296     hal_wdt_ping(watchdogId);
297     return HDF_SUCCESS;
298 }
299 
WatchdogDevGetPriv(struct WatchdogCntlr * watchdogCntlr)300 static int32_t WatchdogDevGetPriv(struct WatchdogCntlr *watchdogCntlr)
301 {
302     (void)watchdogCntlr;
303     return HDF_SUCCESS;
304 }
305 
WatchdogDevReleasePriv(struct WatchdogCntlr * watchdogCntlr)306 static int32_t WatchdogDevReleasePriv(struct WatchdogCntlr *watchdogCntlr)
307 {
308     (void)watchdogCntlr;
309     return HDF_SUCCESS;
310 }
311