1 /* SPDX-License-Identifier: Apache-2.0 */
2 /*
3 * Copyright (c) 2023 Intel Corporation
4 *
5 * Author: Adrian Warecki <adrian.warecki@intel.com>
6 */
7
8 #include <zephyr/drivers/watchdog.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/sys_clock.h>
11 #include <zephyr/math/ilog2.h>
12
13 #include "wdt_dw_common.h"
14 #include "wdt_dw.h"
15
16 LOG_MODULE_REGISTER(wdt_dw_common, CONFIG_WDT_LOG_LEVEL);
17
18 #define WDT_DW_FLAG_CONFIGURED 0x80000000
19
dw_wdt_check_options(const uint8_t options)20 int dw_wdt_check_options(const uint8_t options)
21 {
22 if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
23 LOG_WRN("Pausing watchdog by debugger is not configurable");
24 }
25
26 if (options & WDT_OPT_PAUSE_IN_SLEEP) {
27 LOG_WRN("Pausing watchdog in sleep is not configurable");
28 }
29
30 return 0;
31 }
32
dw_wdt_configure(const uint32_t base,const uint32_t config)33 int dw_wdt_configure(const uint32_t base, const uint32_t config)
34 {
35 uint32_t period;
36
37 if (!(config & WDT_DW_FLAG_CONFIGURED)) {
38 LOG_ERR("Timeout not installed.");
39 return -ENOTSUP;
40 }
41
42 /* Configure timeout */
43 period = config & ~WDT_DW_FLAG_CONFIGURED;
44
45 if (dw_wdt_dual_timeout_period_get(base)) {
46 dw_wdt_timeout_period_init_set(base, period);
47 }
48
49 dw_wdt_timeout_period_set(base, period);
50
51 /* Enable watchdog */
52 dw_wdt_enable(base);
53 dw_wdt_counter_restart(base);
54
55 return 0;
56 }
57
dw_wdt_calc_period(const uint32_t base,const uint32_t clk_freq,const struct wdt_timeout_cfg * config,uint32_t * period_out)58 int dw_wdt_calc_period(const uint32_t base, const uint32_t clk_freq,
59 const struct wdt_timeout_cfg *config, uint32_t *period_out)
60 {
61 uint64_t period64;
62 uint32_t period;
63
64 /* Window timeout is not supported by this driver */
65 if (config->window.min) {
66 LOG_ERR("Window timeout is not supported.");
67 return -ENOTSUP;
68 }
69
70 period64 = (uint64_t)clk_freq * config->window.max;
71 period64 /= 1000;
72 if (!period64 || (period64 >> 31)) {
73 LOG_ERR("Window max is out of range.");
74 return -EINVAL;
75 }
76
77 period = period64 - 1;
78 period = ilog2(period);
79
80 if (period >= dw_wdt_cnt_width_get(base)) {
81 LOG_ERR("Watchdog timeout too long.");
82 return -EINVAL;
83 }
84
85 /* The minimum counter value is 64k, maximum 2G */
86 *period_out = WDT_DW_FLAG_CONFIGURED | (period >= 15 ? period - 15 : 0);
87 return 0;
88 }
89
dw_wdt_probe(const uint32_t base,const uint32_t reset_pulse_length)90 int dw_wdt_probe(const uint32_t base, const uint32_t reset_pulse_length)
91 {
92 /* Check component type */
93 const uint32_t type = dw_wdt_comp_type_get(base);
94
95 if (type != WDT_COMP_TYPE_VALUE) {
96 LOG_ERR("Invalid component type %x", type);
97 return -ENODEV;
98 }
99
100 dw_wdt_reset_pulse_length_set(base, reset_pulse_length);
101
102 return 0;
103 }
104