diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt index 2144af1a5264dfd42c956522af88ce926129e81a..e52ba2da868ce120daf7348aa15cdda02fcc34af 100644 --- a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt @@ -5,10 +5,15 @@ Required properties: - reg : Should contain WDT registers location and length - interrupts : Should contain WDT interrupt +Optional property: +- big-endian: If present the watchdog device's registers are implemented + in big endian mode, otherwise in little mode. + Examples: wdt@73f98000 { compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; reg = <0x73f98000 0x4000>; interrupts = <58>; + big-endian; }; diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt index eb7132ed8bbcb7650bdc20e6a43e3c9222d6621b..b3a701f48118976a285259b0db73fc9d1a4948fa 100644 --- a/Documentation/watchdog/watchdog-api.txt +++ b/Documentation/watchdog/watchdog-api.txt @@ -118,7 +118,7 @@ resets. Note that the pretimeout is the number of seconds before the time when the timeout will go off. It is not the number of seconds until the pretimeout. So, for instance, if you set the timeout to 60 seconds -and the pretimeout to 10 seconds, the pretimout will go of in 50 +and the pretimeout to 10 seconds, the pretimeout will go off in 50 seconds. Setting a pretimeout to zero disables it. There is also a get function for getting the pretimeout: diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index ee4f86ba83eca1856dc85a0ad777e11732e4e5ea..9f210299de2491cd9c9ed654268e0bda991a6c5e 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -296,9 +296,6 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) int ret; struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -EINVAL; - dw_wdt.regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(dw_wdt.regs)) return PTR_ERR(dw_wdt.regs); diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 9d4874f09948aa2110fc207730f57d0fe1772fbd..68c3d379ffa8c599333af45abc1b0841fd10059e 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -28,6 +28,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/timer.h> @@ -190,10 +191,12 @@ static struct regmap_config imx2_wdt_regmap_config = { static int __init imx2_wdt_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct imx2_wdt_device *wdev; struct watchdog_device *wdog; struct resource *res; void __iomem *base; + bool big_endian; int ret; u32 val; @@ -201,6 +204,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (!wdev) return -ENOMEM; + big_endian = of_property_read_bool(np, "big-endian"); + if (big_endian) + imx2_wdt_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c index 3b3148c764a3853c9076d9e14a804f92fdea8347..021e84eb88ebf6aee35bcbefee1261518878500e 100644 --- a/drivers/watchdog/lantiq_wdt.c +++ b/drivers/watchdog/lantiq_wdt.c @@ -192,11 +192,6 @@ ltq_wdt_probe(struct platform_device *pdev) struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct clk *clk; - if (!res) { - dev_err(&pdev->dev, "cannot obtain I/O memory region"); - return -ENOENT; - } - ltq_wdt_membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ltq_wdt_membase)) return PTR_ERR(ltq_wdt_membase); diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 061756e36cf8ddabeed3854b41aa615221bcb62e..fa89bb30d00443d8dfec2c9100ac7c3b6d60b5af 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -230,10 +230,6 @@ static int sh_wdt_probe(struct platform_device *pdev) if (pdev->id != -1) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) - return -EINVAL; - wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); if (unlikely(!wdt)) return -ENOMEM; @@ -249,6 +245,7 @@ static int sh_wdt_probe(struct platform_device *pdev) wdt->clk = NULL; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); wdt->base = devm_ioremap_resource(wdt->dev, res); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index 693b9d2c6e39e0606524675bcf16d20ebfba876b..60deb9d304c0dfcea5bb8b5b8111d164cffcf791 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c @@ -14,6 +14,7 @@ */ #include <linux/clk.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/init.h> #include <linux/io.h> @@ -22,9 +23,12 @@ #include <linux/moduleparam.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/reboot.h> #include <linux/types.h> #include <linux/watchdog.h> +#include <asm/system_misc.h> + #define WDT_MAX_TIMEOUT 16 #define WDT_MIN_TIMEOUT 1 #define WDT_MODE_TIMEOUT(n) ((n) << 3) @@ -70,6 +74,26 @@ static const int wdt_timeout_map[] = { [16] = 0xB, /* 16s */ }; +static void __iomem *reboot_wdt_base; + +static void sun4i_wdt_restart(enum reboot_mode mode, const char *cmd) +{ + /* Enable timer and set reset bit in the watchdog */ + writel(WDT_MODE_EN | WDT_MODE_RST_EN, reboot_wdt_base + WDT_MODE); + + /* + * Restart the watchdog. The default (and lowest) interval + * value for the watchdog is 0.5s. + */ + writel(WDT_CTRL_RELOAD, reboot_wdt_base + WDT_CTRL); + + while (1) { + mdelay(5); + writel(WDT_MODE_EN | WDT_MODE_RST_EN, + reboot_wdt_base + WDT_MODE); + } +} + static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) { struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); @@ -181,6 +205,9 @@ static int sunxi_wdt_probe(struct platform_device *pdev) if (unlikely(err)) return err; + reboot_wdt_base = sunxi_wdt->wdt_base; + arm_pm_restart = sun4i_wdt_restart; + dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", sunxi_wdt->wdt_dev.timeout, nowayout); @@ -191,6 +218,8 @@ static int sunxi_wdt_remove(struct platform_device *pdev) { struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); + arm_pm_restart = NULL; + watchdog_unregister_device(&sunxi_wdt->wdt_dev); watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL);