Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: meson: keep running if already active

If the watchdog is already running (e.g.: started by bootloader) then
the kernel driver should keep the watchdog active but the amlogic driver
turns it off.

Let the driver fix the clock rate if already active because we do not
know the previous timebase value. To avoid unintentional resetting we
temporarily set it to its maximum value.

Then keep the enable bit if is was previously active.

Signed-off-by: Philippe Boos <pboos@baylibre.com>
Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20220801092150.4449-1-pboos@baylibre.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>

authored by

Philippe Boos and committed by
Wim Van Sebroeck
6adbfbab b2462060

+20 -6
+20 -6
drivers/watchdog/meson_gxbb_wdt.c
··· 156 156 struct device *dev = &pdev->dev; 157 157 struct meson_gxbb_wdt *data; 158 158 int ret; 159 + u32 ctrl_reg; 159 160 160 161 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 161 162 if (!data) ··· 190 189 watchdog_set_nowayout(&data->wdt_dev, nowayout); 191 190 watchdog_set_drvdata(&data->wdt_dev, data); 192 191 193 - /* Setup with 1ms timebase */ 194 - writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) | 195 - GXBB_WDT_CTRL_EE_RESET | 196 - GXBB_WDT_CTRL_CLK_EN | 197 - GXBB_WDT_CTRL_CLKDIV_EN, 198 - data->reg_base + GXBB_WDT_CTRL_REG); 192 + ctrl_reg = readl(data->reg_base + GXBB_WDT_CTRL_REG) & 193 + GXBB_WDT_CTRL_EN; 199 194 195 + if (ctrl_reg) { 196 + /* Watchdog is running - keep it running but extend timeout 197 + * to the maximum while setting the timebase 198 + */ 199 + set_bit(WDOG_HW_RUNNING, &data->wdt_dev.status); 200 + meson_gxbb_wdt_set_timeout(&data->wdt_dev, 201 + GXBB_WDT_TCNT_SETUP_MASK / 1000); 202 + } 203 + 204 + /* Setup with 1ms timebase */ 205 + ctrl_reg |= ((clk_get_rate(data->clk) / 1000) & 206 + GXBB_WDT_CTRL_DIV_MASK) | 207 + GXBB_WDT_CTRL_EE_RESET | 208 + GXBB_WDT_CTRL_CLK_EN | 209 + GXBB_WDT_CTRL_CLKDIV_EN; 210 + 211 + writel(ctrl_reg, data->reg_base + GXBB_WDT_CTRL_REG); 200 212 meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout); 201 213 202 214 return devm_watchdog_register_device(dev, &data->wdt_dev);