1 /*
2 * Copyright (c) 2022 HPMicro
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 <stdlib.h>
17 #include <stdio.h>
18 #include "device_resource_if.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_log.h"
21 #include "osal_mem.h"
22 #include "watchdog_if.h"
23 #include "watchdog_core.h"
24 #include "hpm_wdg_drv.h"
25
26 #define HDF_LOG_TAG HPMICRO_WATCHDOG_HDF
27
28 struct HPMWatchdogDevice {
29 uint32_t id;
30 uint32_t base;
31 int32_t status;
32 uint32_t timeoutSeconds;
33 };
34
GetStatus(struct WatchdogCntlr * wdt,int32_t * status)35 static int32_t GetStatus(struct WatchdogCntlr *wdt, int32_t *status)
36 {
37 struct HPMWatchdogDevice *hpmDev = (struct HPMWatchdogDevice *)wdt->priv;
38 *status = hpmDev->status;
39 HDF_LOGD("ID: %u, GetStatus: %d\n", hpmDev->id, *status);
40 return HDF_SUCCESS;
41 }
42
SetTimeout(struct WatchdogCntlr * wdt,uint32_t seconds)43 static int32_t SetTimeout(struct WatchdogCntlr *wdt, uint32_t seconds)
44 {
45 struct HPMWatchdogDevice *hpmDev = (struct HPMWatchdogDevice *)wdt->priv;
46
47 hpmDev->timeoutSeconds = seconds;
48 HDF_LOGD("ID: %u, SetTimeout: %d\n",hpmDev->id, seconds);
49 return HDF_SUCCESS;
50 }
51
GetTimeout(struct WatchdogCntlr * wdt,uint32_t * seconds)52 static int32_t GetTimeout(struct WatchdogCntlr *wdt, uint32_t *seconds)
53 {
54 struct HPMWatchdogDevice *hpmDev = (struct HPMWatchdogDevice *)wdt->priv;
55
56 *seconds = hpmDev->timeoutSeconds;
57 HDF_LOGD("ID: %u, GetTimeout: %d\n",hpmDev->id, *seconds);
58 return HDF_SUCCESS;
59 }
60
Start(struct WatchdogCntlr * wdt)61 static int32_t Start(struct WatchdogCntlr *wdt)
62 {
63 struct HPMWatchdogDevice *hpmDev = (struct HPMWatchdogDevice *)wdt->priv;
64 WDG_Type *base = (WDG_Type *)hpmDev->base;
65 uint32_t timeoutUs = hpmDev->timeoutSeconds * 1000000;
66 uint32_t interruptUs;
67 uint32_t interruptInterval;
68 uint32_t resetUs;
69 uint32_t resetInterval;
70 wdg_control_t wdgCfg;
71
72 interruptInterval = wdg_convert_interrupt_interval_from_us(WDG_EXT_CLK_FREQ, timeoutUs);
73 wdgCfg.reset_interval = 0;
74 wdgCfg.interrupt_interval = interruptInterval;
75 wdgCfg.reset_enable = 1;
76 wdgCfg.interrupt_enable = 0;
77 wdgCfg.clksrc = wdg_clksrc_extclk;
78 wdgCfg.wdg_enable = 0;
79 wdg_init(base, &wdgCfg);
80
81 /*
82 * To calculate high precision "reset_interval"
83 */
84 interruptUs = wdg_get_interrupt_interval_in_us(base, WDG_EXT_CLK_FREQ);
85 if (interruptUs > timeoutUs) {
86 resetUs = 0;
87 resetInterval = 0;
88 } else {
89 resetUs = timeoutUs - interruptUs;
90 resetInterval = wdg_convert_reset_interval_from_us(WDG_EXT_CLK_FREQ, resetUs);
91 }
92
93 wdgCfg.reset_interval = resetInterval;
94 wdgCfg.wdg_enable = 1;
95 wdg_init(base, &wdgCfg);
96
97 hpmDev->status = WATCHDOG_START;
98 HDF_LOGD("ID: %u, Start", hpmDev->id);
99 return HDF_SUCCESS;
100 }
101
Stop(struct WatchdogCntlr * wdt)102 static int32_t Stop(struct WatchdogCntlr *wdt)
103 {
104 struct HPMWatchdogDevice *hpmDev = (struct HPMWatchdogDevice *)wdt->priv;
105 WDG_Type *base = (WDG_Type *)hpmDev->base;
106 wdg_disable(base);
107 hpmDev->status = WATCHDOG_STOP;
108 HDF_LOGD("ID: %u, Stop", hpmDev->id);
109 return HDF_SUCCESS;
110 }
111
Feed(struct WatchdogCntlr * wdt)112 static int32_t Feed(struct WatchdogCntlr *wdt)
113 {
114 struct HPMWatchdogDevice *hpmDev = (struct HPMWatchdogDevice *)wdt->priv;
115 WDG_Type *base = (WDG_Type *)hpmDev->base;
116 wdg_restart(base);
117 return HDF_SUCCESS;
118 }
119
120 static struct WatchdogMethod watchdogOps = {
121 .getStatus = GetStatus,
122 .setTimeout = SetTimeout,
123 .getTimeout = GetTimeout,
124 .start = Start,
125 .stop = Stop,
126 .feed = Feed,
127 };
128
WatchdogDriverBind(struct HdfDeviceObject * device)129 static int32_t WatchdogDriverBind(struct HdfDeviceObject *device)
130 {
131 int32_t ret = HDF_SUCCESS;
132 struct WatchdogCntlr *watchdogCntlr;
133
134 if (device == NULL) {
135 ret = HDF_FAILURE;
136 HDF_LOGE("Bind: HdfDeviceObject null\n");
137 return ret;
138 }
139
140 watchdogCntlr = (struct WatchdogCntlr *)OsalMemCalloc(sizeof(struct WatchdogCntlr));
141 if (watchdogCntlr == NULL) {
142 ret = HDF_ERR_MALLOC_FAIL;
143 HDF_LOGE("Bind: Services malloc Failed!!!\n");
144 return ret;
145 }
146
147 watchdogCntlr->device = device;
148 watchdogCntlr->ops = &watchdogOps;
149
150 ret = WatchdogCntlrAdd(watchdogCntlr);
151 if (ret) {
152 HDF_LOGE("Bind: WatchdogCntlrAdd Failed: %d!!!\n", ret);
153 OsalMemFree(watchdogCntlr);
154 return ret;
155 }
156
157 HDF_LOGI("Bind: successed\n");
158 return ret;
159 }
160
WatchdogDriverInit(struct HdfDeviceObject * device)161 static int32_t WatchdogDriverInit(struct HdfDeviceObject *device)
162 {
163 int32_t ret = HDF_SUCCESS;
164
165 struct WatchdogCntlr *watchdogCntlr = WatchdogCntlrFromDevice(device);
166 if (watchdogCntlr == NULL) {
167 ret = HDF_FAILURE;
168 HDF_LOGE("Init: get WatchdogCntlr Failed!!!\n");
169 goto ERROR1;
170 }
171
172 struct HPMWatchdogDevice *hpmWdtDev = (struct HPMWatchdogDevice *)OsalMemCalloc(
173 sizeof(struct HPMWatchdogDevice));
174 if (hpmWdtDev == NULL) {
175 ret = HDF_ERR_MALLOC_FAIL;
176 HDF_LOGE("Init: HPMWatchdogDevice malloc Failed!!!\n");
177 goto ERROR1;
178 }
179
180 struct DeviceResourceIface *dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
181 if (dri == NULL) {
182 ret = HDF_FAILURE;
183 HDF_LOGE("Init: get DeviceResourceIface Failed!!!\n");
184 goto ERROR2;
185 }
186
187 dri->GetUint32(device->property, "id", &hpmWdtDev->id, 0);
188 dri->GetUint32(device->property, "base", &hpmWdtDev->base, 0);
189 HDF_LOGI("Init: hpmWdtDev->id: %u\n", hpmWdtDev->id);
190 HDF_LOGI("Init: hpmWdtDev->base: 0x%X\n", hpmWdtDev->base);
191
192 watchdogCntlr->wdtId = hpmWdtDev->id;
193 watchdogCntlr->priv = hpmWdtDev;
194
195 return ret;
196
197 ERROR2:
198 OsalMemFree(hpmWdtDev);
199 ERROR1:
200 return ret;
201 }
202
WatchdogDriverRelease(struct HdfDeviceObject * device)203 static void WatchdogDriverRelease(struct HdfDeviceObject *device)
204 {
205 if (device == NULL) {
206 return;
207 }
208
209 struct WatchdogCntlr *watchdogCntlr = WatchdogCntlrFromDevice(device);
210 if (watchdogCntlr) {
211 OsalMemFree(watchdogCntlr);
212 }
213 HDF_LOGI("Release");
214 return;
215 }
216
217
218 struct HdfDriverEntry g_watchdogDriverEntry = {
219 .moduleVersion = 1,
220 .moduleName = "HPMICRO_WATCHDOG_MODULE_HDF",
221 .Bind = WatchdogDriverBind,
222 .Init = WatchdogDriverInit,
223 .Release = WatchdogDriverRelease,
224 };
225
226 HDF_INIT(g_watchdogDriverEntry);