Commit b2eed733 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull watchdog updates from Wim Van Sebroeck:

 - make watchdog_class const

 - rework of the rzg2l_wdt driver

 - other small fixes and improvements

* tag 'linux-watchdog-6.11-rc1' of git://www.linux-watchdog.org/linux-watchdog:
  dt-bindings: watchdog: dlg,da9062-watchdog: Drop blank space
  watchdog: rzn1: Convert comma to semicolon
  watchdog: lenovo_se10_wdt: Convert comma to semicolon
  dt-bindings: watchdog: renesas,wdt: Document RZ/G3S support
  watchdog: rzg2l_wdt: Add suspend/resume support
  watchdog: rzg2l_wdt: Rely on the reset driver for doing proper reset
  watchdog: rzg2l_wdt: Remove comparison with zero
  watchdog: rzg2l_wdt: Remove reset de-assert from probe
  watchdog: rzg2l_wdt: Check return status of pm_runtime_put()
  watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get()
  watchdog: rzg2l_wdt: Make the driver depend on PM
  watchdog: rzg2l_wdt: Restrict the driver to ARCH_RZG2L and ARCH_R9A09G011
  watchdog: imx7ulp_wdt: keep already running watchdog enabled
  watchdog: starfive: Add missing clk_disable_unprepare()
  watchdog: Make watchdog_class const
