Skip to content

Commit 3f7e614

Browse files
asmellbykartben
authored andcommitted
drivers: watchdog: gecko: Fix API corner cases
Properly return the correct error codes when the watchdog API is misused. Fail timeout install if WDT_FLAG_RESET_CPU_CORE is set, a watchdog reset will at a minimum cause a soft reset of the entire SoC. Signed-off-by: Aksel Skauge Mellbye <[email protected]>
1 parent de1ef0a commit 3f7e614

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

drivers/watchdog/wdt_gecko.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,25 @@ static int wdt_gecko_convert_window(uint32_t window, uint32_t period)
8787
return idx;
8888
}
8989

90+
static bool wdt_gecko_is_enabled(WDOG_TypeDef *wdog)
91+
{
92+
#if defined(CONFIG_SOC_FAMILY_SILABS_S2)
93+
return FIELD_GET(WDOG_EN_EN, wdog->EN);
94+
#else
95+
return FIELD_GET(WDOG_CTRL_EN, wdog->CTRL);
96+
#endif
97+
}
98+
9099
static int wdt_gecko_setup(const struct device *dev, uint8_t options)
91100
{
92101
const struct wdt_gecko_cfg *config = dev->config;
93102
struct wdt_gecko_data *data = dev->data;
94103
WDOG_TypeDef *wdog = config->base;
95104

105+
if (wdt_gecko_is_enabled(wdog)) {
106+
return -EBUSY;
107+
}
108+
96109
if (!data->timeout_installed) {
97110
LOG_ERR("No valid timeouts installed");
98111
return -EINVAL;
@@ -134,8 +147,14 @@ static int wdt_gecko_disable(const struct device *dev)
134147
struct wdt_gecko_data *data = dev->data;
135148
WDOG_TypeDef *wdog = config->base;
136149

137-
WDOGn_Enable(wdog, false);
150+
/* Always uninstall timeouts, independent of watchdog enable state */
138151
data->timeout_installed = false;
152+
153+
if (!wdt_gecko_is_enabled(wdog)) {
154+
return -EFAULT;
155+
}
156+
157+
WDOGn_Enable(wdog, false);
139158
LOG_DBG("Disabled the watchdog");
140159

141160
return 0;
@@ -144,10 +163,16 @@ static int wdt_gecko_disable(const struct device *dev)
144163
static int wdt_gecko_install_timeout(const struct device *dev,
145164
const struct wdt_timeout_cfg *cfg)
146165
{
166+
const struct wdt_gecko_cfg *config = dev->config;
147167
struct wdt_gecko_data *data = dev->data;
148-
data->wdog_config = (WDOG_Init_TypeDef)WDOG_INIT_DEFAULT;
149168
uint32_t installed_timeout;
150169

170+
data->wdog_config = (WDOG_Init_TypeDef)WDOG_INIT_DEFAULT;
171+
172+
if (wdt_gecko_is_enabled(config->base)) {
173+
return -EBUSY;
174+
}
175+
151176
if (data->timeout_installed) {
152177
LOG_ERR("No more timeouts can be installed");
153178
return -ENOMEM;
@@ -189,13 +214,12 @@ static int wdt_gecko_install_timeout(const struct device *dev,
189214
/* Set mode of watchdog and callback */
190215
switch (cfg->flags) {
191216
case WDT_FLAG_RESET_SOC:
192-
case WDT_FLAG_RESET_CPU_CORE:
193217
if (cfg->callback != NULL) {
194218
LOG_ERR("Reset mode with callback not supported\n");
195219
return -ENOTSUP;
196220
}
197221
data->wdog_config.resetDisable = false;
198-
LOG_DBG("Configuring reset CPU/SoC mode\n");
222+
LOG_DBG("Configuring reset SoC mode\n");
199223
break;
200224

201225
case WDT_FLAG_RESET_NONE:
@@ -204,6 +228,10 @@ static int wdt_gecko_install_timeout(const struct device *dev,
204228
LOG_DBG("Configuring non-reset mode\n");
205229
break;
206230

231+
case WDT_FLAG_RESET_CPU_CORE:
232+
LOG_ERR("CPU core only reset not supported");
233+
return -ENOTSUP;
234+
207235
default:
208236
LOG_ERR("Unsupported watchdog config flag");
209237
return -EINVAL;
@@ -224,6 +252,10 @@ static int wdt_gecko_feed(const struct device *dev, int channel_id)
224252
return -EINVAL;
225253
}
226254

255+
if (!wdt_gecko_is_enabled(wdog)) {
256+
return -EINVAL;
257+
}
258+
227259
WDOGn_Feed(wdog);
228260
LOG_DBG("Fed the watchdog");
229261

0 commit comments

Comments
 (0)