Commit 12418ece authored by Linus Torvalds's avatar Linus Torvalds

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

Pull watchdog updates from Wim Van Sebroeck:

 - add support for Amlogic C3 and S4 SoCs

 - add IT8613 ID

 - add MSM8226 and MSM8974 compatibles

 - other small fixes and improvements

* tag 'linux-watchdog-6.7-rc1' of git://www.linux-watchdog.org/linux-watchdog: (24 commits)
  dt-bindings: watchdog: Add support for Amlogic C3 and S4 SoCs
  watchdog: mlx-wdt: Parameter desctiption warning fix
  watchdog: aspeed: Add support for aspeed,reset-mask DT property
  dt-bindings: watchdog: aspeed-wdt: Add aspeed,reset-mask property
  watchdog: apple: Deactivate on suspend
  dt-bindings: watchdog: qcom-wdt: Add MSM8226 and MSM8974 compatibles
  dt-bindings: watchdog: fsl-imx7ulp-wdt: Add 'fsl,ext-reset-output'
  wdog: imx7ulp: Enable wdog int_en bit for watchdog any reset
  drivers: watchdog: marvell_gti: Program the max_hw_heartbeat_ms
  drivers: watchdog: marvell_gti: fix zero pretimeout handling
  watchdog: marvell_gti: Replace of_platform.h with explicit includes
  watchdog: imx_sc_wdt: continue if the wdog already enabled
  watchdog: st_lpc: Use device_get_match_data()
  watchdog: wdat_wdt: Add timeout value as a param in ping method
  watchdog: gpio_wdt: Make use of device properties
  sbsa_gwdt: Calculate timeout with 64-bit math
  watchdog: ixp4xx: Make sure restart always works
  watchdog: it87_wdt: add IT8613 ID
  watchdog: marvell_gti_wdt: Fix error code in probe()
  Watchdog: marvell_gti_wdt: Remove redundant dev_err_probe() for platform_get_irq()
  ...
