1 /*
2  * Copyright (c) 2022 Jiangsu Hoperun Software Co., Ltd.
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 <stdlib.h>
10 #include <stdio.h>
11 #include "device_resource_if.h"
12 #include "hdf_device_desc.h"
13 #include "hdf_log.h"
14 #include "watchdog_if.h"
15 #include "watchdog_core.h"
16 #include "wm_regs.h"
17 #include "wm_cpu.h"
18 
19 struct WatchdogResource {
20     int32_t watchdogId;
21 };
22 
23 struct WatchdogDevice {
24     struct WatchdogResource resource;
25 };
26 
27 static int g_watchdogStart;
28 static int g_watchdogTimeout;
29 
30 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr);
31 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds);
32 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds);
33 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status);
34 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr);
35 
36 struct WatchdogMethod g_WatchdogCntlrMethod = {
37     .getStatus = WatchdogDevGetStatus,
38     .setTimeout = WatchdogDevSetTimeout,
39     .getTimeout = WatchdogDevGetTimeout,
40     .start  = WatchdogDevStart,
41     .stop   = NULL,  // WatchdogDevStop
42     .feed   = WatchdogDevFeed,
43     .getPriv = NULL, // WatchdogDevGetPriv
44     .releasePriv = NULL, // WatchdogDevReleasePriv
45 };
46 
WatchdogDevStart(struct WatchdogCntlr * watchdogCntlr)47 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr)
48 {
49     tls_watchdog_start_cal_elapsed_time();
50     g_watchdogStart = 1;
51     return HDF_SUCCESS;
52 }
53 
WatchdogDevSetTimeout(struct WatchdogCntlr * watchdogCntlr,uint32_t seconds)54 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds)
55 {
56     g_watchdogTimeout = seconds;
57     tls_watchdog_init(seconds);
58     return HDF_SUCCESS;
59 }
60 
WatchdogDevGetTimeout(struct WatchdogCntlr * watchdogCntlr,uint32_t * seconds)61 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds)
62 {
63     if (watchdogCntlr == NULL || seconds == NULL) {
64         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
65         return HDF_ERR_INVALID_PARAM;
66     }
67 
68     g_watchdogTimeout = tls_watchdog_stop_cal_elapsed_time();
69 
70     *seconds = g_watchdogTimeout;
71     return HDF_SUCCESS;
72 }
73 
WatchdogDevGetStatus(struct WatchdogCntlr * watchdogCntlr,uint32_t * status)74 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status)
75 {
76     if (watchdogCntlr == NULL || status == NULL) {
77         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
78         return HDF_ERR_INVALID_PARAM;
79     }
80     if (g_watchdogStart == 1) {
81         *status = WATCHDOG_START;
82     } else {
83         *status = WATCHDOG_STOP;
84     }
85     return HDF_SUCCESS;
86 }
87 
WatchdogDevFeed(struct WatchdogCntlr * watchdogCntlr)88 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr)
89 {
90     tls_sys_clk sysclk;
91 
92     tls_sys_clk_get(&sysclk);
93     if (g_watchdogStart == 1) {
94         tls_sys_reset();
95     }
96     return HDF_SUCCESS;
97 }
98 
InitWatchdogDevice(struct WatchdogDevice * watchdogDevice)99 static int InitWatchdogDevice(struct WatchdogDevice *watchdogDevice)
100 {
101     struct WatchdogResource *resource = NULL;
102     if (watchdogDevice == NULL) {
103         HDF_LOGE("%s: invaild parameter\r\n", __func__);
104         return HDF_ERR_INVALID_PARAM;
105     }
106 
107     resource = &watchdogDevice->resource;
108     if (resource == NULL) {
109         HDF_LOGE("resource is NULL\r\n");
110         return HDF_ERR_INVALID_OBJECT;
111     }
112 
113     return HDF_SUCCESS;
114 }
115 
GetWatchdogDeviceResource(struct WatchdogDevice * device,const struct DeviceResourceNode * resourceNode)116 static uint32_t GetWatchdogDeviceResource(
117     struct WatchdogDevice *device, const struct DeviceResourceNode *resourceNode)
118 {
119     struct WatchdogResource *resource = NULL;
120     struct DeviceResourceIface *dri = NULL;
121     if (device == NULL || resourceNode == NULL) {
122         HDF_LOGE("resource or device is NULL\r\n");
123         return HDF_ERR_INVALID_PARAM;
124     }
125 
126     resource = &device->resource;
127     if (resource == NULL) {
128         HDF_LOGE("resource is NULL\r\n");
129         return HDF_ERR_INVALID_OBJECT;
130     }
131 
132     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
133     if (dri == NULL || dri->GetUint32 == NULL) {
134         HDF_LOGE("DeviceResourceIface is invalid\r\n");
135         return HDF_ERR_INVALID_OBJECT;
136     }
137 
138     return HDF_SUCCESS;
139 }
140 
AttachWatchdogDevice(struct WatchdogCntlr * watchdogCntlr,struct HdfDeviceObject * device)141 static int32_t AttachWatchdogDevice(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device)
142 {
143     int32_t ret;
144     struct WatchdogDevice *watchdogDevice = NULL;
145 
146     if (device == NULL || device->property == NULL) {
147         HDF_LOGE("%s: param is NULL\r\n", __func__);
148         return HDF_FAILURE;
149     }
150 
151     watchdogDevice = (struct WatchdogDevice *)OsalMemAlloc(sizeof(struct WatchdogDevice));
152     if (watchdogDevice == NULL) {
153         HDF_LOGE("%s: OsalMemAlloc watchdogDevice error\r\n", __func__);
154         return HDF_ERR_MALLOC_FAIL;
155     }
156 
157     ret = GetWatchdogDeviceResource(watchdogDevice, device->property);
158     if (ret != HDF_SUCCESS) {
159         (void)OsalMemFree(watchdogDevice);
160         return HDF_FAILURE;
161     }
162 
163     watchdogCntlr->priv = watchdogDevice;
164 
165     return InitWatchdogDevice(watchdogDevice);
166 }
167 
168 /* HdfDriverEntry method definitions */
169 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device);
170 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device);
171 static void WatchdogDriverRelease(struct HdfDeviceObject *device);
172 
WatchdogDriverBind(struct HdfDeviceObject * device)173 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device)
174 {
175     struct WatchdogCntlr *watchdogCntlr = NULL;
176 
177     if (device == NULL) {
178         HDF_LOGE("hdfDevice object is null!\r\n");
179         return HDF_FAILURE;
180     }
181 
182     watchdogCntlr = (struct WatchdogCntlr *)OsalMemAlloc(sizeof(struct WatchdogCntlr));
183     if (watchdogCntlr == NULL) {
184         HDF_LOGE("%s: OsalMemAlloc watchdogCntlr error\r\n", __func__);
185         return HDF_ERR_MALLOC_FAIL;
186     }
187 
188     HDF_LOGI("Enter %s\r\n", __func__);
189     device->service = &watchdogCntlr->service;
190     watchdogCntlr->device = device;
191     watchdogCntlr->priv = NULL;
192     return HDF_SUCCESS;
193 }
194 
WatchdogDriverInit(struct HdfDeviceObject * device)195 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device)
196 {
197     int32_t ret;
198     struct WatchdogCntlr *watchdogCntlr = NULL;
199 
200     if (device == NULL) {
201         HDF_LOGE("%s: device is NULL\r\n", __func__);
202         return HDF_ERR_INVALID_OBJECT;
203     }
204 
205     HDF_LOGI("Enter %s:\r\n", __func__);
206 
207     watchdogCntlr = WatchdogCntlrFromDevice(device);
208     if (watchdogCntlr == NULL) {
209         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
210         return HDF_ERR_INVALID_PARAM;
211     }
212 
213     ret = AttachWatchdogDevice(watchdogCntlr, device);
214     if (ret != HDF_SUCCESS) {
215         OsalMemFree(watchdogCntlr);
216         HDF_LOGE("%s:attach error\r\n", __func__);
217         return HDF_ERR_INVALID_PARAM;
218     }
219 
220     watchdogCntlr->ops = &g_WatchdogCntlrMethod;
221 
222     HDF_LOGE("WatchdogDriverInit success!\r\n");
223     return ret;
224 }
225 
WatchdogDriverRelease(struct HdfDeviceObject * device)226 static void WatchdogDriverRelease(struct HdfDeviceObject *device)
227 {
228     struct WatchdogCntlr *watchdogCntlr = NULL;
229     struct WatchdogDevice *watchdogDevice = NULL;
230 
231     if (device == NULL) {
232         HDF_LOGE("device is null\r\n");
233         return;
234     }
235 
236     watchdogCntlr = WatchdogCntlrFromDevice(device);
237     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
238         HDF_LOGE("%s: watchdogCntlr is NULL\r\n", __func__);
239         return HDF_ERR_INVALID_PARAM;
240     }
241 
242     watchdogDevice = (struct WatchdogDevice *)watchdogCntlr->priv;
243     OsalMemFree(watchdogDevice);
244     return;
245 }
246 
247 /* HdfDriverEntry definitions */
248 struct HdfDriverEntry g_watchdogDriverEntry = {
249     .moduleVersion = 1,
250     .moduleName = "WM_WATCHDOG_MODULE_HDF",
251     .Bind = WatchdogDriverBind,
252     .Init = WatchdogDriverInit,
253     .Release = WatchdogDriverRelease,
254 };
255 
256 // Initialize HdfDriverEntry
257 HDF_INIT(g_watchdogDriverEntry);
258