diff options
| -rw-r--r-- | Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt | 5 | ||||
| -rw-r--r-- | Documentation/watchdog/watchdog-api.txt | 2 | ||||
| -rw-r--r-- | drivers/watchdog/dw_wdt.c | 3 | ||||
| -rw-r--r-- | drivers/watchdog/imx2_wdt.c | 7 | ||||
| -rw-r--r-- | drivers/watchdog/lantiq_wdt.c | 5 | ||||
| -rw-r--r-- | drivers/watchdog/shwdt.c | 5 | ||||
| -rw-r--r-- | drivers/watchdog/sunxi_wdt.c | 29 |
7 files changed, 43 insertions, 13 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt index 2144af1a5264..e52ba2da868c 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: | |||
| 5 | - reg : Should contain WDT registers location and length | 5 | - reg : Should contain WDT registers location and length |
| 6 | - interrupts : Should contain WDT interrupt | 6 | - interrupts : Should contain WDT interrupt |
| 7 | 7 | ||
| 8 | Optional property: | ||
| 9 | - big-endian: If present the watchdog device's registers are implemented | ||
| 10 | in big endian mode, otherwise in little mode. | ||
| 11 | |||
| 8 | Examples: | 12 | Examples: |
| 9 | 13 | ||
| 10 | wdt@73f98000 { | 14 | wdt@73f98000 { |
| 11 | compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; | 15 | compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; |
| 12 | reg = <0x73f98000 0x4000>; | 16 | reg = <0x73f98000 0x4000>; |
| 13 | interrupts = <58>; | 17 | interrupts = <58>; |
| 18 | big-endian; | ||
| 14 | }; | 19 | }; |
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt index eb7132ed8bbc..b3a701f48118 100644 --- a/Documentation/watchdog/watchdog-api.txt +++ b/Documentation/watchdog/watchdog-api.txt | |||
| @@ -118,7 +118,7 @@ resets. | |||
| 118 | Note that the pretimeout is the number of seconds before the time | 118 | Note that the pretimeout is the number of seconds before the time |
| 119 | when the timeout will go off. It is not the number of seconds until | 119 | when the timeout will go off. It is not the number of seconds until |
| 120 | the pretimeout. So, for instance, if you set the timeout to 60 seconds | 120 | the pretimeout. So, for instance, if you set the timeout to 60 seconds |
| 121 | and the pretimeout to 10 seconds, the pretimout will go of in 50 | 121 | and the pretimeout to 10 seconds, the pretimeout will go off in 50 |
| 122 | seconds. Setting a pretimeout to zero disables it. | 122 | seconds. Setting a pretimeout to zero disables it. |
| 123 | 123 | ||
| 124 | There is also a get function for getting the pretimeout: | 124 | 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 ee4f86ba83ec..9f210299de24 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) | |||
| 296 | int ret; | 296 | int ret; |
| 297 | struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 297 | struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 298 | 298 | ||
| 299 | if (!mem) | ||
| 300 | return -EINVAL; | ||
| 301 | |||
| 302 | dw_wdt.regs = devm_ioremap_resource(&pdev->dev, mem); | 299 | dw_wdt.regs = devm_ioremap_resource(&pdev->dev, mem); |
| 303 | if (IS_ERR(dw_wdt.regs)) | 300 | if (IS_ERR(dw_wdt.regs)) |
| 304 | return PTR_ERR(dw_wdt.regs); | 301 | return PTR_ERR(dw_wdt.regs); |
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 9d4874f09948..68c3d379ffa8 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
| 31 | #include <linux/of_address.h> | ||
| 31 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 32 | #include <linux/regmap.h> | 33 | #include <linux/regmap.h> |
| 33 | #include <linux/timer.h> | 34 | #include <linux/timer.h> |
| @@ -190,10 +191,12 @@ static struct regmap_config imx2_wdt_regmap_config = { | |||
| 190 | 191 | ||
| 191 | static int __init imx2_wdt_probe(struct platform_device *pdev) | 192 | static int __init imx2_wdt_probe(struct platform_device *pdev) |
| 192 | { | 193 | { |
| 194 | struct device_node *np = pdev->dev.of_node; | ||
| 193 | struct imx2_wdt_device *wdev; | 195 | struct imx2_wdt_device *wdev; |
| 194 | struct watchdog_device *wdog; | 196 | struct watchdog_device *wdog; |
| 195 | struct resource *res; | 197 | struct resource *res; |
| 196 | void __iomem *base; | 198 | void __iomem *base; |
| 199 | bool big_endian; | ||
| 197 | int ret; | 200 | int ret; |
| 198 | u32 val; | 201 | u32 val; |
| 199 | 202 | ||
| @@ -201,6 +204,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) | |||
| 201 | if (!wdev) | 204 | if (!wdev) |
| 202 | return -ENOMEM; | 205 | return -ENOMEM; |
| 203 | 206 | ||
| 207 | big_endian = of_property_read_bool(np, "big-endian"); | ||
| 208 | if (big_endian) | ||
| 209 | imx2_wdt_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
| 210 | |||
| 204 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 211 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 205 | base = devm_ioremap_resource(&pdev->dev, res); | 212 | base = devm_ioremap_resource(&pdev->dev, res); |
| 206 | if (IS_ERR(base)) | 213 | if (IS_ERR(base)) |
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c index 3b3148c764a3..021e84eb88eb 100644 --- a/drivers/watchdog/lantiq_wdt.c +++ b/drivers/watchdog/lantiq_wdt.c | |||
| @@ -192,11 +192,6 @@ ltq_wdt_probe(struct platform_device *pdev) | |||
| 192 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 192 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 193 | struct clk *clk; | 193 | struct clk *clk; |
| 194 | 194 | ||
| 195 | if (!res) { | ||
| 196 | dev_err(&pdev->dev, "cannot obtain I/O memory region"); | ||
| 197 | return -ENOENT; | ||
| 198 | } | ||
| 199 | |||
| 200 | ltq_wdt_membase = devm_ioremap_resource(&pdev->dev, res); | 195 | ltq_wdt_membase = devm_ioremap_resource(&pdev->dev, res); |
| 201 | if (IS_ERR(ltq_wdt_membase)) | 196 | if (IS_ERR(ltq_wdt_membase)) |
| 202 | return PTR_ERR(ltq_wdt_membase); | 197 | return PTR_ERR(ltq_wdt_membase); |
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 061756e36cf8..fa89bb30d004 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c | |||
| @@ -230,10 +230,6 @@ static int sh_wdt_probe(struct platform_device *pdev) | |||
| 230 | if (pdev->id != -1) | 230 | if (pdev->id != -1) |
| 231 | return -EINVAL; | 231 | return -EINVAL; |
| 232 | 232 | ||
| 233 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 234 | if (unlikely(!res)) | ||
| 235 | return -EINVAL; | ||
| 236 | |||
| 237 | wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); | 233 | wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); |
| 238 | if (unlikely(!wdt)) | 234 | if (unlikely(!wdt)) |
| 239 | return -ENOMEM; | 235 | return -ENOMEM; |
| @@ -249,6 +245,7 @@ static int sh_wdt_probe(struct platform_device *pdev) | |||
| 249 | wdt->clk = NULL; | 245 | wdt->clk = NULL; |
| 250 | } | 246 | } |
| 251 | 247 | ||
| 248 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 252 | wdt->base = devm_ioremap_resource(wdt->dev, res); | 249 | wdt->base = devm_ioremap_resource(wdt->dev, res); |
| 253 | if (IS_ERR(wdt->base)) | 250 | if (IS_ERR(wdt->base)) |
| 254 | return PTR_ERR(wdt->base); | 251 | return PTR_ERR(wdt->base); |
diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index 693b9d2c6e39..60deb9d304c0 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
| 17 | #include <linux/delay.h> | ||
| 17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
| @@ -22,9 +23,12 @@ | |||
| 22 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
| 23 | #include <linux/of.h> | 24 | #include <linux/of.h> |
| 24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/reboot.h> | ||
| 25 | #include <linux/types.h> | 27 | #include <linux/types.h> |
| 26 | #include <linux/watchdog.h> | 28 | #include <linux/watchdog.h> |
| 27 | 29 | ||
| 30 | #include <asm/system_misc.h> | ||
| 31 | |||
| 28 | #define WDT_MAX_TIMEOUT 16 | 32 | #define WDT_MAX_TIMEOUT 16 |
| 29 | #define WDT_MIN_TIMEOUT 1 | 33 | #define WDT_MIN_TIMEOUT 1 |
| 30 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) | 34 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) |
| @@ -70,6 +74,26 @@ static const int wdt_timeout_map[] = { | |||
| 70 | [16] = 0xB, /* 16s */ | 74 | [16] = 0xB, /* 16s */ |
| 71 | }; | 75 | }; |
| 72 | 76 | ||
| 77 | static void __iomem *reboot_wdt_base; | ||
| 78 | |||
| 79 | static void sun4i_wdt_restart(enum reboot_mode mode, const char *cmd) | ||
| 80 | { | ||
| 81 | /* Enable timer and set reset bit in the watchdog */ | ||
| 82 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, reboot_wdt_base + WDT_MODE); | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Restart the watchdog. The default (and lowest) interval | ||
| 86 | * value for the watchdog is 0.5s. | ||
| 87 | */ | ||
| 88 | writel(WDT_CTRL_RELOAD, reboot_wdt_base + WDT_CTRL); | ||
| 89 | |||
| 90 | while (1) { | ||
| 91 | mdelay(5); | ||
| 92 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, | ||
| 93 | reboot_wdt_base + WDT_MODE); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 73 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) | 97 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) |
| 74 | { | 98 | { |
| 75 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); | 99 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); |
| @@ -181,6 +205,9 @@ static int sunxi_wdt_probe(struct platform_device *pdev) | |||
| 181 | if (unlikely(err)) | 205 | if (unlikely(err)) |
| 182 | return err; | 206 | return err; |
| 183 | 207 | ||
| 208 | reboot_wdt_base = sunxi_wdt->wdt_base; | ||
| 209 | arm_pm_restart = sun4i_wdt_restart; | ||
| 210 | |||
| 184 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", | 211 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", |
| 185 | sunxi_wdt->wdt_dev.timeout, nowayout); | 212 | sunxi_wdt->wdt_dev.timeout, nowayout); |
| 186 | 213 | ||
| @@ -191,6 +218,8 @@ static int sunxi_wdt_remove(struct platform_device *pdev) | |||
| 191 | { | 218 | { |
| 192 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); | 219 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); |
| 193 | 220 | ||
| 221 | arm_pm_restart = NULL; | ||
| 222 | |||
| 194 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); | 223 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); |
| 195 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); | 224 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); |
| 196 | 225 | ||
