1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong 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 "watchdog.h"
17
18 /**
19 * fls - find last (most-significant) bit set
20 * @x: the word to search
21 *
22 * This is defined the same way as ffs.
23 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
24 */
25 #define START_FLS 32
26 #define OFFSET16 16
27 #define OFFSET8 8
28 #define OFFSET4 4
29 #define OFFSET2 2
30 #define OFFSET1 1
31 #define BORDER_MULTIPLE 1000
32 #define TWO_TO_TENTH 1024
generic_fls(int t)33 static int generic_fls(int t)
34 {
35 int r = START_FLS;
36 int x = t;
37 if (!x) {
38 return 0;
39 }
40 if (!(x & 0xffff0000u)) {
41 x <<= OFFSET16;
42 r -= OFFSET16;
43 }
44 if (!(x & 0xff000000u)) {
45 x <<= OFFSET8;
46 r -= OFFSET8;
47 }
48 if (!(x & 0xf0000000u)) {
49 x <<= OFFSET4;
50 r -= OFFSET4;
51 }
52 if (!(x & 0xc0000000u)) {
53 x <<= OFFSET2;
54 r -= OFFSET2;
55 }
56 if (!(x & 0x80000000u)) {
57 x <<= OFFSET1;
58 r -= OFFSET1;
59 }
60 return r;
61 }
62
ilog2(unsigned int x)63 static inline int ilog2(unsigned int x)
64 {
65 return generic_fls(x) - 1;
66 }
67
roundup_pow_of_two(unsigned long n)68 unsigned long roundup_pow_of_two(unsigned long n)
69 {
70 return 1UL << generic_fls(n - 1);
71 }
72
reg_read(void volatile * base,uint32_t reg)73 static inline uint32_t reg_read(void volatile *base, uint32_t reg)
74 {
75 return OSAL_READL((uintptr_t)base + reg);
76 }
77
reg_write(void volatile * base,uint32_t reg,uint32_t val)78 static inline void reg_write(void volatile *base, uint32_t reg, uint32_t val)
79 {
80 OSAL_WRITEL(val, (uintptr_t)base + reg);
81 }
82
83 // get clock source real rate
GD450wdgGetClockRate(struct GD450wdg * iwdg)84 static inline int32_t GD450wdgGetClockRate(struct GD450wdg *iwdg)
85 {
86 int ret = HDF_SUCCESS;
87
88 /*
89 if "clock_source" is set, use the real rate of clock source
90 otherwise, use the default clock rate
91 */
92 if (iwdg->clock_source != NULL) {
93 // get clock source real rate.
94 // ...
95 ret = HDF_SUCCESS;
96 }
97
98 return ret;
99 }
100
GD450wdgGetSr(struct GD450wdg * iwdg)101 static inline uint32_t GD450wdgGetSr(struct GD450wdg *iwdg)
102 {
103 return reg_read(iwdg->base, IWDG_SR);
104 }
105
GD450wdgStart(struct WatchdogCntlr * wdt)106 int32_t GD450wdgStart(struct WatchdogCntlr *wdt)
107 {
108 struct GD450wdg *iwdg = NULL;
109 uint32_t tout, presc, iwdg_pr, iwdg_rlr, iwdg_sr;
110 uint32_t i = 10;
111
112 if (wdt == NULL) {
113 return HDF_ERR_INVALID_OBJECT;
114 }
115 iwdg = (struct GD450wdg *)wdt->priv;
116
117 // 计算装载值
118 tout = iwdg->seconds; // 超时秒数
119
120 // 计算边界
121 if (tout > (iwdg->max_hw_heartbeat_ms * BORDER_MULTIPLE)) {
122 tout = iwdg->max_hw_heartbeat_ms * BORDER_MULTIPLE;
123 }
124 if (tout < iwdg->min_timeout) {
125 tout = iwdg->min_timeout;
126 }
127
128 presc = DIV_ROUND_UP(tout * iwdg->rate, RLR_MAX + 1);
129
130 /* The prescaler is align on power of 2 and start at 2 ^ PR_SHIFT. */
131 presc = roundup_pow_of_two(presc);
132 iwdg_pr = (presc <= (1 << PR_SHIFT)) ? 0 : ilog2(presc) - PR_SHIFT;
133 if (presc == 0) {
134 return HDF_FAILURE;
135 }
136 iwdg_rlr = ((tout * iwdg->rate) / presc) - 1;
137
138 /* enable write access */
139 reg_write(iwdg->base, IWDG_KR, KR_KEY_EWA);
140
141 /* set prescaler & reload registers */
142 reg_write(iwdg->base, IWDG_PR, iwdg_pr);
143 reg_write(iwdg->base, IWDG_RLR, iwdg_rlr);
144 reg_write(iwdg->base, IWDG_KR, KR_KEY_ENABLE);
145
146 // 等待状态寄存器 SR_PVU | SR_RVU 复位
147 while ((iwdg_sr = GD450wdgGetSr(iwdg)) & (SR_PVU | SR_RVU)) {
148 if (!(--i)) {
149 HDF_LOGE("Fail to set prescaler, reload regs.");
150 return HDF_FAILURE;
151 }
152 }
153
154 /* reload watchdog */
155 reg_write(iwdg->base, IWDG_KR, KR_KEY_RELOAD);
156
157 /* iwdg start */
158 iwdg->start = true;
159
160 return HDF_SUCCESS;
161 }
162
GD450wdgSetTimeout(struct WatchdogCntlr * wdt,uint32_t seconds)163 int32_t GD450wdgSetTimeout(struct WatchdogCntlr *wdt, uint32_t seconds)
164 {
165 struct GD450wdg *iwdg = NULL;
166
167 if (wdt == NULL) {
168 return HDF_ERR_INVALID_OBJECT;
169 }
170
171 iwdg = (struct GD450wdg *)wdt->priv;
172 iwdg->seconds = seconds;
173
174 // 如果iwdg已经是启动状态, 需要重新装载超时值并继续喂狗操作
175 if (iwdg->start) {
176 return GD450wdgStart(wdt);
177 }
178
179 return HDF_SUCCESS;
180 }
181
GD450wdgGetTimeout(struct WatchdogCntlr * wdt,uint32_t * seconds)182 int32_t GD450wdgGetTimeout(struct WatchdogCntlr *wdt, uint32_t *seconds)
183 {
184 struct GD450wdg *iwdg = NULL;
185 if (wdt == NULL || seconds == NULL) {
186 return HDF_ERR_INVALID_OBJECT;
187 }
188 iwdg = (struct GD450wdg *)wdt->priv;
189
190 *seconds = iwdg->seconds;
191
192 return HDF_SUCCESS;
193 }
194
GD450wdgFeed(struct WatchdogCntlr * wdt)195 static int32_t GD450wdgFeed(struct WatchdogCntlr *wdt)
196 {
197 struct GD450wdg *iwdg = NULL;
198
199 if (wdt == NULL) {
200 return HDF_ERR_INVALID_OBJECT;
201 }
202 iwdg = (struct GD450wdg *)wdt->priv;
203
204 /* reload watchdog */
205 reg_write(iwdg->base, IWDG_KR, KR_KEY_RELOAD);
206
207 return HDF_SUCCESS;
208 }
209
GD450wdgGetStatus(struct WatchdogCntlr * wdt,int32_t * status)210 static int32_t GD450wdgGetStatus(struct WatchdogCntlr *wdt, int32_t *status)
211 {
212 (void)status;
213 int32_t ret = WATCHDOG_STOP;
214 struct GD450wdg *iwdg = NULL;
215
216 if (wdt == NULL) {
217 return HDF_ERR_INVALID_OBJECT;
218 }
219 iwdg = (struct GD450wdg *)wdt->priv;
220
221 if (iwdg->start) {
222 ret = WATCHDOG_START;
223 }
224 return ret;
225 }
226
227 /* WatchdogOpen 的时候被调用 */
GD450wdgGetPriv(struct WatchdogCntlr * wdt)228 static int32_t GD450wdgGetPriv(struct WatchdogCntlr *wdt)
229 {
230 int32_t ret;
231 struct GD450wdg *iwdg = NULL;
232
233 if (wdt == NULL) {
234 return HDF_ERR_INVALID_OBJECT;
235 }
236 iwdg = (struct GD450wdg *)wdt->priv;
237
238 // 获取当前时钟源频率
239 ret = GD450wdgGetClockRate(iwdg);
240 if (ret != HDF_SUCCESS) {
241 HDF_LOGE("GD450wdgGetClockRate fail, ret : %#x.", ret);
242 return HDF_FAILURE;
243 }
244
245 // 计算最大最小的超时时间
246 iwdg->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, iwdg->rate);
247 iwdg->max_hw_heartbeat_ms = ((RLR_MAX + 1) * TWO_TO_TENTH * BORDER_MULTIPLE) / iwdg->rate;
248
249 return ret;
250 }
251
252 /* WatchdogClose 的时候被调用 */
GD450wdgReleasePriv(struct WatchdogCntlr * wdt)253 static void GD450wdgReleasePriv(struct WatchdogCntlr *wdt)
254 {
255 (void)wdt;
256 }
257
258 static struct WatchdogMethod g_gd450_iwdg_ops = {.feed = GD450wdgFeed,
259 .getPriv = GD450wdgGetPriv,
260 .getStatus = GD450wdgGetStatus,
261 .getTimeout = GD450wdgGetTimeout,
262 .releasePriv = GD450wdgReleasePriv,
263 .setTimeout = GD450wdgSetTimeout,
264 .start = GD450wdgStart,
265 // iwdg不支持软件停止
266 .stop = NULL};
267
GD450wdgReadDrs(struct GD450wdg * iwdg,const struct DeviceResourceNode * node)268 static int32_t GD450wdgReadDrs(struct GD450wdg *iwdg, const struct DeviceResourceNode *node)
269 {
270 int32_t ret;
271 struct DeviceResourceIface *drsOps = NULL;
272
273 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
274 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
275 HDF_LOGE("%s: invalid drs ops!", __func__);
276 return HDF_FAILURE;
277 }
278
279 // num
280 ret = drsOps->GetUint32(node, "num", &iwdg->num, 0);
281 if (ret != HDF_SUCCESS) {
282 HDF_LOGE("%s: read num fail!", __func__);
283 return ret;
284 }
285
286 // reg_base
287 ret = drsOps->GetUint32(node, "reg_base", &iwdg->phy_base, 0);
288 if (ret != HDF_SUCCESS) {
289 HDF_LOGE("%s: read regBase fail!", __func__);
290 return ret;
291 }
292
293 // reg_step
294 ret = drsOps->GetUint32(node, "reg_step", &iwdg->reg_step, 0);
295 if (ret != HDF_SUCCESS) {
296 HDF_LOGE("%s: read regStep fail!", __func__);
297 return ret;
298 }
299
300 // default timeout
301 ret = drsOps->GetUint32(node, "timeout_sec", &iwdg->seconds, DEFAULT_TIMEOUT);
302 if (ret != HDF_SUCCESS) {
303 HDF_LOGE("%s: read timeout fail!", __func__);
304 return ret;
305 }
306
307 // default source rate
308 ret = drsOps->GetUint32(node, "clock_rate", &iwdg->rate, DEFAULT_CLOCK_RATE);
309 if (ret != HDF_SUCCESS) {
310 HDF_LOGE("%s: read clock_rate fail!", __func__);
311 return ret;
312 }
313
314 // start
315 iwdg->start = drsOps->GetBool(node, "start");
316
317 return HDF_SUCCESS;
318 }
319
GD450wdgBind(struct HdfDeviceObject * device)320 static int32_t GD450wdgBind(struct HdfDeviceObject *device)
321 {
322 int32_t ret;
323 struct GD450wdg *iwdg = NULL;
324
325 if (device == NULL || device->property == NULL) {
326 HDF_LOGE("%s: device or property is null!", __func__);
327 return HDF_ERR_INVALID_OBJECT;
328 }
329
330 // 申请内存空间
331 iwdg = (struct GD450wdg *)OsalMemCalloc(sizeof(struct GD450wdg));
332 if (iwdg == NULL) {
333 HDF_LOGE("%s: malloc iwdg fail!", __func__);
334 return HDF_ERR_MALLOC_FAIL;
335 }
336
337 // 解析配置
338 ret = GD450wdgReadDrs(iwdg, device->property);
339 if (ret != HDF_SUCCESS) {
340 HDF_LOGE("%s: read drs fail:%d", __func__, ret);
341 OsalMemFree(iwdg);
342 return ret;
343 }
344
345 // 寄存器映射
346 iwdg->base = OsalIoRemap(iwdg->phy_base, iwdg->reg_step);
347 if (iwdg->base == NULL) {
348 HDF_LOGE("%s: ioremap regbase fail!", __func__);
349 OsalMemFree(iwdg);
350 return HDF_ERR_IO;
351 }
352
353 // 填充操作符
354 iwdg->wdt.priv = (void *)iwdg;
355 iwdg->wdt.ops = &g_gd450_iwdg_ops;
356 iwdg->wdt.device = device;
357 iwdg->wdt.wdtId = iwdg->num;
358
359 // add device
360 ret = WatchdogCntlrAdd(&iwdg->wdt);
361 if (ret != HDF_SUCCESS) {
362 HDF_LOGE("%s: err add watchdog:%d.", __func__, ret);
363 OsalIoUnmap((void *)iwdg->base);
364 OsalMemFree(iwdg);
365 return ret;
366 }
367
368 return HDF_SUCCESS;
369 }
370
GD450wdgInit(struct HdfDeviceObject * device)371 static int32_t GD450wdgInit(struct HdfDeviceObject *device)
372 {
373 int32_t ret;
374 struct WatchdogCntlr *wdt = NULL;
375 struct GD450wdg *iwdg = NULL;
376
377 // get WatchdogCntlr
378 wdt = WatchdogCntlrFromDevice(device);
379 if (wdt == NULL) {
380 return HDF_FAILURE;
381 }
382 iwdg = (struct GD450wdg *)wdt->priv;
383
384 // get priv data(get clock source)
385 ret = GD450wdgGetPriv(wdt);
386 if (ret != HDF_SUCCESS) {
387 HDF_LOGE("GD450wdgGetPriv fail.");
388 return HDF_FAILURE;
389 }
390
391 // set default timeout
392 ret = GD450wdgSetTimeout(wdt, iwdg->seconds);
393 if (ret != HDF_SUCCESS) {
394 HDF_LOGE("GD450wdgSetTimeout fail.");
395 return HDF_FAILURE;
396 }
397
398 return HDF_SUCCESS;
399 }
400
GD450wdgRelease(struct HdfDeviceObject * device)401 static void GD450wdgRelease(struct HdfDeviceObject *device)
402 {
403 struct WatchdogCntlr *wdt = NULL;
404 struct GD450wdg *iwdg = NULL;
405
406 if (device == NULL) {
407 return;
408 }
409
410 wdt = WatchdogCntlrFromDevice(device);
411 if (wdt == NULL) {
412 return;
413 }
414 WatchdogCntlrRemove(wdt);
415
416 iwdg = (struct GD450wdg *)wdt->priv;
417 if (iwdg->base != NULL) {
418 OsalIoUnmap((void *)iwdg->base);
419 iwdg->base = NULL;
420 }
421 OsalMemFree(iwdg);
422 }
423
424 struct HdfDriverEntry g_hdf_driver_iwdg_entry = {
425 .moduleVersion = 1,
426 .Bind = GD450wdgBind,
427 .Init = GD450wdgInit,
428 .Release = GD450wdgRelease,
429 .moduleName = "gd450_iwdg",
430 };
431 HDF_INIT(g_hdf_driver_iwdg_entry);
432