Эх сурвалжийг харах

Merge tag 'linux-watchdog-4.18-rc1' of git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:
 "Core:
   - simplify getting .drvdata

  renesas_wdt:
   - add support for the R8A77965 WDT and R-Car Gen2
   - remove R-Car M2-W ES2.x from blacklist

  sp805:
   - add restart handler

  hpwdt:
   - claim NMIs generated by iLO5

  mena21_wdt:
   - drop unnecessary mutex lock

  da9062 & da9063:
   - fixes and general cleanups"

* tag 'linux-watchdog-4.18-rc1' of git://www.linux-watchdog.org/linux-watchdog:
  watchdog: da9063: remove duplicated timeout_to_sel calls
  watchdog: da9063: rename helper function to avoid misunderstandings
  watchdog: da9062: remove unused code
  watchdog: da9063: Fix timeout handling during probe
  watchdog: da9063: Fix updating timeout value
  watchdog: da9063: Fix setting/changing timeout
  dt-bindings: watchdog: renesas-wdt: Add R-Car Gen2 support
  watchdog: mena21_wdt: Drop unnecessary mutex lock
  watchdog: renesas-wdt: Add support for the R8A77965 WDT
  watchdog: hpwdt: Claim NMIs generated by iLO5
  watchdog: sp805: add restart handler
  watchdog: renesas-wdt: Remove R-Car M2-W ES2.x from blacklist
  watchdog: simplify getting .drvdata
Linus Torvalds 7 жил өмнө
parent
commit
a2b7ab45b8

+ 16 - 7
Documentation/devicetree/bindings/watchdog/renesas-wdt.txt

@@ -1,18 +1,27 @@
 Renesas Watchdog Timer (WDT) Controller
 
 Required properties:
-- compatible : Should be "renesas,<soctype>-wdt", and
-	       "renesas,rcar-gen3-wdt" or "renesas,rza-wdt" as fallback.
+ - compatible : Must be "renesas,<soctype>-wdt", followed by a generic
+		fallback compatible string when compatible with the generic
+		version.
 	       Examples with soctypes are:
-	         - "renesas,r7s72100-wdt" (RZ/A1)
+		 - "renesas,r8a7743-wdt" (RZ/G1M)
+		 - "renesas,r8a7745-wdt" (RZ/G1E)
+	         - "renesas,r8a7790-wdt" (R-Car H2)
+	         - "renesas,r8a7791-wdt" (R-Car M2-W)
+	         - "renesas,r8a7792-wdt" (R-Car V2H)
+	         - "renesas,r8a7793-wdt" (R-Car M2-N)
+	         - "renesas,r8a7794-wdt" (R-Car E2)
 	         - "renesas,r8a7795-wdt" (R-Car H3)
 	         - "renesas,r8a7796-wdt" (R-Car M3-W)
+		 - "renesas,r8a77965-wdt" (R-Car M3-N)
 	         - "renesas,r8a77970-wdt" (R-Car V3M)
 	         - "renesas,r8a77995-wdt" (R-Car D3)
-
-  When compatible with the generic version, nodes must list the SoC-specific
-  version corresponding to the platform first, followed by the generic
-  version.
+	         - "renesas,r7s72100-wdt" (RZ/A1)
+		The generic compatible string must be:
+		 - "renesas,rza-wdt" for RZ/A
+		 - "renesas,rcar-gen2-wdt" for R-Car Gen2 and RZ/G
+		 - "renesas,rcar-gen3-wdt" for R-Car Gen3
 
 - reg : Should contain WDT registers location and length
 - clocks : the clock feeding the watchdog timer.

+ 2 - 4
drivers/watchdog/cadence_wdt.c

