summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/stm32_iwdg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/stm32_iwdg.c')
-rw-r--r--drivers/watchdog/stm32_iwdg.c109
1 files changed, 7 insertions, 102 deletions
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index 4d252e558c..6ac9e7d56e 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -6,14 +6,11 @@
#include <common.h>
#include <init.h>
#include <watchdog.h>
-#include <restart.h>
#include <asm/io.h>
#include <of_device.h>
#include <linux/log2.h>
#include <linux/iopoll.h>
#include <linux/clk.h>
-#include <mfd/syscon.h>
-#include <reset_source.h>
/* IWDG registers */
#define IWDG_KR 0x00 /* Key register */
@@ -36,40 +33,12 @@
#define SR_PVU BIT(0) /* Watchdog prescaler value update */
#define SR_RVU BIT(1) /* Watchdog counter reload value update */
-#define RCC_MP_GRSTCSETR 0x404
-#define RCC_MP_RSTSCLRR 0x408
-#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
-
-#define STM32MP_RCC_RSTF_POR BIT(0)
-#define STM32MP_RCC_RSTF_BOR BIT(1)
-#define STM32MP_RCC_RSTF_PAD BIT(2)
-#define STM32MP_RCC_RSTF_HCSS BIT(3)
-#define STM32MP_RCC_RSTF_VCORE BIT(4)
-
-#define STM32MP_RCC_RSTF_MPSYS BIT(6)
-#define STM32MP_RCC_RSTF_MCSYS BIT(7)
-#define STM32MP_RCC_RSTF_IWDG1 BIT(8)
-#define STM32MP_RCC_RSTF_IWDG2 BIT(9)
-
-#define STM32MP_RCC_RSTF_STDBY BIT(11)
-#define STM32MP_RCC_RSTF_CSTDBY BIT(12)
-#define STM32MP_RCC_RSTF_MPUP0 BIT(13)
-#define STM32MP_RCC_RSTF_MPUP1 BIT(14)
-
/* set timeout to 100 ms */
#define TIMEOUT_US 100000
-struct stm32_reset_reason {
- uint32_t mask;
- enum reset_src_type type;
- int instance;
-};
-
struct stm32_iwdg {
struct watchdog wdd;
- struct restart_handler restart;
void __iomem *iwdg_base;
- struct regmap *rcc_regmap;
unsigned int timeout;
unsigned int rate;
};
@@ -79,17 +48,6 @@ static inline struct stm32_iwdg *to_stm32_iwdg(struct watchdog *wdd)
return container_of(wdd, struct stm32_iwdg, wdd);
}
-static void __noreturn stm32_iwdg_restart_handler(struct restart_handler *rst)
-{
- struct stm32_iwdg *wd = container_of(rst, struct stm32_iwdg, restart);
-
- regmap_update_bits(wd->rcc_regmap, RCC_MP_GRSTCSETR,
- RCC_MP_GRSTCSETR_MPSYSRST, RCC_MP_GRSTCSETR_MPSYSRST);
-
- mdelay(1000);
- hang();
-}
-
static void stm32_iwdg_ping(struct stm32_iwdg *wd)
{
writel(KR_KEY_RELOAD, wd->iwdg_base + IWDG_KR);
@@ -132,7 +90,7 @@ static int stm32_iwdg_set_timeout(struct watchdog *wdd, unsigned int timeout)
int ret;
if (!timeout)
- return -EINVAL; /* can't disable */
+ return -ENOSYS; /* can't disable */
if (timeout > wdd->timeout_max)
return -EINVAL;
@@ -149,47 +107,6 @@ static int stm32_iwdg_set_timeout(struct watchdog *wdd, unsigned int timeout)
return 0;
}
-static const struct stm32_reset_reason stm32_reset_reasons[] = {
- { STM32MP_RCC_RSTF_POR, RESET_POR, 0 },
- { STM32MP_RCC_RSTF_BOR, RESET_BROWNOUT, 0 },
- { STM32MP_RCC_RSTF_STDBY, RESET_WKE, 0 },
- { STM32MP_RCC_RSTF_CSTDBY, RESET_WKE, 1 },
- { STM32MP_RCC_RSTF_MPSYS, RESET_RST, 2 },
- { STM32MP_RCC_RSTF_MPUP0, RESET_RST, 0 },
- { STM32MP_RCC_RSTF_MPUP1, RESET_RST, 1 },
- { STM32MP_RCC_RSTF_IWDG1, RESET_WDG, 0 },
- { STM32MP_RCC_RSTF_IWDG2, RESET_WDG, 1 },
- { STM32MP_RCC_RSTF_PAD, RESET_EXT, 1 },
- { /* sentinel */ }
-};
-
-static int stm32_set_reset_reason(struct regmap *rcc)
-{
- enum reset_src_type type = RESET_UKWN;
- u32 reg;
- int ret;
- int i, instance = 0;
-
- ret = regmap_read(rcc, RCC_MP_RSTSCLRR, &reg);
- if (ret)
- return ret;
-
- for (i = 0; stm32_reset_reasons[i].mask; i++) {
- if (reg & stm32_reset_reasons[i].mask) {
- type = stm32_reset_reasons[i].type;
- instance = stm32_reset_reasons[i].instance;
- break;
- }
- }
-
- reset_source_set_prinst(type, RESET_SOURCE_DEFAULT_PRIORITY, instance);
-
- pr_info("STM32 RCC reset reason %s (MP_RSTSR: 0x%08x)\n",
- reset_source_name(), reg);
-
- return 0;
-}
-
struct stm32_iwdg_data {
bool has_pclk;
u32 max_prescaler;
@@ -208,8 +125,9 @@ static const struct of_device_id stm32_iwdg_of_match[] = {
{ .compatible = "st,stm32mp1-iwdg", .data = &stm32mp1_iwdg_data },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
-static int stm32_iwdg_probe(struct device_d *dev)
+static int stm32_iwdg_probe(struct device *dev)
{
struct stm32_iwdg_data *data;
struct stm32_iwdg *wd;
@@ -240,6 +158,8 @@ static int stm32_iwdg_probe(struct device_d *dev)
return ret;
wd->rate = clk_get_rate(clk);
+ if (wd->rate == 0)
+ return -EINVAL;
if (data->has_pclk) {
clk = clk_get(dev, "pclk");
@@ -256,6 +176,7 @@ static int stm32_iwdg_probe(struct device_d *dev)
wdd->set_timeout = stm32_iwdg_set_timeout;
wdd->timeout_max = (RLR_MAX + 1) * data->max_prescaler * 1000;
wdd->timeout_max /= wd->rate * 1000;
+ wdd->running = WDOG_HW_RUNNING_UNSUPPORTED; /* ONF bit not present in IP */
ret = watchdog_register(wdd);
if (ret) {
@@ -263,27 +184,11 @@ static int stm32_iwdg_probe(struct device_d *dev)
return ret;
}
- wd->restart.name = "stm32-iwdg";
- wd->restart.restart = stm32_iwdg_restart_handler;
- wd->restart.priority = 200;
-
- wd->rcc_regmap = syscon_regmap_lookup_by_compatible("st,stm32mp1-rcc");
- if (IS_ERR(wd->rcc_regmap))
- dev_warn(dev, "Cannot register restart handler\n");
-
- ret = restart_handler_register(&wd->restart);
- if (ret)
- dev_warn(dev, "Cannot register restart handler\n");
-
- ret = stm32_set_reset_reason(wd->rcc_regmap);
- if (ret)
- dev_warn(dev, "Cannot determine reset reason\n");
-
dev_info(dev, "probed\n");
return 0;
}
-static struct driver_d stm32_iwdg_driver = {
+static struct driver stm32_iwdg_driver = {
.name = "stm32-iwdg",
.probe = stm32_iwdg_probe,
.of_compatible = DRV_OF_COMPAT(stm32_iwdg_of_match),