Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull watchdog updates from Wim Van Sebroeck:

- Add Toshiba Visconti watchdog driver

- it87_wdt: add IT8772 + IT8784

- several fixes and improvements

* tag 'linux-watchdog-5.10-rc1' of git://www.linux-watchdog.org/linux-watchdog:
watchdog: Add Toshiba Visconti watchdog driver
watchdog: bindings: Add binding documentation for Toshiba Visconti watchdog device
watchdog: it87_wdt: add IT8784 ID
watchdog: sp5100_tco: Enable watchdog on Family 17h devices if disabled
watchdog: sp5100: Fix definition of EFCH_PM_DECODEEN3
watchdog: renesas_wdt: support handover from bootloader
watchdog: imx7ulp: Watchdog should continue running for wait/stop mode
watchdog: rti: Simplify with dev_err_probe()
watchdog: davinci: Simplify with dev_err_probe()
watchdog: cadence: Simplify with dev_err_probe()
watchdog: remove unneeded inclusion of <uapi/linux/sched/types.h>
watchdog: Use put_device on error
watchdog: Fix memleak in watchdog_cdev_register
watchdog: imx7ulp: Strictly follow the sequence for wdog operations
watchdog: it87_wdt: add IT8772 ID
watchdog: pcwd_usb: Avoid GFP_ATOMIC where it is not needed
drivers: watchdog: rdc321x_wdt: Fix race condition bugs