@@ -418,8 +418,7 @@ static void cdns_wdt_shutdown(struct platform_device *pdev)
  */
 static int __maybe_unused cdns_wdt_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+	struct cdns_wdt *wdt = dev_get_drvdata(dev);
 
 	if (watchdog_active(&wdt->cdns_wdt_device)) {
 		cdns_wdt_stop(&wdt->cdns_wdt_device);
@@ -438,8 +437,7 @@ static int __maybe_unused cdns_wdt_suspend(struct device *dev)
 static int __maybe_unused cdns_wdt_resume(struct device *dev)
 {
 	int ret;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+	struct cdns_wdt *wdt = dev_get_drvdata(dev);
 
 	if (watchdog_active(&wdt->cdns_wdt_device)) {
 		ret = clk_prepare_enable(wdt->clk);

+ 0 - 10
drivers/watchdog/da9062_wdt.c

@@ -30,14 +30,8 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
 struct da9062_watchdog {
 	struct da9062 *hw;
 	struct watchdog_device wdtdev;
-	unsigned long j_time_stamp;
 };
 
-static void da9062_set_window_start(struct da9062_watchdog *wdt)
-{
-	wdt->j_time_stamp = jiffies;
-}
-
 static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
 {
 	unsigned int i;
@@ -59,8 +53,6 @@ static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt)
 			   DA9062AA_WATCHDOG_MASK,
 			   DA9062AA_WATCHDOG_MASK);
 
-	da9062_set_window_start(wdt);
-
 	return ret;
 }
 
@@ -232,8 +224,6 @@ static int da9062_wdt_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	da9062_set_window_start(wdt);
-
 	return da9062_wdt_ping(&wdt->wdtdev);
 }
 

+ 62 - 11
drivers/watchdog/da9063_wdt.c

@@ -45,8 +45,46 @@ static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
 	return DA9063_TWDSCALE_MAX;
 }
 
-static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
+/*
+ * Return 0 if watchdog is disabled, else non zero.
+ */
+static unsigned int da9063_wdt_is_running(struct da9063 *da9063)
+{
+	unsigned int val;
+
+	regmap_read(da9063->regmap, DA9063_REG_CONTROL_D, &val);
+
+	return val & DA9063_TWDSCALE_MASK;
+}
+
+static int da9063_wdt_disable_timer(struct da9063 *da9063)
 {
+	return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
+				  DA9063_TWDSCALE_MASK,
+				  DA9063_TWDSCALE_DISABLE);
+}
+
+static int
+da9063_wdt_update_timeout(struct da9063 *da9063, unsigned int timeout)
+{
+	unsigned int regval;
+	int ret;
+
+	/*
+	 * The watchdog triggers a reboot if a timeout value is already
+	 * programmed because the timeout value combines two functions
+	 * in one: indicating the counter limit and starting the watchdog.
+	 * The watchdog must be disabled to be able to change the timeout
+	 * value if the watchdog is already running. Then we can set the
+	 * new timeout value which enables the watchdog again.
+	 */
+	ret = da9063_wdt_disable_timer(da9063);
+	if (ret)
+		return ret;
+
+	usleep_range(150, 300);
+	regval = da9063_wdt_timeout_to_sel(timeout);
+
 	return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
 				  DA9063_TWDSCALE_MASK, regval);
 }
@@ -54,11 +92,9 @@ static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
 static int da9063_wdt_start(struct watchdog_device *wdd)
 {
 	struct da9063 *da9063 = watchdog_get_drvdata(wdd);
-	unsigned int selector;
 	int ret;
 
-	selector = da9063_wdt_timeout_to_sel(wdd->timeout);
-	ret = _da9063_wdt_set_timeout(da9063, selector);
+	ret = da9063_wdt_update_timeout(da9063, wdd->timeout);
 	if (ret)
 		dev_err(da9063->dev, "Watchdog failed to start (err = %d)\n",
 			ret);
@@ -71,8 +107,7 @@ static int da9063_wdt_stop(struct watchdog_device *wdd)
 	struct da9063 *da9063 = watchdog_get_drvdata(wdd);
 	int ret;
 
-	ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
-				 DA9063_TWDSCALE_MASK, DA9063_TWDSCALE_DISABLE);
+	ret = da9063_wdt_disable_timer(da9063);
 	if (ret)
 		dev_alert(da9063->dev, "Watchdog failed to stop (err = %d)\n",
 			  ret);