parents f3bfe643 9d08e590
...@@ -15,9 +15,15 @@ allOf: ...@@ -15,9 +15,15 @@ allOf:
properties: properties:
compatible: compatible:
enum: oneOf:
- amlogic,meson-gxbb-wdt - enum:
- amlogic,t7-wdt - amlogic,meson-gxbb-wdt
- amlogic,t7-wdt
- items:
- enum:
- amlogic,c3-wdt
- amlogic,s4-wdt
- const: amlogic,t7-wdt
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs: ...@@ -47,7 +47,15 @@ Optional properties for AST2500-compatible watchdogs:
is configured as push-pull, then set the pulse is configured as push-pull, then set the pulse
polarity to active-high. The default is active-low. polarity to active-high. The default is active-low.
Example: Optional properties for AST2500- and AST2600-compatible watchdogs:
- aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
the watchdog timer expires. On AST2500 this should be a
single word defined using the AST2500_WDT_RESET_* macros;
on AST2600 this should be a two-word array with the first
word defined using the AST2600_WDT_RESET1_* macros and the
second word defined using the AST2600_WDT_RESET2_* macros.
Examples:
wdt1: watchdog@1e785000 { wdt1: watchdog@1e785000 {
compatible = "aspeed,ast2400-wdt"; compatible = "aspeed,ast2400-wdt";
...@@ -55,3 +63,11 @@ Example: ...@@ -55,3 +63,11 @@ Example:
aspeed,reset-type = "system"; aspeed,reset-type = "system";
aspeed,external-signal; aspeed,external-signal;
}; };
#include <dt-bindings/watchdog/aspeed-wdt.h>
wdt2: watchdog@1e785040 {
compatible = "aspeed,ast2600-wdt";
reg = <0x1e785040 0x40>;
aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
(AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
};
...@@ -30,6 +30,11 @@ properties: ...@@ -30,6 +30,11 @@ properties:
clocks: clocks:
maxItems: 1 maxItems: 1
fsl,ext-reset-output:
description:
When set, wdog can generate external reset from the wdog_any pin.
type: boolean
required: required:
- compatible - compatible
- interrupts - interrupts
......
...@@ -21,6 +21,8 @@ properties: ...@@ -21,6 +21,8 @@ properties:
- qcom,apss-wdt-ipq5018 - qcom,apss-wdt-ipq5018
- qcom,apss-wdt-ipq5332 - qcom,apss-wdt-ipq5332
- qcom,apss-wdt-ipq9574 - qcom,apss-wdt-ipq9574
- qcom,apss-wdt-msm8226
- qcom,apss-wdt-msm8974
- qcom,apss-wdt-msm8994 - qcom,apss-wdt-msm8994
- qcom,apss-wdt-qcm2290 - qcom,apss-wdt-qcm2290
- qcom,apss-wdt-qcs404 - qcom,apss-wdt-qcs404
......
...@@ -173,6 +173,8 @@ static int apple_wdt_probe(struct platform_device *pdev) ...@@ -173,6 +173,8 @@ static int apple_wdt_probe(struct platform_device *pdev)
if (!wdt->clk_rate) if (!wdt->clk_rate)
return -EINVAL; return -EINVAL;
platform_set_drvdata(pdev, wdt);
wdt->wdd.ops = &apple_wdt_ops; wdt->wdd.ops = &apple_wdt_ops;
wdt->wdd.info = &apple_wdt_info; wdt->wdd.info = &apple_wdt_info;
wdt->wdd.max_timeout = U32_MAX / wdt->clk_rate; wdt->wdd.max_timeout = U32_MAX / wdt->clk_rate;
...@@ -190,6 +192,28 @@ static int apple_wdt_probe(struct platform_device *pdev) ...@@ -190,6 +192,28 @@ static int apple_wdt_probe(struct platform_device *pdev)
return devm_watchdog_register_device(dev, &wdt->wdd); return devm_watchdog_register_device(dev, &wdt->wdd);
} }
static int apple_wdt_resume(struct device *dev)
{
struct apple_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->wdd) || watchdog_hw_running(&wdt->wdd))
apple_wdt_start(&wdt->wdd);
return 0;
}
static int apple_wdt_suspend(struct device *dev)
{
struct apple_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->wdd) || watchdog_hw_running(&wdt->wdd))
apple_wdt_stop(&wdt->wdd);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(apple_wdt_pm_ops, apple_wdt_suspend, apple_wdt_resume);
static const struct of_device_id apple_wdt_of_match[] = { static const struct of_device_id apple_wdt_of_match[] = {
{ .compatible = "apple,wdt" }, { .compatible = "apple,wdt" },
{}, {},
...@@ -200,6 +224,7 @@ static struct platform_driver apple_wdt_driver = { ...@@ -200,6 +224,7 @@ static struct platform_driver apple_wdt_driver = {
.driver = { .driver = {
.name = "apple-watchdog", .name = "apple-watchdog",
.of_match_table = apple_wdt_of_match, .of_match_table = apple_wdt_of_match,
.pm = pm_sleep_ptr(&apple_wdt_pm_ops),
}, },
.probe = apple_wdt_probe, .probe = apple_wdt_probe,
}; };
......
...@@ -79,6 +79,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table); ...@@ -79,6 +79,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
#define WDT_TIMEOUT_STATUS_BOOT_SECONDARY BIT(1) #define WDT_TIMEOUT_STATUS_BOOT_SECONDARY BIT(1)
#define WDT_CLEAR_TIMEOUT_STATUS 0x14 #define WDT_CLEAR_TIMEOUT_STATUS 0x14
#define WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION BIT(0) #define WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION BIT(0)
#define WDT_RESET_MASK1 0x1c
#define WDT_RESET_MASK2 0x20
/* /*
* WDT_RESET_WIDTH controls the characteristics of the external pulse (if * WDT_RESET_WIDTH controls the characteristics of the external pulse (if
...@@ -402,6 +404,8 @@ static int aspeed_wdt_probe(struct platform_device *pdev) ...@@ -402,6 +404,8 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
if ((of_device_is_compatible(np, "aspeed,ast2500-wdt")) || if ((of_device_is_compatible(np, "aspeed,ast2500-wdt")) ||
(of_device_is_compatible(np, "aspeed,ast2600-wdt"))) { (of_device_is_compatible(np, "aspeed,ast2600-wdt"))) {
u32 reset_mask[2];
size_t nrstmask = of_device_is_compatible(np, "aspeed,ast2600-wdt") ? 2 : 1;
u32 reg = readl(wdt->base + WDT_RESET_WIDTH); u32 reg = readl(wdt->base + WDT_RESET_WIDTH);
reg &= wdt->cfg->ext_pulse_width_mask; reg &= wdt->cfg->ext_pulse_width_mask;
...@@ -419,6 +423,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev) ...@@ -419,6 +423,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
reg |= WDT_OPEN_DRAIN_MAGIC; reg |= WDT_OPEN_DRAIN_MAGIC;
writel(reg, wdt->base + WDT_RESET_WIDTH); writel(reg, wdt->base + WDT_RESET_WIDTH);
ret = of_property_read_u32_array(np, "aspeed,reset-mask", reset_mask, nrstmask);
if (!ret) {
writel(reset_mask[0], wdt->base + WDT_RESET_MASK1);
if (nrstmask > 1)
writel(reset_mask[1], wdt->base + WDT_RESET_MASK2);
}
} }
if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) { if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) {
......
...@@ -348,25 +348,21 @@ static int __init at91wdt_probe(struct platform_device *pdev) ...@@ -348,25 +348,21 @@ static int __init at91wdt_probe(struct platform_device *pdev)
if (IS_ERR(wdt->base)) if (IS_ERR(wdt->base))
return PTR_ERR(wdt->base); return PTR_ERR(wdt->base);
wdt->sclk = devm_clk_get(&pdev->dev, NULL); wdt->sclk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(wdt->sclk)) if (IS_ERR(wdt->sclk)) {
return PTR_ERR(wdt->sclk);
err = clk_prepare_enable(wdt->sclk);
if (err) {
dev_err(&pdev->dev, "Could not enable slow clock\n"); dev_err(&pdev->dev, "Could not enable slow clock\n");
return err; return PTR_ERR(wdt->sclk);
} }
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
err = of_at91wdt_init(pdev->dev.of_node, wdt); err = of_at91wdt_init(pdev->dev.of_node, wdt);
if (err) if (err)
goto err_clk; return err;
} }
err = at91_wdt_init(pdev, wdt); err = at91_wdt_init(pdev, wdt);
if (err) if (err)
goto err_clk; return err;
platform_set_drvdata(pdev, wdt); platform_set_drvdata(pdev, wdt);
...@@ -374,11 +370,6 @@ static int __init at91wdt_probe(struct platform_device *pdev) ...@@ -374,11 +370,6 @@ static int __init at91wdt_probe(struct platform_device *pdev)
wdt->wdd.timeout, wdt->nowayout); wdt->wdd.timeout, wdt->nowayout);
return 0; return 0;
err_clk:
clk_disable_unprepare(wdt->sclk);
return err;
} }
static int __exit at91wdt_remove(struct platform_device *pdev) static int __exit at91wdt_remove(struct platform_device *pdev)
...@@ -388,7 +379,6 @@ static int __exit at91wdt_remove(struct platform_device *pdev) ...@@ -388,7 +379,6 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
pr_warn("I quit now, hardware will probably reboot!\n"); pr_warn("I quit now, hardware will probably reboot!\n");
del_timer(&wdt->timer); del_timer(&wdt->timer);
clk_disable_unprepare(wdt->sclk);
return 0; return 0;
} }
......
...@@ -257,19 +257,13 @@ static int ath79_wdt_probe(struct platform_device *pdev) ...@@ -257,19 +257,13 @@ static int ath79_wdt_probe(struct platform_device *pdev)
if (IS_ERR(wdt_base)) if (IS_ERR(wdt_base))
return PTR_ERR(wdt_base); return PTR_ERR(wdt_base);
wdt_clk = devm_clk_get(&pdev->dev, "wdt"); wdt_clk = devm_clk_get_enabled(&pdev->dev, "wdt");
if (IS_ERR(wdt_clk)) if (IS_ERR(wdt_clk))
return PTR_ERR(wdt_clk); return PTR_ERR(wdt_clk);
err = clk_prepare_enable(wdt_clk);
if (err)
return err;
wdt_freq = clk_get_rate(wdt_clk); wdt_freq = clk_get_rate(wdt_clk);
if (!wdt_freq) { if (!wdt_freq)
err = -EINVAL; return -EINVAL;
goto err_clk_disable;
}
max_timeout = (0xfffffffful / wdt_freq); max_timeout = (0xfffffffful / wdt_freq);
if (timeout < 1 || timeout > max_timeout) { if (timeout < 1 || timeout > max_timeout) {
...@@ -286,20 +280,15 @@ static int ath79_wdt_probe(struct platform_device *pdev) ...@@ -286,20 +280,15 @@ static int ath79_wdt_probe(struct platform_device *pdev)
if (err) { if (err) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"unable to register misc device, err=%d\n", err); "unable to register misc device, err=%d\n", err);
goto err_clk_disable; return err;
} }
return 0; return 0;
err_clk_disable:
clk_disable_unprepare(wdt_clk);
return err;
} }
static void ath79_wdt_remove(struct platform_device *pdev) static void ath79_wdt_remove(struct platform_device *pdev)
{ {
misc_deregister(&ath79_wdt_miscdev); misc_deregister(&ath79_wdt_miscdev);
clk_disable_unprepare(wdt_clk);
} }
static void ath79_wdt_shutdown(struct platform_device *pdev) static void ath79_wdt_shutdown(struct platform_device *pdev)
......
...@@ -5,12 +5,13 @@ ...@@ -5,12 +5,13 @@
* Author: 2013, Alexander Shiyan <shc_work@mail.ru> * Author: 2013, Alexander Shiyan <shc_work@mail.ru>
*/ */
#include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/err.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of.h> #include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
static bool nowayout = WATCHDOG_NOWAYOUT; static bool nowayout = WATCHDOG_NOWAYOUT;
...@@ -106,7 +107,6 @@ static const struct watchdog_ops gpio_wdt_ops = { ...@@ -106,7 +107,6 @@ static const struct watchdog_ops gpio_wdt_ops = {
static int gpio_wdt_probe(struct platform_device *pdev) static int gpio_wdt_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct gpio_wdt_priv *priv; struct gpio_wdt_priv *priv;
enum gpiod_flags gflags; enum gpiod_flags gflags;
unsigned int hw_margin; unsigned int hw_margin;
...@@ -119,7 +119,7 @@ static int gpio_wdt_probe(struct platform_device *pdev) ...@@ -119,7 +119,7 @@ static int gpio_wdt_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv); platform_set_drvdata(pdev, priv);
ret = of_property_read_string(np, "hw_algo", &algo); ret = device_property_read_string(dev, "hw_algo", &algo);
if (ret) if (ret)
return ret; return ret;
if (!strcmp(algo, "toggle")) { if (!strcmp(algo, "toggle")) {
...@@ -136,16 +136,14 @@ static int gpio_wdt_probe(struct platform_device *pdev) ...@@ -136,16 +136,14 @@ static int gpio_wdt_probe(struct platform_device *pdev)
if (IS_ERR(priv->gpiod)) if (IS_ERR(priv->gpiod))
return PTR_ERR(priv->gpiod); return PTR_ERR(priv->gpiod);
ret = of_property_read_u32(np, ret = device_property_read_u32(dev, "hw_margin_ms", &hw_margin);
"hw_margin_ms", &hw_margin);
if (ret) if (ret)
return ret; return ret;
/* Disallow values lower than 2 and higher than 65535 ms */ /* Disallow values lower than 2 and higher than 65535 ms */
if (hw_margin < 2 || hw_margin > 65535) if (hw_margin < 2 || hw_margin > 65535)
return -EINVAL; return -EINVAL;
priv->always_running = of_property_read_bool(np, priv->always_running = device_property_read_bool(dev, "always-running");
"always-running");
watchdog_set_drvdata(&priv->wdd, priv); watchdog_set_drvdata(&priv->wdd, priv);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define LPO_CLK_SHIFT 8 #define LPO_CLK_SHIFT 8
#define WDOG_CS_CLK (LPO_CLK << LPO_CLK_SHIFT) #define WDOG_CS_CLK (LPO_CLK << LPO_CLK_SHIFT)
#define WDOG_CS_EN BIT(7) #define WDOG_CS_EN BIT(7)
#define WDOG_CS_INT_EN BIT(6)
#define WDOG_CS_UPDATE BIT(5) #define WDOG_CS_UPDATE BIT(5)
#define WDOG_CS_WAIT BIT(1) #define WDOG_CS_WAIT BIT(1)
#define WDOG_CS_STOP BIT(0) #define WDOG_CS_STOP BIT(0)
...@@ -62,6 +63,7 @@ struct imx7ulp_wdt_device { ...@@ -62,6 +63,7 @@ struct imx7ulp_wdt_device {
void __iomem *base; void __iomem *base;
struct clk *clk; struct clk *clk;
bool post_rcs_wait; bool post_rcs_wait;
bool ext_reset;
const struct imx_wdt_hw_feature *hw; const struct imx_wdt_hw_feature *hw;
}; };
...@@ -285,6 +287,9 @@ static int imx7ulp_wdt_init(struct imx7ulp_wdt_device *wdt, unsigned int timeout ...@@ -285,6 +287,9 @@ static int imx7ulp_wdt_init(struct imx7ulp_wdt_device *wdt, unsigned int timeout
if (wdt->hw->prescaler_enable) if (wdt->hw->prescaler_enable)
val |= WDOG_CS_PRES; val |= WDOG_CS_PRES;
if (wdt->ext_reset)
val |= WDOG_CS_INT_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);
...@@ -321,6 +326,9 @@ static int imx7ulp_wdt_probe(struct platform_device *pdev) ...@@ -321,6 +326,9 @@ static int imx7ulp_wdt_probe(struct platform_device *pdev)
return PTR_ERR(imx7ulp_wdt->clk); return PTR_ERR(imx7ulp_wdt->clk);
} }
/* The WDOG may need to do external reset through dedicated pin */
imx7ulp_wdt->ext_reset = of_property_read_bool(dev->of_node, "fsl,ext-reset-output");
imx7ulp_wdt->post_rcs_wait = true; imx7ulp_wdt->post_rcs_wait = true;
if (of_device_is_compatible(dev->of_node, if (of_device_is_compatible(dev->of_node,
"fsl,imx8ulp-wdt")) { "fsl,imx8ulp-wdt")) {
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define SC_IRQ_WDOG 1 #define SC_IRQ_WDOG 1
#define SC_IRQ_GROUP_WDOG 1 #define SC_IRQ_GROUP_WDOG 1
#define SC_TIMER_ERR_BUSY 10
static bool nowayout = WATCHDOG_NOWAYOUT; static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0000); module_param(nowayout, bool, 0000);
...@@ -61,7 +62,9 @@ static int imx_sc_wdt_start(struct watchdog_device *wdog) ...@@ -61,7 +62,9 @@ static int imx_sc_wdt_start(struct watchdog_device *wdog)
arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_START_WDOG, arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_START_WDOG,
0, 0, 0, 0, 0, 0, &res); 0, 0, 0, 0, 0, 0, &res);
if (res.a0)
/* Ignore if already enabled(SC_TIMER_ERR_BUSY) */
if (res.a0 && res.a0 != SC_TIMER_ERR_BUSY)
return -EACCES; return -EACCES;
arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_WDOG_ACT, arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_WDOG_ACT,
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
* http://www.ite.com.tw/ * http://www.ite.com.tw/
* *
* Support of the watchdog timers, which are available on * Support of the watchdog timers, which are available on
* IT8607, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665, IT8686, * IT8607, IT8613, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665,
* IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726, IT8728, * IT8686, IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726,
* IT8772, IT8783 and IT8784. * IT8728, IT8772, IT8783 and IT8784.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
/* Chip Id numbers */ /* Chip Id numbers */
#define NO_DEV_ID 0xffff #define NO_DEV_ID 0xffff
#define IT8607_ID 0x8607 #define IT8607_ID 0x8607
#define IT8613_ID 0x8613
#define IT8620_ID 0x8620 #define IT8620_ID 0x8620
#define IT8622_ID 0x8622 #define IT8622_ID 0x8622
#define IT8625_ID 0x8625 #define IT8625_ID 0x8625
...@@ -277,6 +278,7 @@ static int __init it87_wdt_init(void) ...@@ -277,6 +278,7 @@ static int __init it87_wdt_init(void)
max_units = 65535; max_units = 65535;
break; break;
case IT8607_ID: case IT8607_ID:
case IT8613_ID:
case IT8620_ID: case IT8620_ID:
case IT8622_ID: case IT8622_ID:
case IT8625_ID: case IT8625_ID:
......
...@@ -105,6 +105,25 @@ static const struct watchdog_ops ixp4xx_wdt_ops = { ...@@ -105,6 +105,25 @@ static const struct watchdog_ops ixp4xx_wdt_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
/*
* The A0 version of the IXP422 had a bug in the watchdog making
* is useless, but we still need to use it to restart the system
* as it is the only way, so in this special case we register a
* "dummy" watchdog that doesn't really work, but will support
* the restart operation.
*/
static int ixp4xx_wdt_dummy(struct watchdog_device *wdd)
{
return 0;
}
static const struct watchdog_ops ixp4xx_wdt_restart_only_ops = {
.start = ixp4xx_wdt_dummy,
.stop = ixp4xx_wdt_dummy,
.restart = ixp4xx_wdt_restart,
.owner = THIS_MODULE,
};
static const struct watchdog_info ixp4xx_wdt_info = { static const struct watchdog_info ixp4xx_wdt_info = {
.options = WDIOF_KEEPALIVEPING .options = WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE | WDIOF_MAGICCLOSE
...@@ -114,14 +133,17 @@ static const struct watchdog_info ixp4xx_wdt_info = { ...@@ -114,14 +133,17 @@ static const struct watchdog_info ixp4xx_wdt_info = {
static int ixp4xx_wdt_probe(struct platform_device *pdev) static int ixp4xx_wdt_probe(struct platform_device *pdev)
{ {
static const struct watchdog_ops *iwdt_ops;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ixp4xx_wdt *iwdt; struct ixp4xx_wdt *iwdt;
struct clk *clk; struct clk *clk;
int ret; int ret;
if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) { if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
dev_err(dev, "Rev. A0 IXP42x CPU detected - watchdog disabled\n"); dev_info(dev, "Rev. A0 IXP42x CPU detected - only restart supported\n");
return -ENODEV; iwdt_ops = &ixp4xx_wdt_restart_only_ops;
} else {
iwdt_ops = &ixp4xx_wdt_ops;
} }
iwdt = devm_kzalloc(dev, sizeof(*iwdt), GFP_KERNEL); iwdt = devm_kzalloc(dev, sizeof(*iwdt), GFP_KERNEL);
...@@ -141,7 +163,7 @@ static int ixp4xx_wdt_probe(struct platform_device *pdev) ...@@ -141,7 +163,7 @@ static int ixp4xx_wdt_probe(struct platform_device *pdev)
iwdt->rate = IXP4XX_TIMER_FREQ; iwdt->rate = IXP4XX_TIMER_FREQ;
iwdt->wdd.info = &ixp4xx_wdt_info; iwdt->wdd.info = &ixp4xx_wdt_info;
iwdt->wdd.ops = &ixp4xx_wdt_ops; iwdt->wdd.ops = iwdt_ops;
iwdt->wdd.min_timeout = 1; iwdt->wdd.min_timeout = 1;
iwdt->wdd.max_timeout = U32_MAX / iwdt->rate; iwdt->wdd.max_timeout = U32_MAX / iwdt->rate;
iwdt->wdd.parent = dev; iwdt->wdd.parent = dev;
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
/* /*
...@@ -190,6 +190,13 @@ static int gti_wdt_set_pretimeout(struct watchdog_device *wdev, ...@@ -190,6 +190,13 @@ static int gti_wdt_set_pretimeout(struct watchdog_device *wdev,
struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev); struct gti_wdt_priv *priv = watchdog_get_drvdata(wdev);
struct watchdog_device *wdog_dev = &priv->wdev; struct watchdog_device *wdog_dev = &priv->wdev;
if (!timeout) {
/* Disable Interrupt */
writeq(GTI_CWD_INT_ENA_CLR_VAL(priv->wdt_timer_idx),
priv->base + GTI_CWD_INT_ENA_CLR);
return 0;
}
/* pretimeout should 1/3 of max_timeout */ /* pretimeout should 1/3 of max_timeout */
if (timeout * 3 <= wdog_dev->max_timeout) if (timeout * 3 <= wdog_dev->max_timeout)
return gti_wdt_settimeout(wdev, timeout * 3); return gti_wdt_settimeout(wdev, timeout * 3);
...@@ -271,7 +278,7 @@ static int gti_wdt_probe(struct platform_device *pdev) ...@@ -271,7 +278,7 @@ static int gti_wdt_probe(struct platform_device *pdev)
&wdt_idx); &wdt_idx);
if (!err) { if (!err) {
if (wdt_idx >= priv->data->gti_num_timers) if (wdt_idx >= priv->data->gti_num_timers)
return dev_err_probe(&pdev->dev, err, return dev_err_probe(&pdev->dev, -EINVAL,
"GTI wdog timer index not valid"); "GTI wdog timer index not valid");
priv->wdt_timer_idx = wdt_idx; priv->wdt_timer_idx = wdt_idx;
...@@ -292,6 +299,7 @@ static int gti_wdt_probe(struct platform_device *pdev) ...@@ -292,6 +299,7 @@ static int gti_wdt_probe(struct platform_device *pdev)
/* Maximum timeout is 3 times the pretimeout */ /* Maximum timeout is 3 times the pretimeout */
wdog_dev->max_timeout = max_pretimeout * 3; wdog_dev->max_timeout = max_pretimeout * 3;
wdog_dev->max_hw_heartbeat_ms = max_pretimeout * 1000;
/* Minimum first timeout (pretimeout) is 1, so min_timeout as 3 */ /* Minimum first timeout (pretimeout) is 1, so min_timeout as 3 */
wdog_dev->min_timeout = 3; wdog_dev->min_timeout = 3;
wdog_dev->timeout = wdog_dev->pretimeout; wdog_dev->timeout = wdog_dev->pretimeout;
...@@ -308,7 +316,7 @@ static int gti_wdt_probe(struct platform_device *pdev) ...@@ -308,7 +316,7 @@ static int gti_wdt_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
return dev_err_probe(&pdev->dev, irq, "IRQ resource not found\n"); return irq;
err = devm_request_irq(dev, irq, gti_wdt_interrupt, 0, err = devm_request_irq(dev, irq, gti_wdt_interrupt, 0,
pdev->name, &priv->wdev); pdev->name, &priv->wdev);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
* @tleft_idx: index for direct access to time left register; * @tleft_idx: index for direct access to time left register;
* @ping_idx: index for direct access to ping register; * @ping_idx: index for direct access to ping register;
* @reset_idx: index for direct access to reset cause register; * @reset_idx: index for direct access to reset cause register;
* @regmap_val_sz: size of value in register map;
* @wd_type: watchdog HW type; * @wd_type: watchdog HW type;
*/ */
struct mlxreg_wdt { struct mlxreg_wdt {
......
...@@ -187,7 +187,7 @@ static int xwdt_probe(struct platform_device *pdev) ...@@ -187,7 +187,7 @@ static int xwdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(xilinx_wdt_wdd, enable_once); watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
xdev->clk = devm_clk_get_enabled(dev, NULL); xdev->clk = devm_clk_get_prepared(dev, NULL);
if (IS_ERR(xdev->clk)) { if (IS_ERR(xdev->clk)) {
if (PTR_ERR(xdev->clk) != -ENOENT) if (PTR_ERR(xdev->clk) != -ENOENT)
return PTR_ERR(xdev->clk); return PTR_ERR(xdev->clk);
...@@ -218,18 +218,25 @@ static int xwdt_probe(struct platform_device *pdev) ...@@ -218,18 +218,25 @@ static int xwdt_probe(struct platform_device *pdev)
spin_lock_init(&xdev->spinlock); spin_lock_init(&xdev->spinlock);
watchdog_set_drvdata(xilinx_wdt_wdd, xdev); watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
rc = clk_enable(xdev->clk);
if (rc) {
dev_err(dev, "unable to enable clock\n");
return rc;
}
rc = xwdt_selftest(xdev); rc = xwdt_selftest(xdev);
if (rc == XWT_TIMER_FAILED) { if (rc == XWT_TIMER_FAILED) {
dev_err(dev, "SelfTest routine error\n"); dev_err(dev, "SelfTest routine error\n");
clk_disable(xdev->clk);
return rc; return rc;
} }
clk_disable(xdev->clk);
rc = devm_watchdog_register_device(dev, xilinx_wdt_wdd); rc = devm_watchdog_register_device(dev, xilinx_wdt_wdd);
if (rc) if (rc)
return rc; return rc;
clk_disable(xdev->clk);
dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n", dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n",
xilinx_wdt_wdd->timeout); xilinx_wdt_wdd->timeout);
......
...@@ -152,14 +152,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd, ...@@ -152,14 +152,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000); timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000);
if (action) if (action)
sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt); sbsa_gwdt_reg_write((u64)gwdt->clk * timeout, gwdt);
else else
/* /*
* In the single stage mode, The first signal (WS0) is ignored, * In the single stage mode, The first signal (WS0) is ignored,
* the timeout is (WOR * 2), so the WOR should be configured * the timeout is (WOR * 2), so the WOR should be configured
* to half value of timeout. * to half value of timeout.
*/ */
sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt); sbsa_gwdt_reg_write(((u64)gwdt->clk / 2) * timeout, gwdt);
return 0; return 0;
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
...@@ -42,7 +41,7 @@ struct st_wdog { ...@@ -42,7 +41,7 @@ struct st_wdog {
void __iomem *base; void __iomem *base;
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
struct st_wdog_syscfg *syscfg; const struct st_wdog_syscfg *syscfg;
struct clk *clk; struct clk *clk;
unsigned long clkrate; unsigned long clkrate;
bool warm_reset; bool warm_reset;
...@@ -150,7 +149,6 @@ static void st_clk_disable_unprepare(void *data) ...@@ -150,7 +149,6 @@ static void st_clk_disable_unprepare(void *data)
static int st_wdog_probe(struct platform_device *pdev) static int st_wdog_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct st_wdog *st_wdog; struct st_wdog *st_wdog;
struct regmap *regmap; struct regmap *regmap;
...@@ -173,12 +171,7 @@ static int st_wdog_probe(struct platform_device *pdev) ...@@ -173,12 +171,7 @@ static int st_wdog_probe(struct platform_device *pdev)
if (!st_wdog) if (!st_wdog)
return -ENOMEM; return -ENOMEM;
match = of_match_device(st_wdog_match, dev); st_wdog->syscfg = (struct st_wdog_syscfg *)device_get_match_data(dev);
if (!match) {
dev_err(dev, "Couldn't match device\n");
return -ENODEV;
}
st_wdog->syscfg = (struct st_wdog_syscfg *)match->data;
base = devm_platform_ioremap_resource(pdev, 0); base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) if (IS_ERR(base))
......
...@@ -136,11 +136,6 @@ static const struct watchdog_ops sp_wdt_ops = { ...@@ -136,11 +136,6 @@ static const struct watchdog_ops sp_wdt_ops = {
.restart = sp_wdt_restart, .restart = sp_wdt_restart,
}; };
static void sp_clk_disable_unprepare(void *data)
{
clk_disable_unprepare(data);
}
static void sp_reset_control_assert(void *data) static void sp_reset_control_assert(void *data)
{ {
reset_control_assert(data); reset_control_assert(data);
...@@ -156,17 +151,9 @@ static int sp_wdt_probe(struct platform_device *pdev) ...@@ -156,17 +151,9 @@ static int sp_wdt_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->clk = devm_clk_get(dev, NULL); priv->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(priv->clk)) if (IS_ERR(priv->clk))
return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to get clock\n"); return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to enable clock\n");
ret = clk_prepare_enable(priv->clk);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable clock\n");
ret = devm_add_action_or_reset(dev, sp_clk_disable_unprepare, priv->clk);
if (ret)
return ret;
/* The timer and watchdog shared the STC reset */ /* The timer and watchdog shared the STC reset */
priv->rstc = devm_reset_control_get_shared(dev, NULL); priv->rstc = devm_reset_control_get_shared(dev, NULL);
......
...@@ -269,7 +269,7 @@ static int wdat_wdt_stop(struct watchdog_device *wdd) ...@@ -269,7 +269,7 @@ static int wdat_wdt_stop(struct watchdog_device *wdd)
static int wdat_wdt_ping(struct watchdog_device *wdd) static int wdat_wdt_ping(struct watchdog_device *wdd)
{ {
return wdat_wdt_run_action(to_wdat_wdt(wdd), ACPI_WDAT_RESET, 0, NULL); return wdat_wdt_run_action(to_wdat_wdt(wdd), ACPI_WDAT_RESET, wdd->timeout, NULL);
} }
static int wdat_wdt_set_timeout(struct watchdog_device *wdd, static int wdat_wdt_set_timeout(struct watchdog_device *wdd,
......
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
#ifndef DT_BINDINGS_ASPEED_WDT_H
#define DT_BINDINGS_ASPEED_WDT_H
#define AST2500_WDT_RESET_CPU (1 << 0)
#define AST2500_WDT_RESET_COPROC (1 << 1)
#define AST2500_WDT_RESET_SDRAM (1 << 2)
#define AST2500_WDT_RESET_AHB (1 << 3)
#define AST2500_WDT_RESET_I2C (1 << 4)
#define AST2500_WDT_RESET_MAC0 (1 << 5)
#define AST2500_WDT_RESET_MAC1 (1 << 6)
#define AST2500_WDT_RESET_GRAPHICS (1 << 7)
#define AST2500_WDT_RESET_USB2_HOST_HUB (1 << 8)
#define AST2500_WDT_RESET_USB_HOST (1 << 9)
#define AST2500_WDT_RESET_HID_EHCI (1 << 10)
#define AST2500_WDT_RESET_VIDEO (1 << 11)
#define AST2500_WDT_RESET_HAC (1 << 12)
#define AST2500_WDT_RESET_LPC (1 << 13)
#define AST2500_WDT_RESET_SDIO (1 << 14)
#define AST2500_WDT_RESET_MIC (1 << 15)
#define AST2500_WDT_RESET_CRT (1 << 16)
#define AST2500_WDT_RESET_PWM (1 << 17)
#define AST2500_WDT_RESET_PECI (1 << 18)
#define AST2500_WDT_RESET_JTAG (1 << 19)
#define AST2500_WDT_RESET_ADC (1 << 20)
#define AST2500_WDT_RESET_GPIO (1 << 21)
#define AST2500_WDT_RESET_MCTP (1 << 22)
#define AST2500_WDT_RESET_XDMA (1 << 23)
#define AST2500_WDT_RESET_SPI (1 << 24)
#define AST2500_WDT_RESET_SOC_MISC (1 << 25)
#define AST2500_WDT_RESET_DEFAULT 0x023ffff3
#define AST2600_WDT_RESET1_CPU (1 << 0)
#define AST2600_WDT_RESET1_SDRAM (1 << 1)
#define AST2600_WDT_RESET1_AHB (1 << 2)
#define AST2600_WDT_RESET1_SLI (1 << 3)
#define AST2600_WDT_RESET1_SOC_MISC0 (1 << 4)
#define AST2600_WDT_RESET1_COPROC (1 << 5)
#define AST2600_WDT_RESET1_USB_A (1 << 6)
#define AST2600_WDT_RESET1_USB_B (1 << 7)
#define AST2600_WDT_RESET1_UHCI (1 << 8)
#define AST2600_WDT_RESET1_GRAPHICS (1 << 9)
#define AST2600_WDT_RESET1_CRT (1 << 10)
#define AST2600_WDT_RESET1_VIDEO (1 << 11)
#define AST2600_WDT_RESET1_HAC (1 << 12)
#define AST2600_WDT_RESET1_DP (1 << 13)
#define AST2600_WDT_RESET1_DP_MCU (1 << 14)
#define AST2600_WDT_RESET1_GP_MCU (1 << 15)
#define AST2600_WDT_RESET1_MAC0 (1 << 16)
#define AST2600_WDT_RESET1_MAC1 (1 << 17)
#define AST2600_WDT_RESET1_SDIO0 (1 << 18)
#define AST2600_WDT_RESET1_JTAG0 (1 << 19)
#define AST2600_WDT_RESET1_MCTP0 (1 << 20)
#define AST2600_WDT_RESET1_MCTP1 (1 << 21)
#define AST2600_WDT_RESET1_XDMA0 (1 << 22)
#define AST2600_WDT_RESET1_XDMA1 (1 << 23)
#define AST2600_WDT_RESET1_GPIO0 (1 << 24)
#define AST2600_WDT_RESET1_RVAS (1 << 25)
#define AST2600_WDT_RESET1_DEFAULT 0x030f1ff1
#define AST2600_WDT_RESET2_CPU (1 << 0)
#define AST2600_WDT_RESET2_SPI (1 << 1)
#define AST2600_WDT_RESET2_AHB2 (1 << 2)
#define AST2600_WDT_RESET2_SLI2 (1 << 3)
#define AST2600_WDT_RESET2_SOC_MISC1 (1 << 4)
#define AST2600_WDT_RESET2_MAC2 (1 << 5)
#define AST2600_WDT_RESET2_MAC3 (1 << 6)
#define AST2600_WDT_RESET2_SDIO1 (1 << 7)
#define AST2600_WDT_RESET2_JTAG1 (1 << 8)
#define AST2600_WDT_RESET2_GPIO1 (1 << 9)
#define AST2600_WDT_RESET2_MDIO (1 << 10)
#define AST2600_WDT_RESET2_LPC (1 << 11)
#define AST2600_WDT_RESET2_PECI (1 << 12)
#define AST2600_WDT_RESET2_PWM (1 << 13)
#define AST2600_WDT_RESET2_ADC (1 << 14)
#define AST2600_WDT_RESET2_FSI (1 << 15)
#define AST2600_WDT_RESET2_I2C (1 << 16)
#define AST2600_WDT_RESET2_I3C_GLOBAL (1 << 17)
#define AST2600_WDT_RESET2_I3C0 (1 << 18)
#define AST2600_WDT_RESET2_I3C1 (1 << 19)
#define AST2600_WDT_RESET2_I3C2 (1 << 20)
#define AST2600_WDT_RESET2_I3C3 (1 << 21)
#define AST2600_WDT_RESET2_I3C4 (1 << 22)
#define AST2600_WDT_RESET2_I3C5 (1 << 23)
#define AST2600_WDT_RESET2_ESPI (1 << 26)
#define AST2600_WDT_RESET2_DEFAULT 0x03fffff1
#endif
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