mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
linux-watchdog 6.11-rc1 tag
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEABECAAYFAmaglhIACgkQ+iyteGJfRspBfQCgnL07s+8mWMcfjYhc92La4573 Z8QAniBh5nvymZRNKpslMR4UEuCCI3gt =IrbV -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
b2eed73360
@ -29,6 +29,7 @@ properties:
|
|||||||
- renesas,r9a07g043-wdt # RZ/G2UL and RZ/Five
|
- renesas,r9a07g043-wdt # RZ/G2UL and RZ/Five
|
||||||
- renesas,r9a07g044-wdt # RZ/G2{L,LC}
|
- renesas,r9a07g044-wdt # RZ/G2{L,LC}
|
||||||
- renesas,r9a07g054-wdt # RZ/V2L
|
- renesas,r9a07g054-wdt # RZ/V2L
|
||||||
|
- renesas,r9a08g045-wdt # RZ/G3S
|
||||||
- const: renesas,rzg2l-wdt
|
- const: renesas,rzg2l-wdt
|
||||||
|
|
||||||
- items:
|
- items:
|
||||||
|
@ -946,7 +946,8 @@ config RENESAS_RZN1WDT
|
|||||||
|
|
||||||
config RENESAS_RZG2LWDT
|
config RENESAS_RZG2LWDT
|
||||||
tristate "Renesas RZ/G2L WDT Watchdog"
|
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
|
select WATCHDOG_CORE
|
||||||
help
|
help
|
||||||
This driver adds watchdog support for the integrated watchdogs in the
|
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)
|
if (wdt->ext_reset)
|
||||||
val |= WDOG_CS_INT_EN;
|
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 {
|
do {
|
||||||
ret = _imx7ulp_wdt_init(wdt, timeout, val);
|
ret = _imx7ulp_wdt_init(wdt, timeout, val);
|
||||||
toval = readl(wdt->base + WDOG_TOVAL);
|
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);
|
watchdog_set_drvdata(&priv->wdd, priv);
|
||||||
|
|
||||||
priv->wdd.parent = dev;
|
priv->wdd.parent = dev;
|
||||||
priv->wdd.info = &wdt_info,
|
priv->wdd.info = &wdt_info;
|
||||||
priv->wdd.ops = &se10_wdt_ops,
|
priv->wdd.ops = &se10_wdt_ops;
|
||||||
priv->wdd.timeout = WATCHDOG_TIMEOUT; /* Set default timeout */
|
priv->wdd.timeout = WATCHDOG_TIMEOUT; /* Set default timeout */
|
||||||
priv->wdd.min_timeout = MIN_TIMEOUT;
|
priv->wdd.min_timeout = MIN_TIMEOUT;
|
||||||
priv->wdd.max_timeout = MAX_TIMEOUT;
|
priv->wdd.max_timeout = MAX_TIMEOUT;
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/iopoll.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
@ -54,35 +53,11 @@ struct rzg2l_wdt_priv {
|
|||||||
struct reset_control *rstc;
|
struct reset_control *rstc;
|
||||||
unsigned long osc_clk_rate;
|
unsigned long osc_clk_rate;
|
||||||
unsigned long delay;
|
unsigned long delay;
|
||||||
unsigned long minimum_assertion_period;
|
|
||||||
struct clk *pclk;
|
struct clk *pclk;
|
||||||
struct clk *osc_clk;
|
struct clk *osc_clk;
|
||||||
enum rz_wdt_type devtype;
|
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)
|
static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
|
||||||
{
|
{
|
||||||
/* delay timer when change the setting register */
|
/* 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)
|
static int rzg2l_wdt_start(struct watchdog_device *wdev)
|
||||||
{
|
{
|
||||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(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 */
|
/* Initialize time out */
|
||||||
rzg2l_wdt_init_timeout(wdev);
|
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)
|
static int rzg2l_wdt_stop(struct watchdog_device *wdev)
|
||||||
{
|
{
|
||||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
rzg2l_wdt_reset(priv);
|
ret = reset_control_assert(priv->rstc);
|
||||||
pm_runtime_put(wdev->parent);
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = pm_runtime_put(wdev->parent);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
|
static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
wdev->timeout = timeout;
|
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.
|
* to reset the module) so that it is updated with new timeout values.
|
||||||
*/
|
*/
|
||||||
if (watchdog_active(wdev)) {
|
if (watchdog_active(wdev)) {
|
||||||
rzg2l_wdt_stop(wdev);
|
ret = rzg2l_wdt_stop(wdev);
|
||||||
rzg2l_wdt_start(wdev);
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = rzg2l_wdt_start(wdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rzg2l_wdt_restart(struct watchdog_device *wdev,
|
static int rzg2l_wdt_restart(struct watchdog_device *wdev,
|
||||||
unsigned long action, void *data)
|
unsigned long action, void *data)
|
||||||
{
|
{
|
||||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
clk_prepare_enable(priv->pclk);
|
clk_prepare_enable(priv->pclk);
|
||||||
clk_prepare_enable(priv->osc_clk);
|
clk_prepare_enable(priv->osc_clk);
|
||||||
|
|
||||||
if (priv->devtype == WDT_RZG2L) {
|
if (priv->devtype == WDT_RZG2L) {
|
||||||
|
ret = reset_control_deassert(priv->rstc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Generate Reset (WDTRSTB) Signal on parity error */
|
/* Generate Reset (WDTRSTB) Signal on parity error */
|
||||||
rzg2l_wdt_write(priv, 0, PECR);
|
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);
|
rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
|
||||||
} else {
|
} else {
|
||||||
/* RZ/V2M doesn't have parity error registers */
|
/* 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;
|
wdev->timeout = 0;
|
||||||
|
|
||||||
@ -224,13 +226,11 @@ static const struct watchdog_ops rzg2l_wdt_ops = {
|
|||||||
.restart = rzg2l_wdt_restart,
|
.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 watchdog_device *wdev = data;
|
||||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
|
||||||
|
|
||||||
pm_runtime_disable(wdev->parent);
|
pm_runtime_disable(wdev->parent);
|
||||||
reset_control_assert(priv->rstc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rzg2l_wdt_probe(struct platform_device *pdev)
|
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),
|
return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
|
||||||
"failed to get cpg reset");
|
"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);
|
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);
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
|
||||||
priv->wdev.info = &rzg2l_wdt_ident;
|
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;
|
priv->wdev.timeout = WDT_DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
watchdog_set_drvdata(&priv->wdev, priv);
|
watchdog_set_drvdata(&priv->wdev, priv);
|
||||||
ret = devm_add_action_or_reset(&pdev->dev,
|
dev_set_drvdata(dev, priv);
|
||||||
rzg2l_wdt_reset_assert_pm_disable,
|
ret = devm_add_action_or_reset(&pdev->dev, rzg2l_wdt_pm_disable, &priv->wdev);
|
||||||
&priv->wdev);
|
if (ret)
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
watchdog_set_nowayout(&priv->wdev, nowayout);
|
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);
|
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 = {
|
static struct platform_driver rzg2l_wdt_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rzg2l_wdt",
|
.name = "rzg2l_wdt",
|
||||||
.of_match_table = rzg2l_wdt_ids,
|
.of_match_table = rzg2l_wdt_ids,
|
||||||
|
.pm = &rzg2l_wdt_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = rzg2l_wdt_probe,
|
.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->clk_rate_khz = clk_rate / 1000;
|
||||||
wdt->wdtdev.info = &rzn1_wdt_info,
|
wdt->wdtdev.info = &rzn1_wdt_info;
|
||||||
wdt->wdtdev.ops = &rzn1_wdt_ops,
|
wdt->wdtdev.ops = &rzn1_wdt_ops;
|
||||||
wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
|
wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
|
||||||
wdt->wdtdev.parent = dev;
|
wdt->wdtdev.parent = dev;
|
||||||
/*
|
/*
|
||||||
* The period of the watchdog cannot be changed once set
|
* 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");
|
return dev_err_probe(wdt->wdd.parent, ret, "failed to enable apb clock\n");
|
||||||
|
|
||||||
ret = clk_prepare_enable(wdt->core_clk);
|
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 dev_err_probe(wdt->wdd.parent, ret, "failed to enable core clock\n");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1004,7 +1004,7 @@ static struct miscdevice watchdog_miscdev = {
|
|||||||
.fops = &watchdog_fops,
|
.fops = &watchdog_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct class watchdog_class = {
|
static const struct class watchdog_class = {
|
||||||
.name = "watchdog",
|
.name = "watchdog",
|
||||||
.dev_groups = wdt_groups,
|
.dev_groups = wdt_groups,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user