• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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