@@ -98,16 +133,26 @@ static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
 				  unsigned int timeout)
 {
 	struct da9063 *da9063 = watchdog_get_drvdata(wdd);
-	unsigned int selector;
-	int ret;
+	int ret = 0;
+
+	/*
+	 * There are two cases when a set_timeout() will be called:
+	 * 1. The watchdog is off and someone wants to set the timeout for the
+	 *    further use.
+	 * 2. The watchdog is already running and a new timeout value should be
+	 *    set.
+	 *
+	 * The watchdog can't store a timeout value not equal zero without
+	 * enabling the watchdog, so the timeout must be buffered by the driver.
+	 */
+	if (watchdog_active(wdd))
+		ret = da9063_wdt_update_timeout(da9063, timeout);
 
-	selector = da9063_wdt_timeout_to_sel(timeout);
-	ret = _da9063_wdt_set_timeout(da9063, selector);
 	if (ret)
 		dev_err(da9063->dev, "Failed to set watchdog timeout (err = %d)\n",
 			ret);
 	else
-		wdd->timeout = wdt_timeout[selector];
+		wdd->timeout = wdt_timeout[da9063_wdt_timeout_to_sel(timeout)];
 
 	return ret;
 }
@@ -171,6 +216,12 @@ static int da9063_wdt_probe(struct platform_device *pdev)
 
 	watchdog_set_drvdata(wdd, da9063);
 
+	/* Change the timeout to the default value if the watchdog is running */
+	if (da9063_wdt_is_running(da9063)) {
+		da9063_wdt_update_timeout(da9063, DA9063_WDG_TIMEOUT);
+		set_bit(WDOG_HW_RUNNING, &wdd->status);
+	}
+
 	return devm_watchdog_register_device(&pdev->dev, wdd);
 }
 

+ 1 - 1
drivers/watchdog/hpwdt.c

@@ -159,7 +159,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs)
 		"3. OA Forward Progress Log\n"
 		"4. iLO Event Log";
 
-	if (ilo5 && ulReason == NMI_UNKNOWN && mynmi)
+	if (ilo5 && ulReason == NMI_UNKNOWN && !mynmi)
 		return NMI_DONE;
 
 	if (ilo5 && !pretimeout)

+ 0 - 18
drivers/watchdog/mena21_wdt.c

@@ -31,7 +31,6 @@ enum a21_wdt_gpios {
 
 struct a21_wdt_drv {
 	struct watchdog_device wdt;
-	struct mutex lock;
 	unsigned gpios[NUM_GPIOS];
 };
 
@@ -55,12 +54,8 @@ static int a21_wdt_start(struct watchdog_device *wdt)
 {
 	struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
 
-	mutex_lock(&drv->lock);
-
 	gpio_set_value(drv->gpios[GPIO_WD_ENAB], 1);
 
-	mutex_unlock(&drv->lock);
-
 	return 0;
 }
 
@@ -68,12 +63,8 @@ static int a21_wdt_stop(struct watchdog_device *wdt)
 {
 	struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
 
-	mutex_lock(&drv->lock);
-
 	gpio_set_value(drv->gpios[GPIO_WD_ENAB], 0);
 
-	mutex_unlock(&drv->lock);
-
 	return 0;
 }
 
@@ -81,14 +72,10 @@ static int a21_wdt_ping(struct watchdog_device *wdt)
 {
 	struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
 
-	mutex_lock(&drv->lock);
-
 	gpio_set_value(drv->gpios[GPIO_WD_TRIG], 0);
 	ndelay(10);
 	gpio_set_value(drv->gpios[GPIO_WD_TRIG], 1);
 
-	mutex_unlock(&drv->lock);
-
 	return 0;
 }
 
@@ -108,8 +95,6 @@ static int a21_wdt_set_timeout(struct watchdog_device *wdt,
 		return -EINVAL;
 	}
 
-	mutex_lock(&drv->lock);
-
 	if (timeout == 1)
 		gpio_set_value(drv->gpios[GPIO_WD_FAST], 1);
 	else
@@ -117,8 +102,6 @@ static int a21_wdt_set_timeout(struct watchdog_device *wdt,
 
 	wdt->timeout = timeout;
 
-	mutex_unlock(&drv->lock);
-
 	return 0;
 }
 
@@ -191,7 +174,6 @@ static int a21_wdt_probe(struct platform_device *pdev)
 			return ret;
 	}
 
