diff options
| -rw-r--r-- | doc/usage/cmd/wdt.rst | 2 | ||||
| -rw-r--r-- | drivers/watchdog/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/watchdog/designware_wdt.c | 2 | ||||
| -rw-r--r-- | drivers/watchdog/mpc8xxx_wdt.c | 2 | ||||
| -rw-r--r-- | drivers/watchdog/octeontx_wdt.c | 3 | ||||
| -rw-r--r-- | drivers/watchdog/orion_wdt.c | 101 | ||||
| -rw-r--r-- | drivers/watchdog/rti_wdt.c | 4 | ||||
| -rw-r--r-- | drivers/watchdog/sbsa_gwdt.c | 10 | ||||
| -rw-r--r-- | drivers/watchdog/starfive_wdt.c | 4 |
9 files changed, 112 insertions, 17 deletions
diff --git a/doc/usage/cmd/wdt.rst b/doc/usage/cmd/wdt.rst index 711b74d20da..28abf98def9 100644 --- a/doc/usage/cmd/wdt.rst +++ b/doc/usage/cmd/wdt.rst @@ -16,7 +16,7 @@ Synopsis wdt start <timeout_ms> [flags] wdt stop wdt reset - wdt expirer [flags] + wdt expire [flags] Description ----------- diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9ea617f1e43..0e6e6830fc8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -217,6 +217,7 @@ config SPL_WDT_GPIO config WDT_MAX6370 bool "MAX6370 watchdog timer support" depends on WDT + select GPIO select DM_GPIO help Select this to enable max6370 watchdog timer. diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c index bd9d7105366..91228de5e8e 100644 --- a/drivers/watchdog/designware_wdt.c +++ b/drivers/watchdog/designware_wdt.c @@ -122,7 +122,7 @@ static int designware_wdt_probe(struct udevice *dev) return ret; ret = clk_enable(&clk); - if (ret) + if (ret && ret != -ENOSYS) return ret; priv->clk_khz = clk_get_rate(&clk) / 1000; diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 7fcb866f574..068f99c5fc6 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -81,7 +81,7 @@ static int mpc8xxx_wdt_of_to_plat(struct udevice *dev) { struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev); - priv->base = (void __iomem *)devfdt_remap_addr(dev); + priv->base = (void __iomem *)dev_remap_addr(dev); if (!priv->base) return -EINVAL; diff --git a/drivers/watchdog/octeontx_wdt.c b/drivers/watchdog/octeontx_wdt.c index c79d9539c13..7299a9f9739 100644 --- a/drivers/watchdog/octeontx_wdt.c +++ b/drivers/watchdog/octeontx_wdt.c @@ -159,7 +159,8 @@ static const struct octeontx_wdt_data octeon_data = { }; static const struct udevice_id octeontx_wdt_ids[] = { - { .compatible = "arm,sbsa-gwdt", .data = (ulong)&octeontx_data }, + { .compatible = "marvell,cn10624-wdt", .data = (ulong)&octeontx_data }, + { .compatible = "marvell,cn9670-wdt", .data = (ulong)&octeontx_data }, { .compatible = "cavium,octeon-7890-ciu3", .data = (ulong)&octeon_data }, {} }; diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index a2000b968c9..5a6cad135aa 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -40,8 +40,14 @@ struct orion_wdt_priv { #define TIMER_A370_STATUS 0x04 #define WDT_AXP_FIXED_ENABLE_BIT BIT(10) +#define TIMER1_FIXED_ENABLE_BIT BIT(12) #define WDT_A370_EXPIRED BIT(31) +struct orion_watchdog_data { + int (*plat_start)(struct udevice *dev, u64 timeout, ulong flags); + int (*plat_stop)(struct udevice *dev); +}; + static int orion_wdt_reset(struct udevice *dev) { struct orion_wdt_priv *priv = dev_get_priv(dev); @@ -53,7 +59,59 @@ static int orion_wdt_reset(struct udevice *dev) return 0; } -static int orion_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +static int armadaxp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct orion_wdt_priv *priv = dev_get_priv(dev); + u32 reg; + + priv->timeout = DIV_ROUND_UP(timeout_ms, 1000); + + /* Fix the wdt and timer1 clock freqency to 25MHz */ + reg = readl(priv->reg + TIMER_CTRL); + reg |= (WDT_AXP_FIXED_ENABLE_BIT | TIMER1_FIXED_ENABLE_BIT); + writel(reg, priv->reg + TIMER_CTRL); + + /* Set watchdog duration */ + writel(priv->clk_rate * priv->timeout, + priv->reg + priv->wdt_counter_offset); + + /* Clear the watchdog expiration bit */ + reg = readl(priv->reg + TIMER_A370_STATUS); + reg &= ~WDT_A370_EXPIRED; + writel(reg, priv->reg + TIMER_A370_STATUS); + + /* Enable watchdog timer */ + reg = readl(priv->reg + TIMER_CTRL); + reg |= WDT_ENABLE_BIT; + writel(reg, priv->reg + TIMER_CTRL); + + /* Enable reset on watchdog */ + reg = readl(priv->rstout); + reg |= RSTOUT_ENABLE_BIT; + writel(reg, priv->rstout); + + return 0; +} + +static int armadaxp_wdt_stop(struct udevice *dev) +{ + struct orion_wdt_priv *priv = dev_get_priv(dev); + u32 reg; + + /* Disable reset on watchdog */ + reg = readl(priv->rstout); + reg &= ~RSTOUT_ENABLE_BIT; + writel(reg, priv->rstout); + + /* Disable watchdog timer */ + reg = readl(priv->reg + TIMER_CTRL); + reg &= ~WDT_ENABLE_BIT; + writel(reg, priv->reg + TIMER_CTRL); + + return 0; +} + +static int armada380_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { struct orion_wdt_priv *priv = dev_get_priv(dev); u32 reg; @@ -91,7 +149,7 @@ static int orion_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) return 0; } -static int orion_wdt_stop(struct udevice *dev) +static int armada380_wdt_stop(struct udevice *dev) { struct orion_wdt_priv *priv = dev_get_priv(dev); u32 reg; @@ -113,13 +171,29 @@ static int orion_wdt_stop(struct udevice *dev) return 0; } +static int orion_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct orion_watchdog_data *data = + (struct orion_watchdog_data *)dev_get_driver_data(dev); + + return data->plat_start(dev, timeout_ms, flags); +} + +static int orion_wdt_stop(struct udevice *dev) +{ + struct orion_watchdog_data *data = + (struct orion_watchdog_data *)dev_get_driver_data(dev); + + return data->plat_stop(dev); +} + static inline bool save_reg_from_ofdata(struct udevice *dev, int index, void __iomem **reg, int *offset) { fdt_addr_t addr; fdt_size_t off; - addr = devfdt_get_addr_size_index(dev, index, &off); + addr = dev_read_addr_size_index(dev, index, &off); if (addr == FDT_ADDR_T_NONE) return false; @@ -141,8 +215,10 @@ static int orion_wdt_of_to_plat(struct udevice *dev) if (!save_reg_from_ofdata(dev, 1, &priv->rstout, NULL)) goto err; - if (!save_reg_from_ofdata(dev, 2, &priv->rstout_mask, NULL)) - goto err; + if (device_is_compatible(dev, "marvell,armada-380-wdt")) { + if (!save_reg_from_ofdata(dev, 2, &priv->rstout_mask, NULL)) + goto err; + } return 0; err: @@ -173,9 +249,20 @@ static const struct wdt_ops orion_wdt_ops = { .stop = orion_wdt_stop, }; +static struct orion_watchdog_data armada380_data = { + .plat_start = armada380_wdt_start, + .plat_stop = armada380_wdt_stop, +}; + +static struct orion_watchdog_data armadaxp_data = { + .plat_start = armadaxp_wdt_start, + .plat_stop = armadaxp_wdt_stop, +}; + static const struct udevice_id orion_wdt_ids[] = { - { .compatible = "marvell,armada-380-wdt" }, - {} + { .compatible = "marvell,armada-380-wdt", .data = (ulong)&armada380_data}, + { .compatible = "marvell,armada-xp-wdt", .data = (ulong)&armadaxp_data}, + { } }; U_BOOT_DRIVER(orion_wdt) = { diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 7b387266b99..866f555789c 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -39,7 +39,7 @@ #define WDT_PRELOAD_MAX 0xfff struct rti_wdt_priv { - phys_addr_t regs; + void __iomem *regs; unsigned int clk_hz; }; @@ -177,7 +177,7 @@ static int rti_wdt_probe(struct udevice *dev) struct clk clk; int ret; - priv->regs = devfdt_get_addr(dev); + priv->regs = dev_read_addr_ptr(dev); if (!priv->regs) return -EINVAL; diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index 807884c5bc7..3a924cb2b9a 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c @@ -50,6 +50,7 @@ static int sbsa_gwdt_start(struct udevice *dev, u64 timeout, ulong flags) { struct sbsa_gwdt_priv *priv = dev_get_priv(dev); u32 clk; + u64 tout_wdog; /* * it work in the single stage mode in u-boot, @@ -58,8 +59,13 @@ static int sbsa_gwdt_start(struct udevice *dev, u64 timeout, ulong flags) * to half value of timeout. */ clk = get_tbclk(); - writel(clk / (2 * 1000) * timeout, - priv->reg_control + SBSA_GWDT_WOR); + + /* if requested timeout overflows, clamp it to u32_max */ + tout_wdog = ((u64)clk * timeout) / (2 * 1000); + if (tout_wdog > U32_MAX) + tout_wdog = U32_MAX; + + writel(tout_wdog, priv->reg_control + SBSA_GWDT_WOR); /* writing WCS will cause an explicit watchdog refresh */ writel(SBSA_GWDT_WCS_EN, priv->reg_control + SBSA_GWDT_WCS); diff --git a/drivers/watchdog/starfive_wdt.c b/drivers/watchdog/starfive_wdt.c index ee9ec4cdc3a..d2c16150f4c 100644 --- a/drivers/watchdog/starfive_wdt.c +++ b/drivers/watchdog/starfive_wdt.c @@ -290,9 +290,9 @@ static int starfive_wdt_of_to_plat(struct udevice *dev) { struct starfive_wdt_priv *wdt = dev_get_priv(dev); - wdt->base = (void *)dev_read_addr(dev); + wdt->base = dev_read_addr_ptr(dev); if (!wdt->base) - return -ENODEV; + return -EINVAL; wdt->apb_clk = devm_clk_get(dev, "apb"); if (IS_ERR(wdt->apb_clk)) |
