On Tue, Apr 02, 2024 at 04:11:41PM +0300, Matti Vaittinen wrote >> +static int init_wdg_hw(struct wdtbd96801 *w)
+{
+ u32 hw_margin[2];
+ int count, ret;
+ u32 hw_margin_max = BD96801_WDT_DEFAULT_MARGIN, hw_margin_min = 0;
+
+ count = device_property_count_u32(w->dev->parent, "rohm,hw-timeout-ms");
+ if (count < 0 && count != -EINVAL)
+ return count;
+
+ if (count > 0) {
+ if (count > ARRAY_SIZE(hw_margin))
+ return -EINVAL;
+
+ ret = device_property_read_u32_array(w->dev->parent,
+ "rohm,hw-timeout-ms",
+ &hw_margin[0], count);
+ if (ret < 0)
+ return ret;
+
+ if (count == 1)
+ hw_margin_max = hw_margin[0];
+
+ if (count == 2) {
+ hw_margin_max = hw_margin[1];
+ hw_margin_min = hw_margin[0];
+ }
+ }
+
+ ret = bd96801_set_wdt_mode(w, hw_margin_max, hw_margin_min);
+ if (ret)
+ return ret;
+
+ ret = device_property_match_string(w->dev->parent, "rohm,wdg-action",
+ "prstb");
+ if (ret >= 0) {
+ ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+ BD96801_WD_ASSERT_MASK,
+ BD96801_WD_ASSERT_RST);
+ return ret;
+ }
+
+ ret = device_property_match_string(w->dev->parent, "rohm,wdg-action",
+ "intb-only");
+ if (ret >= 0) {
+ ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF,
+ BD96801_WD_ASSERT_MASK,
+ BD96801_WD_ASSERT_IRQ);
+ return ret;
+ }
I don't see the devicetree bindings documented in the series.
I am also a bit surprised that the interrupt isn't handled in the driver.
Please explain.
+
+ return 0;
+}
+
+static int bd96801_wdt_probe(struct platform_device *pdev)
+{
+ struct wdtbd96801 *w;
+ int ret;
+ unsigned int val;
+
+ w = devm_kzalloc(&pdev->dev, sizeof(*w), GFP_KERNEL);
+ if (!w)
+ return -ENOMEM;
+
+ w->regmap = dev_get_regmap(pdev->dev.parent, NULL);
dev_get_regmap() can return NULL.
+ w->dev = &pdev->dev;Without documentation, it looks like the always-running (from
+
+ w->wdt.info = &bd96801_wdt_info;
+ w->wdt.ops = &bd96801_wdt_ops;
+ w->wdt.parent = pdev->dev.parent;
+ w->wdt.timeout = DEFAULT_TIMEOUT;
+ watchdog_set_drvdata(&w->wdt, w);
+
+ w->always_running = device_property_read_bool(pdev->dev.parent,
+ "always-running");
+
linux,wdt-gpio.yaml) may be abused. Its defined meaning is
"the watchdog is always running and can not be stopped". Its
use here seems to be "start watchdog when loading the module and
prevent it from being stopped".
Oh well, looks like the abuse was introduced with bd9576_wdt. That
doesn't make it better. At the very least it needs to be documented
that the property does not have the intended (documented) meaning.
+ ret = regmap_read(w->regmap, BD96801_REG_WD_CONF, &val);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to get the watchdog state\n");
+
+ /*
+ * If the WDG is already enabled we assume it is configured by boot.
+ * In this case we just update the hw-timeout based on values set to
+ * the timeout / mode registers and leave the hardware configs
+ * untouched.
+ */
+ if ((val & BD96801_WD_EN_MASK) != BD96801_WD_DISABLE) {
+ dev_dbg(&pdev->dev, "watchdog was running during probe\n");
+ ret = bd96801_set_heartbeat_from_hw(w, val);
+ if (ret)
+ return ret;
+
+ set_bit(WDOG_HW_RUNNING, &w->wdt.status);
+ } else {
+ /* If WDG is not running so we will initializate it */
+ ret = init_wdg_hw(w);
+ if (ret)
+ return ret;
+ }
+
+ watchdog_init_timeout(&w->wdt, 0, pdev->dev.parent);
+ watchdog_set_nowayout(&w->wdt, nowayout);
+ watchdog_stop_on_reboot(&w->wdt);
+
+ if (w->always_running)
+ bd96801_wdt_start(&w->wdt);
I think this needs to set WDOG_HW_RUNNING or the watchdog will trigger
a reboot if the watchdog device is not opened and the watchdog wasn't
already running when the module was loaded.
That makes me wonder what happens if the property is set and the
watchdog daemon isn't started in the bd9576_wdt driver.