+374 -48
+54
Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + # Copyright 2020 Toshiba Electronic Devices & Storage Corporation 3 + %YAML 1.2 4 + --- 5 + $id: "http://devicetree.org/schemas/watchdog/toshiba,visconti-wdt.yaml#" 6 + $schema: "http://devicetree.org/meta-schemas/core.yaml#" 7 + 8 + title: Toshiba Visconti SoCs PIUWDT Watchdog timer 9 + 10 + maintainers: 11 + - Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 12 + 13 + allOf: 14 + - $ref: watchdog.yaml# 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - toshiba,visconti-wdt 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + clocks: 25 + maxItems: 1 26 + 27 + timeout-sec: true 28 + 29 + required: 30 + - compatible 31 + - reg 32 + - clocks 33 + 34 + additionalProperties: false 35 + 36 + examples: 37 + - | 38 + soc { 39 + #address-cells = <2>; 40 + #size-cells = <2>; 41 + 42 + wdt_clk: wdt-clk { 43 + compatible = "fixed-clock"; 44 + clock-frequency = <150000000>; 45 + #clock-cells = <0>; 46 + }; 47 + 48 + watchdog@28330000 { 49 + compatible = "toshiba,visconti-wdt"; 50 + reg = <0 0x28330000 0 0x1000>; 51 + clocks = <&wdt_clk>; 52 + timeout-sec = <20>; 53 + }; 54 + };
+8
drivers/watchdog/Kconfig
··· 1015 1015 Say Y here to include support watchdog timer embedded into the 1016 1016 pm8916 module. 1017 1017 1018 + config VISCONTI_WATCHDOG 1019 + tristate "Toshiba Visconti series watchdog support" 1020 + depends on ARCH_VISCONTI || COMPILE_TEST 1021 + select WATCHDOG_CORE 1022 + help 1023 + Say Y here to include support for the watchdog timer in Toshiba 1024 + Visconti SoCs. 1025 + 1018 1026 # X86 (i386 + ia64 + x86_64) Architecture 1019 1027 1020 1028 config ACQUIRE_WDT
+1
drivers/watchdog/Makefile
··· 95 95 obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o 96 96 obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o 97 97 obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o 98 + obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o 98 99 99 100 # X86 (i386 + ia64 + x86_64) Architecture 100 101 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+3 -6
drivers/watchdog/cadence_wdt.c
··· 334 334 watchdog_set_drvdata(cdns_wdt_device, wdt); 335 335 336 336 wdt->clk = devm_clk_get(dev, NULL); 337 - if (IS_ERR(wdt->clk)) { 338 - ret = PTR_ERR(wdt->clk); 339 - if (ret != -EPROBE_DEFER) 340 - dev_err(dev, "input clock not found\n"); 341 - return ret; 342 - } 337 + if (IS_ERR(wdt->clk)) 338 + return dev_err_probe(dev, PTR_ERR(wdt->clk), 339 + "input clock not found\n"); 343 340 344 341 ret = clk_prepare_enable(wdt->clk); 345 342 if (ret) {
+3 -6
drivers/watchdog/davinci_wdt.c
··· 206 206 return -ENOMEM; 207 207 208 208 davinci_wdt->clk = devm_clk_get(dev, NULL); 209 - 210 - if (IS_ERR(davinci_wdt->clk)) { 211 - if (PTR_ERR(davinci_wdt->clk) != -EPROBE_DEFER) 212 - dev_err(dev, "failed to get clock node\n"); 213 - return PTR_ERR(davinci_wdt->clk); 214 - } 209 + if (IS_ERR(davinci_wdt->clk)) 210 + return dev_err_probe(dev, PTR_ERR(davinci_wdt->clk), 211 + "failed to get clock node\n"); 215 212 216 213 ret = clk_prepare_enable(davinci_wdt->clk); 217 214 if (ret) {
+65 -14
drivers/watchdog/imx7ulp_wdt.c
··· 5 5 6 6 #include <linux/clk.h> 7 7 #include <linux/io.h> 8 + #include <linux/iopoll.h> 8 9 #include <linux/kernel.h> 9 10 #include <linux/module.h> 10 11 #include <linux/of.h> ··· 22 21 #define WDOG_CS_CLK (LPO_CLK << LPO_CLK_SHIFT) 23 22 #define WDOG_CS_EN BIT(7) 24 23 #define WDOG_CS_UPDATE BIT(5) 24 + #define WDOG_CS_WAIT BIT(1) 25 + #define WDOG_CS_STOP BIT(0) 25 26 26 27 #define WDOG_CNT 0x4 27 28 #define WDOG_TOVAL 0x8 ··· 39 36 #define DEFAULT_TIMEOUT 60 40 37 #define MAX_TIMEOUT 128 41 38 #define WDOG_CLOCK_RATE 1000 39 + #define WDOG_WAIT_TIMEOUT 20 42 40 43 41 static bool nowayout = WATCHDOG_NOWAYOUT; 44 42 module_param(nowayout, bool, 0000); ··· 52 48 struct clk *clk; 53 49 }; 54 50 55 - static void imx7ulp_wdt_enable(struct watchdog_device *wdog, bool enable) 51 + static int imx7ulp_wdt_wait(void __iomem *base, u32 mask) 52 + { 53 + u32 val = readl(base + WDOG_CS); 54 + 55 + if (!(val & mask) && readl_poll_timeout_atomic(base + WDOG_CS, val, 56 + val & mask, 0, 57 + WDOG_WAIT_TIMEOUT)) 58 + return -ETIMEDOUT; 59 + 60 + return 0; 61 + } 62 + 63 + static int imx7ulp_wdt_enable(struct watchdog_device *wdog, bool enable) 56 64 { 57 65 struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); 58 66 59 67 u32 val = readl(wdt->base + WDOG_CS); 68 + int ret; 60 69 70 + local_irq_disable(); 61 71 writel(UNLOCK, wdt->base + WDOG_CNT); 72 + ret = imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); 73 + if (ret) 74 + goto enable_out; 62 75 if (enable) 63 76 writel(val | WDOG_CS_EN, wdt->base + WDOG_CS); 64 77 else 65 78 writel(val & ~WDOG_CS_EN, wdt->base + WDOG_CS); 79 + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); 80 + 81 + enable_out: 82 + local_irq_enable(); 83 + 84 + return ret; 66 85 } 67 86 68 87 static bool imx7ulp_wdt_is_enabled(void __iomem *base) ··· 106 79 107 80 static int imx7ulp_wdt_start(struct watchdog_device *wdog) 108 81 { 109 - 110 - imx7ulp_wdt_enable(wdog, true); 111 - 112 - return 0; 82 + return imx7ulp_wdt_enable(wdog, true); 113 83 } 114 84 115 85 static int imx7ulp_wdt_stop(struct watchdog_device *wdog) 116 86 { 117 - imx7ulp_wdt_enable(wdog, false); 118 - 119 - return 0; 87 + return imx7ulp_wdt_enable(wdog, false); 120 88 } 121 89 122 90 static int imx7ulp_wdt_set_timeout(struct watchdog_device *wdog, ··· 119 97 { 120 98 struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); 121 99 u32 val = WDOG_CLOCK_RATE * timeout; 100 + int ret; 122 101 102 + local_irq_disable(); 123 103 writel(UNLOCK, wdt->base + WDOG_CNT); 104 + ret = imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); 105 + if (ret) 106 + goto timeout_out; 124 107 writel(val, wdt->base + WDOG_TOVAL); 108 + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); 125 109 126 110 wdog->timeout = timeout; 127 111 128 - return 0; 112 + timeout_out: 113 + local_irq_enable(); 114 + 115 + return ret; 129 116 } 130 117 131 118 static int imx7ulp_wdt_restart(struct watchdog_device *wdog, 132 119 unsigned long action, void *data) 133 120 { 134 121 struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); 122 + int ret; 135 123 136 - imx7ulp_wdt_enable(wdog, true); 137 - imx7ulp_wdt_set_timeout(&wdt->wdd, 1); 124 + ret = imx7ulp_wdt_enable(wdog, true); 125 + if (ret) 126 + return ret; 127 + 128 + ret = imx7ulp_wdt_set_timeout(&wdt->wdd, 1); 129 + if (ret) 130 + return ret; 138 131 139 132 /* wait for wdog to fire */ 140 133 while (true) ··· 173 136 WDIOF_MAGICCLOSE, 174 137 }; 175 138 176 - static void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) 139 + static int imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) 177 140 { 178 141 u32 val; 142 + int ret; 179 143 144 + local_irq_disable(); 180 145 /* unlock the wdog for reconfiguration */ 181 146 writel_relaxed(UNLOCK_SEQ0, base + WDOG_CNT); 182 147 writel_relaxed(UNLOCK_SEQ1, base + WDOG_CNT); 148 + ret = imx7ulp_wdt_wait(base, WDOG_CS_ULK); 149 + if (ret) 150 + goto init_out; 183 151 184 152 /* set an initial timeout value in TOVAL */ 185 153 writel(timeout, base + WDOG_TOVAL); 186 154 /* enable 32bit command sequence and reconfigure */ 187 - val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE; 155 + val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE | 156 + WDOG_CS_WAIT | WDOG_CS_STOP; 188 157 writel(val, base + WDOG_CS); 158 + imx7ulp_wdt_wait(base, WDOG_CS_RCS); 159 + 160 + init_out: 161 + local_irq_enable(); 162 + 163 + return ret; 189 164 } 190 165 191 166 static void imx7ulp_wdt_action(void *data) ··· 248 199 watchdog_stop_on_reboot(wdog); 249 200 watchdog_stop_on_unregister(wdog); 250 201 watchdog_set_drvdata(wdog, imx7ulp_wdt); 251 - imx7ulp_wdt_init(imx7ulp_wdt->base, wdog->timeout * WDOG_CLOCK_RATE); 202 + ret = imx7ulp_wdt_init(imx7ulp_wdt->base, wdog->timeout * WDOG_CLOCK_RATE); 203 + if (ret) 204 + return ret; 252 205 253 206 return devm_watchdog_register_device(dev, wdog); 254 207 }
+5 -1
drivers/watchdog/it87_wdt.c
··· 15 15 * Support of the watchdog timers, which are available on 16 16 * IT8607, IT8620, IT8622, IT8625, IT8628, IT8655, IT8665, IT8686, 17 17 * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726, IT8728, 18 - * and IT8783. 18 + * IT8772, IT8783 and IT8784. 19 19 */ 20 20 21 21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ··· 66 66 #define IT8721_ID 0x8721 67 67 #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 68 68 #define IT8728_ID 0x8728 69 + #define IT8772_ID 0x8772 69 70 #define IT8783_ID 0x8783 71 + #define IT8784_ID 0x8784 70 72 #define IT8786_ID 0x8786 71 73 72 74 /* GPIO Configuration Registers LDN=0x07 */ ··· 296 294 case IT8720_ID: 297 295 case IT8721_ID: 298 296 case IT8728_ID: 297 + case IT8772_ID: 299 298 case IT8783_ID: 299 + case IT8784_ID: 300 300 case IT8786_ID: 301 301 max_units = 65535; 302 302 break;
+1 -1
drivers/watchdog/pcwd_usb.c
··· 656 656 657 657 /* set up the memory buffer's */ 658 658 usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size, 659 - GFP_ATOMIC, &usb_pcwd->intr_dma); 659 + GFP_KERNEL, &usb_pcwd->intr_dma); 660 660 if (!usb_pcwd->intr_buffer) { 661 661 pr_err("Out of memory\n"); 662 662 goto error;
+2 -3
drivers/watchdog/rdc321x_wdt.c
··· 231 231 232 232 rdc321x_wdt_device.sb_pdev = pdata->sb_pdev; 233 233 rdc321x_wdt_device.base_reg = r->start; 234 + rdc321x_wdt_device.queue = 0; 235 + rdc321x_wdt_device.default_ticks = ticks; 234 236 235 237 err = misc_register(&rdc321x_wdt_misc); 236 238 if (err < 0) { ··· 247 245 rdc321x_wdt_device.base_reg, RDC_WDT_RST); 248 246 249 247 init_completion(&rdc321x_wdt_device.stop); 250 - rdc321x_wdt_device.queue = 0; 251 248 252 249 clear_bit(0, &rdc321x_wdt_device.inuse); 253 250 254 251 timer_setup(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0); 255 - 256 - rdc321x_wdt_device.default_ticks = ticks; 257 252 258 253 dev_info(&pdev->dev, "watchdog init success\n"); 259 254
+10 -2
drivers/watchdog/renesas_wdt.c
··· 194 194 struct clk *clk; 195 195 unsigned long clks_per_sec; 196 196 int ret, i; 197 + u8 csra; 197 198 198 199 if (rwdt_blacklisted(dev)) 199 200 return -ENODEV; ··· 214 213 pm_runtime_enable(dev); 215 214 pm_runtime_get_sync(dev); 216 215 priv->clk_rate = clk_get_rate(clk); 217 - priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) & 218 - RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0; 216 + csra = readb_relaxed(priv->base + RWTCSRA); 217 + priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0; 219 218 pm_runtime_put(dev); 220 219 221 220 if (!priv->clk_rate) { ··· 252 251 253 252 /* This overrides the default timeout only if DT configuration was found */ 254 253 watchdog_init_timeout(&priv->wdev, 0, dev); 254 + 255 + /* Check if FW enabled the watchdog */ 256 + if (csra & RWTCSRA_TME) { 257 + /* Ensure properly initialized dividers */ 258 + rwdt_start(&priv->wdev); 259 + set_bit(WDOG_HW_RUNNING, &priv->wdev.status); 260 + } 255 261 256 262 ret = watchdog_register_device(&priv->wdev); 257 263 if (ret < 0)
+4 -10
drivers/watchdog/rti_wdt.c
··· 205 205 return -ENOMEM; 206 206 207 207 clk = clk_get(dev, NULL); 208 - if (IS_ERR(clk)) { 209 - if (PTR_ERR(clk) != -EPROBE_DEFER) 210 - dev_err(dev, "failed to get clock\n"); 211 - return PTR_ERR(clk); 212 - } 208 + if (IS_ERR(clk)) 209 + return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n"); 213 210 214 211 wdt->freq = clk_get_rate(clk); 215 212 ··· 227 230 228 231 pm_runtime_enable(dev); 229 232 ret = pm_runtime_get_sync(dev); 230 - if (ret) { 231 - if (ret != -EPROBE_DEFER) 232 - dev_err(&pdev->dev, "runtime pm failed\n"); 233 - return ret; 234 - } 233 + if (ret) 234 + return dev_err_probe(dev, ret, "runtime pm failed\n"); 235 235 236 236 platform_set_drvdata(pdev, wdt); 237 237
+18
drivers/watchdog/sp5100_tco.c
··· 17 17 * AMD Publication 51192 "AMD Bolton FCH Register Reference Guide" 18 18 * AMD Publication 52740 "BIOS and Kernel Developer’s Guide (BKDG) 19 19 * for AMD Family 16h Models 30h-3Fh Processors" 20 + * AMD Publication 55570-B1-PUB "Processor Programming Reference (PPR) 21 + * for AMD Family 17h Model 18h, Revision B1 22 + * Processors (PUB) 23 + * AMD Publication 55772-A1-PUB "Processor Programming Reference (PPR) 24 + * for AMD Family 17h Model 20h, Revision A1 25 + * Processors (PUB) 20 26 */ 21 27 22 28 /* ··· 247 241 break; 248 242 case efch: 249 243 dev_name = SB800_DEVNAME; 244 + /* 245 + * On Family 17h devices, the EFCH_PM_DECODEEN_WDT_TMREN bit of 246 + * EFCH_PM_DECODEEN not only enables the EFCH_PM_WDT_ADDR memory 247 + * region, it also enables the watchdog itself. 248 + */ 249 + if (boot_cpu_data.x86 == 0x17) { 250 + val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN); 251 + if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) { 252 + sp5100_tco_update_pm_reg8(EFCH_PM_DECODEEN, 0xff, 253 + EFCH_PM_DECODEEN_WDT_TMREN); 254 + } 255 + } 250 256 val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN); 251 257 if (val & EFCH_PM_DECODEEN_WDT_TMREN) 252 258 mmio_addr = EFCH_PM_WDT_ADDR;
+1 -1
drivers/watchdog/sp5100_tco.h
··· 70 70 #define EFCH_PM_DECODEEN_WDT_TMREN BIT(7) 71 71 72 72 73 - #define EFCH_PM_DECODEEN3 0x00 73 + #define EFCH_PM_DECODEEN3 0x03 74 74 #define EFCH_PM_DECODEEN_SECOND_RES GENMASK(1, 0) 75 75 #define EFCH_PM_WATCHDOG_DISABLE ((u8)GENMASK(3, 2)) 76 76
+195
drivers/watchdog/visconti_wdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2020 TOSHIBA CORPORATION 4 + * Copyright (c) 2020 Toshiba Electronic Devices & Storage Corporation 5 + * Copyright (c) 2020 Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/io.h> 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/watchdog.h> 15 + 16 + #define WDT_CNT 0x00 17 + #define WDT_MIN 0x04 18 + #define WDT_MAX 0x08 19 + #define WDT_CTL 0x0c 20 + #define WDT_CMD 0x10 21 + #define WDT_CMD_CLEAR 0x4352 22 + #define WDT_CMD_START_STOP 0x5354 23 + #define WDT_DIV 0x30 24 + 25 + #define VISCONTI_WDT_FREQ 2000000 /* 2MHz */ 26 + #define WDT_DEFAULT_TIMEOUT 10U /* in seconds */ 27 + 28 + static bool nowayout = WATCHDOG_NOWAYOUT; 29 + module_param(nowayout, bool, 0); 30 + MODULE_PARM_DESC( 31 + nowayout, 32 + "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT)")"); 33 + 34 + struct visconti_wdt_priv { 35 + struct watchdog_device wdev; 36 + void __iomem *base; 37 + u32 div; 38 + }; 39 + 40 + static int visconti_wdt_start(struct watchdog_device *wdev) 41 + { 42 + struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev); 43 + u32 timeout = wdev->timeout * VISCONTI_WDT_FREQ; 44 + 45 + writel(priv->div, priv->base + WDT_DIV); 46 + writel(0, priv->base + WDT_MIN); 47 + writel(timeout, priv->base + WDT_MAX); 48 + writel(0, priv->base + WDT_CTL); 49 + writel(WDT_CMD_START_STOP, priv->base + WDT_CMD); 50 + 51 + return 0; 52 + } 53 + 54 + static int visconti_wdt_stop(struct watchdog_device *wdev) 55 + { 56 + struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev); 57 + 58 + writel(1, priv->base + WDT_CTL); 59 + writel(WDT_CMD_START_STOP, priv->base + WDT_CMD); 60 + 61 + return 0; 62 + } 63 + 64 + static int visconti_wdt_ping(struct watchdog_device *wdd) 65 + { 66 + struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdd); 67 + 68 + writel(WDT_CMD_CLEAR, priv->base + WDT_CMD); 69 + 70 + return 0; 71 + } 72 + 73 + static unsigned int visconti_wdt_get_timeleft(struct watchdog_device *wdev) 74 + { 75 + struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev); 76 + u32 timeout = wdev->timeout * VISCONTI_WDT_FREQ; 77 + u32 cnt = readl(priv->base + WDT_CNT); 78 + 79 + if (timeout <= cnt) 80 + return 0; 81 + timeout -= cnt; 82 + 83 + return timeout / VISCONTI_WDT_FREQ; 84 + } 85 + 86 + static int visconti_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout) 87 + { 88 + u32 val; 89 + struct visconti_wdt_priv *priv = watchdog_get_drvdata(wdev); 90 + 91 + wdev->timeout = timeout; 92 + val = wdev->timeout * VISCONTI_WDT_FREQ; 93 + 94 + /* Clear counter before setting timeout because WDT expires */ 95 + writel(WDT_CMD_CLEAR, priv->base + WDT_CMD); 96 + writel(val, priv->base + WDT_MAX); 97 + 98 + return 0; 99 + } 100 + 101 + static const struct watchdog_info visconti_wdt_info = { 102 + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 103 + .identity = "Visconti Watchdog", 104 + }; 105 + 106 + static const struct watchdog_ops visconti_wdt_ops = { 107 + .owner = THIS_MODULE, 108 + .start = visconti_wdt_start, 109 + .stop = visconti_wdt_stop, 110 + .ping = visconti_wdt_ping, 111 + .get_timeleft = visconti_wdt_get_timeleft, 112 + .set_timeout = visconti_wdt_set_timeout, 113 + }; 114 + 115 + static void visconti_clk_disable_unprepare(void *data) 116 + { 117 + clk_disable_unprepare(data); 118 + } 119 + 120 + static int visconti_wdt_probe(struct platform_device *pdev) 121 + { 122 + struct watchdog_device *wdev; 123 + struct visconti_wdt_priv *priv; 124 + struct device *dev = &pdev->dev; 125 + struct clk *clk; 126 + int ret; 127 + unsigned long clk_freq; 128 + 129 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 130 + if (!priv) 131 + return -ENOMEM; 132 + 133 + priv->base = devm_platform_ioremap_resource(pdev, 0); 134 + if (IS_ERR(priv->base)) 135 + return PTR_ERR(priv->base); 136 + 137 + clk = devm_clk_get(dev, NULL); 138 + if (IS_ERR(clk)) 139 + return dev_err_probe(dev, PTR_ERR(clk), "Could not get clock\n"); 140 + 141 + ret = clk_prepare_enable(clk); 142 + if (ret) { 143 + dev_err(dev, "Could not enable clock\n"); 144 + return ret; 145 + } 146 + 147 + ret = devm_add_action_or_reset(dev, visconti_clk_disable_unprepare, clk); 148 + if (ret) 149 + return ret; 150 + 151 + clk_freq = clk_get_rate(clk); 152 + if (!clk_freq) 153 + return -EINVAL; 154 + 155 + priv->div = clk_freq / VISCONTI_WDT_FREQ; 156 + 157 + /* Initialize struct watchdog_device. */ 158 + wdev = &priv->wdev; 159 + wdev->info = &visconti_wdt_info; 160 + wdev->ops = &visconti_wdt_ops; 161 + wdev->parent = dev; 162 + wdev->min_timeout = 1; 163 + wdev->max_timeout = 0xffffffff / VISCONTI_WDT_FREQ; 164 + wdev->timeout = min(wdev->max_timeout, WDT_DEFAULT_TIMEOUT); 165 + 166 + watchdog_set_drvdata(wdev, priv); 167 + watchdog_set_nowayout(wdev, nowayout); 168 + watchdog_stop_on_unregister(wdev); 169 + 170 + /* This overrides the default timeout only if DT configuration was found */ 171 + ret = watchdog_init_timeout(wdev, 0, dev); 172 + if (ret) 173 + dev_warn(dev, "Specified timeout value invalid, using default\n"); 174 + 175 + return devm_watchdog_register_device(dev, wdev); 176 + } 177 + 178 + static const struct of_device_id visconti_wdt_of_match[] = { 179 + { .compatible = "toshiba,visconti-wdt", }, 180 + {} 181 + }; 182 + MODULE_DEVICE_TABLE(of, visconti_wdt_of_match); 183 + 184 + static struct platform_driver visconti_wdt_driver = { 185 + .driver = { 186 + .name = "visconti_wdt", 187 + .of_match_table = visconti_wdt_of_match, 188 + }, 189 + .probe = visconti_wdt_probe, 190 + }; 191 + module_platform_driver(visconti_wdt_driver); 192 + 193 + MODULE_DESCRIPTION("TOSHIBA Visconti Watchdog Driver"); 194 + MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp"); 195 + MODULE_LICENSE("GPL v2");
+4 -4
drivers/watchdog/watchdog_dev.c
··· 43 43 #include <linux/watchdog.h> /* For watchdog specific items */ 44 44 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 45 45 46 - #include <uapi/linux/sched/types.h> /* For struct sched_param */ 47 - 48 46 #include "watchdog_core.h" 49 47 #include "watchdog_pretimeout.h" 50 48 ··· 992 994 wd_data->wdd = wdd; 993 995 wdd->wd_data = wd_data; 994 996 995 - if (IS_ERR_OR_NULL(watchdog_kworker)) 997 + if (IS_ERR_OR_NULL(watchdog_kworker)) { 998 + kfree(wd_data); 996 999 return -ENODEV; 1000 + } 997 1001 998 1002 device_initialize(&wd_data->dev); 999 1003 wd_data->dev.devt = MKDEV(MAJOR(watchdog_devt), wdd->id); ··· 1021 1021 pr_err("%s: a legacy watchdog module is probably present.\n", 1022 1022 wdd->info->identity); 1023 1023 old_wd_data = NULL; 1024 - kfree(wd_data); 1024 + put_device(&wd_data->dev); 1025 1025 return err; 1026 1026 } 1027 1027 }