diff options
Diffstat (limited to 'drivers/watchdog')
67 files changed, 261 insertions, 166 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 58e7c100b6ad..1679e0dc869b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1485,6 +1485,7 @@ config W83627HF_WDT NCT6791 NCT6792 NCT6102D/04D/06D + NCT6116D This watchdog simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain @@ -1641,8 +1642,10 @@ config INDYDOG config JZ4740_WDT tristate "Ingenic jz4740 SoC hardware watchdog" - depends on MACH_JZ4740 || MACH_JZ4780 + depends on MIPS + depends on COMMON_CLK select WATCHDOG_CORE + select MFD_SYSCON help Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs. diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 848db958411e..bc6f333565d3 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -221,6 +221,7 @@ static const struct file_operations acq_fops = { .llseek = no_llseek, .write = acq_write, .unlocked_ioctl = acq_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = acq_open, .release = acq_close, }; diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 0d02bb275b3d..0e4c18a2aa42 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c @@ -220,6 +220,7 @@ static const struct file_operations advwdt_fops = { .llseek = no_llseek, .write = advwdt_write, .unlocked_ioctl = advwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = advwdt_open, .release = advwdt_close, }; diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index c157dd3d92a3..42338c7d4540 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -362,6 +362,7 @@ static const struct file_operations ali_fops = { .llseek = no_llseek, .write = ali_write, .unlocked_ioctl = ali_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ali_open, .release = ali_release, }; diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index c8e3ab056767..5af0358f4390 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -294,6 +294,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 668a1c704f28..c087027ffd5d 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -250,6 +250,7 @@ static const struct file_operations ar7_wdt_fops = { .owner = THIS_MODULE, .write = ar7_wdt_write, .unlocked_ioctl = ar7_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ar7_wdt_open, .release = ar7_wdt_release, .llseek = no_llseek, diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 4ec0906bf12c..7e00960651fa 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -258,11 +258,6 @@ static int aspeed_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - /* - * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only - * runs at 1MHz. We chose to always run at 1MHz, as there's no - * good reason to have a faster watchdog counter. - */ wdt->wdd.info = &aspeed_wdt_info; wdt->wdd.ops = &aspeed_wdt_ops; wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS; @@ -278,7 +273,16 @@ static int aspeed_wdt_probe(struct platform_device *pdev) return -EINVAL; config = ofdid->data; - wdt->ctrl = WDT_CTRL_1MHZ_CLK; + /* + * On clock rates: + * - ast2400 wdt can run at PCLK, or 1MHz + * - ast2500 only runs at 1MHz, hard coding bit 4 to 1 + * - ast2600 always runs at 1MHz + * + * Set the ast2400 to run at 1MHz as it simplifies the driver. + */ + if (of_device_is_compatible(np, "aspeed,ast2400-wdt")) + wdt->ctrl = WDT_CTRL_1MHZ_CLK; /* * Control reset on a per-device basis to ensure the diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index 907a4545dee6..6d751eb8191d 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -213,6 +213,7 @@ static const struct file_operations at91wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = at91_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = at91_wdt_open, .release = at91_wdt_close, .write = at91_wdt_write, diff --git a/drivers/watchdog/at91sam9_wdt.h b/drivers/watchdog/at91sam9_wdt.h index 390941c65eee..abfe34dd760a 100644 --- a/drivers/watchdog/at91sam9_wdt.h +++ b/drivers/watchdog/at91sam9_wdt.h @@ -4,33 +4,37 @@ * * Copyright (C) 2007 Andrew Victor * Copyright (C) 2007 Atmel Corporation. + * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries * * Watchdog Timer (WDT) - System peripherals regsters. * Based on AT91SAM9261 datasheet revision D. + * Based on SAM9X60 datasheet. * */ #ifndef AT91_WDT_H #define AT91_WDT_H +#include <linux/bits.h> + #define AT91_WDT_CR 0x00 /* Watchdog Control Register */ -#define AT91_WDT_WDRSTT (1 << 0) /* Restart */ -#define AT91_WDT_KEY (0xa5 << 24) /* KEY Password */ +#define AT91_WDT_WDRSTT BIT(0) /* Restart */ +#define AT91_WDT_KEY (0xa5UL << 24) /* KEY Password */ #define AT91_WDT_MR 0x04 /* Watchdog Mode Register */ -#define AT91_WDT_WDV (0xfff << 0) /* Counter Value */ -#define AT91_WDT_SET_WDV(x) ((x) & AT91_WDT_WDV) -#define AT91_WDT_WDFIEN (1 << 12) /* Fault Interrupt Enable */ -#define AT91_WDT_WDRSTEN (1 << 13) /* Reset Processor */ -#define AT91_WDT_WDRPROC (1 << 14) /* Timer Restart */ -#define AT91_WDT_WDDIS (1 << 15) /* Watchdog Disable */ -#define AT91_WDT_WDD (0xfff << 16) /* Delta Value */ -#define AT91_WDT_SET_WDD(x) (((x) << 16) & AT91_WDT_WDD) -#define AT91_WDT_WDDBGHLT (1 << 28) /* Debug Halt */ -#define AT91_WDT_WDIDLEHLT (1 << 29) /* Idle Halt */ +#define AT91_WDT_WDV (0xfffUL << 0) /* Counter Value */ +#define AT91_WDT_SET_WDV(x) ((x) & AT91_WDT_WDV) +#define AT91_WDT_WDFIEN BIT(12) /* Fault Interrupt Enable */ +#define AT91_WDT_WDRSTEN BIT(13) /* Reset Processor */ +#define AT91_WDT_WDRPROC BIT(14) /* Timer Restart */ +#define AT91_WDT_WDDIS BIT(15) /* Watchdog Disable */ +#define AT91_WDT_WDD (0xfffUL << 16) /* Delta Value */ +#define AT91_WDT_SET_WDD(x) (((x) << 16) & AT91_WDT_WDD) +#define AT91_WDT_WDDBGHLT BIT(28) /* Debug Halt */ +#define AT91_WDT_WDIDLEHLT BIT(29) /* Idle Halt */ -#define AT91_WDT_SR 0x08 /* Watchdog Status Register */ -#define AT91_WDT_WDUNF (1 << 0) /* Watchdog Underflow */ -#define AT91_WDT_WDERR (1 << 1) /* Watchdog Error */ +#define AT91_WDT_SR 0x08 /* Watchdog Status Register */ +#define AT91_WDT_WDUNF BIT(0) /* Watchdog Underflow */ +#define AT91_WDT_WDERR BIT(1) /* Watchdog Error */ #endif diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c index 75de664ef4b0..d6dff97c280b 100644 --- a/drivers/watchdog/ath79_wdt.c +++ b/drivers/watchdog/ath79_wdt.c @@ -234,6 +234,7 @@ static const struct file_operations ath79_wdt_fops = { .llseek = no_llseek, .write = ath79_wdt_write, .unlocked_ioctl = ath79_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ath79_wdt_open, .release = ath79_wdt_release, }; diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index e2af37c9a266..8a043b52aa2f 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -221,6 +221,7 @@ static const struct file_operations bcm63xx_wdt_fops = { .llseek = no_llseek, .write = bcm63xx_wdt_write, .unlocked_ioctl = bcm63xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = bcm63xx_wdt_open, .release = bcm63xx_wdt_release, }; diff --git a/drivers/watchdog/bd70528_wdt.c b/drivers/watchdog/bd70528_wdt.c index bc60e036627a..0170b37e6674 100644 --- a/drivers/watchdog/bd70528_wdt.c +++ b/drivers/watchdog/bd70528_wdt.c @@ -97,7 +97,7 @@ EXPORT_SYMBOL(bd70528_wdt_set); /** * bd70528_wdt_lock - take WDT lock * - * @bd70528: device data for the PMIC instance we want to operate on + * @data: device data for the PMIC instance we want to operate on * * Lock WDT for arming/disarming in order to avoid race condition caused * by WDT state changes initiated by WDT and RTC drivers. @@ -114,7 +114,7 @@ EXPORT_SYMBOL(bd70528_wdt_lock); /** * bd70528_wdt_unlock - unlock WDT lock * - * @bd70528: device data for the PMIC instance we want to operate on + * @data: device data for the PMIC instance we want to operate on * * Unlock WDT lock which has previously been taken by call to * bd70528_wdt_lock. diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c index f8d4e91d0383..06bd4e1a5923 100644 --- a/drivers/watchdog/cadence_wdt.c +++ b/drivers/watchdog/cadence_wdt.c @@ -335,8 +335,10 @@ static int cdns_wdt_probe(struct platform_device *pdev) wdt->clk = devm_clk_get(dev, NULL); if (IS_ERR(wdt->clk)) { - dev_err(dev, "input clock not found\n"); - return PTR_ERR(wdt->clk); + ret = PTR_ERR(wdt->clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "input clock not found\n"); + return ret; } ret = clk_prepare_enable(wdt->clk); diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c index d6d53014cb68..9867a3a936df 100644 --- a/drivers/watchdog/cpu5wdt.c +++ b/drivers/watchdog/cpu5wdt.c @@ -187,6 +187,7 @@ static const struct file_operations cpu5wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = cpu5wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = cpu5wdt_open, .write = cpu5wdt_write, .release = cpu5wdt_release, diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 3a83a48abcae..f5ffa7be066e 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -371,6 +371,7 @@ static const struct file_operations eurwdt_fops = { .llseek = no_llseek, .write = eurwdt_write, .unlocked_ioctl = eurwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = eurwdt_open, .release = eurwdt_release, }; diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index e46104c2fd94..a3c44d75d80e 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -669,6 +669,7 @@ static const struct file_operations watchdog_fops = { .release = watchdog_release, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice watchdog_miscdev = { diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 7d5f56994f09..f6541d1b65e3 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -248,6 +248,7 @@ static const struct file_operations gef_wdt_fops = { .llseek = no_llseek, .write = gef_wdt_write, .unlocked_ioctl = gef_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = gef_wdt_open, .release = gef_wdt_release, }; diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 8d105d98908e..9914a4283cb2 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -201,6 +201,7 @@ static const struct file_operations geodewdt_fops = { .llseek = no_llseek, .write = geodewdt_write, .unlocked_ioctl = geodewdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = geodewdt_open, .release = geodewdt_release, }; diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index 92fd7f33bc4d..2b65ea9451d1 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c @@ -259,6 +259,7 @@ static const struct file_operations ibwdt_fops = { .llseek = no_llseek, .write = ibwdt_write, .unlocked_ioctl = ibwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ibwdt_open, .release = ibwdt_close, }; diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c index 897f7eda9e6a..4a22fe152086 100644 --- a/drivers/watchdog/ibmasr.c +++ b/drivers/watchdog/ibmasr.c @@ -344,6 +344,7 @@ static const struct file_operations asr_fops = { .llseek = no_llseek, .write = asr_write, .unlocked_ioctl = asr_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = asr_open, .release = asr_release, }; diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 8d019a961ccc..f8d58bf0bf66 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -72,7 +72,6 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - static unsigned timeout; module_param(timeout, uint, 0); MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=" @@ -247,13 +246,14 @@ static const struct regmap_config imx2_wdt_regmap_config = { static int __init imx2_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct imx2_wdt_device *wdev; struct watchdog_device *wdog; void __iomem *base; int ret; u32 val; - wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL); + wdev = devm_kzalloc(dev, sizeof(*wdev), GFP_KERNEL); if (!wdev) return -ENOMEM; @@ -261,16 +261,16 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - wdev->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, + wdev->regmap = devm_regmap_init_mmio_clk(dev, NULL, base, &imx2_wdt_regmap_config); if (IS_ERR(wdev->regmap)) { - dev_err(&pdev->dev, "regmap init failed\n"); + dev_err(dev, "regmap init failed\n"); return PTR_ERR(wdev->regmap); } - wdev->clk = devm_clk_get(&pdev->dev, NULL); + wdev->clk = devm_clk_get(dev, NULL); if (IS_ERR(wdev->clk)) { - dev_err(&pdev->dev, "can't get Watchdog clock\n"); + dev_err(dev, "can't get Watchdog clock\n"); return PTR_ERR(wdev->clk); } @@ -280,12 +280,12 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) wdog->min_timeout = 1; wdog->timeout = IMX2_WDT_DEFAULT_TIME; wdog->max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000; - wdog->parent = &pdev->dev; + wdog->parent = dev; ret = platform_get_irq(pdev, 0); if (ret > 0) - if (!devm_request_irq(&pdev->dev, ret, imx2_wdt_isr, 0, - dev_name(&pdev->dev), wdog)) + if (!devm_request_irq(dev, ret, imx2_wdt_isr, 0, + dev_name(dev), wdog)) wdog->info = &imx2_wdt_pretimeout_info; ret = clk_prepare_enable(wdev->clk); @@ -295,13 +295,13 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val); wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0; - wdev->ext_reset = of_property_read_bool(pdev->dev.of_node, + wdev->ext_reset = of_property_read_bool(dev->of_node, "fsl,ext-reset-output"); platform_set_drvdata(pdev, wdog); watchdog_set_drvdata(wdog, wdev); watchdog_set_nowayout(wdog, nowayout); watchdog_set_restart_priority(wdog, 128); - watchdog_init_timeout(wdog, timeout, &pdev->dev); + watchdog_init_timeout(wdog, timeout, dev); if (imx2_wdt_is_running(wdev)) { imx2_wdt_set_timeout(wdog, wdog->timeout); @@ -319,7 +319,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (ret) goto disable_clk; - dev_info(&pdev->dev, "timeout %d sec (nowayout=%d)\n", + dev_info(dev, "timeout %d sec (nowayout=%d)\n", wdog->timeout, nowayout); return 0; @@ -359,9 +359,8 @@ static void imx2_wdt_shutdown(struct platform_device *pdev) } } -#ifdef CONFIG_PM_SLEEP /* Disable watchdog if it is active or non-active but still running */ -static int imx2_wdt_suspend(struct device *dev) +static int __maybe_unused imx2_wdt_suspend(struct device *dev) { struct watchdog_device *wdog = dev_get_drvdata(dev); struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); @@ -382,7 +381,7 @@ static int imx2_wdt_suspend(struct device *dev) } /* Enable watchdog and configure it if necessary */ -static int imx2_wdt_resume(struct device *dev) +static int __maybe_unused imx2_wdt_resume(struct device *dev) { struct watchdog_device *wdog = dev_get_drvdata(dev); struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); @@ -407,7 +406,6 @@ static int imx2_wdt_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(imx2_wdt_pm_ops, imx2_wdt_suspend, imx2_wdt_resume); diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c index 5ce51026989a..0a87c6f4bab2 100644 --- a/drivers/watchdog/imx7ulp_wdt.c +++ b/drivers/watchdog/imx7ulp_wdt.c @@ -17,6 +17,9 @@ #define WDOG_CS_CMD32EN BIT(13) #define WDOG_CS_ULK BIT(11) #define WDOG_CS_RCS BIT(10) +#define LPO_CLK 0x1 +#define LPO_CLK_SHIFT 8 +#define WDOG_CS_CLK (LPO_CLK << LPO_CLK_SHIFT) #define WDOG_CS_EN BIT(7) #define WDOG_CS_UPDATE BIT(5) @@ -41,24 +44,25 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); struct imx7ulp_wdt_device { - struct notifier_block restart_handler; struct watchdog_device wdd; void __iomem *base; struct clk *clk; }; -static inline void imx7ulp_wdt_enable(void __iomem *base, bool enable) +static void imx7ulp_wdt_enable(struct watchdog_device *wdog, bool enable) { - u32 val = readl(base + WDOG_CS); + struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); - writel(UNLOCK, base + WDOG_CNT); + u32 val = readl(wdt->base + WDOG_CS); + + writel(UNLOCK, wdt->base + WDOG_CNT); if (enable) - writel(val | WDOG_CS_EN, base + WDOG_CS); + writel(val | WDOG_CS_EN, wdt->base + WDOG_CS); else - writel(val & ~WDOG_CS_EN, base + WDOG_CS); + writel(val & ~WDOG_CS_EN, wdt->base + WDOG_CS); } -static inline bool imx7ulp_wdt_is_enabled(void __iomem *base) +static bool imx7ulp_wdt_is_enabled(void __iomem *base) { u32 val = readl(base + WDOG_CS); @@ -76,18 +80,15 @@ static int imx7ulp_wdt_ping(struct watchdog_device *wdog) static int imx7ulp_wdt_start(struct watchdog_device *wdog) { - struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); - imx7ulp_wdt_enable(wdt->base, true); + imx7ulp_wdt_enable(wdog, true); return 0; } static int imx7ulp_wdt_stop(struct watchdog_device *wdog) { - struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); - - imx7ulp_wdt_enable(wdt->base, false); + imx7ulp_wdt_enable(wdog, false); return 0; } @@ -106,12 +107,28 @@ static int imx7ulp_wdt_set_timeout(struct watchdog_device *wdog, return 0; } +static int imx7ulp_wdt_restart(struct watchdog_device *wdog, + unsigned long action, void *data) +{ + struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); + + imx7ulp_wdt_enable(wdt->base, true); + imx7ulp_wdt_set_timeout(&wdt->wdd, 1); + + /* wait for wdog to fire */ + while (true) + ; + + return NOTIFY_DONE; +} + static const struct watchdog_ops imx7ulp_wdt_ops = { .owner = THIS_MODULE, .start = imx7ulp_wdt_start, .stop = imx7ulp_wdt_stop, .ping = imx7ulp_wdt_ping, .set_timeout = imx7ulp_wdt_set_timeout, + .restart = imx7ulp_wdt_restart, }; static const struct watchdog_info imx7ulp_wdt_info = { @@ -120,7 +137,7 @@ static const struct watchdog_info imx7ulp_wdt_info = { WDIOF_MAGICCLOSE, }; -static inline void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) +static void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) { u32 val; @@ -131,7 +148,7 @@ static inline void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) /* set an initial timeout value in TOVAL */ writel(timeout, base + WDOG_TOVAL); /* enable 32bit command sequence and reconfigure */ - val = BIT(13) | BIT(8) | BIT(5); + val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE; writel(val, base + WDOG_CS); } diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c index 550358528084..9857bb74a723 100644 --- a/drivers/watchdog/indydog.c +++ b/drivers/watchdog/indydog.c @@ -152,6 +152,7 @@ static const struct file_operations indydog_fops = { .llseek = no_llseek, .write = indydog_write, .unlocked_ioctl = indydog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = indydog_open, .release = indydog_release, }; diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 2cdbd37c700c..470213abfd3d 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -134,6 +134,7 @@ static int mid_wdt_probe(struct platform_device *pdev) wdt_dev->timeout = MID_WDT_DEFAULT_TIMEOUT; wdt_dev->parent = dev; + watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT); watchdog_set_drvdata(wdt_dev, dev); ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq, diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 1c85103b750b..6ad5bf3451ec 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -412,6 +412,7 @@ static const struct file_operations intel_scu_fops = { .llseek = no_llseek, .write = intel_scu_write, .unlocked_ioctl = intel_scu_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = intel_scu_open, .release = intel_scu_release, }; diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c index a9ccdb9a9159..6bf68d4750de 100644 --- a/drivers/watchdog/iop_wdt.c +++ b/drivers/watchdog/iop_wdt.c @@ -202,6 +202,7 @@ static const struct file_operations iop_wdt_fops = { .llseek = no_llseek, .write = iop_wdt_write, .unlocked_ioctl = iop_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = iop_wdt_open, .release = iop_wdt_release, }; diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index 2fe1a3c499ed..2fed40d14007 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -345,6 +345,7 @@ static const struct file_operations it8712f_wdt_fops = { .llseek = no_llseek, .write = it8712f_wdt_write, .unlocked_ioctl = it8712f_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = it8712f_wdt_open, .release = it8712f_wdt_release, }; diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c index 9067998759e3..09886616fd21 100644 --- a/drivers/watchdog/ixp4xx_wdt.c +++ b/drivers/watchdog/ixp4xx_wdt.c @@ -163,6 +163,7 @@ static const struct file_operations ixp4xx_wdt_fops = { .llseek = no_llseek, .write = ixp4xx_wdt_write, .unlocked_ioctl = ixp4xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ixp4xx_wdt_open, .release = ixp4xx_wdt_release, }; diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index c6052ae54f32..bdf9564efa29 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -5,6 +5,7 @@ */ #include <linux/mfd/ingenic-tcu.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> @@ -17,19 +18,7 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/of.h> - -#include <asm/mach-jz4740/timer.h> - -#define JZ_WDT_CLOCK_PCLK 0x1 -#define JZ_WDT_CLOCK_RTC 0x2 -#define JZ_WDT_CLOCK_EXT 0x4 - -#define JZ_WDT_CLOCK_DIV_1 (0 << TCU_TCSR_PRESCALE_LSB) -#define JZ_WDT_CLOCK_DIV_4 (1 << TCU_TCSR_PRESCALE_LSB) -#define JZ_WDT_CLOCK_DIV_16 (2 << TCU_TCSR_PRESCALE_LSB) -#define JZ_WDT_CLOCK_DIV_64 (3 << TCU_TCSR_PRESCALE_LSB) -#define JZ_WDT_CLOCK_DIV_256 (4 << TCU_TCSR_PRESCALE_LSB) -#define JZ_WDT_CLOCK_DIV_1024 (5 << TCU_TCSR_PRESCALE_LSB) +#include <linux/regmap.h> #define DEFAULT_HEARTBEAT 5 #define MAX_HEARTBEAT 2048 @@ -49,15 +38,17 @@ MODULE_PARM_DESC(heartbeat, struct jz4740_wdt_drvdata { struct watchdog_device wdt; - void __iomem *base; - struct clk *rtc_clk; + struct regmap *map; + struct clk *clk; + unsigned long clk_rate; }; static int jz4740_wdt_ping(struct watchdog_device *wdt_dev) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - writew(0x0, drvdata->base + TCU_REG_WDT_TCNT); + regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0); + return 0; } @@ -65,35 +56,17 @@ static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev, unsigned int new_timeout) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - unsigned int rtc_clk_rate; - unsigned int timeout_value; - unsigned short clock_div = JZ_WDT_CLOCK_DIV_1; - u8 tcer; - - rtc_clk_rate = clk_get_rate(drvdata->rtc_clk); - - timeout_value = rtc_clk_rate * new_timeout; - while (timeout_value > 0xffff) { - if (clock_div == JZ_WDT_CLOCK_DIV_1024) { - /* Requested timeout too high; - * use highest possible value. */ - timeout_value = 0xffff; - break; - } - timeout_value >>= 2; - clock_div += (1 << TCU_TCSR_PRESCALE_LSB); - } + u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout); + unsigned int tcer; - tcer = readb(drvdata->base + TCU_REG_WDT_TCER); - writeb(0x0, drvdata->base + TCU_REG_WDT_TCER); - writew(clock_div, drvdata->base + TCU_REG_WDT_TCSR); + regmap_read(drvdata->map, TCU_REG_WDT_TCER, &tcer); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0); - writew((u16)timeout_value, drvdata->base + TCU_REG_WDT_TDR); - writew(0x0, drvdata->base + TCU_REG_WDT_TCNT); - writew(clock_div | JZ_WDT_CLOCK_RTC, drvdata->base + TCU_REG_WDT_TCSR); + regmap_write(drvdata->map, TCU_REG_WDT_TDR, timeout_value); + regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0); if (tcer & TCU_WDT_TCER_TCEN) - writeb(TCU_WDT_TCER_TCEN, drvdata->base + TCU_REG_WDT_TCER); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN); wdt_dev->timeout = new_timeout; return 0; @@ -102,16 +75,20 @@ static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev, static int jz4740_wdt_start(struct watchdog_device *wdt_dev) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - u8 tcer; + unsigned int tcer; + int ret; - tcer = readb(drvdata->base + TCU_REG_WDT_TCER); + ret = clk_prepare_enable(drvdata->clk); + if (ret) + return ret; + + regmap_read(drvdata->map, TCU_REG_WDT_TCER, &tcer); - jz4740_timer_enable_watchdog(); jz4740_wdt_set_timeout(wdt_dev, wdt_dev->timeout); /* Start watchdog if it wasn't started already */ if (!(tcer & TCU_WDT_TCER_TCEN)) - writeb(TCU_WDT_TCER_TCEN, drvdata->base + TCU_REG_WDT_TCER); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN); return 0; } @@ -120,8 +97,8 @@ static int jz4740_wdt_stop(struct watchdog_device *wdt_dev) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - writeb(0x0, drvdata->base + TCU_REG_WDT_TCER); - jz4740_timer_disable_watchdog(); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0); + clk_disable_unprepare(drvdata->clk); return 0; } @@ -162,33 +139,46 @@ static int jz4740_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct jz4740_wdt_drvdata *drvdata; struct watchdog_device *jz4740_wdt; + long rate; + int ret; drvdata = devm_kzalloc(dev, sizeof(struct jz4740_wdt_drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) - heartbeat = DEFAULT_HEARTBEAT; + drvdata->clk = devm_clk_get(&pdev->dev, "wdt"); + if (IS_ERR(drvdata->clk)) { + dev_err(&pdev->dev, "cannot find WDT clock\n"); + return PTR_ERR(drvdata->clk); + } + + /* Set smallest clock possible */ + rate = clk_round_rate(drvdata->clk, 1); + if (rate < 0) + return rate; + ret = clk_set_rate(drvdata->clk, rate); + if (ret) + return ret; + + drvdata->clk_rate = rate; jz4740_wdt = &drvdata->wdt; jz4740_wdt->info = &jz4740_wdt_info; jz4740_wdt->ops = &jz4740_wdt_ops; - jz4740_wdt->timeout = heartbeat; jz4740_wdt->min_timeout = 1; - jz4740_wdt->max_timeout = MAX_HEARTBEAT; + jz4740_wdt->max_timeout = 0xffff / rate; + jz4740_wdt->timeout = clamp(heartbeat, + jz4740_wdt->min_timeout, + jz4740_wdt->max_timeout); jz4740_wdt->parent = dev; watchdog_set_nowayout(jz4740_wdt, nowayout); watchdog_set_drvdata(jz4740_wdt, drvdata); - drvdata->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(drvdata->base)) - return PTR_ERR(drvdata->base); - - drvdata->rtc_clk = devm_clk_get(dev, "rtc"); - if (IS_ERR(drvdata->rtc_clk)) { - dev_err(dev, "cannot find RTC clock\n"); - return PTR_ERR(drvdata->rtc_clk); + drvdata->map = device_node_to_regmap(dev->parent->of_node); + if (!drvdata->map) { + dev_err(dev, "regmap not found\n"); + return -EINVAL; } return devm_watchdog_register_device(dev, &drvdata->wdt); diff --git a/drivers/watchdog/m54xx_wdt.c b/drivers/watchdog/m54xx_wdt.c index 752d03620f0a..22f335e1e164 100644 --- a/drivers/watchdog/m54xx_wdt.c +++ b/drivers/watchdog/m54xx_wdt.c @@ -183,6 +183,7 @@ static const struct file_operations m54xx_wdt_fops = { .llseek = no_llseek, .write = m54xx_wdt_write, .unlocked_ioctl = m54xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = m54xx_wdt_open, .release = m54xx_wdt_release, }; diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index cef2baf59dda..80ff94688487 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -361,6 +361,7 @@ static const struct file_operations zf_fops = { .llseek = no_llseek, .write = zf_write, .unlocked_ioctl = zf_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = zf_open, .release = zf_close, }; diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c index a86faa5000f1..d387bad377c4 100644 --- a/drivers/watchdog/mixcomwd.c +++ b/drivers/watchdog/mixcomwd.c @@ -227,6 +227,7 @@ static const struct file_operations mixcomwd_fops = { .llseek = no_llseek, .write = mixcomwd_write, .unlocked_ioctl = mixcomwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mixcomwd_open, .release = mixcomwd_release, }; diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 25a92857b217..8aa1cb4a295f 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -181,6 +181,7 @@ static const struct file_operations mtx1_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = mtx1_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mtx1_wdt_open, .write = mtx1_wdt_write, .release = mtx1_wdt_release, diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index 74bf7144a970..0bc72dd69b70 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c @@ -241,6 +241,7 @@ static const struct file_operations mv64x60_wdt_fops = { .llseek = no_llseek, .write = mv64x60_wdt_write, .unlocked_ioctl = mv64x60_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mv64x60_wdt_open, .release = mv64x60_wdt_release, }; diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c index 5f0082e300bd..d7a560e348d5 100644 --- a/drivers/watchdog/nv_tco.c +++ b/drivers/watchdog/nv_tco.c @@ -267,6 +267,7 @@ static const struct file_operations nv_tco_fops = { .llseek = no_llseek, .write = nv_tco_write, .unlocked_ioctl = nv_tco_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = nv_tco_open, .release = nv_tco_release, }; diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 2af1a8b3f973..73fbfc99083b 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -473,6 +473,7 @@ static const struct file_operations pc87413_fops = { .llseek = no_llseek, .write = pc87413_write, .unlocked_ioctl = pc87413_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pc87413_open, .release = pc87413_release, }; diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index c3c93e00b320..7a0587fdc52c 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c @@ -752,6 +752,7 @@ static const struct file_operations pcwd_fops = { .llseek = no_llseek, .write = pcwd_write, .unlocked_ioctl = pcwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pcwd_open, .release = pcwd_close, }; diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index e30c1f762045..81508a42a90c 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -646,6 +646,7 @@ static const struct file_operations pcipcwd_fops = { .llseek = no_llseek, .write = pcipcwd_write, .unlocked_ioctl = pcipcwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pcipcwd_open, .release = pcipcwd_release, }; diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 6727f8ab2d18..2f44af1831d0 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -550,6 +550,7 @@ static const struct file_operations usb_pcwd_fops = { .llseek = no_llseek, .write = usb_pcwd_write, .unlocked_ioctl = usb_pcwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = usb_pcwd_open, .release = usb_pcwd_release, }; diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c index 205c3c68fca1..a98abd0d3146 100644 --- a/drivers/watchdog/pika_wdt.c +++ b/drivers/watchdog/pika_wdt.c @@ -214,6 +214,7 @@ static const struct file_operations pikawdt_fops = { .release = pikawdt_release, .write = pikawdt_write, .unlocked_ioctl = pikawdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice pikawdt_miscdev = { diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c index aa53babf2bab..4097d076aab8 100644 --- a/drivers/watchdog/pnx833x_wdt.c +++ b/drivers/watchdog/pnx833x_wdt.c @@ -215,6 +215,7 @@ static const struct file_operations pnx833x_wdt_fops = { .llseek = no_llseek, .write = pnx833x_wdt_write, .unlocked_ioctl = pnx833x_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pnx833x_wdt_open, .release = pnx833x_wdt_release, }; diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index a8a4b3a41a90..1dfede0abf18 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -245,6 +245,7 @@ static const struct file_operations rc32434_wdt_fops = { .llseek = no_llseek, .write = rc32434_wdt_write, .unlocked_ioctl = rc32434_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = rc32434_wdt_open, .release = rc32434_wdt_release, }; diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 2e608ae6cbc7..57187efeb86f 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -199,6 +199,7 @@ static const struct file_operations rdc321x_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = rdc321x_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = rdc321x_wdt_open, .write = rdc321x_wdt_write, .release = rdc321x_wdt_release, diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index b35f7be20c00..dc3c06a92f93 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -163,6 +163,7 @@ static const struct file_operations riowd_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = riowd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = riowd_open, .write = riowd_write, .release = riowd_release, diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index cbd8c957182f..9b93be00109f 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -141,6 +141,7 @@ static const struct file_operations sa1100dog_fops = { .llseek = no_llseek, .write = sa1100dog_write, .unlocked_ioctl = sa1100dog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sa1100dog_open, .release = sa1100dog_release, }; diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 202fc8d8ca5f..da2dad00d473 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -237,6 +237,7 @@ static const struct file_operations sbwdog_fops = { .llseek = no_llseek, .write = sbwdog_write, .unlocked_ioctl = sbwdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sbwdog_open, .release = sbwdog_release, }; diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index c3151642694c..f2cbe6d880a8 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -280,6 +280,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c index 12cdee7d5069..520b8dd77ed4 100644 --- a/drivers/watchdog/sbc7240_wdt.c +++ b/drivers/watchdog/sbc7240_wdt.c @@ -194,9 +194,8 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (wdt_set_timeout(new_timeout)) return -EINVAL; - - /* Fall through */ } + /* Fall through */ case WDIOC_GETTIMEOUT: return put_user(timeout, (int __user *)arg); default: @@ -211,6 +210,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c index 86828c28843f..5e3a9ddb952e 100644 --- a/drivers/watchdog/sbc_epx_c3.c +++ b/drivers/watchdog/sbc_epx_c3.c @@ -156,6 +156,7 @@ static const struct file_operations epx_c3_fops = { .llseek = no_llseek, .write = epx_c3_write, .unlocked_ioctl = epx_c3_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = epx_c3_open, .release = epx_c3_release, }; diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index 3822a60a8d2b..1b20b33879c4 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -186,6 +186,7 @@ static const struct file_operations fitpc2_wdt_fops = { .llseek = no_llseek, .write = fitpc2_wdt_write, .unlocked_ioctl = fitpc2_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = fitpc2_wdt_open, .release = fitpc2_wdt_release, }; diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 960385a766b3..9673eb12dacd 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -307,6 +307,7 @@ static const struct file_operations sc1200wdt_fops = { .llseek = no_llseek, .write = sc1200wdt_write, .unlocked_ioctl = sc1200wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sc1200wdt_open, .release = sc1200wdt_release, }; diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index a612128c5f80..fbe79bcc9297 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -336,6 +336,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 3612f1df381b..83949a385f62 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -337,6 +337,7 @@ static const struct file_operations sch311x_wdt_fops = { .llseek = no_llseek, .write = sch311x_wdt_write, .unlocked_ioctl = sch311x_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sch311x_wdt_open, .release = sch311x_wdt_close, }; diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c index 46268309ee9b..c94098acb78f 100644 --- a/drivers/watchdog/scx200_wdt.c +++ b/drivers/watchdog/scx200_wdt.c @@ -201,6 +201,7 @@ static const struct file_operations scx200_wdt_fops = { .llseek = no_llseek, .write = scx200_wdt_write, .unlocked_ioctl = scx200_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = scx200_wdt_open, .release = scx200_wdt_release, }; diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index f5713030d0f7..43de56acd767 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -505,6 +505,7 @@ static const struct file_operations wb_smsc_wdt_fops = { .llseek = no_llseek, .write = wb_smsc_wdt_write, .unlocked_ioctl = wb_smsc_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wb_smsc_wdt_open, .release = wb_smsc_wdt_release, }; diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c index 0bb17b046140..65cb55f3916f 100644 --- a/drivers/watchdog/sprd_wdt.c +++ b/drivers/watchdog/sprd_wdt.c @@ -327,10 +327,9 @@ static int sprd_wdt_probe(struct platform_device *pdev) static int __maybe_unused sprd_wdt_pm_suspend(struct device *dev) { - struct watchdog_device *wdd = dev_get_drvdata(dev); struct sprd_wdt *wdt = dev_get_drvdata(dev); - if (watchdog_active(wdd)) + if (watchdog_active(&wdt->wdd)) sprd_wdt_stop(&wdt->wdd); sprd_wdt_disable(wdt); @@ -339,7 +338,6 @@ static int __maybe_unused sprd_wdt_pm_suspend(struct device *dev) static int __maybe_unused sprd_wdt_pm_resume(struct device *dev) { - struct watchdog_device *wdd = dev_get_drvdata(dev); struct sprd_wdt *wdt = dev_get_drvdata(dev); int ret; @@ -347,7 +345,7 @@ static int __maybe_unused sprd_wdt_pm_resume(struct device *dev) if (ret) return ret; - if (watchdog_active(wdd)) { + if (watchdog_active(&wdt->wdd)) { ret = sprd_wdt_start(&wdt->wdd); if (ret) { sprd_wdt_disable(wdt); diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 38b31e9947aa..fdf533fe0bb2 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -49,7 +49,7 @@ static int wdt_cfg_leave = 0xAA;/* key to lock configuration space */ enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf, w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p, w83667hg_b, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793, - nct6795, nct6796, nct6102 }; + nct6795, nct6796, nct6102, nct6116 }; static int timeout; /* in seconds */ module_param(timeout, int, 0); @@ -94,6 +94,7 @@ MODULE_PARM_DESC(early_disable, "Disable watchdog at boot time (default=0)"); #define NCT6775_ID 0xb4 #define NCT6776_ID 0xc3 #define NCT6102_ID 0xc4 +#define NCT6116_ID 0xd2 #define NCT6779_ID 0xc5 #define NCT6791_ID 0xc8 #define NCT6792_ID 0xc9 @@ -211,6 +212,7 @@ static int w83627hf_init(struct watchdog_device *wdog, enum chips chip) case nct6795: case nct6796: case nct6102: + case nct6116: /* * These chips have a fixed WDTO# output pin (W83627UHG), * or support more than one WDTO# output pin. @@ -417,6 +419,12 @@ static int wdt_find(int addr) cr_wdt_control = NCT6102D_WDT_CONTROL; cr_wdt_csr = NCT6102D_WDT_CSR; break; + case NCT6116_ID: + ret = nct6102; + cr_wdt_timeout = NCT6102D_WDT_TIMEOUT; + cr_wdt_control = NCT6102D_WDT_CONTROL; + cr_wdt_csr = NCT6102D_WDT_CSR; + break; case 0xff: ret = -ENODEV; break; @@ -482,6 +490,7 @@ static int __init wdt_init(void) "NCT6795", "NCT6796", "NCT6102", + "NCT6116", }; /* Apply system-specific quirks */ diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 6eb5185d6ea6..6b3b667e6f23 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -304,6 +304,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index 16e9cbe72acc..5212e68c6b01 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c @@ -446,6 +446,7 @@ static const struct file_operations wdt_fops = { .llseek = no_llseek, .write = wdt_write, .unlocked_ioctl = wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdt_open, .release = wdt_release, }; diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 6d2071a0590d..a6925847f76f 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c @@ -230,6 +230,7 @@ static const struct file_operations wafwdt_fops = { .llseek = no_llseek, .write = wafwdt_write, .unlocked_ioctl = wafwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wafwdt_open, .release = wafwdt_close, }; diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index dbd2ad4c9294..4b2a85438478 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -34,7 +34,6 @@ #include <linux/init.h> /* For __init/__exit/... */ #include <linux/hrtimer.h> /* For hrtimers */ #include <linux/kernel.h> /* For printk/panic/... */ -#include <linux/kref.h> /* For data references */ #include <linux/kthread.h> /* For kthread_work */ #include <linux/miscdevice.h> /* For handling misc devices */ #include <linux/module.h> /* For module stuff/... */ @@ -52,14 +51,14 @@ /* * struct watchdog_core_data - watchdog core internal data - * @kref: Reference count. + * @dev: The watchdog's internal device * @cdev: The watchdog's Character device. * @wdd: Pointer to watchdog device. * @lock: Lock for watchdog core. * @status: Watchdog core internal status bits. */ struct watchdog_core_data { - struct kref kref; + struct device dev; struct cdev cdev; struct watchdog_device *wdd; struct mutex lock; @@ -158,7 +157,8 @@ static inline void watchdog_update_worker(struct watchdog_device *wdd) ktime_t t = watchdog_next_keepalive(wdd); if (t > 0) - hrtimer_start(&wd_data->timer, t, HRTIMER_MODE_REL); + hrtimer_start(&wd_data->timer, t, + HRTIMER_MODE_REL_HARD); } else { hrtimer_cancel(&wd_data->timer); } @@ -177,7 +177,7 @@ static int __watchdog_ping(struct watchdog_device *wdd) if (ktime_after(earliest_keepalive, now)) { hrtimer_start(&wd_data->timer, ktime_sub(earliest_keepalive, now), - HRTIMER_MODE_REL); + HRTIMER_MODE_REL_HARD); return 0; } @@ -452,7 +452,26 @@ static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status)); } -static DEVICE_ATTR_RO(nowayout); + +static ssize_t nowayout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + unsigned int value; + int ret; + + ret = kstrtouint(buf, 0, &value); + if (ret) + return ret; + if (value > 1) + return -EINVAL; + /* nowayout cannot be disabled once set */ + if (test_bit(WDOG_NO_WAY_OUT, &wdd->status) && !value) + return -EPERM; + watchdog_set_nowayout(wdd, value); + return len; +} +static DEVICE_ATTR_RW(nowayout); static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -839,7 +858,7 @@ static int watchdog_open(struct inode *inode, struct file *file) file->private_data = wd_data; if (!hw_running) - kref_get(&wd_data->kref); + get_device(&wd_data->dev); /* * open_timeout only applies for the first open from @@ -860,11 +879,11 @@ out_clear: return err; } -static void watchdog_core_data_release(struct kref *kref) +static void watchdog_core_data_release(struct device *dev) { struct watchdog_core_data *wd_data; - wd_data = container_of(kref, struct watchdog_core_data, kref); + wd_data = container_of(dev, struct watchdog_core_data, dev); kfree(wd_data); } @@ -924,7 +943,7 @@ done: */ if (!running) { module_put(wd_data->cdev.owner); - kref_put(&wd_data->kref, watchdog_core_data_release); + put_device(&wd_data->dev); } return 0; } @@ -933,6 +952,7 @@ static const struct file_operations watchdog_fops = { .owner = THIS_MODULE, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = watchdog_open, .release = watchdog_release, }; @@ -943,17 +963,22 @@ static struct miscdevice watchdog_miscdev = { .fops = &watchdog_fops, }; +static struct class watchdog_class = { + .name = "watchdog", + .owner = THIS_MODULE, + .dev_groups = wdt_groups, +}; + /* * watchdog_cdev_register: register watchdog character device * @wdd: watchdog device - * @devno: character device number * * Register a watchdog character device including handling the legacy * /dev/watchdog node. /dev/watchdog is actually a miscdevice and * thus we set it up like that. */ -static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) +static int watchdog_cdev_register(struct watchdog_device *wdd) { struct watchdog_core_data *wd_data; int err; @@ -961,7 +986,6 @@ static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) wd_data = kzalloc(sizeof(struct watchdog_core_data), GFP_KERNEL); if (!wd_data) return -ENOMEM; - kref_init(&wd_data->kref); mutex_init(&wd_data->lock); wd_data->wdd = wdd; @@ -971,7 +995,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) return -ENODEV; kthread_init_work(&wd_data->work, watchdog_ping_work); - hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); wd_data->timer.function = watchdog_timer_expired; if (wdd->id == 0) { @@ -990,23 +1014,33 @@ static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) } } + device_initialize(&wd_data->dev); + wd_data->dev.devt = MKDEV(MAJOR(watchdog_devt), wdd->id); + wd_data->dev.class = &watchdog_class; + wd_data->dev.parent = wdd->parent; + wd_data->dev.groups = wdd->groups; + wd_data->dev.release = watchdog_core_data_release; + dev_set_drvdata(&wd_data->dev, wdd); + dev_set_name(&wd_data->dev, "watchdog%d", wdd->id); + /* Fill in the data structures */ cdev_init(&wd_data->cdev, &watchdog_fops); - wd_data->cdev.owner = wdd->ops->owner; /* Add the device */ - err = cdev_add(&wd_data->cdev, devno, 1); + err = cdev_device_add(&wd_data->cdev, &wd_data->dev); if (err) { pr_err("watchdog%d unable to add device %d:%d\n", wdd->id, MAJOR(watchdog_devt), wdd->id); if (wdd->id == 0) { misc_deregister(&watchdog_miscdev); old_wd_data = NULL; - kref_put(&wd_data->kref, watchdog_core_data_release); + put_device(&wd_data->dev); } return err; } + wd_data->cdev.owner = wdd->ops->owner; + /* Record time of most recent heartbeat as 'just before now'. */ wd_data->last_hw_keepalive = ktime_sub(ktime_get(), 1); watchdog_set_open_deadline(wd_data); @@ -1017,9 +1051,10 @@ static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) */ if (watchdog_hw_running(wdd)) { __module_get(wdd->ops->owner); - kref_get(&wd_data->kref); + get_device(&wd_data->dev); if (handle_boot_enabled) - hrtimer_start(&wd_data->timer, 0, HRTIMER_MODE_REL); + hrtimer_start(&wd_data->timer, 0, + HRTIMER_MODE_REL_HARD); else pr_info("watchdog%d running and kernel based pre-userspace handler disabled\n", wdd->id); @@ -1040,7 +1075,7 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) { struct watchdog_core_data *wd_data = wdd->wd_data; - cdev_del(&wd_data->cdev); + cdev_device_del(&wd_data->cdev, &wd_data->dev); if (wdd->id == 0) { misc_deregister(&watchdog_miscdev); old_wd_data = NULL; @@ -1059,15 +1094,9 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) hrtimer_cancel(&wd_data->timer); kthread_cancel_work_sync(&wd_data->work); - kref_put(&wd_data->kref, watchdog_core_data_release); + put_device(&wd_data->dev); } -static struct class watchdog_class = { - .name = "watchdog", - .owner = THIS_MODULE, - .dev_groups = wdt_groups, -}; - static int watchdog_reboot_notifier(struct notifier_block *nb, unsigned long code, void *data) { @@ -1098,27 +1127,14 @@ static int watchdog_reboot_notifier(struct notifier_block *nb, int watchdog_dev_register(struct watchdog_device *wdd) { - struct device *dev; - dev_t devno; int ret; - devno = MKDEV(MAJOR(watchdog_devt), wdd->id); - - ret = watchdog_cdev_register(wdd, devno); + ret = watchdog_cdev_register(wdd); if (ret) return ret; - dev = device_create_with_groups(&watchdog_class, wdd->parent, - devno, wdd, wdd->groups, - "watchdog%d", wdd->id); - if (IS_ERR(dev)) { - watchdog_cdev_unregister(wdd); - return PTR_ERR(dev); - } - ret = watchdog_register_pretimeout(wdd); if (ret) { - device_destroy(&watchdog_class, devno); watchdog_cdev_unregister(wdd); return ret; } @@ -1126,7 +1142,8 @@ int watchdog_dev_register(struct watchdog_device *wdd) if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) { wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; - ret = devm_register_reboot_notifier(dev, &wdd->reboot_nb); + ret = devm_register_reboot_notifier(&wdd->wd_data->dev, + &wdd->reboot_nb); if (ret) { pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", wdd->id, ret); @@ -1148,7 +1165,6 @@ int watchdog_dev_register(struct watchdog_device *wdd) void watchdog_dev_unregister(struct watchdog_device *wdd) { watchdog_unregister_pretimeout(wdd); - device_destroy(&watchdog_class, wdd->wd_data->cdev.dev); watchdog_cdev_unregister(wdd); } diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index e7cf41aa26c3..b069349b52f5 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -202,7 +202,7 @@ static int wdat_wdt_enable_reboot(struct wdat_wdt *wdat) * WDAT specification says that the watchdog is required to reboot * the system when it fires. However, it also states that it is * recommeded to make it configurable through hardware register. We - * enable reboot now if it is configrable, just in case. + * enable reboot now if it is configurable, just in case. */ ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL); if (ret && ret != -EOPNOTSUPP) { diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 6ad7edb4a712..184a06a74f83 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c @@ -472,6 +472,7 @@ static const struct file_operations wdrtas_fops = { .llseek = no_llseek, .write = wdrtas_write, .unlocked_ioctl = wdrtas_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdrtas_open, .release = wdrtas_close, }; diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 7d278b37e083..f9054cb0f8e2 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -523,6 +523,7 @@ static const struct file_operations wdt_fops = { .llseek = no_llseek, .write = wdt_write, .unlocked_ioctl = wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdt_open, .release = wdt_release, }; diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c index eb729d704836..e60993d0767e 100644 --- a/drivers/watchdog/wdt285.c +++ b/drivers/watchdog/wdt285.c @@ -181,6 +181,7 @@ static const struct file_operations watchdog_fops = { .llseek = no_llseek, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = watchdog_open, .release = watchdog_release, }; diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c index 5c52c73e1839..066a4fb4d75b 100644 --- a/drivers/watchdog/wdt977.c +++ b/drivers/watchdog/wdt977.c @@ -422,6 +422,7 @@ static const struct file_operations wdt977_fops = { .llseek = no_llseek, .write = wdt977_write, .unlocked_ioctl = wdt977_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdt977_open, .release = wdt977_release, }; diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 66303ab95685..e528024faa41 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -566,6 +566,7 @@ static const struct file_operations wdtpci_fops = { .llseek = no_llseek, .write = wdtpci_write, .unlocked_ioctl = wdtpci_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdtpci_open, .release = wdtpci_release, }; |