diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-13 09:20:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-13 09:20:42 -0400 |
commit | 55472bae5331f33582d9f0e8919fed8bebcda0da (patch) | |
tree | 4e9d910e8f5de08d1ceb45509ff42641fcd0a6e7 | |
parent | d7a02fa0a8f9ec1b81d57628ca9834563208ef33 (diff) | |
parent | a9f0bda567e32a2b44165b067adfc4a4f56d1815 (diff) | |
download | linux-55472bae5331f33582d9f0e8919fed8bebcda0da.tar.gz linux-55472bae5331f33582d9f0e8919fed8bebcda0da.tar.bz2 linux-55472bae5331f33582d9f0e8919fed8bebcda0da.zip |
Merge tag 'linux-watchdog-5.2-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- a new watchdog driver for the ROHM BD70528 watchdog block
- a new watchdog driver for the i.MX system controller watchdog
- conversions to use device managed functions and other improvements
- refactor watchdog_init_timeout
- make watchdog core configurable as module
- pretimeout governors improvements
- a lot of other fixes
* tag 'linux-watchdog-5.2-rc1' of git://www.linux-watchdog.org/linux-watchdog: (114 commits)
watchdog: Enforce that at least one pretimeout governor is enabled
watchdog: stm32: add dynamic prescaler support
watchdog: Improve Kconfig entry ordering and dependencies
watchdog: npcm: Enable modular builds
watchdog: Make watchdog core configurable as module
watchdog: Move pretimeout governor configuration up
watchdog: Use depends instead of select for pretimeout governors
watchdog: rtd119x: drop unused module.h include
watchdog: intel_scu: make it explicitly non-modular
watchdog: coh901327: make it explicitly non-modular
watchdog: ziirave_wdt: drop warning after calling watchdog_init_timeout
watchdog: xen_wdt: drop warning after calling watchdog_init_timeout
watchdog: stm32_iwdg: drop warning after calling watchdog_init_timeout
watchdog: st_lpc_wdt: drop warning after calling watchdog_init_timeout
watchdog: sp5100_tco: drop warning after calling watchdog_init_timeout
watchdog: renesas_wdt: drop warning after calling watchdog_init_timeout
watchdog: nic7018_wdt: drop warning after calling watchdog_init_timeout
watchdog: ni903x_wdt: drop warning after calling watchdog_init_timeout
watchdog: imx_sc_wdt: drop warning after calling watchdog_init_timeout
watchdog: i6300esb: drop warning after calling watchdog_init_timeout
...
99 files changed, 1490 insertions, 1537 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-sc-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx-sc-wdt.txt new file mode 100644 index 000000000000..02b87e92ae68 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/fsl-imx-sc-wdt.txt @@ -0,0 +1,24 @@ +* Freescale i.MX System Controller Watchdog + +i.MX system controller watchdog is for i.MX SoCs with system controller inside, +the watchdog is managed by system controller, users can ONLY communicate with +system controller from secure mode for watchdog operations, so Linux i.MX system +controller watchdog driver will call ARM SMC API and trap into ARM-Trusted-Firmware +for watchdog operations, ARM-Trusted-Firmware is running at secure EL3 mode and +it will request system controller to execute the watchdog operation passed from +Linux kernel. + +Required properties: +- compatible: Should be : + "fsl,imx8qxp-sc-wdt" + followed by "fsl,imx-sc-wdt"; + +Optional properties: +- timeout-sec : Contains the watchdog timeout in seconds. + +Examples: + +watchdog { + compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt"; + timeout-sec = <60>; +}; diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt index 8682d6a93e5b..fd380eb28df5 100644 --- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt @@ -9,6 +9,7 @@ Required properties: "mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622 "mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623 "mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629 + "mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516 - reg : Specifies base physical address and size of the registers. diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 242eea859637..7ea60371bda0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -30,7 +30,7 @@ menuconfig WATCHDOG if WATCHDOG config WATCHDOG_CORE - bool "WatchDog Timer Driver Core" + tristate "WatchDog Timer Driver Core" ---help--- Say Y here if you want to use the new watchdog timer driver core. This driver provides a framework for all watchdog timer drivers @@ -63,6 +63,66 @@ config WATCHDOG_SYSFS Say Y here if you want to enable watchdog device status read through sysfs attributes. +comment "Watchdog Pretimeout Governors" + +config WATCHDOG_PRETIMEOUT_GOV + bool "Enable watchdog pretimeout governors" + depends on WATCHDOG_CORE + help + The option allows to select watchdog pretimeout governors. + +config WATCHDOG_PRETIMEOUT_GOV_SEL + tristate + depends on WATCHDOG_PRETIMEOUT_GOV + default m + select WATCHDOG_PRETIMEOUT_GOV_PANIC if WATCHDOG_PRETIMEOUT_GOV_NOOP=n + +if WATCHDOG_PRETIMEOUT_GOV + +config WATCHDOG_PRETIMEOUT_GOV_NOOP + tristate "Noop watchdog pretimeout governor" + depends on WATCHDOG_CORE + default WATCHDOG_CORE + help + Noop watchdog pretimeout governor, only an informational + message is added to kernel log buffer. + +config WATCHDOG_PRETIMEOUT_GOV_PANIC + tristate "Panic watchdog pretimeout governor" + depends on WATCHDOG_CORE + default WATCHDOG_CORE + help + Panic watchdog pretimeout governor, on watchdog pretimeout + event put the kernel into panic. + +choice + prompt "Default Watchdog Pretimeout Governor" + default WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC + help + This option selects a default watchdog pretimeout governor. + The governor takes its action, if a watchdog is capable + to report a pretimeout event. + +config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP + bool "noop" + depends on WATCHDOG_PRETIMEOUT_GOV_NOOP + help + Use noop watchdog pretimeout governor by default. If noop + governor is selected by a user, write a short message to + the kernel log buffer and don't do any system changes. + +config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC + bool "panic" + depends on WATCHDOG_PRETIMEOUT_GOV_PANIC + help + Use panic watchdog pretimeout governor by default, if + a watchdog pretimeout event happens, consider that + a watchdog feeder is dead and reboot is unavoidable. + +endchoice + +endif # WATCHDOG_PRETIMEOUT_GOV + # # General Watchdog drivers # @@ -90,6 +150,18 @@ config SOFT_WATCHDOG_PRETIMEOUT watchdog. Be aware that governors might affect the watchdog because it is purely software, e.g. the panic governor will stall it! +config BD70528_WATCHDOG + tristate "ROHM BD70528 PMIC Watchdog" + depends on MFD_ROHM_BD70528 + select WATCHDOG_CORE + help + Support for the watchdog in the ROHM BD70528 PMIC. Watchdog trigger + cause system reset. + + Say Y here to include support for the ROHM BD70528 watchdog. + Alternatively say M to compile the driver as a module, + which will be called bd70528_wdt. + config DA9052_WATCHDOG tristate "Dialog DA9052 Watchdog" depends on PMIC_DA9052 || COMPILE_TEST @@ -552,7 +624,7 @@ config COH901327_WATCHDOG compiled as a module. config NPCM7XX_WATCHDOG - bool "Nuvoton NPCM750 watchdog" + tristate "Nuvoton NPCM750 watchdog" depends on ARCH_NPCM || COMPILE_TEST default y if ARCH_NPCM7XX select WATCHDOG_CORE @@ -641,6 +713,22 @@ config IMX2_WDT To compile this driver as a module, choose M here: the module will be called imx2_wdt. +config IMX_SC_WDT + tristate "IMX SC Watchdog" + depends on HAVE_ARM_SMCCC + select WATCHDOG_CORE + help + This is the driver for the system controller watchdog + on the NXP i.MX SoCs with system controller inside, the + watchdog driver will call ARM SMC API and trap into + ARM-Trusted-Firmware for operations, ARM-Trusted-Firmware + will request system controller to execute the operations. + If you have one of these processors and wish to have + watchdog support enabled, say Y, otherwise say N. + + To compile this driver as a module, choose M here: the + module will be called imx_sc_wdt. + config UX500_WATCHDOG tristate "ST-Ericsson Ux500 watchdog" depends on MFD_DB8500_PRCMU @@ -1179,6 +1267,15 @@ config HP_WATCHDOG To compile this driver as a module, choose M here: the module will be called hpwdt. +config HPWDT_NMI_DECODING + bool "NMI support for the HP ProLiant iLO2+ Hardware Watchdog Timer" + depends on HP_WATCHDOG + default y + help + Enables the NMI handler for the watchdog pretimeout NMI and the iLO + "Generate NMI to System" virtual button. When an NMI is claimed + by the driver, panic is called. + config KEMPLD_WDT tristate "Kontron COM Watchdog Timer" depends on MFD_KEMPLD @@ -1190,15 +1287,6 @@ config KEMPLD_WDT This driver can also be built as a module. If so, the module will be called kempld_wdt. -config HPWDT_NMI_DECODING - bool "NMI support for the HP ProLiant iLO2+ Hardware Watchdog Timer" - depends on HP_WATCHDOG - default y - help - Enables the NMI handler for the watchdog pretimeout NMI and the iLO - "Generate NMI to System" virtual button. When an NMI is claimed - by the driver, panic is called. - config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" depends on X86 @@ -1647,7 +1735,7 @@ config BCM_KONA_WDT config BCM_KONA_WDT_DEBUG bool "DEBUGFS support for BCM Kona Watchdog" - depends on BCM_KONA_WDT || COMPILE_TEST + depends on BCM_KONA_WDT help If enabled, adds /sys/kernel/debug/bcm_kona_wdt/info which provides access to the driver's internal data structures as well as watchdog @@ -2024,53 +2112,4 @@ config USBPCWATCHDOG Most people will say N. -comment "Watchdog Pretimeout Governors" - -config WATCHDOG_PRETIMEOUT_GOV - bool "Enable watchdog pretimeout governors" - help - The option allows to select watchdog pretimeout governors. - -if WATCHDOG_PRETIMEOUT_GOV - -choice - prompt "Default Watchdog Pretimeout Governor" - default WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC - help - This option selects a default watchdog pretimeout governor. - The governor takes its action, if a watchdog is capable - to report a pretimeout event. - -config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP - bool "noop" - select WATCHDOG_PRETIMEOUT_GOV_NOOP - help - Use noop watchdog pretimeout governor by default. If noop - governor is selected by a user, write a short message to - the kernel log buffer and don't do any system changes. - -config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC - bool "panic" - select WATCHDOG_PRETIMEOUT_GOV_PANIC - help - Use panic watchdog pretimeout governor by default, if - a watchdog pretimeout event happens, consider that - a watchdog feeder is dead and reboot is unavoidable. - -endchoice - -config WATCHDOG_PRETIMEOUT_GOV_NOOP - tristate "Noop watchdog pretimeout governor" - help - Noop watchdog pretimeout governor, only an informational - message is added to kernel log buffer. - -config WATCHDOG_PRETIMEOUT_GOV_PANIC - tristate "Panic watchdog pretimeout governor" - help - Panic watchdog pretimeout governor, on watchdog pretimeout - event put the kernel into panic. - -endif # WATCHDOG_PRETIMEOUT_GOV - endif # WATCHDOG diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index ba930e464657..7caa920e7e60 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o +obj-$(CONFIG_IMX_SC_WDT) += imx_sc_wdt.o obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o @@ -205,6 +206,7 @@ obj-$(CONFIG_WATCHDOG_SUN4V) += sun4v_wdt.o obj-$(CONFIG_XEN_WDT) += xen_wdt.o # Architecture Independent +obj-$(CONFIG_BD70528_WATCHDOG) += bd70528_wdt.o obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o obj-$(CONFIG_DA9062_WATCHDOG) += da9062_wdt.o diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index 7e9884960eb9..689b8a0593c1 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -277,8 +277,8 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; timeout = new_timeout; wdt_keepalive(); - /* Fall through */ } + /* Fall through */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c index 4b4054f54df9..e5dcb26d85f0 100644 --- a/drivers/watchdog/armada_37xx_wdt.c +++ b/drivers/watchdog/armada_37xx_wdt.c @@ -244,6 +244,11 @@ static const struct watchdog_ops armada_37xx_wdt_ops = { .get_timeleft = armada_37xx_wdt_get_timeleft, }; +static void armada_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int armada_37xx_wdt_probe(struct platform_device *pdev) { struct armada_37xx_watchdog *dev; @@ -278,12 +283,14 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev) ret = clk_prepare_enable(dev->clk); if (ret) return ret; + ret = devm_add_action_or_reset(&pdev->dev, + armada_clk_disable_unprepare, dev->clk); + if (ret) + return ret; dev->clk_rate = clk_get_rate(dev->clk); - if (!dev->clk_rate) { - ret = -EINVAL; - goto disable_clk; - } + if (!dev->clk_rate) + return -EINVAL; /* * Since the timeout in seconds is given as 32 bit unsigned int, and @@ -307,35 +314,15 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev) set_bit(WDOG_HW_RUNNING, &dev->wdt.status); watchdog_set_nowayout(&dev->wdt, nowayout); - ret = watchdog_register_device(&dev->wdt); + watchdog_stop_on_reboot(&dev->wdt); + ret = devm_watchdog_register_device(&pdev->dev, &dev->wdt); if (ret) - goto disable_clk; + return ret; dev_info(&pdev->dev, "Initial timeout %d sec%s\n", dev->wdt.timeout, nowayout ? ", nowayout" : ""); return 0; - -disable_clk: - clk_disable_unprepare(dev->clk); - return ret; -} - -static int armada_37xx_wdt_remove(struct platform_device *pdev) -{ - struct watchdog_device *wdt = platform_get_drvdata(pdev); - struct armada_37xx_watchdog *dev = watchdog_get_drvdata(wdt); - - watchdog_unregister_device(wdt); - clk_disable_unprepare(dev->clk); - return 0; -} - -static void armada_37xx_wdt_shutdown(struct platform_device *pdev) -{ - struct watchdog_device *wdt = platform_get_drvdata(pdev); - - armada_37xx_wdt_stop(wdt); } static int __maybe_unused armada_37xx_wdt_suspend(struct device *dev) @@ -370,8 +357,6 @@ MODULE_DEVICE_TABLE(of, armada_37xx_wdt_match); static struct platform_driver armada_37xx_wdt_driver = { .probe = armada_37xx_wdt_probe, - .remove = armada_37xx_wdt_remove, - .shutdown = armada_37xx_wdt_shutdown, .driver = { .name = "armada_37xx_wdt", .of_match_table = of_match_ptr(armada_37xx_wdt_match), diff --git a/drivers/watchdog/asm9260_wdt.c b/drivers/watchdog/asm9260_wdt.c index 9768e44ffeb8..c5b9aae544dd 100644 --- a/drivers/watchdog/asm9260_wdt.c +++ b/drivers/watchdog/asm9260_wdt.c @@ -196,6 +196,11 @@ static const struct watchdog_ops asm9260_wdt_ops = { .restart = asm9260_restart, }; +static void asm9260_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int asm9260_wdt_get_dt_clks(struct asm9260_wdt_priv *priv) { int err; @@ -219,26 +224,32 @@ static int asm9260_wdt_get_dt_clks(struct asm9260_wdt_priv *priv) dev_err(priv->dev, "Failed to enable ahb_clk!\n"); return err; } + err = devm_add_action_or_reset(priv->dev, + asm9260_clk_disable_unprepare, + priv->clk_ahb); + if (err) + return err; err = clk_set_rate(priv->clk, CLOCK_FREQ); if (err) { - clk_disable_unprepare(priv->clk_ahb); dev_err(priv->dev, "Failed to set rate!\n"); return err; } err = clk_prepare_enable(priv->clk); if (err) { - clk_disable_unprepare(priv->clk_ahb); dev_err(priv->dev, "Failed to enable clk!\n"); return err; } + err = devm_add_action_or_reset(priv->dev, + asm9260_clk_disable_unprepare, + priv->clk); + if (err) + return err; /* wdt has internal divider */ clk = clk_get_rate(priv->clk); if (!clk) { - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_ahb); dev_err(priv->dev, "Failed, clk is 0!\n"); return -EINVAL; } @@ -274,25 +285,23 @@ static void asm9260_wdt_get_dt_mode(struct asm9260_wdt_priv *priv) static int asm9260_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct asm9260_wdt_priv *priv; struct watchdog_device *wdd; - struct resource *res; int ret; static const char * const mode_name[] = { "hw", "sw", "debug", }; - priv = devm_kzalloc(&pdev->dev, sizeof(struct asm9260_wdt_priv), - GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(struct asm9260_wdt_priv), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->dev = &pdev->dev; + priv->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->iobase = devm_ioremap_resource(&pdev->dev, res); + priv->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->iobase)) return PTR_ERR(priv->iobase); - priv->rst = devm_reset_control_get_exclusive(&pdev->dev, "wdt_rst"); + priv->rst = devm_reset_control_get_exclusive(dev, "wdt_rst"); if (IS_ERR(priv->rst)) return PTR_ERR(priv->rst); @@ -305,7 +314,7 @@ static int asm9260_wdt_probe(struct platform_device *pdev) wdd->ops = &asm9260_wdt_ops; wdd->min_timeout = 1; wdd->max_timeout = BM_WDTC_MAX(priv->wdt_freq); - wdd->parent = &pdev->dev; + wdd->parent = dev; watchdog_set_drvdata(wdd, priv); @@ -315,7 +324,7 @@ static int asm9260_wdt_probe(struct platform_device *pdev) * the max instead. */ wdd->timeout = ASM9260_WDT_DEFAULT_TIMEOUT; - watchdog_init_timeout(wdd, 0, &pdev->dev); + watchdog_init_timeout(wdd, 0, dev); asm9260_wdt_get_dt_mode(priv); @@ -327,49 +336,25 @@ static int asm9260_wdt_probe(struct platform_device *pdev) * Not all supported platforms specify an interrupt for the * watchdog, so let's make it optional. */ - ret = devm_request_irq(&pdev->dev, priv->irq, - asm9260_wdt_irq, 0, pdev->name, priv); + ret = devm_request_irq(dev, priv->irq, asm9260_wdt_irq, 0, + pdev->name, priv); if (ret < 0) - dev_warn(&pdev->dev, "failed to request IRQ\n"); + dev_warn(dev, "failed to request IRQ\n"); } watchdog_set_restart_priority(wdd, 128); - ret = watchdog_register_device(wdd); + watchdog_stop_on_reboot(wdd); + watchdog_stop_on_unregister(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) - goto clk_off; + return ret; platform_set_drvdata(pdev, priv); - dev_info(&pdev->dev, "Watchdog enabled (timeout: %d sec, mode: %s)\n", + dev_info(dev, "Watchdog enabled (timeout: %d sec, mode: %s)\n", wdd->timeout, mode_name[priv->mode]); return 0; - -clk_off: - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_ahb); - return ret; -} - -static void asm9260_wdt_shutdown(struct platform_device *pdev) -{ - struct asm9260_wdt_priv *priv = platform_get_drvdata(pdev); - - asm9260_wdt_disable(&priv->wdd); -} - -static int asm9260_wdt_remove(struct platform_device *pdev) -{ - struct asm9260_wdt_priv *priv = platform_get_drvdata(pdev); - - asm9260_wdt_disable(&priv->wdd); - - watchdog_unregister_device(&priv->wdd); - - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_ahb); - - return 0; } static const struct of_device_id asm9260_wdt_of_match[] = { @@ -384,8 +369,6 @@ static struct platform_driver asm9260_wdt_driver = { .of_match_table = asm9260_wdt_of_match, }, .probe = asm9260_wdt_probe, - .remove = asm9260_wdt_remove, - .shutdown = asm9260_wdt_shutdown, }; module_platform_driver(asm9260_wdt_driver); diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 1abe4d021fd2..34117745c65f 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -187,22 +187,21 @@ static const struct watchdog_info aspeed_wdt_info = { static int aspeed_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; const struct aspeed_wdt_config *config; const struct of_device_id *ofdid; struct aspeed_wdt *wdt; - struct resource *res; struct device_node *np; const char *reset_type; u32 duration; u32 status; int ret; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(&pdev->dev, res); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); @@ -214,12 +213,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev) wdt->wdd.info = &aspeed_wdt_info; wdt->wdd.ops = &aspeed_wdt_ops; wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS; - wdt->wdd.parent = &pdev->dev; + wdt->wdd.parent = dev; wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT; - watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev); + watchdog_init_timeout(&wdt->wdd, 0, dev); - np = pdev->dev.of_node; + np = dev->of_node; ofdid = of_match_node(aspeed_wdt_of_table, np); if (!ofdid) @@ -288,11 +287,11 @@ static int aspeed_wdt_probe(struct platform_device *pdev) u32 max_duration = config->ext_pulse_width_mask + 1; if (duration == 0 || duration > max_duration) { - dev_err(&pdev->dev, "Invalid pulse duration: %uus\n", - duration); + dev_err(dev, "Invalid pulse duration: %uus\n", + duration); duration = max(1U, min(max_duration, duration)); - dev_info(&pdev->dev, "Pulse duration set to %uus\n", - duration); + dev_info(dev, "Pulse duration set to %uus\n", + duration); } /* @@ -314,9 +313,9 @@ static int aspeed_wdt_probe(struct platform_device *pdev) if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) wdt->wdd.bootstatus = WDIOF_CARDRESET; - ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd); + ret = devm_watchdog_register_device(dev, &wdt->wdd); if (ret) { - dev_err(&pdev->dev, "failed to register\n"); + dev_err(dev, "failed to register\n"); return ret; } diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index f4050a229eb5..292b5a1ca831 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -327,7 +327,6 @@ static inline int of_at91wdt_init(struct device_node *np, struct at91wdt *wdt) static int __init at91wdt_probe(struct platform_device *pdev) { - struct resource *r; int err; struct at91wdt *wdt; @@ -346,8 +345,7 @@ static int __init at91wdt_probe(struct platform_device *pdev) wdt->wdd.min_timeout = 1; wdt->wdd.max_timeout = 0xFFFF; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(&pdev->dev, r); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c index 4f56b63f9691..02234c254b10 100644 --- a/drivers/watchdog/ath79_wdt.c +++ b/drivers/watchdog/ath79_wdt.c @@ -250,15 +250,13 @@ static struct miscdevice ath79_wdt_miscdev = { static int ath79_wdt_probe(struct platform_device *pdev) { - struct resource *res; u32 ctrl; int err; if (wdt_base) return -EBUSY; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt_base = devm_ioremap_resource(&pdev->dev, res); + wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt_base)) return PTR_ERR(wdt_base); diff --git a/drivers/watchdog/atlas7_wdt.c b/drivers/watchdog/atlas7_wdt.c index 4abdcabd8219..79337d2a8a8e 100644 --- a/drivers/watchdog/atlas7_wdt.c +++ b/drivers/watchdog/atlas7_wdt.c @@ -125,80 +125,57 @@ static const struct of_device_id atlas7_wdt_ids[] = { {} }; +static void atlas7_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int atlas7_wdt_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; struct atlas7_wdog *wdt; - struct resource *res; struct clk *clk; int ret; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(&pdev->dev, res); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - clk = of_clk_get(np, 0); + clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); ret = clk_prepare_enable(clk); if (ret) { - dev_err(&pdev->dev, "clk enable failed\n"); - goto err; + dev_err(dev, "clk enable failed\n"); + return ret; } + ret = devm_add_action_or_reset(dev, atlas7_clk_disable_unprepare, clk); + if (ret) + return ret; /* disable watchdog hardware */ writel(0, wdt->base + ATLAS7_WDT_CNT_CTRL); wdt->tick_rate = clk_get_rate(clk); - if (!wdt->tick_rate) { - ret = -EINVAL; - goto err1; - } + if (!wdt->tick_rate) + return -EINVAL; wdt->clk = clk; atlas7_wdd.min_timeout = 1; atlas7_wdd.max_timeout = UINT_MAX / wdt->tick_rate; - watchdog_init_timeout(&atlas7_wdd, 0, &pdev->dev); + watchdog_init_timeout(&atlas7_wdd, 0, dev); watchdog_set_nowayout(&atlas7_wdd, nowayout); watchdog_set_drvdata(&atlas7_wdd, wdt); platform_set_drvdata(pdev, &atlas7_wdd); - ret = watchdog_register_device(&atlas7_wdd); - if (ret) - goto err1; - - return 0; - -err1: - clk_disable_unprepare(clk); -err: - clk_put(clk); - return ret; -} - -static void atlas7_wdt_shutdown(struct platform_device *pdev) -{ - struct watchdog_device *wdd = platform_get_drvdata(pdev); - struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); - - atlas7_wdt_disable(wdd); - clk_disable_unprepare(wdt->clk); -} - -static int atlas7_wdt_remove(struct platform_device *pdev) -{ - struct watchdog_device *wdd = platform_get_drvdata(pdev); - struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); - - atlas7_wdt_shutdown(pdev); - clk_put(wdt->clk); - return 0; + watchdog_stop_on_reboot(&atlas7_wdd); + watchdog_stop_on_unregister(&atlas7_wdd); + return devm_watchdog_register_device(dev, &atlas7_wdd); } static int __maybe_unused atlas7_wdt_suspend(struct device *dev) @@ -236,8 +213,6 @@ static struct platform_driver atlas7_wdt_driver = { .of_match_table = atlas7_wdt_ids, }, .probe = atlas7_wdt_probe, - .remove = atlas7_wdt_remove, - .shutdown = atlas7_wdt_shutdown, }; module_platform_driver(atlas7_wdt_driver); diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index 1834524ae373..560c1c54c177 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -177,7 +177,6 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) wdt = devm_kzalloc(dev, sizeof(struct bcm2835_wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - platform_set_drvdata(pdev, wdt); spin_lock_init(&wdt->lock); diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index ce3f646e8077..d3d88f6703d7 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -107,11 +107,15 @@ static const struct watchdog_ops bcm7038_wdt_ops = { .get_timeleft = bcm7038_wdt_get_timeleft, }; +static void bcm7038_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int bcm7038_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct bcm7038_watchdog *wdt; - struct resource *res; int err; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); @@ -120,8 +124,7 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdt); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(dev, res); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); @@ -131,6 +134,11 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) err = clk_prepare_enable(wdt->clk); if (err) return err; + err = devm_add_action_or_reset(dev, + bcm7038_clk_disable_unprepare, + wdt->clk); + if (err) + return err; wdt->rate = clk_get_rate(wdt->clk); /* Prevent divide-by-zero exception */ if (!wdt->rate) @@ -148,10 +156,11 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) wdt->wdd.parent = dev; watchdog_set_drvdata(&wdt->wdd, wdt); - err = watchdog_register_device(&wdt->wdd); + watchdog_stop_on_reboot(&wdt->wdd); + watchdog_stop_on_unregister(&wdt->wdd); + err = devm_watchdog_register_device(dev, &wdt->wdd); if (err) { dev_err(dev, "Failed to register watchdog device\n"); - clk_disable_unprepare(wdt->clk); return err; } @@ -160,19 +169,6 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) return 0; } -static int bcm7038_wdt_remove(struct platform_device *pdev) -{ - struct bcm7038_watchdog *wdt = platform_get_drvdata(pdev); - - if (!nowayout) - bcm7038_wdt_stop(&wdt->wdd); - - watchdog_unregister_device(&wdt->wdd); - clk_disable_unprepare(wdt->clk); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int bcm7038_wdt_suspend(struct device *dev) { @@ -198,14 +194,6 @@ static int bcm7038_wdt_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, bcm7038_wdt_suspend, bcm7038_wdt_resume); -static void bcm7038_wdt_shutdown(struct platform_device *pdev) -{ - struct bcm7038_watchdog *wdt = platform_get_drvdata(pdev); - - if (watchdog_active(&wdt->wdd)) - bcm7038_wdt_stop(&wdt->wdd); -} - static const struct of_device_id bcm7038_wdt_match[] = { { .compatible = "brcm,bcm7038-wdt" }, {}, @@ -214,8 +202,6 @@ MODULE_DEVICE_TABLE(of, bcm7038_wdt_match); static struct platform_driver bcm7038_wdt_driver = { .probe = bcm7038_wdt_probe, - .remove = bcm7038_wdt_remove, - .shutdown = bcm7038_wdt_shutdown, .driver = { .name = "bcm7038-wdt", .of_match_table = bcm7038_wdt_match, diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index 4249b47902bd..e2ad44816359 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c @@ -271,16 +271,10 @@ static struct watchdog_device bcm_kona_wdt_wdd = { .timeout = SECWDOG_MAX_COUNT >> SECWDOG_DEFAULT_RESOLUTION, }; -static void bcm_kona_wdt_shutdown(struct platform_device *pdev) -{ - bcm_kona_wdt_stop(&bcm_kona_wdt_wdd); -} - static int bcm_kona_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct bcm_kona_wdt *wdt; - struct resource *res; int ret; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); @@ -289,8 +283,7 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) spin_lock_init(&wdt->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(dev, res); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return -ENODEV; @@ -303,7 +296,7 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdt); watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt); - bcm_kona_wdt_wdd.parent = &pdev->dev; + bcm_kona_wdt_wdd.parent = dev; ret = bcm_kona_wdt_set_timeout_reg(&bcm_kona_wdt_wdd, 0); if (ret) { @@ -311,7 +304,9 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) return ret; } - ret = watchdog_register_device(&bcm_kona_wdt_wdd); + watchdog_stop_on_reboot(&bcm_kona_wdt_wdd); + watchdog_stop_on_unregister(&bcm_kona_wdt_wdd); + ret = devm_watchdog_register_device(dev, &bcm_kona_wdt_wdd); if (ret) { dev_err(dev, "Failed to register watchdog device"); return ret; @@ -326,8 +321,6 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) static int bcm_kona_wdt_remove(struct platform_device *pdev) { bcm_kona_wdt_debug_exit(pdev); - bcm_kona_wdt_shutdown(pdev); - watchdog_unregister_device(&bcm_kona_wdt_wdd); dev_dbg(&pdev->dev, "Watchdog driver disabled"); return 0; @@ -346,7 +339,6 @@ static struct platform_driver bcm_kona_wdt_driver = { }, .probe = bcm_kona_wdt_probe, .remove = bcm_kona_wdt_remove, - .shutdown = bcm_kona_wdt_shutdown, }; module_platform_driver(bcm_kona_wdt_driver); diff --git a/drivers/watchdog/bd70528_wdt.c b/drivers/watchdog/bd70528_wdt.c new file mode 100644 index 000000000000..b0152fef4fc7 --- /dev/null +++ b/drivers/watchdog/bd70528_wdt.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors +// ROHM BD70528MWV watchdog driver + +#include <linux/bcd.h> +#include <linux/kernel.h> +#include <linux/mfd/rohm-bd70528.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/watchdog.h> + +/* + * Max time we can set is 1 hour, 59 minutes and 59 seconds + * and Minimum time is 1 second + */ +#define WDT_MAX_MS ((2 * 60 * 60 - 1) * 1000) +#define WDT_MIN_MS 1000 +#define DEFAULT_TIMEOUT 60 + +#define WD_CTRL_MAGIC1 0x55 +#define WD_CTRL_MAGIC2 0xAA + +struct wdtbd70528 { + struct device *dev; + struct regmap *regmap; + struct rohm_regmap_dev *mfd; + struct watchdog_device wdt; +}; + +/** + * bd70528_wdt_set - arm or disarm watchdog timer + * + * @data: device data for the PMIC instance we want to operate on + * @enable: new state of WDT. zero to disable, non zero to enable + * @old_state: previous state of WDT will be filled here + * + * Arm or disarm WDT on BD70528 PMIC. Expected to be called only by + * BD70528 RTC and BD70528 WDT drivers. The rtc_timer_lock must be taken + * by calling bd70528_wdt_lock before calling bd70528_wdt_set. + */ +int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable, int *old_state) +{ + int ret, i; + unsigned int tmp; + struct bd70528_data *bd70528 = container_of(data, struct bd70528_data, + chip); + u8 wd_ctrl_arr[3] = { WD_CTRL_MAGIC1, WD_CTRL_MAGIC2, 0 }; + u8 *wd_ctrl = &wd_ctrl_arr[2]; + + ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, &tmp); + if (ret) + return ret; + + *wd_ctrl = (u8)tmp; + + if (old_state) { + if (*wd_ctrl & BD70528_MASK_WDT_EN) + *old_state |= BD70528_WDT_STATE_BIT; + else + *old_state &= ~BD70528_WDT_STATE_BIT; + if ((!enable) == (!(*old_state & BD70528_WDT_STATE_BIT))) + return 0; + } + + if (enable) { + if (*wd_ctrl & BD70528_MASK_WDT_EN) + return 0; + *wd_ctrl |= BD70528_MASK_WDT_EN; + } else { + if (*wd_ctrl & BD70528_MASK_WDT_EN) + *wd_ctrl &= ~BD70528_MASK_WDT_EN; + else + return 0; + } + + for (i = 0; i < 3; i++) { + ret = regmap_write(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, + wd_ctrl_arr[i]); + if (ret) + return ret; + } + + ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, &tmp); + if ((tmp & BD70528_MASK_WDT_EN) != (*wd_ctrl & BD70528_MASK_WDT_EN)) { + dev_err(bd70528->chip.dev, + "Watchdog ctrl mismatch (hw) 0x%x (set) 0x%x\n", + tmp, *wd_ctrl); + ret = -EIO; + } + + return ret; +} +EXPORT_SYMBOL(bd70528_wdt_set); + +/** + * bd70528_wdt_lock - take WDT lock + * + * @bd70528: 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. + */ +void bd70528_wdt_lock(struct rohm_regmap_dev *data) +{ + struct bd70528_data *bd70528 = container_of(data, struct bd70528_data, + chip); + + mutex_lock(&bd70528->rtc_timer_lock); +} +EXPORT_SYMBOL(bd70528_wdt_lock); + +/** + * bd70528_wdt_unlock - unlock WDT lock + * + * @bd70528: 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. + */ +void bd70528_wdt_unlock(struct rohm_regmap_dev *data) +{ + struct bd70528_data *bd70528 = container_of(data, struct bd70528_data, + chip); + + mutex_unlock(&bd70528->rtc_timer_lock); +} +EXPORT_SYMBOL(bd70528_wdt_unlock); + +static int bd70528_wdt_set_locked(struct wdtbd70528 *w, int enable) +{ + return bd70528_wdt_set(w->mfd, enable, NULL); +} + +static int bd70528_wdt_change(struct wdtbd70528 *w, int enable) +{ + int ret; + + bd70528_wdt_lock(w->mfd); + ret = bd70528_wdt_set_locked(w, enable); + bd70528_wdt_unlock(w->mfd); + + return ret; +} + +static int bd70528_wdt_start(struct watchdog_device *wdt) +{ + struct wdtbd70528 *w = watchdog_get_drvdata(wdt); + + dev_dbg(w->dev, "WDT ping...\n"); + return bd70528_wdt_change(w, 1); +} + +static int bd70528_wdt_stop(struct watchdog_device *wdt) +{ + struct wdtbd70528 *w = watchdog_get_drvdata(wdt); + + dev_dbg(w->dev, "WDT stopping...\n"); + return bd70528_wdt_change(w, 0); +} + +static int bd70528_wdt_set_timeout(struct watchdog_device *wdt, + unsigned int timeout) +{ + unsigned int hours; + unsigned int minutes; + unsigned int seconds; + int ret; + struct wdtbd70528 *w = watchdog_get_drvdata(wdt); + + seconds = timeout; + hours = timeout / (60 * 60); + /* Maximum timeout is 1h 59m 59s => hours is 1 or 0 */ + if (hours) + seconds -= (60 * 60); + minutes = seconds / 60; + seconds = seconds % 60; + + bd70528_wdt_lock(w->mfd); + + ret = bd70528_wdt_set_locked(w, 0); + if (ret) + goto out_unlock; + + ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_HOUR, + BD70528_MASK_WDT_HOUR, hours); + if (ret) { + dev_err(w->dev, "Failed to set WDT hours\n"); + goto out_en_unlock; + } + ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_MINUTE, + BD70528_MASK_WDT_MINUTE, bin2bcd(minutes)); + if (ret) { + dev_err(w->dev, "Failed to set WDT minutes\n"); + goto out_en_unlock; + } + ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_SEC, + BD70528_MASK_WDT_SEC, bin2bcd(seconds)); + if (ret) + dev_err(w->dev, "Failed to set WDT seconds\n"); + else + dev_dbg(w->dev, "WDT tmo set to %u\n", timeout); + +out_en_unlock: + ret = bd70528_wdt_set_locked(w, 1); +out_unlock: + bd70528_wdt_unlock(w->mfd); + + return ret; +} + +static const struct watchdog_info bd70528_wdt_info = { + .identity = "bd70528-wdt", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, +}; + +static const struct watchdog_ops bd70528_wdt_ops = { + .start = bd70528_wdt_start, + .stop = bd70528_wdt_stop, + .set_timeout = bd70528_wdt_set_timeout, +}; + +static int bd70528_wdt_probe(struct platform_device *pdev) +{ + struct rohm_regmap_dev *bd70528; + struct wdtbd70528 *w; + int ret; + unsigned int reg; + + bd70528 = dev_get_drvdata(pdev->dev.parent); + if (!bd70528) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + w = devm_kzalloc(&pdev->dev, sizeof(*w), GFP_KERNEL); + if (!w) + return -ENOMEM; + + w->regmap = bd70528->regmap; + w->mfd = bd70528; + w->dev = &pdev->dev; + + w->wdt.info = &bd70528_wdt_info; + w->wdt.ops = &bd70528_wdt_ops; + w->wdt.min_hw_heartbeat_ms = WDT_MIN_MS; + w->wdt.max_hw_heartbeat_ms = WDT_MAX_MS; + w->wdt.parent = pdev->dev.parent; + w->wdt.timeout = DEFAULT_TIMEOUT; + watchdog_set_drvdata(&w->wdt, w); + watchdog_init_timeout(&w->wdt, 0, pdev->dev.parent); + + ret = bd70528_wdt_set_timeout(&w->wdt, w->wdt.timeout); + if (ret) { + dev_err(&pdev->dev, "Failed to set the watchdog timeout\n"); + return ret; + } + + bd70528_wdt_lock(w->mfd); + ret = regmap_read(w->regmap, BD70528_REG_WDT_CTRL, ®); + bd70528_wdt_unlock(w->mfd); + + if (ret) { + dev_err(&pdev->dev, "Failed to get the watchdog state\n"); + return ret; + } + if (reg & BD70528_MASK_WDT_EN) { + dev_dbg(&pdev->dev, "watchdog was running during probe\n"); + set_bit(WDOG_HW_RUNNING, &w->wdt.status); + } + + ret = devm_watchdog_register_device(&pdev->dev, &w->wdt); + if (ret < 0) + dev_err(&pdev->dev, "watchdog registration failed: %d\n", ret); + + return ret; +} + +static struct platform_driver bd70528_wdt = { + .driver = { + .name = "bd70528-wdt" + }, + .probe = bd70528_wdt_probe, +}; + +module_platform_driver(bd70528_wdt); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD70528 watchdog driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c index c3924356d173..a22f2d431a35 100644 --- a/drivers/watchdog/cadence_wdt.c +++ b/drivers/watchdog/cadence_wdt.c @@ -274,6 +274,11 @@ static const struct watchdog_ops cdns_wdt_ops = { .set_timeout = cdns_wdt_settimeout, }; +static void cdns_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + /************************Platform Operations*****************************/ /** * cdns_wdt_probe - Probe call for the device. @@ -285,13 +290,13 @@ static const struct watchdog_ops cdns_wdt_ops = { */ static int cdns_wdt_probe(struct platform_device *pdev) { - struct resource *res; + struct device *dev = &pdev->dev; int ret, irq; unsigned long clock_f; struct cdns_wdt *wdt; struct watchdog_device *cdns_wdt_device; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -302,19 +307,18 @@ static int cdns_wdt_probe(struct platform_device *pdev) cdns_wdt_device->min_timeout = CDNS_WDT_MIN_TIMEOUT; cdns_wdt_device->max_timeout = CDNS_WDT_MAX_TIMEOUT; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->regs = devm_ioremap_resource(&pdev->dev, res); + wdt->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->regs)) return PTR_ERR(wdt->regs); /* Register the interrupt */ - wdt->rst = of_property_read_bool(pdev->dev.of_node, "reset-on-timeout"); + wdt->rst = of_property_read_bool(dev->of_node, "reset-on-timeout"); irq = platform_get_irq(pdev, 0); if (!wdt->rst && irq >= 0) { - ret = devm_request_irq(&pdev->dev, irq, cdns_wdt_irq_handler, 0, + ret = devm_request_irq(dev, irq, cdns_wdt_irq_handler, 0, pdev->name, pdev); if (ret) { - dev_err(&pdev->dev, + dev_err(dev, "cannot register interrupt handler err=%d\n", ret); return ret; @@ -322,30 +326,28 @@ static int cdns_wdt_probe(struct platform_device *pdev) } /* Initialize the members of cdns_wdt structure */ - cdns_wdt_device->parent = &pdev->dev; - - ret = watchdog_init_timeout(cdns_wdt_device, wdt_timeout, &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "unable to set timeout value\n"); - return ret; - } + cdns_wdt_device->parent = dev; + watchdog_init_timeout(cdns_wdt_device, wdt_timeout, dev); watchdog_set_nowayout(cdns_wdt_device, nowayout); watchdog_stop_on_reboot(cdns_wdt_device); watchdog_set_drvdata(cdns_wdt_device, wdt); - wdt->clk = devm_clk_get(&pdev->dev, NULL); + wdt->clk = devm_clk_get(dev, NULL); if (IS_ERR(wdt->clk)) { - dev_err(&pdev->dev, "input clock not found\n"); - ret = PTR_ERR(wdt->clk); - return ret; + dev_err(dev, "input clock not found\n"); + return PTR_ERR(wdt->clk); } ret = clk_prepare_enable(wdt->clk); if (ret) { - dev_err(&pdev->dev, "unable to enable clock\n"); + dev_err(dev, "unable to enable clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, cdns_clk_disable_unprepare, + wdt->clk); + if (ret) + return ret; clock_f = clk_get_rate(wdt->clk); if (clock_f <= CDNS_WDT_CLK_75MHZ) { @@ -358,56 +360,20 @@ static int cdns_wdt_probe(struct platform_device *pdev) spin_lock_init(&wdt->io_lock); - ret = watchdog_register_device(cdns_wdt_device); + watchdog_stop_on_reboot(cdns_wdt_device); + watchdog_stop_on_unregister(cdns_wdt_device); + ret = devm_watchdog_register_device(dev, cdns_wdt_device); if (ret) { - dev_err(&pdev->dev, "Failed to register wdt device\n"); - goto err_clk_disable; + dev_err(dev, "Failed to register wdt device\n"); + return ret; } platform_set_drvdata(pdev, wdt); - dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n", + dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n", wdt->regs, cdns_wdt_device->timeout, nowayout ? ", nowayout" : ""); return 0; - -err_clk_disable: - clk_disable_unprepare(wdt->clk); - - return ret; -} - -/** - * cdns_wdt_remove - Probe call for the device. - * - * @pdev: handle to the platform device structure. - * Return: 0 on success, otherwise negative error. - * - * Unregister the device after releasing the resources. - */ -static int cdns_wdt_remove(struct platform_device *pdev) -{ - struct cdns_wdt *wdt = platform_get_drvdata(pdev); - - cdns_wdt_stop(&wdt->cdns_wdt_device); - watchdog_unregister_device(&wdt->cdns_wdt_device); - clk_disable_unprepare(wdt->clk); - - return 0; -} - -/** - * cdns_wdt_shutdown - Stop the device. - * - * @pdev: handle to the platform structure. - * - */ -static void cdns_wdt_shutdown(struct platform_device *pdev) -{ - struct cdns_wdt *wdt = platform_get_drvdata(pdev); - - cdns_wdt_stop(&wdt->cdns_wdt_device); - clk_disable_unprepare(wdt->clk); } /** @@ -462,8 +428,6 @@ MODULE_DEVICE_TABLE(of, cdns_wdt_of_match); /* Driver Structure */ static struct platform_driver cdns_wdt_driver = { .probe = cdns_wdt_probe, - .remove = cdns_wdt_remove, - .shutdown = cdns_wdt_shutdown, .driver = { .name = "cdns-wdt", .of_match_table = cdns_wdt_of_match, diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c index f29d1edc5bad..260c50b08483 100644 --- a/drivers/watchdog/coh901327_wdt.c +++ b/drivers/watchdog/coh901327_wdt.c @@ -6,7 +6,7 @@ * Watchdog driver for the ST-Ericsson AB COH 901 327 IP core * Author: Linus Walleij <linus.walleij@stericsson.com> */ -#include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/mod_devicetable.h> #include <linux/types.h> #include <linux/watchdog.h> @@ -243,27 +243,15 @@ static struct watchdog_device coh901327_wdt = { .timeout = U300_WDOG_DEFAULT_TIMEOUT, }; -static int __exit coh901327_remove(struct platform_device *pdev) -{ - watchdog_unregister_device(&coh901327_wdt); - coh901327_disable(); - free_irq(irq, pdev); - clk_disable_unprepare(clk); - clk_put(clk); - return 0; -} - static int __init coh901327_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int ret; u16 val; - struct resource *res; parent = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - virtbase = devm_ioremap_resource(dev, res); + virtbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(virtbase)) return PTR_ERR(virtbase); @@ -408,19 +396,13 @@ static struct platform_driver coh901327_driver = { .driver = { .name = "coh901327_wdog", .of_match_table = coh901327_dt_match, + .suppress_bind_attrs = true, }, - .remove = __exit_p(coh901327_remove), .suspend = coh901327_suspend, .resume = coh901327_resume, }; +builtin_platform_driver_probe(coh901327_driver, coh901327_probe); -module_platform_driver_probe(coh901327_driver, coh901327_probe); - -MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); -MODULE_DESCRIPTION("COH 901 327 Watchdog"); - +/* not really modular, but ... */ module_param(margin, uint, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); - -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:coh901327-watchdog"); diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c index e263bad99574..a2feef1ff307 100644 --- a/drivers/watchdog/da9052_wdt.c +++ b/drivers/watchdog/da9052_wdt.c @@ -150,13 +150,13 @@ static const struct watchdog_ops da9052_wdt_ops = { static int da9052_wdt_probe(struct platform_device *pdev) { - struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct da9052 *da9052 = dev_get_drvdata(dev->parent); struct da9052_wdt_data *driver_data; struct watchdog_device *da9052_wdt; int ret; - driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data), - GFP_KERNEL); + driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); if (!driver_data) return -ENOMEM; driver_data->da9052 = da9052; @@ -166,18 +166,17 @@ static int da9052_wdt_probe(struct platform_device *pdev) da9052_wdt->timeout = DA9052_DEF_TIMEOUT; da9052_wdt->info = &da9052_wdt_info; da9052_wdt->ops = &da9052_wdt_ops; - da9052_wdt->parent = &pdev->dev; + da9052_wdt->parent = dev; watchdog_set_drvdata(da9052_wdt, driver_data); ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG, DA9052_CONTROLD_TWDSCALE, 0); if (ret < 0) { - dev_err(&pdev->dev, "Failed to disable watchdog bits, %d\n", - ret); + dev_err(dev, "Failed to disable watchdog bits, %d\n", ret); return ret; } - ret = devm_watchdog_register_device(&pdev->dev, &driver_data->wdt); + ret = devm_watchdog_register_device(dev, &driver_data->wdt); if (ret != 0) { dev_err(da9052->dev, "watchdog_register_device() failed: %d\n", ret); diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c index 26a5b2984094..389a4bdd208c 100644 --- a/drivers/watchdog/da9055_wdt.c +++ b/drivers/watchdog/da9055_wdt.c @@ -119,13 +119,13 @@ static const struct watchdog_ops da9055_wdt_ops = { static int da9055_wdt_probe(struct platform_device *pdev) { - struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct da9055 *da9055 = dev_get_drvdata(dev->parent); struct da9055_wdt_data *driver_data; struct watchdog_device *da9055_wdt; int ret; - driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data), - GFP_KERNEL); + driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); if (!driver_data) return -ENOMEM; @@ -136,17 +136,17 @@ static int da9055_wdt_probe(struct platform_device *pdev) da9055_wdt->timeout = DA9055_DEF_TIMEOUT; da9055_wdt->info = &da9055_wdt_info; da9055_wdt->ops = &da9055_wdt_ops; - da9055_wdt->parent = &pdev->dev; + da9055_wdt->parent = dev; watchdog_set_nowayout(da9055_wdt, nowayout); watchdog_set_drvdata(da9055_wdt, driver_data); ret = da9055_wdt_stop(da9055_wdt); if (ret < 0) { - dev_err(&pdev->dev, "Failed to stop watchdog, %d\n", ret); + dev_err(dev, "Failed to stop watchdog, %d\n", ret); return ret; } - ret = devm_watchdog_register_device(&pdev->dev, &driver_data->wdt); + ret = devm_watchdog_register_device(dev, &driver_data->wdt); if (ret != 0) dev_err(da9055->dev, "watchdog_register_device() failed: %d\n", ret); diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c index fe169d8e1fb2..aac749cfaccb 100644 --- a/drivers/watchdog/da9062_wdt.c +++ b/drivers/watchdog/da9062_wdt.c @@ -46,14 +46,9 @@ static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs) static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt) { - int ret; - - ret = regmap_update_bits(wdt->hw->regmap, - DA9062AA_CONTROL_F, - DA9062AA_WATCHDOG_MASK, - DA9062AA_WATCHDOG_MASK); - - return ret; + return regmap_update_bits(wdt->hw->regmap, DA9062AA_CONTROL_F, + DA9062AA_WATCHDOG_MASK, + DA9062AA_WATCHDOG_MASK); } static int da9062_wdt_update_timeout_register(struct da9062_watchdog *wdt, @@ -190,15 +185,16 @@ MODULE_DEVICE_TABLE(of, da9062_compatible_id_table); static int da9062_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret; struct da9062 *chip; struct da9062_watchdog *wdt; - chip = dev_get_drvdata(pdev->dev.parent); + chip = dev_get_drvdata(dev->parent); if (!chip) return -EINVAL; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -211,13 +207,13 @@ static int da9062_wdt_probe(struct platform_device *pdev) wdt->wdtdev.min_hw_heartbeat_ms = DA9062_RESET_PROTECTION_MS; wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT; wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; - wdt->wdtdev.parent = &pdev->dev; + wdt->wdtdev.parent = dev; watchdog_set_restart_priority(&wdt->wdtdev, 128); watchdog_set_drvdata(&wdt->wdtdev, wdt); - ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev); + ret = devm_watchdog_register_device(dev, &wdt->wdtdev); if (ret < 0) { dev_err(wdt->hw->dev, "watchdog registration failed (%d)\n", ret); diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c index 384dca16af8b..3d65e92a4e3f 100644 --- a/drivers/watchdog/da9063_wdt.c +++ b/drivers/watchdog/da9063_wdt.c @@ -188,17 +188,18 @@ static const struct watchdog_ops da9063_watchdog_ops = { static int da9063_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct da9063 *da9063; struct watchdog_device *wdd; - if (!pdev->dev.parent) + if (!dev->parent) return -EINVAL; - da9063 = dev_get_drvdata(pdev->dev.parent); + da9063 = dev_get_drvdata(dev->parent); if (!da9063) return -EINVAL; - wdd = devm_kzalloc(&pdev->dev, sizeof(*wdd), GFP_KERNEL); + wdd = devm_kzalloc(dev, sizeof(*wdd), GFP_KERNEL); if (!wdd) return -ENOMEM; @@ -207,22 +208,24 @@ static int da9063_wdt_probe(struct platform_device *pdev) wdd->min_timeout = DA9063_WDT_MIN_TIMEOUT; wdd->max_timeout = DA9063_WDT_MAX_TIMEOUT; wdd->min_hw_heartbeat_ms = DA9063_RESET_PROTECTION_MS; - wdd->timeout = DA9063_WDG_TIMEOUT; - wdd->parent = &pdev->dev; - + wdd->parent = dev; wdd->status = WATCHDOG_NOWAYOUT_INIT_STATUS; watchdog_set_restart_priority(wdd, 128); - watchdog_set_drvdata(wdd, da9063); + /* Set default timeout, maybe override it with DT value, scale it */ + wdd->timeout = DA9063_WDG_TIMEOUT; + watchdog_init_timeout(wdd, 0, dev); + da9063_wdt_set_timeout(wdd, wdd->timeout); + /* Change the timeout to the default value if the watchdog is running */ if (da9063_wdt_is_running(da9063)) { - da9063_wdt_update_timeout(da9063, DA9063_WDG_TIMEOUT); + da9063_wdt_update_timeout(da9063, wdd->timeout); set_bit(WDOG_HW_RUNNING, &wdd->status); } - return devm_watchdog_register_device(&pdev->dev, wdd); + return devm_watchdog_register_device(dev, wdd); } static struct platform_driver da9063_wdt_driver = { diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index ebb85d60b6d5..7b2ee35b5ffd 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -191,11 +191,15 @@ static const struct watchdog_ops davinci_wdt_ops = { .restart = davinci_wdt_restart, }; +static void davinci_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int davinci_wdt_probe(struct platform_device *pdev) { int ret = 0; struct device *dev = &pdev->dev; - struct resource *wdt_mem; struct watchdog_device *wdd; struct davinci_wdt_device *davinci_wdt; @@ -207,15 +211,19 @@ static int davinci_wdt_probe(struct platform_device *pdev) if (IS_ERR(davinci_wdt->clk)) { if (PTR_ERR(davinci_wdt->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get clock node\n"); + dev_err(dev, "failed to get clock node\n"); return PTR_ERR(davinci_wdt->clk); } ret = clk_prepare_enable(davinci_wdt->clk); if (ret) { - dev_err(&pdev->dev, "failed to prepare clock\n"); + dev_err(dev, "failed to prepare clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, davinci_clk_disable_unprepare, + davinci_wdt->clk); + if (ret) + return ret; platform_set_drvdata(pdev, davinci_wdt); @@ -225,7 +233,7 @@ static int davinci_wdt_probe(struct platform_device *pdev) wdd->min_timeout = 1; wdd->max_timeout = MAX_HEARTBEAT; wdd->timeout = DEFAULT_HEARTBEAT; - wdd->parent = &pdev->dev; + wdd->parent = dev; watchdog_init_timeout(wdd, heartbeat, dev); @@ -235,35 +243,17 @@ static int davinci_wdt_probe(struct platform_device *pdev) watchdog_set_nowayout(wdd, 1); watchdog_set_restart_priority(wdd, 128); - wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - davinci_wdt->base = devm_ioremap_resource(dev, wdt_mem); - if (IS_ERR(davinci_wdt->base)) { - ret = PTR_ERR(davinci_wdt->base); - goto err_clk_disable; - } + davinci_wdt->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(davinci_wdt->base)) + return PTR_ERR(davinci_wdt->base); - ret = watchdog_register_device(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { dev_err(dev, "cannot register watchdog device\n"); - goto err_clk_disable; + return ret; } return 0; - -err_clk_disable: - clk_disable_unprepare(davinci_wdt->clk); - - return ret; -} - -static int davinci_wdt_remove(struct platform_device *pdev) -{ - struct davinci_wdt_device *davinci_wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&davinci_wdt->wdd); - clk_disable_unprepare(davinci_wdt->clk); - - return 0; } static const struct of_device_id davinci_wdt_of_match[] = { @@ -278,7 +268,6 @@ static struct platform_driver platform_wdt_driver = { .of_match_table = davinci_wdt_of_match, }, .probe = davinci_wdt_probe, - .remove = davinci_wdt_remove, }; module_platform_driver(platform_wdt_driver); diff --git a/drivers/watchdog/digicolor_wdt.c b/drivers/watchdog/digicolor_wdt.c index a9e11df155b8..8af6e9a67d0d 100644 --- a/drivers/watchdog/digicolor_wdt.c +++ b/drivers/watchdog/digicolor_wdt.c @@ -116,7 +116,6 @@ static struct watchdog_device dc_wdt_wdd = { static int dc_wdt_probe(struct platform_device *pdev) { - struct resource *res; struct device *dev = &pdev->dev; struct dc_wdt *wdt; int ret; @@ -125,8 +124,7 @@ static int dc_wdt_probe(struct platform_device *pdev) if (!wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(dev, res); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index aa95f57cc1c3..39e43750ab08 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -238,15 +238,13 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct dw_wdt *dw_wdt; - struct resource *mem; int ret; dw_wdt = devm_kzalloc(dev, sizeof(*dw_wdt), GFP_KERNEL); if (!dw_wdt) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dw_wdt->regs = devm_ioremap_resource(dev, mem); + dw_wdt->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dw_wdt->regs)) return PTR_ERR(dw_wdt->regs); diff --git a/drivers/watchdog/ebc-c384_wdt.c b/drivers/watchdog/ebc-c384_wdt.c index 4c4c8ce78021..c176f59fea28 100644 --- a/drivers/watchdog/ebc-c384_wdt.c +++ b/drivers/watchdog/ebc-c384_wdt.c @@ -117,10 +117,7 @@ static int ebc_c384_wdt_probe(struct device *dev, unsigned int id) wdd->max_timeout = WATCHDOG_MAX_TIMEOUT; watchdog_set_nowayout(wdd, nowayout); - - if (watchdog_init_timeout(wdd, timeout, dev)) - dev_warn(dev, "Invalid timeout (%u seconds), using default (%u seconds)\n", - timeout, WATCHDOG_TIMEOUT); + watchdog_init_timeout(wdd, timeout, dev); return devm_watchdog_register_device(dev, wdd); } diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index f9b14e6efd9a..38e26f160b9a 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -89,18 +89,17 @@ static const struct watchdog_ops ep93xx_wdt_ops = { static int ep93xx_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct ep93xx_wdt_priv *priv; struct watchdog_device *wdd; - struct resource *res; unsigned long val; int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->mmio = devm_ioremap_resource(&pdev->dev, res); + priv->mmio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->mmio)) return PTR_ERR(priv->mmio); @@ -112,21 +111,21 @@ static int ep93xx_wdt_probe(struct platform_device *pdev) wdd->ops = &ep93xx_wdt_ops; wdd->min_timeout = 1; wdd->max_hw_heartbeat_ms = 200; - wdd->parent = &pdev->dev; + wdd->parent = dev; watchdog_set_nowayout(wdd, nowayout); wdd->timeout = WDT_TIMEOUT; - watchdog_init_timeout(wdd, timeout, &pdev->dev); + watchdog_init_timeout(wdd, timeout, dev); watchdog_set_drvdata(wdd, priv); - ret = devm_watchdog_register_device(&pdev->dev, wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) return ret; - dev_info(&pdev->dev, "EP93XX watchdog driver %s\n", - (val & 0x08) ? " (nCS1 disable detected)" : ""); + dev_info(dev, "EP93XX watchdog driver %s\n", + (val & 0x08) ? " (nCS1 disable detected)" : ""); return 0; } diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 021c6ace9462..041172e6c469 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -338,8 +338,11 @@ static int f71862fg_pin_configure(unsigned short ioaddr) static int watchdog_start(void) { + int err; + u8 tmp; + /* Make sure we don't die as soon as the watchdog is enabled below */ - int err = watchdog_keepalive(); + err = watchdog_keepalive(); if (err) return err; @@ -386,19 +389,18 @@ static int watchdog_start(void) break; case f81866: - /* Set pin 70 to WDTRST# */ - superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, - BIT(3) | BIT(0)); - superio_set_bit(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, - BIT(2)); /* * GPIO1 Control Register when 27h BIT3:2 = 01 & BIT0 = 0. * The PIN 70(GPIO15/WDTRST) is controlled by 2Ch: * BIT5: 0 -> WDTRST# * 1 -> GPIO15 */ - superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_GPIO1, - BIT(5)); + tmp = superio_inb(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL); + tmp &= ~(BIT(3) | BIT(0)); + tmp |= BIT(2); + superio_outb(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, tmp); + + superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_GPIO1, 5); break; default: diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c index a9c2912ee280..9ea0e56fa7ee 100644 --- a/drivers/watchdog/ftwdt010_wdt.c +++ b/drivers/watchdog/ftwdt010_wdt.c @@ -124,7 +124,6 @@ static const struct watchdog_info ftwdt010_wdt_info = { static int ftwdt010_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct ftwdt010_wdt *gwdt; unsigned int reg; int irq; @@ -134,8 +133,7 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev) if (!gwdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gwdt->base = devm_ioremap_resource(dev, res); + gwdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gwdt->base)) return PTR_ERR(gwdt->base); @@ -171,7 +169,7 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev) ret = devm_watchdog_register_device(dev, &gwdt->wdd); if (ret) { - dev_err(&pdev->dev, "failed to register watchdog\n"); + dev_err(dev, "failed to register watchdog\n"); return ret; } diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index ea77cae03c9d..bc24674b4d9e 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c @@ -154,25 +154,14 @@ static int gpio_wdt_probe(struct platform_device *pdev) priv->wdd.parent = dev; priv->wdd.timeout = SOFT_TIMEOUT_DEF; - watchdog_init_timeout(&priv->wdd, 0, &pdev->dev); + watchdog_init_timeout(&priv->wdd, 0, dev); watchdog_stop_on_reboot(&priv->wdd); if (priv->always_running) gpio_wdt_start(&priv->wdd); - ret = watchdog_register_device(&priv->wdd); - - return ret; -} - -static int gpio_wdt_remove(struct platform_device *pdev) -{ - struct gpio_wdt_priv *priv = platform_get_drvdata(pdev); - - watchdog_unregister_device(&priv->wdd); - - return 0; + return devm_watchdog_register_device(dev, &priv->wdd); } static const struct of_device_id gpio_wdt_dt_ids[] = { @@ -187,7 +176,6 @@ static struct platform_driver gpio_wdt_driver = { .of_match_table = gpio_wdt_dt_ids, }, .probe = gpio_wdt_probe, - .remove = gpio_wdt_remove, }; #ifdef CONFIG_GPIO_WATCHDOG_ARCH_INITCALL diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index ef30c7e9728d..db1bf6f546ae 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -311,8 +311,7 @@ static int hpwdt_init_one(struct pci_dev *dev, goto error_init_nmi_decoding; watchdog_set_nowayout(&hpwdt_dev, nowayout); - if (watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL)) - dev_warn(&dev->dev, "Invalid soft_margin: %d.\n", soft_margin); + watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL); if (pretimeout && hpwdt_dev.timeout <= PRETIMEOUT_SEC) { dev_warn(&dev->dev, "timeout <= pretimeout. Setting pretimeout to zero\n"); diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 950c71a8bb22..17941c03996b 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -311,10 +311,7 @@ static int esb_probe(struct pci_dev *pdev, edev->wdd.min_timeout = ESB_HEARTBEAT_MIN; edev->wdd.max_timeout = ESB_HEARTBEAT_MAX; edev->wdd.timeout = ESB_HEARTBEAT_DEFAULT; - if (watchdog_init_timeout(&edev->wdd, heartbeat, NULL)) - dev_info(&pdev->dev, - "heartbeat value must be " ESB_HEARTBEAT_RANGE - ", using %u\n", edev->wdd.timeout); + watchdog_init_timeout(&edev->wdd, heartbeat, NULL); watchdog_set_nowayout(&edev->wdd, nowayout); watchdog_stop_on_reboot(&edev->wdd); watchdog_stop_on_unregister(&edev->wdd); @@ -328,8 +325,8 @@ static int esb_probe(struct pci_dev *pdev, goto err_unmap; } dev_info(&pdev->dev, - "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", - edev->base, edev->wdd.timeout, nowayout); + "initialized. heartbeat=%d sec (nowayout=%d)\n", + edev->wdd.timeout, nowayout); return 0; err_unmap: diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 0a5318b7865e..89cea6ce9a08 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -545,6 +545,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) } watchdog_stop_on_reboot(&p->wddev); + watchdog_stop_on_unregister(&p->wddev); ret = devm_watchdog_register_device(dev, &p->wddev); if (ret != 0) { pr_err("cannot register watchdog device (err=%d)\n", ret); @@ -557,17 +558,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev) return 0; } -static int iTCO_wdt_remove(struct platform_device *pdev) -{ - struct iTCO_wdt_private *p = platform_get_drvdata(pdev); - - /* Stop the timer before we leave */ - if (!nowayout) - iTCO_wdt_stop(&p->wddev); - - return 0; -} - #ifdef CONFIG_PM_SLEEP /* * Suspend-to-idle requires this, because it stops the ticks and timekeeping, so @@ -620,7 +610,6 @@ static const struct dev_pm_ops iTCO_wdt_pm = { static struct platform_driver iTCO_wdt_driver = { .probe = iTCO_wdt_probe, - .remove = iTCO_wdt_remove, .driver = { .name = DRV_NAME, .pm = ITCO_WDT_PM_OPS, diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c index a3134ffa59f8..0fc31aadeee3 100644 --- a/drivers/watchdog/imgpdc_wdt.c +++ b/drivers/watchdog/imgpdc_wdt.c @@ -178,59 +178,69 @@ static const struct watchdog_ops pdc_wdt_ops = { .restart = pdc_wdt_restart, }; +static void pdc_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int pdc_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; u64 div; int ret, val; unsigned long clk_rate; - struct resource *res; struct pdc_wdt_dev *pdc_wdt; - pdc_wdt = devm_kzalloc(&pdev->dev, sizeof(*pdc_wdt), GFP_KERNEL); + pdc_wdt = devm_kzalloc(dev, sizeof(*pdc_wdt), GFP_KERNEL); if (!pdc_wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pdc_wdt->base = devm_ioremap_resource(&pdev->dev, res); + pdc_wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pdc_wdt->base)) return PTR_ERR(pdc_wdt->base); - pdc_wdt->sys_clk = devm_clk_get(&pdev->dev, "sys"); + pdc_wdt->sys_clk = devm_clk_get(dev, "sys"); if (IS_ERR(pdc_wdt->sys_clk)) { - dev_err(&pdev->dev, "failed to get the sys clock\n"); + dev_err(dev, "failed to get the sys clock\n"); return PTR_ERR(pdc_wdt->sys_clk); } - pdc_wdt->wdt_clk = devm_clk_get(&pdev->dev, "wdt"); + pdc_wdt->wdt_clk = devm_clk_get(dev, "wdt"); if (IS_ERR(pdc_wdt->wdt_clk)) { - dev_err(&pdev->dev, "failed to get the wdt clock\n"); + dev_err(dev, "failed to get the wdt clock\n"); return PTR_ERR(pdc_wdt->wdt_clk); } ret = clk_prepare_enable(pdc_wdt->sys_clk); if (ret) { - dev_err(&pdev->dev, "could not prepare or enable sys clock\n"); + dev_err(dev, "could not prepare or enable sys clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, pdc_clk_disable_unprepare, + pdc_wdt->sys_clk); + if (ret) + return ret; ret = clk_prepare_enable(pdc_wdt->wdt_clk); if (ret) { - dev_err(&pdev->dev, "could not prepare or enable wdt clock\n"); - goto disable_sys_clk; + dev_err(dev, "could not prepare or enable wdt clock\n"); + return ret; } + ret = devm_add_action_or_reset(dev, pdc_clk_disable_unprepare, + pdc_wdt->wdt_clk); + if (ret) + return ret; /* We use the clock rate to calculate the max timeout */ clk_rate = clk_get_rate(pdc_wdt->wdt_clk); if (clk_rate == 0) { - dev_err(&pdev->dev, "failed to get clock rate\n"); - ret = -EINVAL; - goto disable_wdt_clk; + dev_err(dev, "failed to get clock rate\n"); + return -EINVAL; } if (order_base_2(clk_rate) > PDC_WDT_CONFIG_DELAY_MASK + 1) { - dev_err(&pdev->dev, "invalid clock rate\n"); - ret = -EINVAL; - goto disable_wdt_clk; + dev_err(dev, "invalid clock rate\n"); + return -EINVAL; } if (order_base_2(clk_rate) == 0) @@ -245,10 +255,10 @@ static int pdc_wdt_probe(struct platform_device *pdev) do_div(div, clk_rate); pdc_wdt->wdt_dev.max_timeout = div; pdc_wdt->wdt_dev.timeout = PDC_WDT_DEF_TIMEOUT; - pdc_wdt->wdt_dev.parent = &pdev->dev; + pdc_wdt->wdt_dev.parent = dev; watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt); - watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, &pdev->dev); + watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, dev); pdc_wdt_stop(&pdc_wdt->wdt_dev); @@ -259,24 +269,22 @@ static int pdc_wdt_probe(struct platform_device *pdev) case PDC_WDT_TICKLE_STATUS_TICKLE: case PDC_WDT_TICKLE_STATUS_TIMEOUT: pdc_wdt->wdt_dev.bootstatus |= WDIOF_CARDRESET; - dev_info(&pdev->dev, - "watchdog module last reset due to timeout\n"); + dev_info(dev, "watchdog module last reset due to timeout\n"); break; case PDC_WDT_TICKLE_STATUS_HRESET: - dev_info(&pdev->dev, + dev_info(dev, "watchdog module last reset due to hard reset\n"); break; case PDC_WDT_TICKLE_STATUS_SRESET: - dev_info(&pdev->dev, + dev_info(dev, "watchdog module last reset due to soft reset\n"); break; case PDC_WDT_TICKLE_STATUS_USER: - dev_info(&pdev->dev, + dev_info(dev, "watchdog module last reset due to user reset\n"); break; default: - dev_info(&pdev->dev, - "contains an illegal status code (%08x)\n", val); + dev_info(dev, "contains an illegal status code (%08x)\n", val); break; } @@ -285,36 +293,9 @@ static int pdc_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pdc_wdt); - ret = watchdog_register_device(&pdc_wdt->wdt_dev); - if (ret) - goto disable_wdt_clk; - - return 0; - -disable_wdt_clk: - clk_disable_unprepare(pdc_wdt->wdt_clk); -disable_sys_clk: - clk_disable_unprepare(pdc_wdt->sys_clk); - return ret; -} - -static void pdc_wdt_shutdown(struct platform_device *pdev) -{ - struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev); - - pdc_wdt_stop(&pdc_wdt->wdt_dev); -} - -static int pdc_wdt_remove(struct platform_device *pdev) -{ - struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev); - - pdc_wdt_stop(&pdc_wdt->wdt_dev); - watchdog_unregister_device(&pdc_wdt->wdt_dev); - clk_disable_unprepare(pdc_wdt->wdt_clk); - clk_disable_unprepare(pdc_wdt->sys_clk); - - return 0; + watchdog_stop_on_reboot(&pdc_wdt->wdt_dev); + watchdog_stop_on_unregister(&pdc_wdt->wdt_dev); + return devm_watchdog_register_device(dev, &pdc_wdt->wdt_dev); } static const struct of_device_id pdc_wdt_match[] = { @@ -329,8 +310,6 @@ static struct platform_driver pdc_wdt_driver = { .of_match_table = pdc_wdt_match, }, .probe = pdc_wdt_probe, - .remove = pdc_wdt_remove, - .shutdown = pdc_wdt_shutdown, }; module_platform_driver(pdc_wdt_driver); diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 2b52514eaa86..a606005dd65f 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -178,8 +178,10 @@ static void __imx2_wdt_set_timeout(struct watchdog_device *wdog, static int imx2_wdt_set_timeout(struct watchdog_device *wdog, unsigned int new_timeout) { - __imx2_wdt_set_timeout(wdog, new_timeout); + unsigned int actual; + actual = min(new_timeout, wdog->max_hw_heartbeat_ms * 1000); + __imx2_wdt_set_timeout(wdog, actual); wdog->timeout = new_timeout; return 0; } @@ -247,7 +249,6 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) { struct imx2_wdt_device *wdev; struct watchdog_device *wdog; - struct resource *res; void __iomem *base; int ret; u32 val; @@ -256,8 +257,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (!wdev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c new file mode 100644 index 000000000000..49848b66186c --- /dev/null +++ b/drivers/watchdog/imx_sc_wdt.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018-2019 NXP. + */ + +#include <linux/arm-smccc.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reboot.h> +#include <linux/watchdog.h> + +#define DEFAULT_TIMEOUT 60 +/* + * Software timer tick implemented in scfw side, support 10ms to 0xffffffff ms + * in theory, but for normal case, 1s~128s is enough, you can change this max + * value in case it's not enough. + */ +#define MAX_TIMEOUT 128 + +#define IMX_SIP_TIMER 0xC2000002 +#define IMX_SIP_TIMER_START_WDOG 0x01 +#define IMX_SIP_TIMER_STOP_WDOG 0x02 +#define IMX_SIP_TIMER_SET_WDOG_ACT 0x03 +#define IMX_SIP_TIMER_PING_WDOG 0x04 +#define IMX_SIP_TIMER_SET_TIMEOUT_WDOG 0x05 +#define IMX_SIP_TIMER_GET_WDOG_STAT 0x06 +#define IMX_SIP_TIMER_SET_PRETIME_WDOG 0x07 + +#define SC_TIMER_WDOG_ACTION_PARTITION 0 + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0000); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int imx_sc_wdt_ping(struct watchdog_device *wdog) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_PING_WDOG, + 0, 0, 0, 0, 0, 0, &res); + + return 0; +} + +static int imx_sc_wdt_start(struct watchdog_device *wdog) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_START_WDOG, + 0, 0, 0, 0, 0, 0, &res); + if (res.a0) + return -EACCES; + + arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_WDOG_ACT, + SC_TIMER_WDOG_ACTION_PARTITION, + 0, 0, 0, 0, 0, &res); + return res.a0 ? -EACCES : 0; +} + +static int imx_sc_wdt_stop(struct watchdog_device *wdog) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_STOP_WDOG, + 0, 0, 0, 0, 0, 0, &res); + + return res.a0 ? -EACCES : 0; +} + +static int imx_sc_wdt_set_timeout(struct watchdog_device *wdog, + unsigned int timeout) +{ + struct arm_smccc_res res; + + wdog->timeout = timeout; + arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_TIMEOUT_WDOG, + timeout * 1000, 0, 0, 0, 0, 0, &res); + + return res.a0 ? -EACCES : 0; +} + +static const struct watchdog_ops imx_sc_wdt_ops = { + .owner = THIS_MODULE, + .start = imx_sc_wdt_start, + .stop = imx_sc_wdt_stop, + .ping = imx_sc_wdt_ping, + .set_timeout = imx_sc_wdt_set_timeout, +}; + +static const struct watchdog_info imx_sc_wdt_info = { + .identity = "i.MX SC watchdog timer", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE | WDIOF_PRETIMEOUT, +}; + +static int imx_sc_wdt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct watchdog_device *imx_sc_wdd; + int ret; + + imx_sc_wdd = devm_kzalloc(dev, sizeof(*imx_sc_wdd), GFP_KERNEL); + if (!imx_sc_wdd) + return -ENOMEM; + + platform_set_drvdata(pdev, imx_sc_wdd); + + imx_sc_wdd->info = &imx_sc_wdt_info; + imx_sc_wdd->ops = &imx_sc_wdt_ops; + imx_sc_wdd->min_timeout = 1; + imx_sc_wdd->max_timeout = MAX_TIMEOUT; + imx_sc_wdd->parent = dev; + imx_sc_wdd->timeout = DEFAULT_TIMEOUT; + + watchdog_init_timeout(imx_sc_wdd, 0, dev); + watchdog_stop_on_reboot(imx_sc_wdd); + watchdog_stop_on_unregister(imx_sc_wdd); + + ret = devm_watchdog_register_device(dev, imx_sc_wdd); + if (ret) { + dev_err(dev, "Failed to register watchdog device\n"); + return ret; + } + + return 0; +} + +static int __maybe_unused imx_sc_wdt_suspend(struct device *dev) +{ + struct watchdog_device *imx_sc_wdd = dev_get_drvdata(dev); + + if (watchdog_active(imx_sc_wdd)) + imx_sc_wdt_stop(imx_sc_wdd); + + return 0; +} + +static int __maybe_unused imx_sc_wdt_resume(struct device *dev) +{ + struct watchdog_device *imx_sc_wdd = dev_get_drvdata(dev); + + if (watchdog_active(imx_sc_wdd)) + imx_sc_wdt_start(imx_sc_wdd); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(imx_sc_wdt_pm_ops, + imx_sc_wdt_suspend, imx_sc_wdt_resume); + +static const struct of_device_id imx_sc_wdt_dt_ids[] = { + { .compatible = "fsl,imx-sc-wdt", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_sc_wdt_dt_ids); + +static struct platform_driver imx_sc_wdt_driver = { + .probe = imx_sc_wdt_probe, + .driver = { + .name = "imx-sc-wdt", + .of_match_table = imx_sc_wdt_dt_ids, + .pm = &imx_sc_wdt_pm_ops, + }, +}; +module_platform_driver(imx_sc_wdt_driver); + +MODULE_AUTHOR("Robin Gong <yibin.gong@nxp.com>"); +MODULE_DESCRIPTION("NXP i.MX system controller watchdog driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 72c108a12c19..6cf7cc1ff615 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -110,12 +110,13 @@ static const struct watchdog_ops mid_wdt_ops = { static int mid_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct watchdog_device *wdt_dev; - struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data; + struct intel_mid_wdt_pdata *pdata = dev->platform_data; int ret; if (!pdata) { - dev_err(&pdev->dev, "missing platform data\n"); + dev_err(dev, "missing platform data\n"); return -EINVAL; } @@ -125,7 +126,7 @@ static int mid_wdt_probe(struct platform_device *pdev) return ret; } - wdt_dev = devm_kzalloc(&pdev->dev, sizeof(*wdt_dev), GFP_KERNEL); + wdt_dev = devm_kzalloc(dev, sizeof(*wdt_dev), GFP_KERNEL); if (!wdt_dev) return -ENOMEM; @@ -134,16 +135,15 @@ static int mid_wdt_probe(struct platform_device *pdev) wdt_dev->min_timeout = MID_WDT_TIMEOUT_MIN; wdt_dev->max_timeout = MID_WDT_TIMEOUT_MAX; wdt_dev->timeout = MID_WDT_DEFAULT_TIMEOUT; - wdt_dev->parent = &pdev->dev; + wdt_dev->parent = dev; - watchdog_set_drvdata(wdt_dev, &pdev->dev); + watchdog_set_drvdata(wdt_dev, dev); - ret = devm_request_irq(&pdev->dev, pdata->irq, mid_wdt_irq, + ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog", wdt_dev); if (ret) { - dev_err(&pdev->dev, "error requesting warning irq %d\n", - pdata->irq); + dev_err(dev, "error requesting warning irq %d\n", pdata->irq); return ret; } @@ -163,13 +163,13 @@ static int mid_wdt_probe(struct platform_device *pdev) /* Make sure the watchdog is serviced */ set_bit(WDOG_HW_RUNNING, &wdt_dev->status); - ret = devm_watchdog_register_device(&pdev->dev, wdt_dev); + ret = devm_watchdog_register_device(dev, wdt_dev); if (ret) { - dev_err(&pdev->dev, "error registering watchdog device\n"); + dev_err(dev, "error registering watchdog device\n"); return ret; } - dev_info(&pdev->dev, "Intel MID watchdog device probed\n"); + dev_info(dev, "Intel MID watchdog device probed\n"); return 0; } diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 3181a72c7ddf..f7baf75d38c0 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -25,7 +25,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/compiler.h> -#include <linux/module.h> #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/types.h> @@ -224,7 +223,7 @@ static int intel_scu_set_heartbeat(u32 t) watchdog_device.timer_tbl_ptr->freq_hz); pr_debug("set_heartbeat: timer_set is %x (hex)\n", watchdog_device.timer_set); - pr_debug("set_hearbeat: timer_margin is %x (hex)\n", timer_margin); + pr_debug("set_heartbeat: timer_margin is %x (hex)\n", timer_margin); pr_debug("set_heartbeat: threshold is %x (hex)\n", watchdog_device.threshold); pr_debug("set_heartbeat: soft_threshold is %x (hex)\n", @@ -545,21 +544,4 @@ register_reboot_error: iounmap(watchdog_device.timer_load_count_addr); return ret; } - -static void __exit intel_scu_watchdog_exit(void) -{ - - misc_deregister(&watchdog_device.miscdev); - unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); - /* disable the timer */ - iowrite32(0x00000002, watchdog_device.timer_control_addr); - iounmap(watchdog_device.timer_load_count_addr); -} - late_initcall(intel_scu_watchdog_init); -module_exit(intel_scu_watchdog_exit); - -MODULE_AUTHOR("Intel Corporation"); -MODULE_DESCRIPTION("Intel SCU Watchdog Device Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(WDT_VER); diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index ec4d99a830ba..d1bc7cbd4f2b 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -163,12 +163,12 @@ MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches); static int jz4740_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct jz4740_wdt_drvdata *drvdata; struct watchdog_device *jz4740_wdt; - struct resource *res; int ret; - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct jz4740_wdt_drvdata), + drvdata = devm_kzalloc(dev, sizeof(struct jz4740_wdt_drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -182,27 +182,24 @@ static int jz4740_wdt_probe(struct platform_device *pdev) jz4740_wdt->timeout = heartbeat; jz4740_wdt->min_timeout = 1; jz4740_wdt->max_timeout = MAX_HEARTBEAT; - jz4740_wdt->parent = &pdev->dev; + jz4740_wdt->parent = dev; watchdog_set_nowayout(jz4740_wdt, nowayout); watchdog_set_drvdata(jz4740_wdt, drvdata); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->base = devm_ioremap_resource(&pdev->dev, res); + drvdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); - drvdata->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); + drvdata->rtc_clk = devm_clk_get(dev, "rtc"); if (IS_ERR(drvdata->rtc_clk)) { - dev_err(&pdev->dev, "cannot find RTC clock\n"); + dev_err(dev, "cannot find RTC clock\n"); return PTR_ERR(drvdata->rtc_clk); } - ret = devm_watchdog_register_device(&pdev->dev, &drvdata->wdt); + ret = devm_watchdog_register_device(dev, &drvdata->wdt); if (ret < 0) return ret; - platform_set_drvdata(pdev, drvdata); - return 0; } diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c index e268add43010..543eb0f27a42 100644 --- a/drivers/watchdog/kempld_wdt.c +++ b/drivers/watchdog/kempld_wdt.c @@ -467,7 +467,7 @@ static int kempld_wdt_probe(struct platform_device *pdev) KEMPLD_WDT_CFG_GLOBAL_LOCK)) { if (!nowayout) dev_warn(dev, - "Forcing nowayout - watchdog lock enabled!\n"); + "Forcing nowayout - watchdog lock enabled!\n"); nowayout = true; } @@ -492,7 +492,9 @@ static int kempld_wdt_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, wdt_data); - ret = watchdog_register_device(wdd); + watchdog_stop_on_reboot(wdd); + watchdog_stop_on_unregister(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) return ret; @@ -501,26 +503,6 @@ static int kempld_wdt_probe(struct platform_device *pdev) return 0; } -static void kempld_wdt_shutdown(struct platform_device *pdev) -{ - struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); - - kempld_wdt_stop(&wdt_data->wdd); -} - -static int kempld_wdt_remove(struct platform_device *pdev) -{ - struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); - struct watchdog_device *wdd = &wdt_data->wdd; - int ret = 0; - - if (!nowayout) - ret = kempld_wdt_stop(wdd); - watchdog_unregister_device(wdd); - - return ret; -} - #ifdef CONFIG_PM /* Disable watchdog if it is active during suspend */ static int kempld_wdt_suspend(struct platform_device *pdev, @@ -567,8 +549,6 @@ static struct platform_driver kempld_wdt_driver = { .name = "kempld-wdt", }, .probe = kempld_wdt_probe, - .remove = kempld_wdt_remove, - .shutdown = kempld_wdt_shutdown, .suspend = kempld_wdt_suspend, .resume = kempld_wdt_resume, }; diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c index 83da84d6074b..4caf02ba5d49 100644 --- a/drivers/watchdog/lantiq_wdt.c +++ b/drivers/watchdog/lantiq_wdt.c @@ -203,7 +203,6 @@ static int ltq_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct ltq_wdt_priv *priv; struct watchdog_device *wdt; - struct resource *res; struct clk *clk; const struct ltq_wdt_hw *ltq_wdt_hw; int ret; @@ -213,8 +212,7 @@ static int ltq_wdt_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->membase = devm_ioremap_resource(dev, res); + priv->membase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->membase)) return PTR_ERR(priv->membase); diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c index 3aee50c64a36..d8075e2affa7 100644 --- a/drivers/watchdog/loongson1_wdt.c +++ b/drivers/watchdog/loongson1_wdt.c @@ -83,38 +83,44 @@ static const struct watchdog_ops ls1x_wdt_ops = { .set_timeout = ls1x_wdt_set_timeout, }; +static void ls1x_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int ls1x_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct ls1x_wdt_drvdata *drvdata; struct watchdog_device *ls1x_wdt; unsigned long clk_rate; - struct resource *res; int err; - drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->base = devm_ioremap_resource(&pdev->dev, res); + drvdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); - drvdata->clk = devm_clk_get(&pdev->dev, pdev->name); + drvdata->clk = devm_clk_get(dev, pdev->name); if (IS_ERR(drvdata->clk)) return PTR_ERR(drvdata->clk); err = clk_prepare_enable(drvdata->clk); if (err) { - dev_err(&pdev->dev, "clk enable failed\n"); + dev_err(dev, "clk enable failed\n"); return err; } + err = devm_add_action_or_reset(dev, ls1x_clk_disable_unprepare, + drvdata->clk); + if (err) + return err; clk_rate = clk_get_rate(drvdata->clk); - if (!clk_rate) { - err = -EINVAL; - goto err0; - } + if (!clk_rate) + return -EINVAL; drvdata->clk_rate = clk_rate; ls1x_wdt = &drvdata->wdt; @@ -123,41 +129,27 @@ static int ls1x_wdt_probe(struct platform_device *pdev) ls1x_wdt->timeout = DEFAULT_HEARTBEAT; ls1x_wdt->min_timeout = 1; ls1x_wdt->max_hw_heartbeat_ms = U32_MAX / clk_rate * 1000; - ls1x_wdt->parent = &pdev->dev; + ls1x_wdt->parent = dev; - watchdog_init_timeout(ls1x_wdt, heartbeat, &pdev->dev); + watchdog_init_timeout(ls1x_wdt, heartbeat, dev); watchdog_set_nowayout(ls1x_wdt, nowayout); watchdog_set_drvdata(ls1x_wdt, drvdata); - err = watchdog_register_device(&drvdata->wdt); + err = devm_watchdog_register_device(dev, &drvdata->wdt); if (err) { - dev_err(&pdev->dev, "failed to register watchdog device\n"); - goto err0; + dev_err(dev, "failed to register watchdog device\n"); + return err; } platform_set_drvdata(pdev, drvdata); - dev_info(&pdev->dev, "Loongson1 Watchdog driver registered\n"); - - return 0; -err0: - clk_disable_unprepare(drvdata->clk); - return err; -} - -static int ls1x_wdt_remove(struct platform_device *pdev) -{ - struct ls1x_wdt_drvdata *drvdata = platform_get_drvdata(pdev); - - watchdog_unregister_device(&drvdata->wdt); - clk_disable_unprepare(drvdata->clk); + dev_info(dev, "Loongson1 Watchdog driver registered\n"); return 0; } static struct platform_driver ls1x_wdt_driver = { .probe = ls1x_wdt_probe, - .remove = ls1x_wdt_remove, .driver = { .name = "ls1x-wdt", }, diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c index 331cadb459ac..0e82abd71d35 100644 --- a/drivers/watchdog/lpc18xx_wdt.c +++ b/drivers/watchdog/lpc18xx_wdt.c @@ -200,19 +200,22 @@ static const struct watchdog_ops lpc18xx_wdt_ops = { .restart = lpc18xx_wdt_restart, }; +static void lpc18xx_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int lpc18xx_wdt_probe(struct platform_device *pdev) { struct lpc18xx_wdt_dev *lpc18xx_wdt; struct device *dev = &pdev->dev; - struct resource *res; int ret; lpc18xx_wdt = devm_kzalloc(dev, sizeof(*lpc18xx_wdt), GFP_KERNEL); if (!lpc18xx_wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - lpc18xx_wdt->base = devm_ioremap_resource(dev, res); + lpc18xx_wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(lpc18xx_wdt->base)) return PTR_ERR(lpc18xx_wdt->base); @@ -233,19 +236,26 @@ static int lpc18xx_wdt_probe(struct platform_device *pdev) dev_err(dev, "could not prepare or enable sys clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, lpc18xx_clk_disable_unprepare, + lpc18xx_wdt->reg_clk); + if (ret) + return ret; ret = clk_prepare_enable(lpc18xx_wdt->wdt_clk); if (ret) { dev_err(dev, "could not prepare or enable wdt clock\n"); - goto disable_reg_clk; + return ret; } + ret = devm_add_action_or_reset(dev, lpc18xx_clk_disable_unprepare, + lpc18xx_wdt->wdt_clk); + if (ret) + return ret; /* We use the clock rate to calculate timeouts */ lpc18xx_wdt->clk_rate = clk_get_rate(lpc18xx_wdt->wdt_clk); if (lpc18xx_wdt->clk_rate == 0) { dev_err(dev, "failed to get clock rate\n"); - ret = -EINVAL; - goto disable_wdt_clk; + return -EINVAL; } lpc18xx_wdt->wdt_dev.info = &lpc18xx_wdt_info; @@ -276,24 +286,8 @@ static int lpc18xx_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, lpc18xx_wdt); - ret = watchdog_register_device(&lpc18xx_wdt->wdt_dev); - if (ret) - goto disable_wdt_clk; - - return 0; - -disable_wdt_clk: - clk_disable_unprepare(lpc18xx_wdt->wdt_clk); -disable_reg_clk: - clk_disable_unprepare(lpc18xx_wdt->reg_clk); - return ret; -} - -static void lpc18xx_wdt_shutdown(struct platform_device *pdev) -{ - struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); - - lpc18xx_wdt_stop(&lpc18xx_wdt->wdt_dev); + watchdog_stop_on_reboot(&lpc18xx_wdt->wdt_dev); + return devm_watchdog_register_device(dev, &lpc18xx_wdt->wdt_dev); } static int lpc18xx_wdt_remove(struct platform_device *pdev) @@ -303,10 +297,6 @@ static int lpc18xx_wdt_remove(struct platform_device *pdev) dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); del_timer(&lpc18xx_wdt->timer); - watchdog_unregister_device(&lpc18xx_wdt->wdt_dev); - clk_disable_unprepare(lpc18xx_wdt->wdt_clk); - clk_disable_unprepare(lpc18xx_wdt->reg_clk); - return 0; } @@ -323,7 +313,6 @@ static struct platform_driver lpc18xx_wdt_driver = { }, .probe = lpc18xx_wdt_probe, .remove = lpc18xx_wdt_remove, - .shutdown = lpc18xx_wdt_shutdown, }; module_platform_driver(lpc18xx_wdt_driver); diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 53759415cf06..c0c9e948adbc 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -177,6 +177,7 @@ static inline void zf_set_timer(unsigned short new, unsigned char n) switch (n) { case WD1: zf_writew(COUNTER_1, new); + /* fall through */ case WD2: zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); default: @@ -318,7 +319,7 @@ static long zf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: - zf_ping(0); + zf_ping(NULL); break; default: return -ENOTTY; diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index bf6a068245ba..3a899628a834 100644 --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c @@ -187,9 +187,7 @@ static void max63xx_mmap_set(struct max63xx_wdt *wdt, u8 set) static int max63xx_mmap_init(struct platform_device *p, struct max63xx_wdt *wdt) { - struct resource *mem = platform_get_resource(p, IORESOURCE_MEM, 0); - - wdt->base = devm_ioremap_resource(&p->dev, mem); + wdt->base = devm_platform_ioremap_resource(p, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); @@ -202,11 +200,12 @@ static int max63xx_mmap_init(struct platform_device *p, struct max63xx_wdt *wdt) static int max63xx_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct max63xx_wdt *wdt; struct max63xx_timeout *table; int err; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -217,7 +216,7 @@ static int max63xx_wdt_probe(struct platform_device *pdev) wdt->timeout = max63xx_select_timeout(table, heartbeat); if (!wdt->timeout) { - dev_err(&pdev->dev, "unable to satisfy %ds heartbeat request\n", + dev_err(dev, "unable to satisfy %ds heartbeat request\n", heartbeat); return -EINVAL; } @@ -229,30 +228,22 @@ static int max63xx_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &wdt->wdd); watchdog_set_drvdata(&wdt->wdd, wdt); - wdt->wdd.parent = &pdev->dev; + wdt->wdd.parent = dev; wdt->wdd.timeout = wdt->timeout->twd; wdt->wdd.info = &max63xx_wdt_info; wdt->wdd.ops = &max63xx_wdt_ops; watchdog_set_nowayout(&wdt->wdd, nowayout); - err = watchdog_register_device(&wdt->wdd); + err = devm_watchdog_register_device(dev, &wdt->wdd); if (err) return err; - dev_info(&pdev->dev, "using %ds heartbeat with %ds initial delay\n", + dev_info(dev, "using %ds heartbeat with %ds initial delay\n", wdt->timeout->twd, wdt->timeout->tdelay); return 0; } -static int max63xx_wdt_remove(struct platform_device *pdev) -{ - struct watchdog_device *wdd = platform_get_drvdata(pdev); - - watchdog_unregister_device(wdd); - return 0; -} - static const struct platform_device_id max63xx_id_table[] = { { "max6369_wdt", (kernel_ulong_t)max6369_table, }, { "max6370_wdt", (kernel_ulong_t)max6369_table, }, @@ -266,7 +257,6 @@ MODULE_DEVICE_TABLE(platform, max63xx_id_table); static struct platform_driver max63xx_wdt_driver = { .probe = max63xx_wdt_probe, - .remove = max63xx_wdt_remove, .id_table = max63xx_id_table, .driver = { .name = "max63xx_wdt", diff --git a/drivers/watchdog/max77620_wdt.c b/drivers/watchdog/max77620_wdt.c index 70c9cd3ba938..3ca6b9337932 100644 --- a/drivers/watchdog/max77620_wdt.c +++ b/drivers/watchdog/max77620_wdt.c @@ -112,17 +112,18 @@ static const struct watchdog_ops max77620_wdt_ops = { static int max77620_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct max77620_wdt *wdt; struct watchdog_device *wdt_dev; unsigned int regval; int ret; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - wdt->dev = &pdev->dev; - wdt->rmap = dev_get_regmap(pdev->dev.parent, NULL); + wdt->dev = dev; + wdt->rmap = dev_get_regmap(dev->parent, NULL); if (!wdt->rmap) { dev_err(wdt->dev, "Failed to get parent regmap\n"); return -ENODEV; @@ -183,25 +184,16 @@ static int max77620_wdt_probe(struct platform_device *pdev) watchdog_set_nowayout(wdt_dev, nowayout); watchdog_set_drvdata(wdt_dev, wdt); - ret = watchdog_register_device(wdt_dev); + watchdog_stop_on_unregister(wdt_dev); + ret = devm_watchdog_register_device(dev, wdt_dev); if (ret < 0) { - dev_err(&pdev->dev, "watchdog registration failed: %d\n", ret); + dev_err(dev, "watchdog registration failed: %d\n", ret); return ret; } return 0; } -static int max77620_wdt_remove(struct platform_device *pdev) -{ - struct max77620_wdt *wdt = platform_get_drvdata(pdev); - - max77620_wdt_stop(&wdt->wdt_dev); - watchdog_unregister_device(&wdt->wdt_dev); - - return 0; -} - static const struct platform_device_id max77620_wdt_devtype[] = { { .name = "max77620-watchdog", }, { }, @@ -213,7 +205,6 @@ static struct platform_driver max77620_wdt_driver = { .name = "max77620-watchdog", }, .probe = max77620_wdt_probe, - .remove = max77620_wdt_remove, .id_table = max77620_wdt_devtype, }; diff --git a/drivers/watchdog/mena21_wdt.c b/drivers/watchdog/mena21_wdt.c index 6db69883ece6..e9ca4e0e25dc 100644 --- a/drivers/watchdog/mena21_wdt.c +++ b/drivers/watchdog/mena21_wdt.c @@ -127,19 +127,20 @@ static struct watchdog_device a21_wdt = { static int a21_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct a21_wdt_drv *drv; unsigned int reset = 0; int num_gpios; int ret; int i; - drv = devm_kzalloc(&pdev->dev, sizeof(struct a21_wdt_drv), GFP_KERNEL); + drv = devm_kzalloc(dev, sizeof(struct a21_wdt_drv), GFP_KERNEL); if (!drv) return -ENOMEM; - num_gpios = gpiod_count(&pdev->dev, NULL); + num_gpios = gpiod_count(dev, NULL); if (num_gpios != NUM_GPIOS) { - dev_err(&pdev->dev, "gpios DT property wrong, got %d want %d", + dev_err(dev, "gpios DT property wrong, got %d want %d", num_gpios, NUM_GPIOS); return -ENODEV; } @@ -152,12 +153,9 @@ static int a21_wdt_probe(struct platform_device *pdev) gflags = GPIOD_ASIS; else gflags = GPIOD_IN; - drv->gpios[i] = devm_gpiod_get_index(&pdev->dev, NULL, i, - gflags); - if (IS_ERR(drv->gpios[i])) { - ret = PTR_ERR(drv->gpios[i]); - return ret; - } + drv->gpios[i] = devm_gpiod_get_index(dev, NULL, i, gflags); + if (IS_ERR(drv->gpios[i])) + return PTR_ERR(drv->gpios[i]); gpiod_set_consumer_name(drv->gpios[i], "MEN A21 Watchdog"); @@ -173,10 +171,10 @@ static int a21_wdt_probe(struct platform_device *pdev) } } - watchdog_init_timeout(&a21_wdt, 30, &pdev->dev); + watchdog_init_timeout(&a21_wdt, 30, dev); watchdog_set_nowayout(&a21_wdt, nowayout); watchdog_set_drvdata(&a21_wdt, drv); - a21_wdt.parent = &pdev->dev; + a21_wdt.parent = dev; reset = a21_wdt_get_bootstatus(drv); if (reset == 2) @@ -189,15 +187,15 @@ static int a21_wdt_probe(struct platform_device *pdev) a21_wdt.bootstatus |= WDIOF_EXTERN2; drv->wdt = a21_wdt; - dev_set_drvdata(&pdev->dev, drv); + dev_set_drvdata(dev, drv); - ret = devm_watchdog_register_device(&pdev->dev, &a21_wdt); + ret = devm_watchdog_register_device(dev, &a21_wdt); if (ret) { - dev_err(&pdev->dev, "Cannot register watchdog device\n"); + dev_err(dev, "Cannot register watchdog device\n"); return ret; } - dev_info(&pdev->dev, "MEN A21 watchdog timer driver enabled\n"); + dev_info(dev, "MEN A21 watchdog timer driver enabled\n"); return 0; } diff --git a/drivers/watchdog/menf21bmc_wdt.c b/drivers/watchdog/menf21bmc_wdt.c index 3aefddebb386..b1dbff553cdc 100644 --- a/drivers/watchdog/menf21bmc_wdt.c +++ b/drivers/watchdog/menf21bmc_wdt.c @@ -117,12 +117,12 @@ static const struct watchdog_ops menf21bmc_wdt_ops = { static int menf21bmc_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret, bmc_timeout; struct menf21bmc_wdt *drv_data; - struct i2c_client *i2c_client = to_i2c_client(pdev->dev.parent); + struct i2c_client *i2c_client = to_i2c_client(dev->parent); - drv_data = devm_kzalloc(&pdev->dev, - sizeof(struct menf21bmc_wdt), GFP_KERNEL); + drv_data = devm_kzalloc(dev, sizeof(struct menf21bmc_wdt), GFP_KERNEL); if (!drv_data) return -ENOMEM; @@ -130,7 +130,7 @@ static int menf21bmc_wdt_probe(struct platform_device *pdev) drv_data->wdt.info = &menf21bmc_wdt_info; drv_data->wdt.min_timeout = BMC_WD_TIMEOUT_MIN; drv_data->wdt.max_timeout = BMC_WD_TIMEOUT_MAX; - drv_data->wdt.parent = &pdev->dev; + drv_data->wdt.parent = dev; drv_data->i2c_client = i2c_client; /* @@ -140,40 +140,28 @@ static int menf21bmc_wdt_probe(struct platform_device *pdev) bmc_timeout = i2c_smbus_read_word_data(drv_data->i2c_client, BMC_CMD_WD_TIME); if (bmc_timeout < 0) { - dev_err(&pdev->dev, "failed to get current WDT timeout\n"); + dev_err(dev, "failed to get current WDT timeout\n"); return bmc_timeout; } - watchdog_init_timeout(&drv_data->wdt, bmc_timeout / 10, &pdev->dev); + watchdog_init_timeout(&drv_data->wdt, bmc_timeout / 10, dev); watchdog_set_nowayout(&drv_data->wdt, nowayout); watchdog_set_drvdata(&drv_data->wdt, drv_data); platform_set_drvdata(pdev, drv_data); ret = menf21bmc_wdt_set_bootstatus(drv_data); if (ret < 0) { - dev_err(&pdev->dev, "failed to set Watchdog bootstatus\n"); + dev_err(dev, "failed to set Watchdog bootstatus\n"); return ret; } - ret = watchdog_register_device(&drv_data->wdt); + ret = devm_watchdog_register_device(dev, &drv_data->wdt); if (ret) { - dev_err(&pdev->dev, "failed to register Watchdog device\n"); + dev_err(dev, "failed to register Watchdog device\n"); return ret; } - dev_info(&pdev->dev, "MEN 14F021P00 BMC Watchdog device enabled\n"); - - return 0; -} - -static int menf21bmc_wdt_remove(struct platform_device *pdev) -{ - struct menf21bmc_wdt *drv_data = platform_get_drvdata(pdev); - - dev_warn(&pdev->dev, - "Unregister MEN 14F021P00 BMC Watchdog device, board may reset\n"); - - watchdog_unregister_device(&drv_data->wdt); + dev_info(dev, "MEN 14F021P00 BMC Watchdog device enabled\n"); return 0; } @@ -191,7 +179,6 @@ static struct platform_driver menf21bmc_wdt = { .name = DEVNAME, }, .probe = menf21bmc_wdt_probe, - .remove = menf21bmc_wdt_remove, .shutdown = menf21bmc_wdt_shutdown, }; diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c index 69adeab3fde7..d17c1a6ed723 100644 --- a/drivers/watchdog/meson_gxbb_wdt.c +++ b/drivers/watchdog/meson_gxbb_wdt.c @@ -136,32 +136,40 @@ static const struct of_device_id meson_gxbb_wdt_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, meson_gxbb_wdt_dt_ids); +static void meson_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int meson_gxbb_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct meson_gxbb_wdt *data; - struct resource *res; int ret; - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->reg_base = devm_ioremap_resource(&pdev->dev, res); + data->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->reg_base)) return PTR_ERR(data->reg_base); - data->clk = devm_clk_get(&pdev->dev, NULL); + data->clk = devm_clk_get(dev, NULL); if (IS_ERR(data->clk)) return PTR_ERR(data->clk); ret = clk_prepare_enable(data->clk); if (ret) return ret; + ret = devm_add_action_or_reset(dev, meson_clk_disable_unprepare, + data->clk); + if (ret) + return ret; platform_set_drvdata(pdev, data); - data->wdt_dev.parent = &pdev->dev; + data->wdt_dev.parent = dev; data->wdt_dev.info = &meson_gxbb_wdt_info; data->wdt_dev.ops = &meson_gxbb_wdt_ops; data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK; @@ -178,37 +186,12 @@ static int meson_gxbb_wdt_probe(struct platform_device *pdev) meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout); - ret = watchdog_register_device(&data->wdt_dev); - if (ret) { - clk_disable_unprepare(data->clk); - return ret; - } - - return 0; -} - -static int meson_gxbb_wdt_remove(struct platform_device *pdev) -{ - struct meson_gxbb_wdt *data = platform_get_drvdata(pdev); - - watchdog_unregister_device(&data->wdt_dev); - - clk_disable_unprepare(data->clk); - - return 0; -} - -static void meson_gxbb_wdt_shutdown(struct platform_device *pdev) -{ - struct meson_gxbb_wdt *data = platform_get_drvdata(pdev); - - meson_gxbb_wdt_stop(&data->wdt_dev); + watchdog_stop_on_reboot(&data->wdt_dev); + return devm_watchdog_register_device(dev, &data->wdt_dev); } static struct platform_driver meson_gxbb_wdt_driver = { .probe = meson_gxbb_wdt_probe, - .remove = meson_gxbb_wdt_remove, - .shutdown = meson_gxbb_wdt_shutdown, .driver = { .name = "meson-gxbb-wdt", .pm = &meson_gxbb_wdt_pm_ops, diff --git a/drivers/watchdog/meson_wdt.c b/drivers/watchdog/meson_wdt.c index cd0275a6cdac..01889cef81e1 100644 --- a/drivers/watchdog/meson_wdt.c +++ b/drivers/watchdog/meson_wdt.c @@ -164,28 +164,27 @@ MODULE_DEVICE_TABLE(of, meson_wdt_dt_ids); static int meson_wdt_probe(struct platform_device *pdev) { - struct resource *res; + struct device *dev = &pdev->dev; struct meson_wdt_dev *meson_wdt; const struct of_device_id *of_id; int err; - meson_wdt = devm_kzalloc(&pdev->dev, sizeof(*meson_wdt), GFP_KERNEL); + meson_wdt = devm_kzalloc(dev, sizeof(*meson_wdt), GFP_KERNEL); if (!meson_wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - meson_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); + meson_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(meson_wdt->wdt_base)) return PTR_ERR(meson_wdt->wdt_base); - of_id = of_match_device(meson_wdt_dt_ids, &pdev->dev); + of_id = of_match_device(meson_wdt_dt_ids, dev); if (!of_id) { - dev_err(&pdev->dev, "Unable to initialize WDT data\n"); + dev_err(dev, "Unable to initialize WDT data\n"); return -ENODEV; } meson_wdt->data = of_id->data; - meson_wdt->wdt_dev.parent = &pdev->dev; + meson_wdt->wdt_dev.parent = dev; meson_wdt->wdt_dev.info = &meson_wdt_info; meson_wdt->wdt_dev.ops = &meson_wdt_ops; meson_wdt->wdt_dev.max_timeout = @@ -197,18 +196,18 @@ static int meson_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&meson_wdt->wdt_dev, meson_wdt); - watchdog_init_timeout(&meson_wdt->wdt_dev, timeout, &pdev->dev); + watchdog_init_timeout(&meson_wdt->wdt_dev, timeout, dev); watchdog_set_nowayout(&meson_wdt->wdt_dev, nowayout); watchdog_set_restart_priority(&meson_wdt->wdt_dev, 128); meson_wdt_stop(&meson_wdt->wdt_dev); watchdog_stop_on_reboot(&meson_wdt->wdt_dev); - err = devm_watchdog_register_device(&pdev->dev, &meson_wdt->wdt_dev); + err = devm_watchdog_register_device(dev, &meson_wdt->wdt_dev); if (err) return err; - dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", + dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", meson_wdt->wdt_dev.timeout, nowayout); return 0; diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c index 70c2cbf9c993..03b9ac4b99af 100644 --- a/drivers/watchdog/mlx_wdt.c +++ b/drivers/watchdog/mlx_wdt.c @@ -233,20 +233,21 @@ static int mlxreg_wdt_init_timeout(struct mlxreg_wdt *wdt, static int mlxreg_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct mlxreg_core_platform_data *pdata; struct mlxreg_wdt *wdt; int rc; - pdata = dev_get_platdata(&pdev->dev); + pdata = dev_get_platdata(dev); if (!pdata) { - dev_err(&pdev->dev, "Failed to get platform data.\n"); + dev_err(dev, "Failed to get platform data.\n"); return -EINVAL; } - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - wdt->wdd.parent = &pdev->dev; + wdt->wdd.parent = dev; wdt->regmap = pdata->regmap; mlxreg_wdt_config(wdt, pdata); @@ -266,12 +267,11 @@ static int mlxreg_wdt_probe(struct platform_device *pdev) set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); } mlxreg_wdt_check_card_reset(wdt); - rc = devm_watchdog_register_device(&pdev->dev, &wdt->wdd); + rc = devm_watchdog_register_device(dev, &wdt->wdd); register_error: if (rc) - dev_err(&pdev->dev, - "Cannot register watchdog device (err=%d)\n", rc); + dev_err(dev, "Cannot register watchdog device (err=%d)\n", rc); return rc; } diff --git a/drivers/watchdog/moxart_wdt.c b/drivers/watchdog/moxart_wdt.c index 430c3ab84c07..6340a1f5f471 100644 --- a/drivers/watchdog/moxart_wdt.c +++ b/drivers/watchdog/moxart_wdt.c @@ -91,8 +91,6 @@ static int moxart_wdt_probe(struct platform_device *pdev) { struct moxart_wdt_dev *moxart_wdt; struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct resource *res; struct clk *clk; int err; unsigned int max_timeout; @@ -104,12 +102,11 @@ static int moxart_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, moxart_wdt); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - moxart_wdt->base = devm_ioremap_resource(dev, res); + moxart_wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(moxart_wdt->base)) return PTR_ERR(moxart_wdt->base); - clk = of_clk_get(node, 0); + clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { pr_err("%s: of_clk_get failed\n", __func__); return PTR_ERR(clk); @@ -136,7 +133,8 @@ static int moxart_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&moxart_wdt->dev, moxart_wdt); - err = watchdog_register_device(&moxart_wdt->dev); + watchdog_stop_on_unregister(&moxart_wdt->dev); + err = devm_watchdog_register_device(dev, &moxart_wdt->dev); if (err) return err; @@ -146,15 +144,6 @@ static int moxart_wdt_probe(struct platform_device *pdev) return 0; } -static int moxart_wdt_remove(struct platform_device *pdev) -{ - struct moxart_wdt_dev *moxart_wdt = platform_get_drvdata(pdev); - - moxart_wdt_stop(&moxart_wdt->dev); - - return 0; -} - static const struct of_device_id moxart_watchdog_match[] = { { .compatible = "moxa,moxart-watchdog" }, { }, @@ -163,7 +152,6 @@ MODULE_DEVICE_TABLE(of, moxart_watchdog_match); static struct platform_driver moxart_wdt_driver = { .probe = moxart_wdt_probe, - .remove = moxart_wdt_remove, .driver = { .name = "moxart-watchdog", .of_match_table = moxart_watchdog_match, diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 069072e6747d..9b6d6a5a27ad 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -149,8 +149,7 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev) if (!ddata) return -ENOMEM; - res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); - ddata->base = devm_ioremap_resource(dev, res); + ddata->base = devm_platform_ioremap_resource(ofdev, 0); if (IS_ERR(ddata->base)) return PTR_ERR(ddata->base); @@ -205,9 +204,10 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev) if (ddata->wdd.timeout < ddata->wdd.min_timeout) ddata->wdd.timeout = ddata->wdd.min_timeout; - ret = watchdog_register_device(&ddata->wdd); + ret = devm_watchdog_register_device(dev, &ddata->wdd); if (ret) { - dev_err(dev, "cannot register watchdog device (err=%d)\n", ret); + dev_err(dev, "cannot register watchdog device (err=%d)\n", + ret); return ret; } @@ -219,17 +219,6 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev) return 0; } -static int mpc8xxx_wdt_remove(struct platform_device *ofdev) -{ - struct mpc8xxx_wdt_ddata *ddata = platform_get_drvdata(ofdev); - - dev_crit(&ofdev->dev, "Watchdog removed, expect the %s soon!\n", - reset ? "reset" : "machine check exception"); - watchdog_unregister_device(&ddata->wdd); - - return 0; -} - static const struct of_device_id mpc8xxx_wdt_match[] = { { .compatible = "mpc83xx_wdt", @@ -260,7 +249,6 @@ MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); static struct platform_driver mpc8xxx_wdt_driver = { .probe = mpc8xxx_wdt_probe, - .remove = mpc8xxx_wdt_remove, .driver = { .name = "mpc8xxx_wdt", .of_match_table = mpc8xxx_wdt_match, diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c index 81208cd3f4ec..cbb3c0dde136 100644 --- a/drivers/watchdog/mt7621_wdt.c +++ b/drivers/watchdog/mt7621_wdt.c @@ -133,21 +133,19 @@ static struct watchdog_device mt7621_wdt_dev = { static int mt7621_wdt_probe(struct platform_device *pdev) { - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mt7621_wdt_base = devm_ioremap_resource(&pdev->dev, res); + struct device *dev = &pdev->dev; + mt7621_wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mt7621_wdt_base)) return PTR_ERR(mt7621_wdt_base); - mt7621_wdt_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); + mt7621_wdt_reset = devm_reset_control_get_exclusive(dev, NULL); if (!IS_ERR(mt7621_wdt_reset)) reset_control_deassert(mt7621_wdt_reset); mt7621_wdt_dev.bootstatus = mt7621_wdt_bootcause(); watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout, - &pdev->dev); + dev); watchdog_set_nowayout(&mt7621_wdt_dev, nowayout); if (mt7621_wdt_is_running(&mt7621_wdt_dev)) { /* @@ -164,7 +162,7 @@ static int mt7621_wdt_probe(struct platform_device *pdev) set_bit(WDOG_HW_RUNNING, &mt7621_wdt_dev.status); } - return devm_watchdog_register_device(&pdev->dev, &mt7621_wdt_dev); + return devm_watchdog_register_device(dev, &mt7621_wdt_dev); } static void mt7621_wdt_shutdown(struct platform_device *pdev) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 4baf64f21aa1..9c3d0033260d 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -153,18 +153,17 @@ static const struct watchdog_ops mtk_wdt_ops = { static int mtk_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct mtk_wdt_dev *mtk_wdt; - struct resource *res; int err; - mtk_wdt = devm_kzalloc(&pdev->dev, sizeof(*mtk_wdt), GFP_KERNEL); + mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); if (!mtk_wdt) return -ENOMEM; platform_set_drvdata(pdev, mtk_wdt); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mtk_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); + mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mtk_wdt->wdt_base)) return PTR_ERR(mtk_wdt->wdt_base); @@ -173,9 +172,9 @@ static int mtk_wdt_probe(struct platform_device *pdev) mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT; mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; - mtk_wdt->wdt_dev.parent = &pdev->dev; + mtk_wdt->wdt_dev.parent = dev; - watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev); + watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev); watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); @@ -183,29 +182,13 @@ static int mtk_wdt_probe(struct platform_device *pdev) mtk_wdt_stop(&mtk_wdt->wdt_dev); - err = watchdog_register_device(&mtk_wdt->wdt_dev); + watchdog_stop_on_reboot(&mtk_wdt->wdt_dev); + err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev); if (unlikely(err)) return err; - dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", - mtk_wdt->wdt_dev.timeout, nowayout); - - return 0; -} - -static void mtk_wdt_shutdown(struct platform_device *pdev) -{ - struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); - - if (watchdog_active(&mtk_wdt->wdt_dev)) - mtk_wdt_stop(&mtk_wdt->wdt_dev); -} - -static int mtk_wdt_remove(struct platform_device *pdev) -{ - struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&mtk_wdt->wdt_dev); + dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", + mtk_wdt->wdt_dev.timeout, nowayout); return 0; } @@ -247,8 +230,6 @@ static const struct dev_pm_ops mtk_wdt_pm_ops = { static struct platform_driver mtk_wdt_driver = { .probe = mtk_wdt_probe, - .remove = mtk_wdt_remove, - .shutdown = mtk_wdt_shutdown, .driver = { .name = DRV_NAME, .pm = &mtk_wdt_pm_ops, diff --git a/drivers/watchdog/ni903x_wdt.c b/drivers/watchdog/ni903x_wdt.c index dc67742e9018..fbc1df86c6cc 100644 --- a/drivers/watchdog/ni903x_wdt.c +++ b/drivers/watchdog/ni903x_wdt.c @@ -217,9 +217,7 @@ static int ni903x_acpi_add(struct acpi_device *device) wdd->parent = dev; watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, nowayout); - ret = watchdog_init_timeout(wdd, timeout, dev); - if (ret) - dev_err(dev, "unable to set timeout value, using default\n"); + watchdog_init_timeout(wdd, timeout, dev); ret = watchdog_register_device(wdd); if (ret) { diff --git a/drivers/watchdog/nic7018_wdt.c b/drivers/watchdog/nic7018_wdt.c index dcd265685837..82843abe38f8 100644 --- a/drivers/watchdog/nic7018_wdt.c +++ b/drivers/watchdog/nic7018_wdt.c @@ -211,10 +211,7 @@ static int nic7018_probe(struct platform_device *pdev) watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, nowayout); - - ret = watchdog_init_timeout(wdd, timeout, dev); - if (ret) - dev_warn(dev, "unable to set timeout value, using default\n"); + watchdog_init_timeout(wdd, timeout, dev); /* Unlock WDT register */ outb(UNLOCK, wdt->io_base + WDT_REG_LOCK); diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c index 0d4213652ecc..9d6c1689b12c 100644 --- a/drivers/watchdog/npcm_wdt.c +++ b/drivers/watchdog/npcm_wdt.c @@ -181,16 +181,14 @@ static int npcm_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct npcm_wdt *wdt; - struct resource *res; int irq; int ret; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->reg = devm_ioremap_resource(dev, res); + wdt->reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->reg)) return PTR_ERR(wdt->reg); @@ -216,8 +214,8 @@ static int npcm_wdt_probe(struct platform_device *pdev) set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); } - ret = devm_request_irq(dev, irq, npcm_wdt_interrupt, 0, - "watchdog", wdt); + ret = devm_request_irq(dev, irq, npcm_wdt_interrupt, 0, "watchdog", + wdt); if (ret) return ret; diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c index 8a36350bab7b..f36eae34e848 100644 --- a/drivers/watchdog/nuc900_wdt.c +++ b/drivers/watchdog/nuc900_wdt.c @@ -242,7 +242,6 @@ static struct miscdevice nuc900wdt_miscdev = { static int nuc900wdt_probe(struct platform_device *pdev) { - struct resource *res; int ret = 0; nuc900_wdt = devm_kzalloc(&pdev->dev, sizeof(*nuc900_wdt), @@ -254,8 +253,7 @@ static int nuc900wdt_probe(struct platform_device *pdev) spin_lock_init(&nuc900_wdt->wdt_lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nuc900_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); + nuc900_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(nuc900_wdt->wdt_base)) return PTR_ERR(nuc900_wdt->wdt_base); diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index d3f7eb046678..03786992b701 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -151,43 +151,46 @@ static u32 xwdt_selftest(struct xwdt_device *xdev) return XWT_TIMER_FAILED; } +static void xwdt_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int xwdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int rc; u32 pfreq = 0, enable_once = 0; - struct resource *res; struct xwdt_device *xdev; struct watchdog_device *xilinx_wdt_wdd; - xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); + xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL); if (!xdev) return -ENOMEM; xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd; xilinx_wdt_wdd->info = &xilinx_wdt_ident; xilinx_wdt_wdd->ops = &xilinx_wdt_ops; - xilinx_wdt_wdd->parent = &pdev->dev; + xilinx_wdt_wdd->parent = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xdev->base = devm_ioremap_resource(&pdev->dev, res); + xdev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xdev->base)) return PTR_ERR(xdev->base); - rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-interval", + rc = of_property_read_u32(dev->of_node, "xlnx,wdt-interval", &xdev->wdt_interval); if (rc) - dev_warn(&pdev->dev, - "Parameter \"xlnx,wdt-interval\" not found\n"); + dev_warn(dev, "Parameter \"xlnx,wdt-interval\" not found\n"); - rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-enable-once", + rc = of_property_read_u32(dev->of_node, "xlnx,wdt-enable-once", &enable_once); if (rc) - dev_warn(&pdev->dev, + dev_warn(dev, "Parameter \"xlnx,wdt-enable-once\" not found\n"); watchdog_set_nowayout(xilinx_wdt_wdd, enable_once); - xdev->clk = devm_clk_get(&pdev->dev, NULL); + xdev->clk = devm_clk_get(dev, NULL); if (IS_ERR(xdev->clk)) { if (PTR_ERR(xdev->clk) != -ENOENT) return PTR_ERR(xdev->clk); @@ -198,10 +201,10 @@ static int xwdt_probe(struct platform_device *pdev) */ xdev->clk = NULL; - rc = of_property_read_u32(pdev->dev.of_node, "clock-frequency", + rc = of_property_read_u32(dev->of_node, "clock-frequency", &pfreq); if (rc) - dev_warn(&pdev->dev, + dev_warn(dev, "The watchdog clock freq cannot be obtained\n"); } else { pfreq = clk_get_rate(xdev->clk); @@ -220,44 +223,34 @@ static int xwdt_probe(struct platform_device *pdev) rc = clk_prepare_enable(xdev->clk); if (rc) { - dev_err(&pdev->dev, "unable to enable clock\n"); + dev_err(dev, "unable to enable clock\n"); return rc; } + rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare, + xdev->clk); + if (rc) + return rc; rc = xwdt_selftest(xdev); if (rc == XWT_TIMER_FAILED) { - dev_err(&pdev->dev, "SelfTest routine error\n"); - goto err_clk_disable; + dev_err(dev, "SelfTest routine error\n"); + return rc; } - rc = watchdog_register_device(xilinx_wdt_wdd); + rc = devm_watchdog_register_device(dev, xilinx_wdt_wdd); if (rc) { - dev_err(&pdev->dev, "Cannot register watchdog (err=%d)\n", rc); - goto err_clk_disable; + dev_err(dev, "Cannot register watchdog (err=%d)\n", rc); + return rc; } clk_disable(xdev->clk); - dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", + dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", xdev->base, xilinx_wdt_wdd->timeout); platform_set_drvdata(pdev, xdev); return 0; -err_clk_disable: - clk_disable_unprepare(xdev->clk); - - return rc; -} - -static int xwdt_remove(struct platform_device *pdev) -{ - struct xwdt_device *xdev = platform_get_drvdata(pdev); - - watchdog_unregister_device(&xdev->xilinx_wdt_wdd); - clk_disable_unprepare(xdev->clk); - - return 0; } /** @@ -305,7 +298,6 @@ MODULE_DEVICE_TABLE(of, xwdt_of_match); static struct platform_driver xwdt_driver = { .probe = xwdt_probe, - .remove = xwdt_remove, .driver = { .name = WATCHDOG_NAME, .of_match_table = xwdt_of_match, diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index cbd752f9ac56..d49688d93f6a 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -231,7 +231,6 @@ static const struct watchdog_ops omap_wdt_ops = { static int omap_wdt_probe(struct platform_device *pdev) { struct omap_wd_timer_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct resource *res; struct omap_wdt_dev *wdev; int ret; @@ -245,8 +244,7 @@ static int omap_wdt_probe(struct platform_device *pdev) mutex_init(&wdev->lock); /* reserve static register mappings */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdev->base = devm_ioremap_resource(&pdev->dev, res); + wdev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdev->base)) return PTR_ERR(wdev->base); diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 9db3b09f7568..cdb0d174c5e2 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -349,13 +349,6 @@ static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate; } -static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, - unsigned int timeout) -{ - wdt_dev->timeout = timeout; - return 0; -} - static const struct watchdog_info orion_wdt_info = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .identity = "Orion Watchdog", @@ -366,7 +359,6 @@ static const struct watchdog_ops orion_wdt_ops = { .start = orion_wdt_start, .stop = orion_wdt_stop, .ping = orion_wdt_ping, - .set_timeout = orion_wdt_set_timeout, .get_timeleft = orion_wdt_get_timeleft, }; @@ -502,8 +494,7 @@ static int orion_wdt_get_regs(struct platform_device *pdev, of_device_is_compatible(node, "marvell,armada-xp-wdt")) { /* Dedicated RSTOUT register, can be requested. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dev->rstout = devm_ioremap_resource(&pdev->dev, res); + dev->rstout = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dev->rstout)) return PTR_ERR(dev->rstout); @@ -511,8 +502,7 @@ static int orion_wdt_get_regs(struct platform_device *pdev, of_device_is_compatible(node, "marvell,armada-380-wdt")) { /* Dedicated RSTOUT register, can be requested. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dev->rstout = devm_ioremap_resource(&pdev->dev, res); + dev->rstout = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dev->rstout)) return PTR_ERR(dev->rstout); diff --git a/drivers/watchdog/pic32-dmt.c b/drivers/watchdog/pic32-dmt.c index c797305f8338..9a3c53e03c60 100644 --- a/drivers/watchdog/pic32-dmt.c +++ b/drivers/watchdog/pic32-dmt.c @@ -168,70 +168,61 @@ static struct watchdog_device pic32_dmt_wdd = { .ops = &pic32_dmt_fops, }; +static void pic32_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int pic32_dmt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret; struct pic32_dmt *dmt; - struct resource *mem; struct watchdog_device *wdd = &pic32_dmt_wdd; - dmt = devm_kzalloc(&pdev->dev, sizeof(*dmt), GFP_KERNEL); + dmt = devm_kzalloc(dev, sizeof(*dmt), GFP_KERNEL); if (!dmt) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dmt->regs = devm_ioremap_resource(&pdev->dev, mem); + dmt->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dmt->regs)) return PTR_ERR(dmt->regs); - dmt->clk = devm_clk_get(&pdev->dev, NULL); + dmt->clk = devm_clk_get(dev, NULL); if (IS_ERR(dmt->clk)) { - dev_err(&pdev->dev, "clk not found\n"); + dev_err(dev, "clk not found\n"); return PTR_ERR(dmt->clk); } ret = clk_prepare_enable(dmt->clk); if (ret) return ret; + ret = devm_add_action_or_reset(dev, pic32_clk_disable_unprepare, + dmt->clk); + if (ret) + return ret; wdd->timeout = pic32_dmt_get_timeout_secs(dmt); if (!wdd->timeout) { - dev_err(&pdev->dev, - "failed to read watchdog register timeout\n"); - ret = -EINVAL; - goto out_disable_clk; + dev_err(dev, "failed to read watchdog register timeout\n"); + return -EINVAL; } - dev_info(&pdev->dev, "timeout %d\n", wdd->timeout); + dev_info(dev, "timeout %d\n", wdd->timeout); wdd->bootstatus = pic32_dmt_bootstatus(dmt) ? WDIOF_CARDRESET : 0; watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT); watchdog_set_drvdata(wdd, dmt); - ret = watchdog_register_device(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { - dev_err(&pdev->dev, "watchdog register failed, err %d\n", ret); - goto out_disable_clk; + dev_err(dev, "watchdog register failed, err %d\n", ret); + return ret; } platform_set_drvdata(pdev, wdd); return 0; - -out_disable_clk: - clk_disable_unprepare(dmt->clk); - return ret; -} - -static int pic32_dmt_remove(struct platform_device *pdev) -{ - struct watchdog_device *wdd = platform_get_drvdata(pdev); - struct pic32_dmt *dmt = watchdog_get_drvdata(wdd); - - watchdog_unregister_device(wdd); - clk_disable_unprepare(dmt->clk); - - return 0; } static const struct of_device_id pic32_dmt_of_ids[] = { @@ -242,7 +233,6 @@ MODULE_DEVICE_TABLE(of, pic32_dmt_of_ids); static struct platform_driver pic32_dmt_driver = { .probe = pic32_dmt_probe, - .remove = pic32_dmt_remove, .driver = { .name = "pic32-dmt", .of_match_table = of_match_ptr(pic32_dmt_of_ids), diff --git a/drivers/watchdog/pic32-wdt.c b/drivers/watchdog/pic32-wdt.c index e2761068dc6f..540500940cc0 100644 --- a/drivers/watchdog/pic32-wdt.c +++ b/drivers/watchdog/pic32-wdt.c @@ -166,89 +166,77 @@ static const struct of_device_id pic32_wdt_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, pic32_wdt_dt_ids); +static void pic32_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int pic32_wdt_drv_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret; struct watchdog_device *wdd = &pic32_wdd; struct pic32_wdt *wdt; - struct resource *mem; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->regs = devm_ioremap_resource(&pdev->dev, mem); + wdt->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->regs)) return PTR_ERR(wdt->regs); - wdt->rst_base = devm_ioremap(&pdev->dev, PIC32_BASE_RESET, 0x10); + wdt->rst_base = devm_ioremap(dev, PIC32_BASE_RESET, 0x10); if (!wdt->rst_base) return -ENOMEM; - wdt->clk = devm_clk_get(&pdev->dev, NULL); + wdt->clk = devm_clk_get(dev, NULL); if (IS_ERR(wdt->clk)) { - dev_err(&pdev->dev, "clk not found\n"); + dev_err(dev, "clk not found\n"); return PTR_ERR(wdt->clk); } ret = clk_prepare_enable(wdt->clk); if (ret) { - dev_err(&pdev->dev, "clk enable failed\n"); + dev_err(dev, "clk enable failed\n"); return ret; } + ret = devm_add_action_or_reset(dev, pic32_clk_disable_unprepare, + wdt->clk); + if (ret) + return ret; if (pic32_wdt_is_win_enabled(wdt)) { - dev_err(&pdev->dev, "windowed-clear mode is not supported.\n"); - ret = -ENODEV; - goto out_disable_clk; + dev_err(dev, "windowed-clear mode is not supported.\n"); + return -ENODEV; } - wdd->timeout = pic32_wdt_get_timeout_secs(wdt, &pdev->dev); + wdd->timeout = pic32_wdt_get_timeout_secs(wdt, dev); if (!wdd->timeout) { - dev_err(&pdev->dev, - "failed to read watchdog register timeout\n"); - ret = -EINVAL; - goto out_disable_clk; + dev_err(dev, "failed to read watchdog register timeout\n"); + return -EINVAL; } - dev_info(&pdev->dev, "timeout %d\n", wdd->timeout); + dev_info(dev, "timeout %d\n", wdd->timeout); wdd->bootstatus = pic32_wdt_bootstatus(wdt) ? WDIOF_CARDRESET : 0; watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT); watchdog_set_drvdata(wdd, wdt); - ret = watchdog_register_device(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { - dev_err(&pdev->dev, "watchdog register failed, err %d\n", ret); - goto out_disable_clk; + dev_err(dev, "watchdog register failed, err %d\n", ret); + return ret; } platform_set_drvdata(pdev, wdd); return 0; - -out_disable_clk: - clk_disable_unprepare(wdt->clk); - - return ret; -} - -static int pic32_wdt_drv_remove(struct platform_device *pdev) -{ - struct watchdog_device *wdd = platform_get_drvdata(pdev); - struct pic32_wdt *wdt = watchdog_get_drvdata(wdd); - - watchdog_unregister_device(wdd); - clk_disable_unprepare(wdt->clk); - - return 0; } static struct platform_driver pic32_wdt_driver = { .probe = pic32_wdt_drv_probe, - .remove = pic32_wdt_drv_remove, .driver = { .name = "pic32-wdt", .of_match_table = of_match_ptr(pic32_wdt_dt_ids), diff --git a/drivers/watchdog/pm8916_wdt.c b/drivers/watchdog/pm8916_wdt.c index 7f10041fcf5b..2d3652004e39 100644 --- a/drivers/watchdog/pm8916_wdt.c +++ b/drivers/watchdog/pm8916_wdt.c @@ -132,15 +132,16 @@ static const struct watchdog_ops pm8916_wdt_ops = { static int pm8916_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct pm8916_wdt *wdt; struct device *parent; int err, irq; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - parent = pdev->dev.parent; + parent = dev->parent; /* * The pm8916-pon-wdt is a child of the pon device, which is a child @@ -150,20 +151,20 @@ static int pm8916_wdt_probe(struct platform_device *pdev) */ wdt->regmap = dev_get_regmap(parent->parent, NULL); if (!wdt->regmap) { - dev_err(&pdev->dev, "failed to locate regmap\n"); + dev_err(dev, "failed to locate regmap\n"); return -ENODEV; } err = device_property_read_u32(parent, "reg", &wdt->baseaddr); if (err) { - dev_err(&pdev->dev, "failed to get pm8916-pon address\n"); + dev_err(dev, "failed to get pm8916-pon address\n"); return err; } irq = platform_get_irq(pdev, 0); if (irq > 0) { - if (devm_request_irq(&pdev->dev, irq, pm8916_wdt_isr, 0, - "pm8916_wdt", wdt)) + if (devm_request_irq(dev, irq, pm8916_wdt_isr, 0, "pm8916_wdt", + wdt)) irq = 0; } @@ -172,23 +173,23 @@ static int pm8916_wdt_probe(struct platform_device *pdev) wdt->baseaddr + PON_PMIC_WD_RESET_S2_CTL, RESET_TYPE_HARD); if (err) { - dev_err(&pdev->dev, "failed configure watchdog\n"); + dev_err(dev, "failed configure watchdog\n"); return err; } wdt->wdev.info = (irq > 0) ? &pm8916_wdt_pt_ident : &pm8916_wdt_ident, wdt->wdev.ops = &pm8916_wdt_ops, - wdt->wdev.parent = &pdev->dev; + wdt->wdev.parent = dev; wdt->wdev.min_timeout = PM8916_WDT_MIN_TIMEOUT; wdt->wdev.max_timeout = PM8916_WDT_MAX_TIMEOUT; wdt->wdev.timeout = PM8916_WDT_DEFAULT_TIMEOUT; wdt->wdev.pretimeout = 0; watchdog_set_drvdata(&wdt->wdev, wdt); - watchdog_init_timeout(&wdt->wdev, 0, &pdev->dev); + watchdog_init_timeout(&wdt->wdev, 0, dev); pm8916_wdt_configure_timers(&wdt->wdev); - return devm_watchdog_register_device(&pdev->dev, &wdt->wdev); + return devm_watchdog_register_device(dev, &wdt->wdev); } static const struct of_device_id pm8916_wdt_id_table[] = { diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 8e261799c84e..d9e03544aeae 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -183,54 +183,50 @@ static struct watchdog_device pnx4008_wdd = { .max_timeout = MAX_HEARTBEAT, }; +static void pnx4008_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int pnx4008_wdt_probe(struct platform_device *pdev) { - struct resource *r; + struct device *dev = &pdev->dev; int ret = 0; - watchdog_init_timeout(&pnx4008_wdd, heartbeat, &pdev->dev); + watchdog_init_timeout(&pnx4008_wdd, heartbeat, dev); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt_base = devm_ioremap_resource(&pdev->dev, r); + wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt_base)) return PTR_ERR(wdt_base); - wdt_clk = devm_clk_get(&pdev->dev, NULL); + wdt_clk = devm_clk_get(dev, NULL); if (IS_ERR(wdt_clk)) return PTR_ERR(wdt_clk); ret = clk_prepare_enable(wdt_clk); if (ret) return ret; + ret = devm_add_action_or_reset(dev, pnx4008_clk_disable_unprepare, + wdt_clk); + if (ret) + return ret; pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? WDIOF_CARDRESET : 0; - pnx4008_wdd.parent = &pdev->dev; + pnx4008_wdd.parent = dev; watchdog_set_nowayout(&pnx4008_wdd, nowayout); watchdog_set_restart_priority(&pnx4008_wdd, 128); - pnx4008_wdt_stop(&pnx4008_wdd); /* disable for now */ + if (readl(WDTIM_CTRL(wdt_base)) & COUNT_ENAB) + set_bit(WDOG_HW_RUNNING, &pnx4008_wdd.status); - ret = watchdog_register_device(&pnx4008_wdd); + ret = devm_watchdog_register_device(dev, &pnx4008_wdd); if (ret < 0) { - dev_err(&pdev->dev, "cannot register watchdog device\n"); - goto disable_clk; + dev_err(dev, "cannot register watchdog device\n"); + return ret; } - dev_info(&pdev->dev, "heartbeat %d sec\n", pnx4008_wdd.timeout); - - return 0; - -disable_clk: - clk_disable_unprepare(wdt_clk); - return ret; -} - -static int pnx4008_wdt_remove(struct platform_device *pdev) -{ - watchdog_unregister_device(&pnx4008_wdd); - - clk_disable_unprepare(wdt_clk); + dev_info(dev, "heartbeat %d sec\n", pnx4008_wdd.timeout); return 0; } @@ -249,7 +245,6 @@ static struct platform_driver platform_wdt_driver = { .of_match_table = of_match_ptr(pnx4008_wdt_match), }, .probe = pnx4008_wdt_probe, - .remove = pnx4008_wdt_remove, }; module_platform_driver(platform_wdt_driver); diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 5dfd604477a4..6d29c33b1316 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -142,22 +142,28 @@ static const struct watchdog_info qcom_wdt_info = { .identity = KBUILD_MODNAME, }; +static void qcom_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int qcom_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct qcom_wdt *wdt; struct resource *res; - struct device_node *np = pdev->dev.of_node; + struct device_node *np = dev->of_node; const u32 *regs; u32 percpu_offset; int ret; - regs = of_device_get_match_data(&pdev->dev); + regs = of_device_get_match_data(dev); if (!regs) { - dev_err(&pdev->dev, "Unsupported QCOM WDT module\n"); + dev_err(dev, "Unsupported QCOM WDT module\n"); return -ENODEV; } - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -172,21 +178,25 @@ static int qcom_wdt_probe(struct platform_device *pdev) res->start += percpu_offset; res->end += percpu_offset; - wdt->base = devm_ioremap_resource(&pdev->dev, res); + wdt->base = devm_ioremap_resource(dev, res); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - wdt->clk = devm_clk_get(&pdev->dev, NULL); + wdt->clk = devm_clk_get(dev, NULL); if (IS_ERR(wdt->clk)) { - dev_err(&pdev->dev, "failed to get input clock\n"); + dev_err(dev, "failed to get input clock\n"); return PTR_ERR(wdt->clk); } ret = clk_prepare_enable(wdt->clk); if (ret) { - dev_err(&pdev->dev, "failed to setup clock\n"); + dev_err(dev, "failed to setup clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, qcom_clk_disable_unprepare, + wdt->clk); + if (ret) + return ret; /* * We use the clock rate to calculate the max timeout, so ensure it's @@ -199,16 +209,15 @@ static int qcom_wdt_probe(struct platform_device *pdev) wdt->rate = clk_get_rate(wdt->clk); if (wdt->rate == 0 || wdt->rate > 0x10000000U) { - dev_err(&pdev->dev, "invalid clock rate\n"); - ret = -EINVAL; - goto err_clk_unprepare; + dev_err(dev, "invalid clock rate\n"); + return -EINVAL; } wdt->wdd.info = &qcom_wdt_info; wdt->wdd.ops = &qcom_wdt_ops; wdt->wdd.min_timeout = 1; wdt->wdd.max_timeout = 0x10000000U / wdt->rate; - wdt->wdd.parent = &pdev->dev; + wdt->wdd.parent = dev; wdt->layout = regs; if (readl(wdt_addr(wdt, WDT_STS)) & 1) @@ -220,29 +229,16 @@ static int qcom_wdt_probe(struct platform_device *pdev) * the max instead. */ wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U); - watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev); + watchdog_init_timeout(&wdt->wdd, 0, dev); - ret = watchdog_register_device(&wdt->wdd); + ret = devm_watchdog_register_device(dev, &wdt->wdd); if (ret) { - dev_err(&pdev->dev, "failed to register watchdog\n"); - goto err_clk_unprepare; + dev_err(dev, "failed to register watchdog\n"); + return ret; } platform_set_drvdata(pdev, wdt); return 0; - -err_clk_unprepare: - clk_disable_unprepare(wdt->clk); - return ret; -} - -static int qcom_wdt_remove(struct platform_device *pdev) -{ - struct qcom_wdt *wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&wdt->wdd); - clk_disable_unprepare(wdt->clk); - return 0; } static int __maybe_unused qcom_wdt_suspend(struct device *dev) @@ -277,7 +273,6 @@ MODULE_DEVICE_TABLE(of, qcom_wdt_of_table); static struct platform_driver qcom_watchdog_driver = { .probe = qcom_wdt_probe, - .remove = qcom_wdt_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = qcom_wdt_of_table, diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c index 622ede529912..565dbc1ec638 100644 --- a/drivers/watchdog/renesas_wdt.c +++ b/drivers/watchdog/renesas_wdt.c @@ -151,7 +151,6 @@ static const struct soc_device_attribute rwdt_quirks_match[] = { .data = (void *)1, /* needs single CPU */ }, { .soc_id = "r8a7792", - .revision = "*", .data = (void *)0, /* needs SMP disabled */ }, { /* sentinel */ } @@ -177,7 +176,6 @@ static inline bool rwdt_blacklisted(struct device *dev) { return false; } static int rwdt_probe(struct platform_device *pdev) { struct rwdt_priv *priv; - struct resource *res; struct clk *clk; unsigned long clks_per_sec; int ret, i; @@ -189,8 +187,7 @@ static int rwdt_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); @@ -238,9 +235,7 @@ static int rwdt_probe(struct platform_device *pdev) watchdog_stop_on_unregister(&priv->wdev); /* This overrides the default timeout only if DT configuration was found */ - ret = watchdog_init_timeout(&priv->wdev, 0, &pdev->dev); - if (ret) - dev_warn(&pdev->dev, "Specified timeout value invalid, using default\n"); + watchdog_init_timeout(&priv->wdev, 0, &pdev->dev); ret = watchdog_register_device(&priv->wdev); if (ret < 0) diff --git a/drivers/watchdog/rn5t618_wdt.c b/drivers/watchdog/rn5t618_wdt.c index e60f55702ab7..21fcb36f9074 100644 --- a/drivers/watchdog/rn5t618_wdt.c +++ b/drivers/watchdog/rn5t618_wdt.c @@ -146,11 +146,12 @@ static const struct watchdog_ops rn5t618_wdt_ops = { static int rn5t618_wdt_probe(struct platform_device *pdev) { - struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct rn5t618 *rn5t618 = dev_get_drvdata(dev->parent); struct rn5t618_wdt *wdt; int min_timeout, max_timeout; - wdt = devm_kzalloc(&pdev->dev, sizeof(struct rn5t618_wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(struct rn5t618_wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -163,10 +164,10 @@ static int rn5t618_wdt_probe(struct platform_device *pdev) wdt->wdt_dev.min_timeout = min_timeout; wdt->wdt_dev.max_timeout = max_timeout; wdt->wdt_dev.timeout = max_timeout; - wdt->wdt_dev.parent = &pdev->dev; + wdt->wdt_dev.parent = dev; watchdog_set_drvdata(&wdt->wdt_dev, wdt); - watchdog_init_timeout(&wdt->wdt_dev, timeout, &pdev->dev); + watchdog_init_timeout(&wdt->wdt_dev, timeout, dev); watchdog_set_nowayout(&wdt->wdt_dev, nowayout); platform_set_drvdata(pdev, wdt); diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c index db7c57d82cfd..905e60f45eec 100644 --- a/drivers/watchdog/rt2880_wdt.c +++ b/drivers/watchdog/rt2880_wdt.c @@ -141,19 +141,18 @@ static struct watchdog_device rt288x_wdt_dev = { static int rt288x_wdt_probe(struct platform_device *pdev) { - struct resource *res; + struct device *dev = &pdev->dev; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rt288x_wdt_base = devm_ioremap_resource(&pdev->dev, res); + rt288x_wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rt288x_wdt_base)) return PTR_ERR(rt288x_wdt_base); - rt288x_wdt_clk = devm_clk_get(&pdev->dev, NULL); + rt288x_wdt_clk = devm_clk_get(dev, NULL); if (IS_ERR(rt288x_wdt_clk)) return PTR_ERR(rt288x_wdt_clk); - rt288x_wdt_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); + rt288x_wdt_reset = devm_reset_control_get_exclusive(dev, NULL); if (!IS_ERR(rt288x_wdt_reset)) reset_control_deassert(rt288x_wdt_reset); @@ -161,31 +160,20 @@ static int rt288x_wdt_probe(struct platform_device *pdev) rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause(); rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq); - rt288x_wdt_dev.parent = &pdev->dev; + rt288x_wdt_dev.parent = dev; watchdog_init_timeout(&rt288x_wdt_dev, rt288x_wdt_dev.max_timeout, - &pdev->dev); + dev); watchdog_set_nowayout(&rt288x_wdt_dev, nowayout); - ret = watchdog_register_device(&rt288x_wdt_dev); + watchdog_stop_on_reboot(&rt288x_wdt_dev); + ret = devm_watchdog_register_device(dev, &rt288x_wdt_dev); if (!ret) - dev_info(&pdev->dev, "Initialized\n"); + dev_info(dev, "Initialized\n"); return 0; } -static int rt288x_wdt_remove(struct platform_device *pdev) -{ - watchdog_unregister_device(&rt288x_wdt_dev); - - return 0; -} - -static void rt288x_wdt_shutdown(struct platform_device *pdev) -{ - rt288x_wdt_stop(&rt288x_wdt_dev); -} - static const struct of_device_id rt288x_wdt_match[] = { { .compatible = "ralink,rt2880-wdt" }, {}, @@ -194,8 +182,6 @@ MODULE_DEVICE_TABLE(of, rt288x_wdt_match); static struct platform_driver rt288x_wdt_driver = { .probe = rt288x_wdt_probe, - .remove = rt288x_wdt_remove, - .shutdown = rt288x_wdt_shutdown, .driver = { .name = KBUILD_MODNAME, .of_match_table = rt288x_wdt_match, diff --git a/drivers/watchdog/rtd119x_wdt.c b/drivers/watchdog/rtd119x_wdt.c index d001c17ddfde..834b94ff3f90 100644 --- a/drivers/watchdog/rtd119x_wdt.c +++ b/drivers/watchdog/rtd119x_wdt.c @@ -9,7 +9,6 @@ #include <linux/bitops.h> #include <linux/clk.h> #include <linux/io.h> -#include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> @@ -95,37 +94,43 @@ static const struct of_device_id rtd119x_wdt_dt_ids[] = { { } }; +static void rtd119x_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int rtd119x_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct rtd119x_watchdog_device *data; - struct resource *res; int ret; - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->base = devm_ioremap_resource(&pdev->dev, res); + data->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->base)) return PTR_ERR(data->base); - data->clk = of_clk_get(pdev->dev.of_node, 0); + data->clk = devm_clk_get(dev, NULL); if (IS_ERR(data->clk)) return PTR_ERR(data->clk); ret = clk_prepare_enable(data->clk); - if (ret) { - clk_put(data->clk); + if (ret) + return ret; + ret = devm_add_action_or_reset(dev, rtd119x_clk_disable_unprepare, + data->clk); + if (ret) return ret; - } data->wdt_dev.info = &rtd119x_wdt_info; data->wdt_dev.ops = &rtd119x_wdt_ops; data->wdt_dev.timeout = 120; data->wdt_dev.max_timeout = 0xffffffff / clk_get_rate(data->clk); data->wdt_dev.min_timeout = 1; - data->wdt_dev.parent = &pdev->dev; + data->wdt_dev.parent = dev; watchdog_stop_on_reboot(&data->wdt_dev); watchdog_set_drvdata(&data->wdt_dev, data); @@ -135,31 +140,11 @@ static int rtd119x_wdt_probe(struct platform_device *pdev) rtd119x_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout); rtd119x_wdt_stop(&data->wdt_dev); - ret = devm_watchdog_register_device(&pdev->dev, &data->wdt_dev); - if (ret) { - clk_disable_unprepare(data->clk); - clk_put(data->clk); - return ret; - } - - return 0; -} - -static int rtd119x_wdt_remove(struct platform_device *pdev) -{ - struct rtd119x_watchdog_device *data = platform_get_drvdata(pdev); - - watchdog_unregister_device(&data->wdt_dev); - - clk_disable_unprepare(data->clk); - clk_put(data->clk); - - return 0; + return devm_watchdog_register_device(dev, &data->wdt_dev); } static struct platform_driver rtd119x_wdt_driver = { .probe = rtd119x_wdt_probe, - .remove = rtd119x_wdt_remove, .driver = { .name = "rtd1295-watchdog", .of_match_table = rtd119x_wdt_dt_ids, diff --git a/drivers/watchdog/rza_wdt.c b/drivers/watchdog/rza_wdt.c index 781bb572e6af..7b6c365f7cd3 100644 --- a/drivers/watchdog/rza_wdt.c +++ b/drivers/watchdog/rza_wdt.c @@ -166,35 +166,34 @@ static const struct watchdog_ops rza_wdt_ops = { static int rza_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct rza_wdt *priv; - struct resource *res; unsigned long rate; int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get(dev, NULL); if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); rate = clk_get_rate(priv->clk); if (rate < 16384) { - dev_err(&pdev->dev, "invalid clock rate (%ld)\n", rate); + dev_err(dev, "invalid clock rate (%ld)\n", rate); return -ENOENT; } priv->wdev.info = &rza_wdt_ident, priv->wdev.ops = &rza_wdt_ops, - priv->wdev.parent = &pdev->dev; + priv->wdev.parent = dev; - priv->cks = (u8)(uintptr_t)of_device_get_match_data(&pdev->dev); + priv->cks = (u8)(uintptr_t) of_device_get_match_data(dev); if (priv->cks == CKS_4BIT) { /* Assume slowest clock rate possible (CKS=0xF) */ priv->wdev.max_timeout = (DIVIDER_4BIT * U8_MAX) / rate; @@ -209,19 +208,19 @@ static int rza_wdt_probe(struct platform_device *pdev) * max_hw_heartbeat_ms. */ priv->wdev.max_hw_heartbeat_ms = (1000 * U8_MAX) / rate; - dev_dbg(&pdev->dev, "max hw timeout of %dms\n", - priv->wdev.max_hw_heartbeat_ms); + dev_dbg(dev, "max hw timeout of %dms\n", + priv->wdev.max_hw_heartbeat_ms); } priv->wdev.min_timeout = 1; priv->wdev.timeout = DEFAULT_TIMEOUT; - watchdog_init_timeout(&priv->wdev, 0, &pdev->dev); + watchdog_init_timeout(&priv->wdev, 0, dev); watchdog_set_drvdata(&priv->wdev, priv); - ret = devm_watchdog_register_device(&pdev->dev, &priv->wdev); + ret = devm_watchdog_register_device(dev, &priv->wdev); if (ret) - dev_err(&pdev->dev, "Cannot register watchdog device\n"); + dev_err(dev, "Cannot register watchdog device\n"); return ret; } diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index adaa43543f0a..4267b9e8734b 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -522,7 +522,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct s3c2410_wdt *wdt; - struct resource *wdt_mem; struct resource *wdt_irq; unsigned int wtcon; int started = 0; @@ -554,8 +553,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) } /* get the memory region for the watchdog timer */ - wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->reg_base = devm_ioremap_resource(dev, wdt_mem); + wdt->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->reg_base)) { ret = PTR_ERR(wdt->reg_base); goto err; diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c index 1e93c1b0e3cf..111695223aae 100644 --- a/drivers/watchdog/sama5d4_wdt.c +++ b/drivers/watchdog/sama5d4_wdt.c @@ -199,15 +199,15 @@ static int sama5d4_wdt_init(struct sama5d4_wdt *wdt) static int sama5d4_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct sama5d4_wdt *wdt; - struct resource *res; void __iomem *regs; u32 irq = 0; u32 timeout; int ret; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -221,33 +221,31 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(wdd, wdt); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); wdt->reg_base = regs; - irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + irq = irq_of_parse_and_map(dev->of_node, 0); if (!irq) - dev_warn(&pdev->dev, "failed to get IRQ from DT\n"); + dev_warn(dev, "failed to get IRQ from DT\n"); - ret = of_sama5d4_wdt_init(pdev->dev.of_node, wdt); + ret = of_sama5d4_wdt_init(dev->of_node, wdt); if (ret) return ret; if ((wdt->mr & AT91_WDT_WDFIEN) && irq) { - ret = devm_request_irq(&pdev->dev, irq, sama5d4_wdt_irq_handler, + ret = devm_request_irq(dev, irq, sama5d4_wdt_irq_handler, IRQF_SHARED | IRQF_IRQPOLL | IRQF_NO_SUSPEND, pdev->name, pdev); if (ret) { - dev_err(&pdev->dev, - "cannot register interrupt handler\n"); + dev_err(dev, "cannot register interrupt handler\n"); return ret; } } - watchdog_init_timeout(wdd, wdt_timeout, &pdev->dev); + watchdog_init_timeout(wdd, wdt_timeout, dev); timeout = WDT_SEC2TICKS(wdd->timeout); @@ -260,31 +258,21 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) watchdog_set_nowayout(wdd, nowayout); - ret = watchdog_register_device(wdd); + watchdog_stop_on_unregister(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { - dev_err(&pdev->dev, "failed to register watchdog device\n"); + dev_err(dev, "failed to register watchdog device\n"); return ret; } platform_set_drvdata(pdev, wdt); - dev_info(&pdev->dev, "initialized (timeout = %d sec, nowayout = %d)\n", + dev_info(dev, "initialized (timeout = %d sec, nowayout = %d)\n", wdd->timeout, nowayout); return 0; } -static int sama5d4_wdt_remove(struct platform_device *pdev) -{ - struct sama5d4_wdt *wdt = platform_get_drvdata(pdev); - - sama5d4_wdt_stop(&wdt->wdd); - - watchdog_unregister_device(&wdt->wdd); - - return 0; -} - static const struct of_device_id sama5d4_wdt_of_match[] = { { .compatible = "atmel,sama5d4-wdt", }, { } @@ -312,7 +300,6 @@ static SIMPLE_DEV_PM_OPS(sama5d4_wdt_pm_ops, NULL, static struct platform_driver sama5d4_wdt_driver = { .probe = sama5d4_wdt_probe, - .remove = sama5d4_wdt_remove, .driver = { .name = "sama5d4_wdt", .pm = &sama5d4_wdt_pm_ops, diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 0692d42e5c67..5a6ced7a7e8f 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(sbwd_lock); * * wdog is the iomem address of the cfg register */ -void sbwdog_set(char __iomem *wdog, unsigned long t) +static void sbwdog_set(char __iomem *wdog, unsigned long t) { spin_lock(&sbwd_lock); __raw_writeb(0, wdog); @@ -81,7 +81,7 @@ void sbwdog_set(char __iomem *wdog, unsigned long t) * * wdog is the iomem address of the cfg register */ -void sbwdog_pet(char __iomem *wdog) +static void sbwdog_pet(char __iomem *wdog) { spin_lock(&sbwd_lock); __raw_writeb(__raw_readb(wdog) | 1, wdog); diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index e221e47396ab..3219422f67a9 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c @@ -231,7 +231,6 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct sbsa_gwdt *gwdt; - struct resource *res; int ret, irq; u32 status; @@ -240,13 +239,11 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, gwdt); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - cf_base = devm_ioremap_resource(dev, res); + cf_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(cf_base)) return PTR_ERR(cf_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - rf_base = devm_ioremap_resource(dev, res); + rf_base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(rf_base)) return PTR_ERR(rf_base); @@ -313,7 +310,8 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) */ sbsa_gwdt_set_timeout(wdd, wdd->timeout); - ret = watchdog_register_device(wdd); + watchdog_stop_on_reboot(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) return ret; @@ -324,22 +322,6 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) return 0; } -static void sbsa_gwdt_shutdown(struct platform_device *pdev) -{ - struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev); - - sbsa_gwdt_stop(&gwdt->wdd); -} - -static int sbsa_gwdt_remove(struct platform_device *pdev) -{ - struct sbsa_gwdt *gwdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&gwdt->wdd); - - return 0; -} - /* Disable watchdog if it is active during suspend */ static int __maybe_unused sbsa_gwdt_suspend(struct device *dev) { @@ -385,8 +367,6 @@ static struct platform_driver sbsa_gwdt_driver = { .of_match_table = sbsa_gwdt_of_match, }, .probe = sbsa_gwdt_probe, - .remove = sbsa_gwdt_remove, - .shutdown = sbsa_gwdt_shutdown, .id_table = sbsa_gwdt_pdev_match, }; diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index a7d6425db807..e7617b7df70b 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -220,7 +220,6 @@ static struct watchdog_device sh_wdt_dev = { static int sh_wdt_probe(struct platform_device *pdev) { struct sh_wdt *wdt; - struct resource *res; int rc; /* @@ -245,8 +244,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); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); diff --git a/drivers/watchdog/sirfsoc_wdt.c b/drivers/watchdog/sirfsoc_wdt.c index ac0c9d2c4aee..e79a4097d50b 100644 --- a/drivers/watchdog/sirfsoc_wdt.c +++ b/drivers/watchdog/sirfsoc_wdt.c @@ -146,22 +146,23 @@ static struct watchdog_device sirfsoc_wdd = { static int sirfsoc_wdt_probe(struct platform_device *pdev) { - struct resource *res; + struct device *dev = &pdev->dev; int ret; void __iomem *base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); watchdog_set_drvdata(&sirfsoc_wdd, (__force void *)base); - watchdog_init_timeout(&sirfsoc_wdd, timeout, &pdev->dev); + watchdog_init_timeout(&sirfsoc_wdd, timeout, dev); watchdog_set_nowayout(&sirfsoc_wdd, nowayout); - sirfsoc_wdd.parent = &pdev->dev; + sirfsoc_wdd.parent = dev; - ret = watchdog_register_device(&sirfsoc_wdd); + watchdog_stop_on_reboot(&sirfsoc_wdd); + watchdog_stop_on_unregister(&sirfsoc_wdd); + ret = devm_watchdog_register_device(dev, &sirfsoc_wdd); if (ret) return ret; @@ -170,19 +171,6 @@ static int sirfsoc_wdt_probe(struct platform_device *pdev) return 0; } -static void sirfsoc_wdt_shutdown(struct platform_device *pdev) -{ - struct watchdog_device *wdd = platform_get_drvdata(pdev); - - sirfsoc_wdt_disable(wdd); -} - -static int sirfsoc_wdt_remove(struct platform_device *pdev) -{ - sirfsoc_wdt_shutdown(pdev); - return 0; -} - #ifdef CONFIG_PM_SLEEP static int sirfsoc_wdt_suspend(struct device *dev) { @@ -220,8 +208,6 @@ static struct platform_driver sirfsoc_wdt_driver = { .of_match_table = sirfsoc_wdt_of_match, }, .probe = sirfsoc_wdt_probe, - .remove = sirfsoc_wdt_remove, - .shutdown = sirfsoc_wdt_shutdown, }; module_platform_driver(sirfsoc_wdt_driver); diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 41aaae2d5287..553735b256e2 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c @@ -395,9 +395,7 @@ static int sp5100_tco_probe(struct platform_device *pdev) wdd->min_timeout = 1; wdd->max_timeout = 0xffff; - if (watchdog_init_timeout(wdd, heartbeat, NULL)) - dev_info(dev, "timeout value invalid, using %d\n", - wdd->timeout); + watchdog_init_timeout(wdd, heartbeat, NULL); watchdog_set_nowayout(wdd, nowayout); watchdog_stop_on_reboot(wdd); watchdog_stop_on_unregister(wdd); diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c index ff9397d9638a..14874e9b207b 100644 --- a/drivers/watchdog/sprd_wdt.c +++ b/drivers/watchdog/sprd_wdt.c @@ -245,9 +245,7 @@ static u32 sprd_wdt_get_timeleft(struct watchdog_device *wdd) u32 val; val = sprd_wdt_get_cnt_value(wdt); - val = val / SPRD_WDT_CNT_STEP; - - return val; + return val / SPRD_WDT_CNT_STEP; } static const struct watchdog_ops sprd_wdt_ops = { @@ -269,70 +267,68 @@ static const struct watchdog_info sprd_wdt_info = { static int sprd_wdt_probe(struct platform_device *pdev) { - struct resource *wdt_res; + struct device *dev = &pdev->dev; struct sprd_wdt *wdt; int ret; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(&pdev->dev, wdt_res); + wdt->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - wdt->enable = devm_clk_get(&pdev->dev, "enable"); + wdt->enable = devm_clk_get(dev, "enable"); if (IS_ERR(wdt->enable)) { - dev_err(&pdev->dev, "can't get the enable clock\n"); + dev_err(dev, "can't get the enable clock\n"); return PTR_ERR(wdt->enable); } - wdt->rtc_enable = devm_clk_get(&pdev->dev, "rtc_enable"); + wdt->rtc_enable = devm_clk_get(dev, "rtc_enable"); if (IS_ERR(wdt->rtc_enable)) { - dev_err(&pdev->dev, "can't get the rtc enable clock\n"); + dev_err(dev, "can't get the rtc enable clock\n"); return PTR_ERR(wdt->rtc_enable); } wdt->irq = platform_get_irq(pdev, 0); if (wdt->irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ resource\n"); + dev_err(dev, "failed to get IRQ resource\n"); return wdt->irq; } - ret = devm_request_irq(&pdev->dev, wdt->irq, sprd_wdt_isr, - IRQF_NO_SUSPEND, "sprd-wdt", (void *)wdt); + ret = devm_request_irq(dev, wdt->irq, sprd_wdt_isr, IRQF_NO_SUSPEND, + "sprd-wdt", (void *)wdt); if (ret) { - dev_err(&pdev->dev, "failed to register irq\n"); + dev_err(dev, "failed to register irq\n"); return ret; } wdt->wdd.info = &sprd_wdt_info; wdt->wdd.ops = &sprd_wdt_ops; - wdt->wdd.parent = &pdev->dev; + wdt->wdd.parent = dev; wdt->wdd.min_timeout = SPRD_WDT_MIN_TIMEOUT; wdt->wdd.max_timeout = SPRD_WDT_MAX_TIMEOUT; wdt->wdd.timeout = SPRD_WDT_MAX_TIMEOUT; ret = sprd_wdt_enable(wdt); if (ret) { - dev_err(&pdev->dev, "failed to enable wdt\n"); + dev_err(dev, "failed to enable wdt\n"); return ret; } - ret = devm_add_action(&pdev->dev, sprd_wdt_disable, wdt); + ret = devm_add_action_or_reset(dev, sprd_wdt_disable, wdt); if (ret) { - sprd_wdt_disable(wdt); - dev_err(&pdev->dev, "Failed to add wdt disable action\n"); + dev_err(dev, "Failed to add wdt disable action\n"); return ret; } watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT); - watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev); + watchdog_init_timeout(&wdt->wdd, 0, dev); - ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd); + ret = devm_watchdog_register_device(dev, &wdt->wdd); if (ret) { sprd_wdt_disable(wdt); - dev_err(&pdev->dev, "failed to register watchdog\n"); + dev_err(dev, "failed to register watchdog\n"); return ret; } platform_set_drvdata(pdev, wdt); diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c index 177829b379da..7a90184eb950 100644 --- a/drivers/watchdog/st_lpc_wdt.c +++ b/drivers/watchdog/st_lpc_wdt.c @@ -142,13 +142,18 @@ static struct watchdog_device st_wdog_dev = { .ops = &st_wdog_ops, }; +static void st_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int st_wdog_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; const struct of_device_id *match; - struct device_node *np = pdev->dev.of_node; + struct device_node *np = dev->of_node; struct st_wdog *st_wdog; struct regmap *regmap; - struct resource *res; struct clk *clk; void __iomem *base; uint32_t mode; @@ -156,7 +161,7 @@ static int st_wdog_probe(struct platform_device *pdev) ret = of_property_read_u32(np, "st,lpc-mode", &mode); if (ret) { - dev_err(&pdev->dev, "An LPC mode must be provided\n"); + dev_err(dev, "An LPC mode must be provided\n"); return -EINVAL; } @@ -164,35 +169,34 @@ static int st_wdog_probe(struct platform_device *pdev) if (mode != ST_LPC_MODE_WDT) return -ENODEV; - st_wdog = devm_kzalloc(&pdev->dev, sizeof(*st_wdog), GFP_KERNEL); + st_wdog = devm_kzalloc(dev, sizeof(*st_wdog), GFP_KERNEL); if (!st_wdog) return -ENOMEM; - match = of_match_device(st_wdog_match, &pdev->dev); + match = of_match_device(st_wdog_match, dev); if (!match) { - dev_err(&pdev->dev, "Couldn't match device\n"); + dev_err(dev, "Couldn't match device\n"); return -ENODEV; } st_wdog->syscfg = (struct st_wdog_syscfg *)match->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); if (IS_ERR(regmap)) { - dev_err(&pdev->dev, "No syscfg phandle specified\n"); + dev_err(dev, "No syscfg phandle specified\n"); return PTR_ERR(regmap); } - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { - dev_err(&pdev->dev, "Unable to request clock\n"); + dev_err(dev, "Unable to request clock\n"); return PTR_ERR(clk); } - st_wdog->dev = &pdev->dev; + st_wdog->dev = dev; st_wdog->base = base; st_wdog->clk = clk; st_wdog->regmap = regmap; @@ -200,39 +204,38 @@ static int st_wdog_probe(struct platform_device *pdev) st_wdog->clkrate = clk_get_rate(st_wdog->clk); if (!st_wdog->clkrate) { - dev_err(&pdev->dev, "Unable to fetch clock rate\n"); + dev_err(dev, "Unable to fetch clock rate\n"); return -EINVAL; } st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate; - st_wdog_dev.parent = &pdev->dev; + st_wdog_dev.parent = dev; ret = clk_prepare_enable(clk); if (ret) { - dev_err(&pdev->dev, "Unable to enable clock\n"); + dev_err(dev, "Unable to enable clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, st_clk_disable_unprepare, clk); + if (ret) + return ret; watchdog_set_drvdata(&st_wdog_dev, st_wdog); watchdog_set_nowayout(&st_wdog_dev, WATCHDOG_NOWAYOUT); /* Init Watchdog timeout with value in DT */ - ret = watchdog_init_timeout(&st_wdog_dev, 0, &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "Unable to initialise watchdog timeout\n"); - clk_disable_unprepare(clk); + ret = watchdog_init_timeout(&st_wdog_dev, 0, dev); + if (ret) return ret; - } - ret = watchdog_register_device(&st_wdog_dev); + ret = devm_watchdog_register_device(dev, &st_wdog_dev); if (ret) { - dev_err(&pdev->dev, "Unable to register watchdog\n"); - clk_disable_unprepare(clk); + dev_err(dev, "Unable to register watchdog\n"); return ret; } st_wdog_setup(st_wdog, true); - dev_info(&pdev->dev, "LPC Watchdog driver registered, reset type is %s", + dev_info(dev, "LPC Watchdog driver registered, reset type is %s", st_wdog->warm_reset ? "warm" : "cold"); return ret; @@ -243,8 +246,6 @@ static int st_wdog_remove(struct platform_device *pdev) struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev); st_wdog_setup(st_wdog, false); - watchdog_unregister_device(&st_wdog_dev); - clk_disable_unprepare(st_wdog->clk); return 0; } diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c index e00e3b3526c6..d569a3634d9b 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c @@ -34,36 +34,44 @@ #define KR_KEY_EWA 0x5555 /* write access enable */ #define KR_KEY_DWA 0x0000 /* write access disable */ -/* IWDG_PR register bit values */ -#define PR_4 0x00 /* prescaler set to 4 */ -#define PR_8 0x01 /* prescaler set to 8 */ -#define PR_16 0x02 /* prescaler set to 16 */ -#define PR_32 0x03 /* prescaler set to 32 */ -#define PR_64 0x04 /* prescaler set to 64 */ -#define PR_128 0x05 /* prescaler set to 128 */ -#define PR_256 0x06 /* prescaler set to 256 */ +/* IWDG_PR register */ +#define PR_SHIFT 2 +#define PR_MIN BIT(PR_SHIFT) /* IWDG_RLR register values */ -#define RLR_MIN 0x07C /* min value supported by reload register */ -#define RLR_MAX 0xFFF /* max value supported by reload register */ +#define RLR_MIN 0x2 /* min value recommended */ +#define RLR_MAX GENMASK(11, 0) /* max value of reload register */ /* IWDG_SR register bit mask */ -#define FLAG_PVU BIT(0) /* Watchdog prescaler value update */ -#define FLAG_RVU BIT(1) /* Watchdog counter reload value update */ +#define SR_PVU BIT(0) /* Watchdog prescaler value update */ +#define SR_RVU BIT(1) /* Watchdog counter reload value update */ /* set timeout to 100000 us */ #define TIMEOUT_US 100000 #define SLEEP_US 1000 -#define HAS_PCLK true +struct stm32_iwdg_data { + bool has_pclk; + u32 max_prescaler; +}; + +static const struct stm32_iwdg_data stm32_iwdg_data = { + .has_pclk = false, + .max_prescaler = 256, +}; + +static const struct stm32_iwdg_data stm32mp1_iwdg_data = { + .has_pclk = true, + .max_prescaler = 1024, +}; struct stm32_iwdg { struct watchdog_device wdd; + const struct stm32_iwdg_data *data; void __iomem *regs; struct clk *clk_lsi; struct clk *clk_pclk; unsigned int rate; - bool has_pclk; }; static inline u32 reg_read(void __iomem *base, u32 reg) @@ -79,31 +87,35 @@ static inline void reg_write(void __iomem *base, u32 reg, u32 val) static int stm32_iwdg_start(struct watchdog_device *wdd) { struct stm32_iwdg *wdt = watchdog_get_drvdata(wdd); - u32 val = FLAG_PVU | FLAG_RVU; - u32 reload; + u32 tout, presc, iwdg_rlr, iwdg_pr, iwdg_sr; int ret; dev_dbg(wdd->parent, "%s\n", __func__); - /* prescaler fixed to 256 */ - reload = clamp_t(unsigned int, ((wdd->timeout * wdt->rate) / 256) - 1, - RLR_MIN, RLR_MAX); + tout = clamp_t(unsigned int, wdd->timeout, + wdd->min_timeout, wdd->max_hw_heartbeat_ms / 1000); + + presc = DIV_ROUND_UP(tout * wdt->rate, RLR_MAX + 1); + + /* The prescaler is align on power of 2 and start at 2 ^ PR_SHIFT. */ + presc = roundup_pow_of_two(presc); + iwdg_pr = presc <= 1 << PR_SHIFT ? 0 : ilog2(presc) - PR_SHIFT; + iwdg_rlr = ((tout * wdt->rate) / presc) - 1; /* enable write access */ reg_write(wdt->regs, IWDG_KR, KR_KEY_EWA); /* set prescaler & reload registers */ - reg_write(wdt->regs, IWDG_PR, PR_256); /* prescaler fix to 256 */ - reg_write(wdt->regs, IWDG_RLR, reload); + reg_write(wdt->regs, IWDG_PR, iwdg_pr); + reg_write(wdt->regs, IWDG_RLR, iwdg_rlr); reg_write(wdt->regs, IWDG_KR, KR_KEY_ENABLE); /* wait for the registers to be updated (max 100ms) */ - ret = readl_relaxed_poll_timeout(wdt->regs + IWDG_SR, val, - !(val & (FLAG_PVU | FLAG_RVU)), + ret = readl_relaxed_poll_timeout(wdt->regs + IWDG_SR, iwdg_sr, + !(iwdg_sr & (SR_PVU | SR_RVU)), SLEEP_US, TIMEOUT_US); if (ret) { - dev_err(wdd->parent, - "Fail to set prescaler or reload registers\n"); + dev_err(wdd->parent, "Fail to set prescaler, reload regs\n"); return ret; } @@ -138,38 +150,52 @@ static int stm32_iwdg_set_timeout(struct watchdog_device *wdd, return 0; } +static void stm32_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int stm32_iwdg_clk_init(struct platform_device *pdev, struct stm32_iwdg *wdt) { + struct device *dev = &pdev->dev; u32 ret; - wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi"); + wdt->clk_lsi = devm_clk_get(dev, "lsi"); if (IS_ERR(wdt->clk_lsi)) { - dev_err(&pdev->dev, "Unable to get lsi clock\n"); + dev_err(dev, "Unable to get lsi clock\n"); return PTR_ERR(wdt->clk_lsi); } /* optional peripheral clock */ - if (wdt->has_pclk) { - wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk"); + if (wdt->data->has_pclk) { + wdt->clk_pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(wdt->clk_pclk)) { - dev_err(&pdev->dev, "Unable to get pclk clock\n"); + dev_err(dev, "Unable to get pclk clock\n"); return PTR_ERR(wdt->clk_pclk); } ret = clk_prepare_enable(wdt->clk_pclk); if (ret) { - dev_err(&pdev->dev, "Unable to prepare pclk clock\n"); + dev_err(dev, "Unable to prepare pclk clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, + stm32_clk_disable_unprepare, + wdt->clk_pclk); + if (ret) + return ret; } ret = clk_prepare_enable(wdt->clk_lsi); if (ret) { - dev_err(&pdev->dev, "Unable to prepare lsi clock\n"); - clk_disable_unprepare(wdt->clk_pclk); + dev_err(dev, "Unable to prepare lsi clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, stm32_clk_disable_unprepare, + wdt->clk_lsi); + if (ret) + return ret; wdt->rate = clk_get_rate(wdt->clk_lsi); @@ -191,35 +217,31 @@ static const struct watchdog_ops stm32_iwdg_ops = { }; static const struct of_device_id stm32_iwdg_of_match[] = { - { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK }, - { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK }, + { .compatible = "st,stm32-iwdg", .data = &stm32_iwdg_data }, + { .compatible = "st,stm32mp1-iwdg", .data = &stm32mp1_iwdg_data }, { /* end node */ } }; MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); static int stm32_iwdg_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct watchdog_device *wdd; - const struct of_device_id *match; struct stm32_iwdg *wdt; - struct resource *res; int ret; - match = of_match_device(stm32_iwdg_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; - wdt->has_pclk = match->data; + wdt->data = of_device_get_match_data(&pdev->dev); + if (!wdt->data) + return -ENODEV; /* This is the timer base. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->regs = devm_ioremap_resource(&pdev->dev, res); + wdt->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->regs)) { - dev_err(&pdev->dev, "Could not get resource\n"); + dev_err(dev, "Could not get resource\n"); return PTR_ERR(wdt->regs); } @@ -229,50 +251,30 @@ static int stm32_iwdg_probe(struct platform_device *pdev) /* Initialize struct watchdog_device. */ wdd = &wdt->wdd; + wdd->parent = dev; wdd->info = &stm32_iwdg_info; wdd->ops = &stm32_iwdg_ops; - wdd->min_timeout = ((RLR_MIN + 1) * 256) / wdt->rate; - wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * 256 * 1000) / wdt->rate; - wdd->parent = &pdev->dev; + wdd->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, wdt->rate); + wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler * + 1000) / wdt->rate; watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT); + watchdog_init_timeout(wdd, 0, dev); - ret = watchdog_init_timeout(wdd, 0, &pdev->dev); - if (ret) - dev_warn(&pdev->dev, - "unable to set timeout value, using default\n"); - - ret = watchdog_register_device(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { - dev_err(&pdev->dev, "failed to register watchdog device\n"); - goto err; + dev_err(dev, "failed to register watchdog device\n"); + return ret; } platform_set_drvdata(pdev, wdt); return 0; -err: - clk_disable_unprepare(wdt->clk_lsi); - clk_disable_unprepare(wdt->clk_pclk); - - return ret; -} - -static int stm32_iwdg_remove(struct platform_device *pdev) -{ - struct stm32_iwdg *wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&wdt->wdd); - clk_disable_unprepare(wdt->clk_lsi); - clk_disable_unprepare(wdt->clk_pclk); - - return 0; } static struct platform_driver stm32_iwdg_driver = { .probe = stm32_iwdg_probe, - .remove = stm32_iwdg_remove, .driver = { .name = "iwdg", .of_match_table = of_match_ptr(stm32_iwdg_of_match), diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index 994c54cc68e9..671f4ba7b4ed 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c @@ -89,31 +89,31 @@ static struct notifier_block wdt_notifier = { static int stmp3xxx_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret; - watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev); + watchdog_set_drvdata(&stmp3xxx_wdd, dev); stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT); - stmp3xxx_wdd.parent = &pdev->dev; + stmp3xxx_wdd.parent = dev; - ret = watchdog_register_device(&stmp3xxx_wdd); + ret = devm_watchdog_register_device(dev, &stmp3xxx_wdd); if (ret < 0) { - dev_err(&pdev->dev, "cannot register watchdog device\n"); + dev_err(dev, "cannot register watchdog device\n"); return ret; } if (register_reboot_notifier(&wdt_notifier)) - dev_warn(&pdev->dev, "cannot register reboot notifier\n"); + dev_warn(dev, "cannot register reboot notifier\n"); - dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n", - stmp3xxx_wdd.timeout); + dev_info(dev, "initialized watchdog with heartbeat %ds\n", + stmp3xxx_wdd.timeout); return 0; } static int stmp3xxx_wdt_remove(struct platform_device *pdev) { unregister_reboot_notifier(&wdt_notifier); - watchdog_unregister_device(&stmp3xxx_wdd); return 0; } diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c index ad431d8ad95f..45d0c543466f 100644 --- a/drivers/watchdog/stpmic1_wdt.c +++ b/drivers/watchdog/stpmic1_wdt.c @@ -81,18 +81,19 @@ static const struct watchdog_ops pmic_watchdog_ops = { static int pmic_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret; struct stpmic1 *pmic; struct stpmic1_wdt *wdt; - if (!pdev->dev.parent) + if (!dev->parent) return -EINVAL; - pmic = dev_get_drvdata(pdev->dev.parent); + pmic = dev_get_drvdata(dev->parent); if (!pmic) return -EINVAL; - wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(struct stpmic1_wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -102,15 +103,15 @@ static int pmic_wdt_probe(struct platform_device *pdev) wdt->wdtdev.ops = &pmic_watchdog_ops; wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT; wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT; - wdt->wdtdev.parent = &pdev->dev; + wdt->wdtdev.parent = dev; wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT; - watchdog_init_timeout(&wdt->wdtdev, 0, &pdev->dev); + watchdog_init_timeout(&wdt->wdtdev, 0, dev); watchdog_set_nowayout(&wdt->wdtdev, nowayout); watchdog_set_drvdata(&wdt->wdtdev, wdt); - ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev); + ret = devm_watchdog_register_device(dev, &wdt->wdtdev); if (ret) return ret; diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index c6c73656997e..9c22f7753c6b 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c @@ -233,20 +233,19 @@ MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids); static int sunxi_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct sunxi_wdt_dev *sunxi_wdt; - struct resource *res; int err; - sunxi_wdt = devm_kzalloc(&pdev->dev, sizeof(*sunxi_wdt), GFP_KERNEL); + sunxi_wdt = devm_kzalloc(dev, sizeof(*sunxi_wdt), GFP_KERNEL); if (!sunxi_wdt) return -EINVAL; - sunxi_wdt->wdt_regs = of_device_get_match_data(&pdev->dev); + sunxi_wdt->wdt_regs = of_device_get_match_data(dev); if (!sunxi_wdt->wdt_regs) return -ENODEV; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sunxi_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); + sunxi_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sunxi_wdt->wdt_base)) return PTR_ERR(sunxi_wdt->wdt_base); @@ -255,9 +254,9 @@ static int sunxi_wdt_probe(struct platform_device *pdev) sunxi_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; sunxi_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT; sunxi_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT; - sunxi_wdt->wdt_dev.parent = &pdev->dev; + sunxi_wdt->wdt_dev.parent = dev; - watchdog_init_timeout(&sunxi_wdt->wdt_dev, timeout, &pdev->dev); + watchdog_init_timeout(&sunxi_wdt->wdt_dev, timeout, dev); watchdog_set_nowayout(&sunxi_wdt->wdt_dev, nowayout); watchdog_set_restart_priority(&sunxi_wdt->wdt_dev, 128); @@ -266,12 +265,12 @@ static int sunxi_wdt_probe(struct platform_device *pdev) sunxi_wdt_stop(&sunxi_wdt->wdt_dev); watchdog_stop_on_reboot(&sunxi_wdt->wdt_dev); - err = devm_watchdog_register_device(&pdev->dev, &sunxi_wdt->wdt_dev); + err = devm_watchdog_register_device(dev, &sunxi_wdt->wdt_dev); if (unlikely(err)) return err; - dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", - sunxi_wdt->wdt_dev.timeout, nowayout); + dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", + sunxi_wdt->wdt_dev.timeout, nowayout); return 0; } diff --git a/drivers/watchdog/tangox_wdt.c b/drivers/watchdog/tangox_wdt.c index d0b53f3c0d17..1afb0e9d808c 100644 --- a/drivers/watchdog/tangox_wdt.c +++ b/drivers/watchdog/tangox_wdt.c @@ -108,10 +108,14 @@ static const struct watchdog_ops tangox_wdt_ops = { .restart = tangox_wdt_restart, }; +static void tangox_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int tangox_wdt_probe(struct platform_device *pdev) { struct tangox_wdt_device *dev; - struct resource *res; u32 config; int err; @@ -119,8 +123,7 @@ static int tangox_wdt_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->base = devm_ioremap_resource(&pdev->dev, res); + dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->base)) return PTR_ERR(dev->base); @@ -131,12 +134,14 @@ static int tangox_wdt_probe(struct platform_device *pdev) err = clk_prepare_enable(dev->clk); if (err) return err; + err = devm_add_action_or_reset(&pdev->dev, + tangox_clk_disable_unprepare, dev->clk); + if (err) + return err; dev->clk_rate = clk_get_rate(dev->clk); - if (!dev->clk_rate) { - err = -EINVAL; - goto err; - } + if (!dev->clk_rate) + return -EINVAL; dev->wdt.parent = &pdev->dev; dev->wdt.info = &tangox_wdt_info; @@ -170,31 +175,16 @@ static int tangox_wdt_probe(struct platform_device *pdev) watchdog_set_restart_priority(&dev->wdt, 128); - err = watchdog_register_device(&dev->wdt); + watchdog_stop_on_unregister(&dev->wdt); + err = devm_watchdog_register_device(&pdev->dev, &dev->wdt); if (err) - goto err; + return err; platform_set_drvdata(pdev, dev); dev_info(&pdev->dev, "SMP86xx/SMP87xx watchdog registered\n"); return 0; - - err: - clk_disable_unprepare(dev->clk); - return err; -} - -static int tangox_wdt_remove(struct platform_device *pdev) -{ - struct tangox_wdt_device *dev = platform_get_drvdata(pdev); - - tangox_wdt_stop(&dev->wdt); - clk_disable_unprepare(dev->clk); - - watchdog_unregister_device(&dev->wdt); - - return 0; } static const struct of_device_id tangox_wdt_dt_ids[] = { @@ -206,7 +196,6 @@ MODULE_DEVICE_TABLE(of, tangox_wdt_dt_ids); static struct platform_driver tangox_wdt_driver = { .probe = tangox_wdt_probe, - .remove = tangox_wdt_remove, .driver = { .name = "tangox-wdt", .of_match_table = tangox_wdt_dt_ids, diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c index 877dd39bd41f..a58b000acc4f 100644 --- a/drivers/watchdog/tegra_wdt.c +++ b/drivers/watchdog/tegra_wdt.c @@ -181,15 +181,14 @@ static const struct watchdog_ops tegra_wdt_ops = { static int tegra_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct tegra_wdt *wdt; - struct resource *res; void __iomem *regs; int ret; /* This is the timer base. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); @@ -197,7 +196,7 @@ static int tegra_wdt_probe(struct platform_device *pdev) * Allocate our watchdog driver data, which has the * struct watchdog_device nested within it. */ - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -212,39 +211,27 @@ static int tegra_wdt_probe(struct platform_device *pdev) wdd->ops = &tegra_wdt_ops; wdd->min_timeout = MIN_WDT_TIMEOUT; wdd->max_timeout = MAX_WDT_TIMEOUT; - wdd->parent = &pdev->dev; + wdd->parent = dev; watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, nowayout); - ret = devm_watchdog_register_device(&pdev->dev, wdd); + watchdog_stop_on_unregister(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { - dev_err(&pdev->dev, - "failed to register watchdog device\n"); + dev_err(dev, "failed to register watchdog device\n"); return ret; } platform_set_drvdata(pdev, wdt); - dev_info(&pdev->dev, - "initialized (heartbeat = %d sec, nowayout = %d)\n", + dev_info(dev, "initialized (heartbeat = %d sec, nowayout = %d)\n", heartbeat, nowayout); return 0; } -static int tegra_wdt_remove(struct platform_device *pdev) -{ - struct tegra_wdt *wdt = platform_get_drvdata(pdev); - - tegra_wdt_stop(&wdt->wdd); - - dev_info(&pdev->dev, "removed wdt\n"); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int tegra_wdt_runtime_suspend(struct device *dev) { @@ -280,7 +267,6 @@ static const struct dev_pm_ops tegra_wdt_pm_ops = { static struct platform_driver tegra_wdt_driver = { .probe = tegra_wdt_probe, - .remove = tegra_wdt_remove, .driver = { .name = "tegra-wdt", .pm = &tegra_wdt_pm_ops, diff --git a/drivers/watchdog/tqmx86_wdt.c b/drivers/watchdog/tqmx86_wdt.c index 52941207a12a..72d0b0adde38 100644 --- a/drivers/watchdog/tqmx86_wdt.c +++ b/drivers/watchdog/tqmx86_wdt.c @@ -70,11 +70,12 @@ static struct watchdog_ops tqmx86_wdt_ops = { static int tqmx86_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct tqmx86_wdt *priv; struct resource *res; int err; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -82,14 +83,13 @@ static int tqmx86_wdt_probe(struct platform_device *pdev) if (!res) return -ENODEV; - priv->io_base = devm_ioport_map(&pdev->dev, res->start, - resource_size(res)); + priv->io_base = devm_ioport_map(dev, res->start, resource_size(res)); if (!priv->io_base) return -ENOMEM; watchdog_set_drvdata(&priv->wdd, priv); - priv->wdd.parent = &pdev->dev; + priv->wdd.parent = dev; priv->wdd.info = &tqmx86_wdt_info; priv->wdd.ops = &tqmx86_wdt_ops; priv->wdd.min_timeout = 1; @@ -97,16 +97,16 @@ static int tqmx86_wdt_probe(struct platform_device *pdev) priv->wdd.max_hw_heartbeat_ms = 4096*1000; priv->wdd.timeout = WDT_TIMEOUT; - watchdog_init_timeout(&priv->wdd, timeout, &pdev->dev); + watchdog_init_timeout(&priv->wdd, timeout, dev); watchdog_set_nowayout(&priv->wdd, WATCHDOG_NOWAYOUT); tqmx86_wdt_set_timeout(&priv->wdd, priv->wdd.timeout); - err = devm_watchdog_register_device(&pdev->dev, &priv->wdd); + err = devm_watchdog_register_device(dev, &priv->wdd); if (err) return err; - dev_info(&pdev->dev, "TQMx86 watchdog\n"); + dev_info(dev, "TQMx86 watchdog\n"); return 0; } diff --git a/drivers/watchdog/ts4800_wdt.c b/drivers/watchdog/ts4800_wdt.c index 89843b16b04a..9dc6d7f45806 100644 --- a/drivers/watchdog/ts4800_wdt.c +++ b/drivers/watchdog/ts4800_wdt.c @@ -108,7 +108,8 @@ static const struct watchdog_info ts4800_wdt_info = { static int ts4800_wdt_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct device_node *syscon_np; struct watchdog_device *wdd; struct ts4800_wdt *wdt; @@ -117,18 +118,18 @@ static int ts4800_wdt_probe(struct platform_device *pdev) syscon_np = of_parse_phandle(np, "syscon", 0); if (!syscon_np) { - dev_err(&pdev->dev, "no syscon property\n"); + dev_err(dev, "no syscon property\n"); return -ENODEV; } ret = of_property_read_u32_index(np, "syscon", 1, ®); if (ret < 0) { - dev_err(&pdev->dev, "no offset in syscon\n"); + dev_err(dev, "no offset in syscon\n"); return ret; } /* allocate memory for watchdog struct */ - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -137,13 +138,13 @@ static int ts4800_wdt_probe(struct platform_device *pdev) wdt->regmap = syscon_node_to_regmap(syscon_np); of_node_put(syscon_np); if (IS_ERR(wdt->regmap)) { - dev_err(&pdev->dev, "cannot get parent's regmap\n"); + dev_err(dev, "cannot get parent's regmap\n"); return PTR_ERR(wdt->regmap); } /* Initialize struct watchdog_device */ wdd = &wdt->wdd; - wdd->parent = &pdev->dev; + wdd->parent = dev; wdd->info = &ts4800_wdt_info; wdd->ops = &ts4800_wdt_ops; wdd->min_timeout = ts4800_wdt_map[0].timeout; @@ -151,7 +152,7 @@ static int ts4800_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, nowayout); - watchdog_init_timeout(wdd, 0, &pdev->dev); + watchdog_init_timeout(wdd, 0, dev); /* * As this watchdog supports only a few values, ts4800_wdt_set_timeout @@ -169,31 +170,20 @@ static int ts4800_wdt_probe(struct platform_device *pdev) */ ts4800_wdt_stop(wdd); - ret = watchdog_register_device(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) { - dev_err(&pdev->dev, - "failed to register watchdog device\n"); + dev_err(dev, "failed to register watchdog device\n"); return ret; } platform_set_drvdata(pdev, wdt); - dev_info(&pdev->dev, - "initialized (timeout = %d sec, nowayout = %d)\n", + dev_info(dev, "initialized (timeout = %d sec, nowayout = %d)\n", wdd->timeout, nowayout); return 0; } -static int ts4800_wdt_remove(struct platform_device *pdev) -{ - struct ts4800_wdt *wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&wdt->wdd); - - return 0; -} - static const struct of_device_id ts4800_wdt_of_match[] = { { .compatible = "technologic,ts4800-wdt", }, { }, @@ -202,7 +192,6 @@ MODULE_DEVICE_TABLE(of, ts4800_wdt_of_match); static struct platform_driver ts4800_wdt_driver = { .probe = ts4800_wdt_probe, - .remove = ts4800_wdt_remove, .driver = { .name = "ts4800_wdt", .of_match_table = ts4800_wdt_of_match, diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 811e43c39ec4..bf918f5fa131 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -122,22 +122,20 @@ static const struct watchdog_ops ts72xx_wdt_ops = { static int ts72xx_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct ts72xx_wdt_priv *priv; struct watchdog_device *wdd; - struct resource *res; int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->control_reg = devm_ioremap_resource(&pdev->dev, res); + priv->control_reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->control_reg)) return PTR_ERR(priv->control_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->feed_reg = devm_ioremap_resource(&pdev->dev, res); + priv->feed_reg = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->feed_reg)) return PTR_ERR(priv->feed_reg); @@ -146,20 +144,20 @@ static int ts72xx_wdt_probe(struct platform_device *pdev) wdd->ops = &ts72xx_wdt_ops; wdd->min_timeout = 1; wdd->max_hw_heartbeat_ms = 8000; - wdd->parent = &pdev->dev; + wdd->parent = dev; watchdog_set_nowayout(wdd, nowayout); wdd->timeout = TS72XX_WDT_DEFAULT_TIMEOUT; - watchdog_init_timeout(wdd, timeout, &pdev->dev); + watchdog_init_timeout(wdd, timeout, dev); watchdog_set_drvdata(wdd, priv); - ret = devm_watchdog_register_device(&pdev->dev, wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) return ret; - dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); + dev_info(dev, "TS-72xx Watchdog driver\n"); return 0; } diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c index 569fe85e52da..74c5737cd934 100644 --- a/drivers/watchdog/twl4030_wdt.c +++ b/drivers/watchdog/twl4030_wdt.c @@ -70,10 +70,10 @@ static const struct watchdog_ops twl4030_wdt_ops = { static int twl4030_wdt_probe(struct platform_device *pdev) { - int ret = 0; + struct device *dev = &pdev->dev; struct watchdog_device *wdt; - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) return -ENOMEM; @@ -83,27 +83,14 @@ static int twl4030_wdt_probe(struct platform_device *pdev) wdt->timeout = 30; wdt->min_timeout = 1; wdt->max_timeout = 30; - wdt->parent = &pdev->dev; + wdt->parent = dev; watchdog_set_nowayout(wdt, nowayout); platform_set_drvdata(pdev, wdt); twl4030_wdt_stop(wdt); - ret = watchdog_register_device(wdt); - if (ret) - return ret; - - return 0; -} - -static int twl4030_wdt_remove(struct platform_device *pdev) -{ - struct watchdog_device *wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(wdt); - - return 0; + return devm_watchdog_register_device(dev, wdt); } #ifdef CONFIG_PM @@ -137,7 +124,6 @@ MODULE_DEVICE_TABLE(of, twl_wdt_of_match); static struct platform_driver twl4030_wdt_driver = { .probe = twl4030_wdt_probe, - .remove = twl4030_wdt_remove, .suspend = twl4030_wdt_suspend, .resume = twl4030_wdt_resume, .driver = { diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 6f7a9deb27d0..fcb4da5b1f4c 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -103,7 +103,6 @@ static struct watchdog_device txx9wdt = { static int __init txx9wdt_probe(struct platform_device *dev) { - struct resource *res; int ret; txx9_imclk = clk_get(NULL, "imbus_clk"); @@ -119,8 +118,7 @@ static int __init txx9wdt_probe(struct platform_device *dev) goto exit; } - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - txx9wdt_reg = devm_ioremap_resource(&dev->dev, res); + txx9wdt_reg = devm_platform_ioremap_resource(dev, 0); if (IS_ERR(txx9wdt_reg)) { ret = PTR_ERR(txx9wdt_reg); goto exit; diff --git a/drivers/watchdog/uniphier_wdt.c b/drivers/watchdog/uniphier_wdt.c index e20a7a459d69..8e9242c23022 100644 --- a/drivers/watchdog/uniphier_wdt.c +++ b/drivers/watchdog/uniphier_wdt.c @@ -191,8 +191,6 @@ static int uniphier_wdt_probe(struct platform_device *pdev) if (!wdev) return -ENOMEM; - platform_set_drvdata(pdev, wdev); - parent = of_get_parent(dev->of_node); /* parent should be syscon node */ regmap = syscon_node_to_regmap(parent); of_node_put(parent); diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index 37c084353cce..9fa7f95f7554 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -86,8 +86,9 @@ static struct watchdog_device ux500_wdt = { static int ux500_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int ret; - struct ux500_wdt_data *pdata = dev_get_platdata(&pdev->dev); + struct ux500_wdt_data *pdata = dev_get_platdata(dev); if (pdata) { if (pdata->timeout > 0) @@ -96,7 +97,7 @@ static int ux500_wdt_probe(struct platform_device *pdev) ux500_wdt.max_timeout = WATCHDOG_MAX28; } - ux500_wdt.parent = &pdev->dev; + ux500_wdt.parent = dev; watchdog_set_nowayout(&ux500_wdt, nowayout); /* disable auto off on sleep */ @@ -105,18 +106,11 @@ static int ux500_wdt_probe(struct platform_device *pdev) /* set HW initial value */ prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000); - ret = watchdog_register_device(&ux500_wdt); + ret = devm_watchdog_register_device(dev, &ux500_wdt); if (ret) return ret; - dev_info(&pdev->dev, "initialized\n"); - - return 0; -} - -static int ux500_wdt_remove(struct platform_device *dev) -{ - watchdog_unregister_device(&ux500_wdt); + dev_info(dev, "initialized\n"); return 0; } @@ -153,7 +147,6 @@ static int ux500_wdt_resume(struct platform_device *pdev) static struct platform_driver ux500_wdt_driver = { .probe = ux500_wdt_probe, - .remove = ux500_wdt_remove, .suspend = ux500_wdt_suspend, .resume = ux500_wdt_resume, .driver = { diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index eb8fa25f8eb2..62be9e52a4de 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -105,34 +105,48 @@ static void watchdog_check_min_max_timeout(struct watchdog_device *wdd) * timeout module parameter (if it is valid value) or the timeout-sec property * (only if it is a valid value and the timeout_parm is out of bounds). * If none of them are valid then we keep the old value (which should normally - * be the default timeout value). + * be the default timeout value). Note that for the module parameter, '0' means + * 'use default' while it is an invalid value for the timeout-sec property. + * It should simply be dropped if you want to use the default value then. * - * A zero is returned on success and -EINVAL for failure. + * A zero is returned on success or -EINVAL if all provided values are out of + * bounds. */ int watchdog_init_timeout(struct watchdog_device *wdd, unsigned int timeout_parm, struct device *dev) { + const char *dev_str = wdd->parent ? dev_name(wdd->parent) : + (const char *)wdd->info->identity; unsigned int t = 0; int ret = 0; watchdog_check_min_max_timeout(wdd); - /* try to get the timeout module parameter first */ - if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) { - wdd->timeout = timeout_parm; - return ret; - } - if (timeout_parm) + /* check the driver supplied value (likely a module parameter) first */ + if (timeout_parm) { + if (!watchdog_timeout_invalid(wdd, timeout_parm)) { + wdd->timeout = timeout_parm; + return 0; + } + pr_err("%s: driver supplied timeout (%u) out of range\n", + dev_str, timeout_parm); ret = -EINVAL; + } /* try to get the timeout_sec property */ - if (dev == NULL || dev->of_node == NULL) - return ret; - of_property_read_u32(dev->of_node, "timeout-sec", &t); - if (!watchdog_timeout_invalid(wdd, t) && t) - wdd->timeout = t; - else + if (dev && dev->of_node && + of_property_read_u32(dev->of_node, "timeout-sec", &t) == 0) { + if (t && !watchdog_timeout_invalid(wdd, t)) { + wdd->timeout = t; + return 0; + } + pr_err("%s: DT supplied timeout (%u) out of range\n", dev_str, t); ret = -EINVAL; + } + + if (ret < 0 && wdd->timeout) + pr_warn("%s: falling back to default timeout (%u)\n", dev_str, + wdd->timeout); return ret; } diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 56ad19608a9b..430ee4e9b185 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -287,7 +287,7 @@ static unsigned int wdat_wdt_get_timeleft(struct watchdog_device *wdd) struct wdat_wdt *wdat = to_wdat_wdt(wdd); u32 periods = 0; - wdat_wdt_run_action(wdat, ACPI_WDAT_GET_COUNTDOWN, 0, &periods); + wdat_wdt_run_action(wdat, ACPI_WDAT_GET_CURRENT_COUNTDOWN, 0, &periods); return periods * wdat->period / 1000; } @@ -308,6 +308,7 @@ static const struct watchdog_ops wdat_wdt_ops = { static int wdat_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; const struct acpi_wdat_entry *entries; const struct acpi_table_wdat *tbl; struct wdat_wdt *wdat; @@ -321,11 +322,11 @@ static int wdat_wdt_probe(struct platform_device *pdev) if (ACPI_FAILURE(status)) return -ENODEV; - wdat = devm_kzalloc(&pdev->dev, sizeof(*wdat), GFP_KERNEL); + wdat = devm_kzalloc(dev, sizeof(*wdat), GFP_KERNEL); if (!wdat) return -ENOMEM; - regs = devm_kcalloc(&pdev->dev, pdev->num_resources, sizeof(*regs), + regs = devm_kcalloc(dev, pdev->num_resources, sizeof(*regs), GFP_KERNEL); if (!regs) return -ENOMEM; @@ -350,15 +351,15 @@ static int wdat_wdt_probe(struct platform_device *pdev) res = &pdev->resource[i]; if (resource_type(res) == IORESOURCE_MEM) { - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_ioremap_resource(dev, res); if (IS_ERR(reg)) return PTR_ERR(reg); } else if (resource_type(res) == IORESOURCE_IO) { - reg = devm_ioport_map(&pdev->dev, res->start, 1); + reg = devm_ioport_map(dev, res->start, 1); if (!reg) return -ENOMEM; } else { - dev_err(&pdev->dev, "Unsupported resource\n"); + dev_err(dev, "Unsupported resource\n"); return -EINVAL; } @@ -376,12 +377,11 @@ static int wdat_wdt_probe(struct platform_device *pdev) action = entries[i].action; if (action >= MAX_WDAT_ACTIONS) { - dev_dbg(&pdev->dev, "Skipping unknown action: %u\n", - action); + dev_dbg(dev, "Skipping unknown action: %u\n", action); continue; } - instr = devm_kzalloc(&pdev->dev, sizeof(*instr), GFP_KERNEL); + instr = devm_kzalloc(dev, sizeof(*instr), GFP_KERNEL); if (!instr) return -ENOMEM; @@ -398,7 +398,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { r.flags = IORESOURCE_IO; } else { - dev_dbg(&pdev->dev, "Unsupported address space: %d\n", + dev_dbg(dev, "Unsupported address space: %d\n", gas->space_id); continue; } @@ -413,14 +413,15 @@ static int wdat_wdt_probe(struct platform_device *pdev) } if (!instr->reg) { - dev_err(&pdev->dev, "I/O resource not found\n"); + dev_err(dev, "I/O resource not found\n"); return -EINVAL; } instructions = wdat->instructions[action]; if (!instructions) { - instructions = devm_kzalloc(&pdev->dev, - sizeof(*instructions), GFP_KERNEL); + instructions = devm_kzalloc(dev, + sizeof(*instructions), + GFP_KERNEL); if (!instructions) return -ENOMEM; @@ -441,7 +442,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdat); watchdog_set_nowayout(&wdat->wdd, nowayout); - return devm_watchdog_register_device(&pdev->dev, &wdat->wdd); + return devm_watchdog_register_device(dev, &wdat->wdd); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 116c2f47b463..9b6565a3fab4 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -180,8 +180,9 @@ static const struct watchdog_ops wm831x_wdt_ops = { static int wm831x_wdt_probe(struct platform_device *pdev) { - struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *chip_pdata = dev_get_platdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct wm831x *wm831x = dev_get_drvdata(dev->parent); + struct wm831x_pdata *chip_pdata = dev_get_platdata(dev->parent); struct wm831x_watchdog_pdata *pdata; struct wm831x_wdt_drvdata *driver_data; struct watchdog_device *wm831x_wdt; @@ -198,8 +199,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) if (reg & WM831X_WDOG_DEBUG) dev_warn(wm831x->dev, "Watchdog is paused\n"); - driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data), - GFP_KERNEL); + driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); if (!driver_data) return -ENOMEM; @@ -210,7 +210,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) wm831x_wdt->info = &wm831x_wdt_info; wm831x_wdt->ops = &wm831x_wdt_ops; - wm831x_wdt->parent = &pdev->dev; + wm831x_wdt->parent = dev; watchdog_set_nowayout(wm831x_wdt, nowayout); watchdog_set_drvdata(wm831x_wdt, driver_data); @@ -240,10 +240,9 @@ static int wm831x_wdt_probe(struct platform_device *pdev) reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT; if (pdata->update_gpio) { - ret = devm_gpio_request_one(&pdev->dev, - pdata->update_gpio, - GPIOF_OUT_INIT_LOW, - "Watchdog update"); + ret = devm_gpio_request_one(dev, pdata->update_gpio, + GPIOF_OUT_INIT_LOW, + "Watchdog update"); if (ret < 0) { dev_err(wm831x->dev, "Failed to request update GPIO: %d\n", @@ -268,7 +267,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) } } - ret = devm_watchdog_register_device(&pdev->dev, &driver_data->wdt); + ret = devm_watchdog_register_device(dev, &driver_data->wdt); if (ret != 0) { dev_err(wm831x->dev, "watchdog_register_device() failed: %d\n", ret); diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c index f1c016d015b3..25a1af5e1787 100644 --- a/drivers/watchdog/xen_wdt.c +++ b/drivers/watchdog/xen_wdt.c @@ -122,35 +122,33 @@ static struct watchdog_device xen_wdt_dev = { static int xen_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct sched_watchdog wd = { .id = ~0 }; int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd); if (ret == -ENOSYS) { - dev_err(&pdev->dev, "watchdog not supported by hypervisor\n"); + dev_err(dev, "watchdog not supported by hypervisor\n"); return -ENODEV; } if (ret != -EINVAL) { - dev_err(&pdev->dev, "unexpected hypervisor error (%d)\n", ret); + dev_err(dev, "unexpected hypervisor error (%d)\n", ret); return -ENODEV; } - if (watchdog_init_timeout(&xen_wdt_dev, timeout, NULL)) - dev_info(&pdev->dev, "timeout value invalid, using %d\n", - xen_wdt_dev.timeout); + watchdog_init_timeout(&xen_wdt_dev, timeout, NULL); watchdog_set_nowayout(&xen_wdt_dev, nowayout); watchdog_stop_on_reboot(&xen_wdt_dev); watchdog_stop_on_unregister(&xen_wdt_dev); - ret = devm_watchdog_register_device(&pdev->dev, &xen_wdt_dev); + ret = devm_watchdog_register_device(dev, &xen_wdt_dev); if (ret) { - dev_err(&pdev->dev, "cannot register watchdog device (%d)\n", - ret); + dev_err(dev, "cannot register watchdog device (%d)\n", ret); return ret; } - dev_info(&pdev->dev, "initialized (timeout=%ds, nowayout=%d)\n", - xen_wdt_dev.timeout, nowayout); + dev_info(dev, "initialized (timeout=%ds, nowayout=%d)\n", + xen_wdt_dev.timeout, nowayout); return 0; } diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c index d3594aa3a374..43e6b575c32c 100644 --- a/drivers/watchdog/ziirave_wdt.c +++ b/drivers/watchdog/ziirave_wdt.c @@ -658,11 +658,7 @@ static int ziirave_wdt_probe(struct i2c_client *client, w_priv->wdd.parent = &client->dev; w_priv->wdd.groups = ziirave_wdt_groups; - ret = watchdog_init_timeout(&w_priv->wdd, wdt_timeout, &client->dev); - if (ret) { - dev_info(&client->dev, - "Unable to select timeout value, using default\n"); - } + watchdog_init_timeout(&w_priv->wdd, wdt_timeout, &client->dev); /* * The default value set in the watchdog should be perfectly valid, so diff --git a/drivers/watchdog/zx2967_wdt.c b/drivers/watchdog/zx2967_wdt.c index 9261f7c77f6d..c8549bf07cc9 100644 --- a/drivers/watchdog/zx2967_wdt.c +++ b/drivers/watchdog/zx2967_wdt.c @@ -188,11 +188,15 @@ static void zx2967_wdt_reset_sysctrl(struct device *dev) of_node_put(out_args.np); } +static void zx2967_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int zx2967_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct zx2967_wdt *wdt; - struct resource *base; int ret; struct reset_control *rstc; @@ -207,10 +211,9 @@ static int zx2967_wdt_probe(struct platform_device *pdev) wdt->wdt_device.timeout = ZX2967_WDT_DEFAULT_TIMEOUT; wdt->wdt_device.max_timeout = ZX2967_WDT_MAX_TIMEOUT; wdt->wdt_device.min_timeout = ZX2967_WDT_MIN_TIMEOUT; - wdt->wdt_device.parent = &pdev->dev; + wdt->wdt_device.parent = dev; - base = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->reg_base = devm_ioremap_resource(dev, base); + wdt->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wdt->reg_base)) return PTR_ERR(wdt->reg_base); @@ -227,13 +230,16 @@ static int zx2967_wdt_probe(struct platform_device *pdev) dev_err(dev, "failed to enable clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, zx2967_clk_disable_unprepare, + wdt->clock); + if (ret) + return ret; clk_set_rate(wdt->clock, ZX2967_WDT_CLK_FREQ); rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(rstc)) { dev_err(dev, "failed to get rstc"); - ret = PTR_ERR(rstc); - goto err; + return PTR_ERR(rstc); } reset_control_assert(rstc); @@ -244,28 +250,14 @@ static int zx2967_wdt_probe(struct platform_device *pdev) ZX2967_WDT_DEFAULT_TIMEOUT, dev); watchdog_set_nowayout(&wdt->wdt_device, WATCHDOG_NOWAYOUT); - ret = watchdog_register_device(&wdt->wdt_device); + ret = devm_watchdog_register_device(dev, &wdt->wdt_device); if (ret) - goto err; + return ret; dev_info(dev, "watchdog enabled (timeout=%d sec, nowayout=%d)", wdt->wdt_device.timeout, WATCHDOG_NOWAYOUT); return 0; - -err: - clk_disable_unprepare(wdt->clock); - return ret; -} - -static int zx2967_wdt_remove(struct platform_device *pdev) -{ - struct zx2967_wdt *wdt = platform_get_drvdata(pdev); - - watchdog_unregister_device(&wdt->wdt_device); - clk_disable_unprepare(wdt->clock); - - return 0; } static const struct of_device_id zx2967_wdt_match[] = { @@ -276,7 +268,6 @@ MODULE_DEVICE_TABLE(of, zx2967_wdt_match); static struct platform_driver zx2967_wdt_driver = { .probe = zx2967_wdt_probe, - .remove = zx2967_wdt_remove, .driver = { .name = "zx2967-wdt", .of_match_table = of_match_ptr(zx2967_wdt_match), |