-	mutex_init(&drv->lock);
 	watchdog_init_timeout(&a21_wdt, 30, &pdev->dev);
 	watchdog_set_nowayout(&a21_wdt, nowayout);
 	watchdog_set_drvdata(&a21_wdt, drv);

+ 2 - 4
drivers/watchdog/of_xilinx_wdt.c

@@ -268,8 +268,7 @@ static int xwdt_remove(struct platform_device *pdev)
  */
 static int __maybe_unused xwdt_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct xwdt_device *xdev = platform_get_drvdata(pdev);
+	struct xwdt_device *xdev = dev_get_drvdata(dev);
 
 	if (watchdog_active(&xdev->xilinx_wdt_wdd))
 		xilinx_wdt_stop(&xdev->xilinx_wdt_wdd);
@@ -285,8 +284,7 @@ static int __maybe_unused xwdt_suspend(struct device *dev)
  */
 static int __maybe_unused xwdt_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct xwdt_device *xdev = platform_get_drvdata(pdev);
+	struct xwdt_device *xdev = dev_get_drvdata(dev);
 	int ret = 0;
 
 	if (watchdog_active(&xdev->xilinx_wdt_wdd))

+ 1 - 1
drivers/watchdog/renesas_wdt.c

@@ -146,7 +146,7 @@ static const struct soc_device_attribute rwdt_quirks_match[] = {
 		.data = (void *)1,	/* needs single CPU */
 	}, {
 		.soc_id = "r8a7791",
-		.revision = "ES[12].*",
+		.revision = "ES1.*",
 		.data = (void *)1,	/* needs single CPU */
 	}, {
 		.soc_id = "r8a7792",

+ 14 - 0
drivers/watchdog/sp805_wdt.c

@@ -121,6 +121,18 @@ static unsigned int wdt_timeleft(struct watchdog_device *wdd)
 	return div_u64(load, rate);
 }
 
+static int
+wdt_restart(struct watchdog_device *wdd, unsigned long mode, void *cmd)
+{
+	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	writel_relaxed(0, wdt->base + WDTCONTROL);
+	writel_relaxed(0, wdt->base + WDTLOAD);
+	writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
+
+	return 0;
+}
+
 static int wdt_config(struct watchdog_device *wdd, bool ping)
 {
 	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
@@ -197,6 +209,7 @@ static const struct watchdog_ops wdt_ops = {
 	.ping		= wdt_ping,
 	.set_timeout	= wdt_setload,
 	.get_timeleft	= wdt_timeleft,
+	.restart	= wdt_restart,
 };
 
 static int
@@ -230,6 +243,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 	spin_lock_init(&wdt->lock);
 	watchdog_set_nowayout(&wdt->wdd, nowayout);
 	watchdog_set_drvdata(&wdt->wdd, wdt);
+	watchdog_set_restart_priority(&wdt->wdd, 128);
 	wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT);
 
 	ret = watchdog_register_device(&wdt->wdd);

+ 2 - 4
drivers/watchdog/wdat_wdt.c

@@ -447,8 +447,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int wdat_wdt_suspend_noirq(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct wdat_wdt *wdat = platform_get_drvdata(pdev);
+	struct wdat_wdt *wdat = dev_get_drvdata(dev);
 	int ret;
 
 	if (!watchdog_active(&wdat->wdd))
@@ -475,8 +474,7 @@ static int wdat_wdt_suspend_noirq(struct device *dev)
 
 static int wdat_wdt_resume_noirq(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct wdat_wdt *wdat = platform_get_drvdata(pdev);
+	struct wdat_wdt *wdat = dev_get_drvdata(dev);
 	int ret;
 
 	if (!watchdog_active(&wdat->wdd))