parents 9cf601e8 63d097d4
......@@ -29,6 +29,7 @@ properties:
- renesas,r9a07g043-wdt # RZ/G2UL and RZ/Five
- renesas,r9a07g044-wdt # RZ/G2{L,LC}
- renesas,r9a07g054-wdt # RZ/V2L
- renesas,r9a08g045-wdt # RZ/G3S
- const: renesas,rzg2l-wdt
- items:
......
......@@ -946,7 +946,8 @@ config RENESAS_RZN1WDT
config RENESAS_RZG2LWDT
tristate "Renesas RZ/G2L WDT Watchdog"
depends on ARCH_RENESAS || COMPILE_TEST
depends on ARCH_RZG2L || ARCH_R9A09G011 || COMPILE_TEST
depends on PM || COMPILE_TEST
select WATCHDOG_CORE
help
This driver adds watchdog support for the integrated watchdogs in the
......
......@@ -290,6 +290,11 @@ static int imx7ulp_wdt_init(struct imx7ulp_wdt_device *wdt, unsigned int timeout
if (wdt->ext_reset)
val |= WDOG_CS_INT_EN;
if (readl(wdt->base + WDOG_CS) & WDOG_CS_EN) {
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
val |= WDOG_CS_EN;
}
do {
ret = _imx7ulp_wdt_init(wdt, timeout, val);
toval = readl(wdt->base + WDOG_TOVAL);
......
......@@ -196,8 +196,8 @@ static int se10_wdt_probe(struct platform_device *pdev)
watchdog_set_drvdata(&priv->wdd, priv);
priv->wdd.parent = dev;
priv->wdd.info = &wdt_info,
priv->wdd.ops = &se10_wdt_ops,
priv->wdd.info = &wdt_info;
priv->wdd.ops = &se10_wdt_ops;
priv->wdd.timeout = WATCHDOG_TIMEOUT; /* Set default timeout */
priv->wdd.min_timeout = MIN_TIMEOUT;
priv->wdd.max_timeout = MAX_TIMEOUT;
......
......@@ -8,7 +8,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
......@@ -54,35 +53,11 @@ struct rzg2l_wdt_priv {
struct reset_control *rstc;
unsigned long osc_clk_rate;
unsigned long delay;
unsigned long minimum_assertion_period;
struct clk *pclk;
struct clk *osc_clk;
enum rz_wdt_type devtype;
};
static int rzg2l_wdt_reset(struct rzg2l_wdt_priv *priv)
{
int err, status;
if (priv->devtype == WDT_RZV2M) {
/* WDT needs TYPE-B reset control */
err = reset_control_assert(priv->rstc);
if (err)
return err;
ndelay(priv->minimum_assertion_period);
err = reset_control_deassert(priv->rstc);
if (err)
return err;
err = read_poll_timeout(reset_control_status, status,
status != 1, 0, 1000, false,
priv->rstc);
} else {
err = reset_control_reset(priv->rstc);
}
return err;
}
static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
{
/* delay timer when change the setting register */
......@@ -123,8 +98,17 @@ static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev)
static int rzg2l_wdt_start(struct watchdog_device *wdev)
{
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
int ret;
pm_runtime_get_sync(wdev->parent);
ret = pm_runtime_resume_and_get(wdev->parent);
if (ret)
return ret;
ret = reset_control_deassert(priv->rstc);
if (ret) {
pm_runtime_put(wdev->parent);
return ret;
}
/* Initialize time out */
rzg2l_wdt_init_timeout(wdev);
......@@ -141,15 +125,23 @@ static int rzg2l_wdt_start(struct watchdog_device *wdev)
static int rzg2l_wdt_stop(struct watchdog_device *wdev)
{
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
int ret;
rzg2l_wdt_reset(priv);
pm_runtime_put(wdev->parent);
ret = reset_control_assert(priv->rstc);
if (ret)
return ret;
ret = pm_runtime_put(wdev->parent);
if (ret < 0)
return ret;
return 0;
}
static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
{
int ret = 0;
wdev->timeout = timeout;
/*
......@@ -158,22 +150,30 @@ static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int time
* to reset the module) so that it is updated with new timeout values.
*/
if (watchdog_active(wdev)) {
rzg2l_wdt_stop(wdev);
rzg2l_wdt_start(wdev);
ret = rzg2l_wdt_stop(wdev);
if (ret)
return ret;
ret = rzg2l_wdt_start(wdev);
}
return 0;
return ret;
}
static int rzg2l_wdt_restart(struct watchdog_device *wdev,
unsigned long action, void *data)
{
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
int ret;
clk_prepare_enable(priv->pclk);
clk_prepare_enable(priv->osc_clk);
if (priv->devtype == WDT_RZG2L) {
ret = reset_control_deassert(priv->rstc);
if (ret)
return ret;
/* Generate Reset (WDTRSTB) Signal on parity error */
rzg2l_wdt_write(priv, 0, PECR);
......@@ -181,7 +181,9 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
} else {
/* RZ/V2M doesn't have parity error registers */
rzg2l_wdt_reset(priv);
ret = reset_control_reset(priv->rstc);
if (ret)
return ret;
wdev->timeout = 0;
......@@ -224,13 +226,11 @@ static const struct watchdog_ops rzg2l_wdt_ops = {
.restart = rzg2l_wdt_restart,
};
static void rzg2l_wdt_reset_assert_pm_disable(void *data)
static void rzg2l_wdt_pm_disable(void *data)
{
struct watchdog_device *wdev = data;
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
pm_runtime_disable(wdev->parent);
reset_control_assert(priv->rstc);
}
static int rzg2l_wdt_probe(struct platform_device *pdev)
......@@ -273,19 +273,8 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
"failed to get cpg reset");
ret = reset_control_deassert(priv->rstc);
if (ret)
return dev_err_probe(dev, ret, "failed to deassert");
priv->devtype = (uintptr_t)of_device_get_match_data(dev);
if (priv->devtype == WDT_RZV2M) {
priv->minimum_assertion_period = RZV2M_A_NSEC +
3 * F2CYCLE_NSEC(pclk_rate) + 5 *
max(F2CYCLE_NSEC(priv->osc_clk_rate),
F2CYCLE_NSEC(pclk_rate));
}
pm_runtime_enable(&pdev->dev);
priv->wdev.info = &rzg2l_wdt_ident;
......@@ -297,10 +286,9 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
priv->wdev.timeout = WDT_DEFAULT_TIMEOUT;
watchdog_set_drvdata(&priv->wdev, priv);
ret = devm_add_action_or_reset(&pdev->dev,
rzg2l_wdt_reset_assert_pm_disable,
&priv->wdev);
if (ret < 0)
dev_set_drvdata(dev, priv);
ret = devm_add_action_or_reset(&pdev->dev, rzg2l_wdt_pm_disable, &priv->wdev);
if (ret)
return ret;
watchdog_set_nowayout(&priv->wdev, nowayout);
......@@ -320,10 +308,35 @@ static const struct of_device_id rzg2l_wdt_ids[] = {
};
MODULE_DEVICE_TABLE(of, rzg2l_wdt_ids);
static int rzg2l_wdt_suspend_late(struct device *dev)
{
struct rzg2l_wdt_priv *priv = dev_get_drvdata(dev);
if (!watchdog_active(&priv->wdev))
return 0;
return rzg2l_wdt_stop(&priv->wdev);
}
static int rzg2l_wdt_resume_early(struct device *dev)
{
struct rzg2l_wdt_priv *priv = dev_get_drvdata(dev);
if (!watchdog_active(&priv->wdev))
return 0;
return rzg2l_wdt_start(&priv->wdev);
}
static const struct dev_pm_ops rzg2l_wdt_pm_ops = {
LATE_SYSTEM_SLEEP_PM_OPS(rzg2l_wdt_suspend_late, rzg2l_wdt_resume_early)
};
static struct platform_driver rzg2l_wdt_driver = {
.driver = {
.name = "rzg2l_wdt",
.of_match_table = rzg2l_wdt_ids,
.pm = &rzg2l_wdt_pm_ops,
},
.probe = rzg2l_wdt_probe,
};
......
......@@ -140,9 +140,9 @@ static int rzn1_wdt_probe(struct platform_device *pdev)
}
wdt->clk_rate_khz = clk_rate / 1000;
wdt->wdtdev.info = &rzn1_wdt_info,
wdt->wdtdev.ops = &rzn1_wdt_ops,
wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
wdt->wdtdev.info = &rzn1_wdt_info;
wdt->wdtdev.ops = &rzn1_wdt_ops;
wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
wdt->wdtdev.parent = dev;
/*
* The period of the watchdog cannot be changed once set
......
......@@ -152,8 +152,10 @@ static int starfive_wdt_enable_clock(struct starfive_wdt *wdt)
return dev_err_probe(wdt->wdd.parent, ret, "failed to enable apb clock\n");
ret = clk_prepare_enable(wdt->core_clk);
if (ret)
if (ret) {
clk_disable_unprepare(wdt->apb_clk);
return dev_err_probe(wdt->wdd.parent, ret, "failed to enable core clock\n");
}
return 0;
}
......
......@@ -1004,7 +1004,7 @@ static struct miscdevice watchdog_miscdev = {
.fops = &watchdog_fops,
};
static struct class watchdog_class = {
static const struct class watchdog_class = {
.name = "watchdog",
.dev_groups = wdt_groups,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment