• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include "hcs_macro.h"
19 #include "hdf_config_macro.h"
20 #include "hdf_device_desc.h"
21 #include "hdf_log.h"
22 #include "watchdog_core.h"
23 #include "watchdog_if.h"
24 
25 #define REG32_READ(reg) (*(volatile uint32_t *)(reg))
26 #define REG32_WRITE(reg, value) (*(volatile uint32_t *)(reg) = value)
27 
28 #define RWDT_PROTECT_KEY 0x50d83aa1
29 #define RWDT_PROTECT 0x3ff480a4
30 #define RWDT_CFG0 0x3ff4808c
31 #define RWDT_CFG0_VALUE ((1 << 10) | (7 << 11) | (3 << 28) | (1 << 31))
32 #define RWDT_CFG1 0x3ff48090
33 #define RWDT_FEED 0x3ff480a0
34 #define RWDT_TICK_BASE 0x3ff48070
35 #define RWDT_TICK ((REG32_READ(RWDT_TICK_BASE) >> 30) & 3)
36 #define RWDT_WOG() REG32_WRITE(RWDT_FEED, (1 << 31))
37 #define RWDT_IS_RUN() (REG32_READ(RWDT_CFG0) & (1 << 31))
38 
39 #define SLOW_CK_TICK (150 * 1000)
40 #define XTAL_32K_TICK (32768)
41 #define CK8M_D256_OUT_TICK (8 * 1000 * 1000 / 256)
42 
43 typedef struct {
44     int watchdogId;
45     int timeout; // Maximum interval between watchdog feeding, unit: ms
46 } WatchdogDeviceInfo;
47 
48 static int g_watchdogStart = 0;
49 static int g_watchdogTimeout = 0;
50 
51 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr);
52 static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr);
53 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds);
54 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds);
55 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status);
56 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr);
57 
58 struct WatchdogMethod g_WatchdogCntlrMethod = {
59     .getStatus = WatchdogDevGetStatus,
60     .setTimeout = WatchdogDevSetTimeout,
61     .getTimeout = WatchdogDevGetTimeout,
62     .start = WatchdogDevStart,
63     .stop = WatchdogDevStop,
64     .feed = WatchdogDevFeed,
65     .getPriv = NULL,
66     .releasePriv = NULL,
67 };
68 
69 #define WATCHDOG_FIND_CONFIG(node, name, device)             \
70     do {                                                     \
71         if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
72             (device)->watchdogId = HCS_PROP(node, id);         \
73             (device)->timeout = HCS_PROP(node, timeout);       \
74             result = HDF_SUCCESS;                            \
75         }                                                    \
76     } while (0)
77 
78 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
79 #define PLATFORM_WATCHDOG_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), watchdog_config)
80 
GetWatchdogDeviceInfoResource(WatchdogDeviceInfo * device,const char * deviceMatchAttr)81 static uint32_t GetWatchdogDeviceInfoResource(WatchdogDeviceInfo *device, const char *deviceMatchAttr)
82 {
83     int32_t result = HDF_FAILURE;
84     if (device == NULL || deviceMatchAttr == NULL) {
85         HDF_LOGE("device or deviceMatchAttr is NULL");
86         return HDF_ERR_INVALID_PARAM;
87     }
88 
89     HCS_FOREACH_CHILD_VARGS(PLATFORM_WATCHDOG_CONFIG, WATCHDOG_FIND_CONFIG, deviceMatchAttr, device);
90 
91     if (result != HDF_SUCCESS) {
92         HDF_LOGE("resourceNode %s is NULL", deviceMatchAttr);
93         return result;
94     }
95 
96     return HDF_SUCCESS;
97 }
98 
AttachWatchdogDeviceInfo(struct WatchdogCntlr * watchdogCntlr,struct HdfDeviceObject * device)99 static int32_t AttachWatchdogDeviceInfo(struct WatchdogCntlr *watchdogCntlr, struct HdfDeviceObject *device)
100 {
101     int32_t ret;
102     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
103 
104     if (device == NULL || device->deviceMatchAttr == NULL) {
105         HDF_LOGE("%s: param is NULL", __func__);
106         return HDF_FAILURE;
107     }
108 
109     watchdogdeviceinfo = (WatchdogDeviceInfo *)OsalMemAlloc(sizeof(WatchdogDeviceInfo));
110     if (watchdogdeviceinfo == NULL) {
111         HDF_LOGE("%s: OsalMemAlloc WatchdogDeviceInfo error", __func__);
112         return HDF_ERR_MALLOC_FAIL;
113     }
114 
115     ret = GetWatchdogDeviceInfoResource(watchdogdeviceinfo, device->deviceMatchAttr);
116     if (ret != HDF_SUCCESS) {
117         (void)OsalMemFree(watchdogdeviceinfo);
118         return HDF_FAILURE;
119     }
120 
121     (void)OsalMutexInit(&watchdogCntlr->lock);
122 
123     watchdogCntlr->priv = watchdogdeviceinfo;
124     watchdogCntlr->wdtId = watchdogdeviceinfo->watchdogId;
125 
126     return HDF_SUCCESS;
127 }
128 
129 /* HdfDriverEntry method definitions */
130 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device);
131 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device);
132 static void WatchdogDriverRelease(struct HdfDeviceObject *device);
133 
134 /* HdfDriverEntry definitions */
135 struct HdfDriverEntry g_watchdogDriverEntry = {
136     .moduleVersion = 1,
137     .moduleName = "ESP32U4_WATCHDOG_MODULE_HDF",
138     .Bind = WatchdogDriverBind,
139     .Init = WatchdogDriverInit,
140     .Release = WatchdogDriverRelease,
141 };
142 
143 // Initialize HdfDriverEntry
144 HDF_INIT(g_watchdogDriverEntry);
145 
WatchdogDriverBind(struct HdfDeviceObject * device)146 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device)
147 {
148     struct WatchdogCntlr *watchdogCntlr = NULL;
149     if (device == NULL) {
150         HDF_LOGE("hdfDevice object is null!");
151         return HDF_FAILURE;
152     }
153 
154     watchdogCntlr = (struct WatchdogCntlr *)OsalMemAlloc(sizeof(struct WatchdogCntlr));
155     if (watchdogCntlr == NULL) {
156         HDF_LOGE("%s: OsalMemAlloc watchdogCntlr error", __func__);
157         return HDF_ERR_MALLOC_FAIL;
158     }
159 
160     device->service = &watchdogCntlr->service;
161     watchdogCntlr->device = device;
162     watchdogCntlr->priv = NULL;
163     return HDF_SUCCESS;
164 }
165 
WatchdogDriverInit(struct HdfDeviceObject * device)166 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device)
167 {
168     int32_t ret;
169     struct WatchdogCntlr *watchdogCntlr = NULL;
170 
171     if (device == NULL) {
172         HDF_LOGE("%s: device is NULL", __func__);
173         return HDF_ERR_INVALID_OBJECT;
174     }
175 
176     watchdogCntlr = WatchdogCntlrFromDevice(device);
177     if (watchdogCntlr == NULL) {
178         HDF_LOGE("%s: watchdogCntlr is NULL", __func__);
179         return HDF_ERR_INVALID_PARAM;
180     }
181 
182     ret = AttachWatchdogDeviceInfo(watchdogCntlr, device);
183     if (ret != HDF_SUCCESS) {
184         OsalMemFree(watchdogCntlr);
185         HDF_LOGE("%s:attach error", __func__);
186         return HDF_ERR_INVALID_PARAM;
187     }
188 
189     watchdogCntlr->ops = &g_WatchdogCntlrMethod;
190     HDF_LOGI("WatchdogDriverInit success!");
191     return ret;
192 }
193 
WatchdogDriverRelease(struct HdfDeviceObject * device)194 static void WatchdogDriverRelease(struct HdfDeviceObject *device)
195 {
196     struct WatchdogCntlr *watchdogCntlr = NULL;
197     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
198 
199     if (device == NULL) {
200         HDF_LOGE("device is null");
201         return;
202     }
203 
204     watchdogCntlr = WatchdogCntlrFromDevice(device);
205     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
206         HDF_LOGE("%s: watchdogCntlr is NULL", __func__);
207         return;
208     }
209 
210     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
211     if (watchdogdeviceinfo != NULL) {
212         OsalMemFree(watchdogdeviceinfo);
213     }
214     return;
215 }
216 
217 #define XTAL_TICK 1
218 #define CK8M_TICK 2
219 
WatchdogDevStart(struct WatchdogCntlr * watchdogCntlr)220 static int32_t WatchdogDevStart(struct WatchdogCntlr *watchdogCntlr)
221 {
222     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
223     int32_t watchdogId = 0;
224     int32_t timeout = 0;
225     int32_t ticks = 0;
226     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
227         HDF_LOGE("%s: watchdogCntlr is NULL", __func__);
228         return HDF_ERR_INVALID_PARAM;
229     }
230 
231     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
232     if (watchdogdeviceinfo == NULL) {
233         HDF_LOGE("%s: OBJECT is NULL", __func__);
234         return HDF_ERR_INVALID_OBJECT;
235     }
236 
237     watchdogId = watchdogdeviceinfo->watchdogId;
238     timeout = watchdogdeviceinfo->timeout;
239 
240     switch (RWDT_TICK) {
241         case XTAL_TICK:
242             ticks = XTAL_32K_TICK;
243             break;
244         case CK8M_TICK:
245             ticks = CK8M_D256_OUT_TICK;
246             break;
247         default:
248             ticks = SLOW_CK_TICK;
249             break;
250     }
251     REG32_WRITE(RWDT_PROTECT, RWDT_PROTECT_KEY);
252     RWDT_WOG();
253     REG32_WRITE(RWDT_CFG0, RWDT_CFG0_VALUE);
254     REG32_WRITE(RWDT_CFG1, (timeout * ticks));
255     REG32_WRITE(RWDT_PROTECT, 0);
256 
257     HDF_LOGI("Watchdog Started! timeout: %d second", timeout);
258     g_watchdogStart = 1;
259     return HDF_SUCCESS;
260 }
261 
WatchdogDevStop(struct WatchdogCntlr * watchdogCntlr)262 static int32_t WatchdogDevStop(struct WatchdogCntlr *watchdogCntlr)
263 {
264     if (!watchdogCntlr) {
265         return HDF_FAILURE;
266     }
267     if (!RWDT_IS_RUN()) {
268         return HDF_SUCCESS;
269     }
270     REG32_WRITE(RWDT_PROTECT, RWDT_PROTECT_KEY);
271     RWDT_WOG();
272     REG32_WRITE(RWDT_CFG0, 0);
273     REG32_WRITE(RWDT_PROTECT, 0);
274     return HDF_SUCCESS;
275 }
276 
WatchdogDevSetTimeout(struct WatchdogCntlr * watchdogCntlr,uint32_t seconds)277 static int32_t WatchdogDevSetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t seconds)
278 {
279     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
280     if (watchdogCntlr == NULL || watchdogCntlr->priv == NULL) {
281         HDF_LOGE("%s: watchdogCntlr is NULL", __func__);
282         return HDF_ERR_INVALID_PARAM;
283     }
284 
285     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
286     if (watchdogdeviceinfo == NULL) {
287         HDF_LOGE("%s: OBJECT is NULL", __func__);
288         return HDF_ERR_INVALID_OBJECT;
289     }
290 
291     watchdogdeviceinfo->timeout = seconds;
292 
293     return HDF_SUCCESS;
294 }
295 
WatchdogDevGetTimeout(struct WatchdogCntlr * watchdogCntlr,uint32_t * seconds)296 static int32_t WatchdogDevGetTimeout(struct WatchdogCntlr *watchdogCntlr, uint32_t *seconds)
297 {
298     WatchdogDeviceInfo *watchdogdeviceinfo = NULL;
299     if (watchdogCntlr == NULL || seconds == NULL) {
300         HDF_LOGE("%s: PARAM is NULL", __func__);
301         return HDF_ERR_INVALID_PARAM;
302     }
303 
304     watchdogdeviceinfo = (WatchdogDeviceInfo *)watchdogCntlr->priv;
305     if (watchdogdeviceinfo == NULL) {
306         HDF_LOGE("%s: OBJECT is NULL", __func__);
307         return HDF_ERR_INVALID_OBJECT;
308     }
309 
310     *seconds = watchdogdeviceinfo->timeout;
311     return HDF_SUCCESS;
312 }
313 
WatchdogDevGetStatus(struct WatchdogCntlr * watchdogCntlr,uint32_t * status)314 static int32_t WatchdogDevGetStatus(struct WatchdogCntlr *watchdogCntlr, uint32_t *status)
315 {
316     if (watchdogCntlr == NULL || status == NULL) {
317         HDF_LOGE("%s: PARAM is NULL", __func__);
318         return HDF_ERR_INVALID_PARAM;
319     }
320     if (g_watchdogStart == 1) {
321         *status = WATCHDOG_START;
322     } else {
323         *status = WATCHDOG_STOP;
324     }
325     return HDF_SUCCESS;
326 }
327 
WatchdogDevFeed(struct WatchdogCntlr * watchdogCntlr)328 static int32_t WatchdogDevFeed(struct WatchdogCntlr *watchdogCntlr)
329 {
330     if (!watchdogCntlr) {
331         return HDF_FAILURE;
332     }
333     REG32_WRITE(RWDT_PROTECT, RWDT_PROTECT_KEY);
334     RWDT_WOG();
335     REG32_WRITE(RWDT_PROTECT, 0);
336     return HDF_SUCCESS;
337 }