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

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

Pull watchdog updates from Wim Van Sebroeck:

- add MEN 16z069 IP-Core driver

- renesas-wdt: add support for the R8A77990 wdt

- stm32_iwdg: Add stm32mp1 support and pclk feature

- sp805_wdt, orion_wdt, sprd_wdt: several improvements

- imx2_wdt, stmp3xxx: switch to SPDX identifier

* tag 'linux-watchdog-4.19-rc1' of git://www.linux-watchdog.org/linux-watchdog:
watchdog: fix dependencies of menz69_wdt.o
watchdog: sp805: Add clock-frequency property
watchdog: add driver for the MEN 16z069 IP-Core
watchdog: sprd_wdt: Remove redundant dev_err call in sprd_wdt_probe()
watchdog: stmp3xxx: Switch to SPDX identifier
watchdog: imx2_wdt: Switch to SPDX identifier
watchdog: sp805: set WDOG_HW_RUNNING when appropriate
watchdog: sp805: add 'timeout-sec' DT property support
dt-bindings: watchdog: Add optional 'timeout-sec' property for sp805
dt-bindings: watchdog: Consolidate SP805 binding docs
watchdog: orion_wdt: Mark watchdog as active when running at probe
watchdog: stm32: add pclk feature for stm32mp1
dt-bindings: watchdog: add stm32mp1 support
dt-bindings: watchdog: renesas-wdt: Add support for the R8A77990 wdt

+351 -105
+22 -7
Documentation/devicetree/bindings/watchdog/arm,sp805.txt
··· 1 1 ARM AMBA Primecell SP805 Watchdog 2 2 3 + SP805 WDT is a ARM Primecell Peripheral and has a standard-id register that 4 + can be used to identify the peripheral type, vendor, and revision. 5 + This value can be used for driver matching. 6 + 7 + As SP805 WDT is a primecell IP, it follows the base bindings specified in 8 + 'arm/primecell.txt' 9 + 3 10 Required properties: 4 - - compatible: Should be "arm,sp805" & "arm,primecell" 5 - - reg: Should contain location and length for watchdog timer register. 6 - - interrupts: Should contain the list of watchdog timer interrupts. 7 - - clocks: clocks driving the watchdog timer hardware. This list should be 2 8 - clocks. With 2 clocks, the order is wdogclk clock, apb_pclk. 11 + - compatible: Should be "arm,sp805" & "arm,primecell" 12 + - reg: Should contain location and length for watchdog timer register 13 + - clocks: Clocks driving the watchdog timer hardware. This list should be 14 + 2 clocks. With 2 clocks, the order is wdog_clk, apb_pclk 15 + wdog_clk can be equal to or be a sub-multiple of the apb_pclk 16 + frequency 17 + - clock-names: Shall be "wdog_clk" for first clock and "apb_pclk" for the 18 + second one 19 + 20 + Optional properties: 21 + - interrupts: Should specify WDT interrupt number 22 + - timeout-sec: Should specify default WDT timeout in seconds. If unset, the 23 + default timeout is determined by the driver 9 24 10 25 Example: 11 26 watchdog@66090000 { 12 27 compatible = "arm,sp805", "arm,primecell"; 13 28 reg = <0x66090000 0x1000>; 14 29 interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>; 15 - clocks = <&apb_pclk>,<&apb_pclk>; 16 - clock-names = "wdogclk", "apb_pclk"; 30 + clocks = <&wdt_clk>, <&apb_pclk>; 31 + clock-names = "wdog_clk", "apb_pclk"; 17 32 };
+1
Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
··· 16 16 - "renesas,r8a7796-wdt" (R-Car M3-W) 17 17 - "renesas,r8a77965-wdt" (R-Car M3-N) 18 18 - "renesas,r8a77970-wdt" (R-Car V3M) 19 + - "renesas,r8a77990-wdt" (R-Car E3) 19 20 - "renesas,r8a77995-wdt" (R-Car D3) 20 21 - "renesas,r7s72100-wdt" (RZ/A1) 21 22 The generic compatible string must be:
-31
Documentation/devicetree/bindings/watchdog/sp805-wdt.txt
··· 1 - * ARM SP805 Watchdog Timer (WDT) Controller 2 - 3 - SP805 WDT is a ARM Primecell Peripheral and has a standard-id register that 4 - can be used to identify the peripheral type, vendor, and revision. 5 - This value can be used for driver matching. 6 - 7 - As SP805 WDT is a primecell IP, it follows the base bindings specified in 8 - 'arm/primecell.txt' 9 - 10 - Required properties: 11 - - compatible : Should be "arm,sp805-wdt", "arm,primecell" 12 - - reg : Base address and size of the watchdog timer registers. 13 - - clocks : From common clock binding. 14 - First clock is PCLK and the second is WDOGCLK. 15 - WDOGCLK can be equal to or be a sub-multiple of the PCLK frequency. 16 - - clock-names : From common clock binding. 17 - Shall be "apb_pclk" for first clock and "wdog_clk" for the 18 - second one. 19 - 20 - Optional properties: 21 - - interrupts : Should specify WDT interrupt number. 22 - 23 - Examples: 24 - 25 - cluster1_core0_watchdog: wdt@c000000 { 26 - compatible = "arm,sp805-wdt", "arm,primecell"; 27 - reg = <0x0 0xc000000 0x0 0x1000>; 28 - clocks = <&clockgen 4 3>, <&clockgen 4 3>; 29 - clock-names = "apb_pclk", "wdog_clk"; 30 - }; 31 -
+10 -3
Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
··· 2 2 --------------------------------- 3 3 4 4 Required properties: 5 - - compatible: "st,stm32-iwdg" 6 - - reg: physical base address and length of the registers set for the device 7 - - clocks: must contain a single entry describing the clock input 5 + - compatible: Should be either: 6 + - "st,stm32-iwdg" 7 + - "st,stm32mp1-iwdg" 8 + - reg: Physical base address and length of the registers set for the device 9 + - clocks: Reference to the clock entry lsi. Additional pclk clock entry 10 + is required only for st,stm32mp1-iwdg. 11 + - clock-names: Name of the clocks used. 12 + "lsi" for st,stm32-iwdg 13 + "lsi", "pclk" for st,stm32mp1-iwdg 8 14 9 15 Optional Properties: 10 16 - timeout-sec: Watchdog timeout value in seconds. ··· 21 15 compatible = "st,stm32-iwdg"; 22 16 reg = <0x40003000 0x400>; 23 17 clocks = <&clk_lsi>; 18 + clock-names = "lsi"; 24 19 timeout-sec = <32>; 25 20 };
+6
MAINTAINERS
··· 9427 9427 F: drivers/hwmon/menf21bmc_hwmon.c 9428 9428 F: Documentation/hwmon/menf21bmc 9429 9429 9430 + MEN Z069 WATCHDOG DRIVER 9431 + M: Johannes Thumshirn <jth@kernel.org> 9432 + L: linux-watchdog@vger.kernel.org 9433 + S: Maintained 9434 + F: drivers/watchdog/menz069_wdt.c 9435 + 9430 9436 MESON AO CEC DRIVER FOR AMLOGIC SOCS 9431 9437 M: Neil Armstrong <narmstrong@baylibre.com> 9432 9438 L: linux-media@lists.freedesktop.org
+10
drivers/watchdog/Kconfig
··· 161 161 This driver can also be built as a module. If so the module 162 162 will be called menf21bmc_wdt. 163 163 164 + config MENZ069_WATCHDOG 165 + tristate "MEN 16Z069 Watchdog" 166 + depends on MCB 167 + select WATCHDOG_CORE 168 + help 169 + Say Y here to include support for the MEN 16Z069 Watchdog. 170 + 171 + This driver can also be built as a module. If so the module 172 + will be called menz069_wdt. 173 + 164 174 config TANGOX_WATCHDOG 165 175 tristate "Sigma Designs SMP86xx/SMP87xx watchdog" 166 176 select WATCHDOG_CORE
+1
drivers/watchdog/Makefile
··· 215 215 obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o 216 216 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o 217 217 obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o 218 + obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o 218 219 obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
+1 -4
drivers/watchdog/imx2_wdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Watchdog driver for IMX2 and later processors 3 4 * ··· 7 6 * 8 7 * some parts adapted by similar drivers from Darius Augulis and Vladimir 9 8 * Zapolskiy, additional improvements by Wim Van Sebroeck. 10 - * 11 - * This program is free software; you can redistribute it and/or modify it 12 - * under the terms of the GNU General Public License version 2 as published by 13 - * the Free Software Foundation. 14 9 * 15 10 * NOTE: MX1 has a slightly different Watchdog than MX2 and later: 16 11 *
+170
drivers/watchdog/menz69_wdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Watchdog driver for the MEN z069 IP-Core 4 + * 5 + * Copyright (C) 2018 Johannes Thumshirn <jth@kernel.org> 6 + */ 7 + #include <linux/io.h> 8 + #include <linux/kernel.h> 9 + #include <linux/mcb.h> 10 + #include <linux/module.h> 11 + #include <linux/watchdog.h> 12 + 13 + struct men_z069_drv { 14 + struct watchdog_device wdt; 15 + void __iomem *base; 16 + struct resource *mem; 17 + }; 18 + 19 + #define MEN_Z069_WTR 0x10 20 + #define MEN_Z069_WTR_WDEN BIT(15) 21 + #define MEN_Z069_WTR_WDET_MASK 0x7fff 22 + #define MEN_Z069_WVR 0x14 23 + 24 + #define MEN_Z069_TIMER_FREQ 500 /* 500 Hz */ 25 + #define MEN_Z069_WDT_COUNTER_MIN 1 26 + #define MEN_Z069_WDT_COUNTER_MAX 0x7fff 27 + #define MEN_Z069_DEFAULT_TIMEOUT 30 28 + 29 + static bool nowayout = WATCHDOG_NOWAYOUT; 30 + module_param(nowayout, bool, 0); 31 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 32 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 33 + 34 + static int men_z069_wdt_start(struct watchdog_device *wdt) 35 + { 36 + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); 37 + u16 val; 38 + 39 + val = readw(drv->base + MEN_Z069_WTR); 40 + val |= MEN_Z069_WTR_WDEN; 41 + writew(val, drv->base + MEN_Z069_WTR); 42 + 43 + return 0; 44 + } 45 + 46 + static int men_z069_wdt_stop(struct watchdog_device *wdt) 47 + { 48 + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); 49 + u16 val; 50 + 51 + val = readw(drv->base + MEN_Z069_WTR); 52 + val &= ~MEN_Z069_WTR_WDEN; 53 + writew(val, drv->base + MEN_Z069_WTR); 54 + 55 + return 0; 56 + } 57 + 58 + static int men_z069_wdt_ping(struct watchdog_device *wdt) 59 + { 60 + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); 61 + u16 val; 62 + 63 + /* The watchdog trigger value toggles between 0x5555 and 0xaaaa */ 64 + val = readw(drv->base + MEN_Z069_WVR); 65 + val ^= 0xffff; 66 + writew(val, drv->base + MEN_Z069_WVR); 67 + 68 + return 0; 69 + } 70 + 71 + static int men_z069_wdt_set_timeout(struct watchdog_device *wdt, 72 + unsigned int timeout) 73 + { 74 + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); 75 + u16 reg, val, ena; 76 + 77 + wdt->timeout = timeout; 78 + val = timeout * MEN_Z069_TIMER_FREQ; 79 + 80 + reg = readw(drv->base + MEN_Z069_WVR); 81 + ena = reg & MEN_Z069_WTR_WDEN; 82 + reg = ena | val; 83 + writew(reg, drv->base + MEN_Z069_WTR); 84 + 85 + return 0; 86 + } 87 + 88 + static const struct watchdog_info men_z069_info = { 89 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 90 + .identity = "MEN z069 Watchdog", 91 + }; 92 + 93 + static const struct watchdog_ops men_z069_ops = { 94 + .owner = THIS_MODULE, 95 + .start = men_z069_wdt_start, 96 + .stop = men_z069_wdt_stop, 97 + .ping = men_z069_wdt_ping, 98 + .set_timeout = men_z069_wdt_set_timeout, 99 + }; 100 + 101 + static struct watchdog_device men_z069_wdt = { 102 + .info = &men_z069_info, 103 + .ops = &men_z069_ops, 104 + .timeout = MEN_Z069_DEFAULT_TIMEOUT, 105 + .min_timeout = 1, 106 + .max_timeout = MEN_Z069_WDT_COUNTER_MAX / MEN_Z069_TIMER_FREQ, 107 + }; 108 + 109 + static int men_z069_probe(struct mcb_device *dev, 110 + const struct mcb_device_id *id) 111 + { 112 + struct men_z069_drv *drv; 113 + struct resource *mem; 114 + 115 + drv = devm_kzalloc(&dev->dev, sizeof(struct men_z069_drv), GFP_KERNEL); 116 + if (!drv) 117 + return -ENOMEM; 118 + 119 + mem = mcb_request_mem(dev, "z069-wdt"); 120 + if (IS_ERR(mem)) 121 + return PTR_ERR(mem); 122 + 123 + drv->base = devm_ioremap(&dev->dev, mem->start, resource_size(mem)); 124 + if (drv->base == NULL) 125 + goto release_mem; 126 + 127 + drv->mem = mem; 128 + 129 + drv->wdt = men_z069_wdt; 130 + watchdog_init_timeout(&drv->wdt, 0, &dev->dev); 131 + watchdog_set_nowayout(&drv->wdt, nowayout); 132 + watchdog_set_drvdata(&drv->wdt, drv); 133 + drv->wdt.parent = &dev->dev; 134 + mcb_set_drvdata(dev, drv); 135 + 136 + return watchdog_register_device(&men_z069_wdt); 137 + 138 + release_mem: 139 + mcb_release_mem(mem); 140 + return -ENOMEM; 141 + } 142 + 143 + static void men_z069_remove(struct mcb_device *dev) 144 + { 145 + struct men_z069_drv *drv = mcb_get_drvdata(dev); 146 + 147 + watchdog_unregister_device(&drv->wdt); 148 + mcb_release_mem(drv->mem); 149 + } 150 + 151 + static const struct mcb_device_id men_z069_ids[] = { 152 + { .device = 0x45 }, 153 + { } 154 + }; 155 + MODULE_DEVICE_TABLE(mcb, men_z069_ids); 156 + 157 + static struct mcb_driver men_z069_driver = { 158 + .driver = { 159 + .name = "z069-wdt", 160 + .owner = THIS_MODULE, 161 + }, 162 + .probe = men_z069_probe, 163 + .remove = men_z069_remove, 164 + .id_table = men_z069_ids, 165 + }; 166 + module_mcb_driver(men_z069_driver); 167 + 168 + MODULE_AUTHOR("Johannes Thumshirn <jth@kernel.org>"); 169 + MODULE_LICENSE("GPL v2"); 170 + MODULE_ALIAS("mcb:16z069");
+2
drivers/watchdog/orion_wdt.c
··· 581 581 */ 582 582 if (!orion_wdt_enabled(&dev->wdt)) 583 583 orion_wdt_stop(&dev->wdt); 584 + else 585 + set_bit(WDOG_HW_RUNNING, &dev->wdt.status); 584 586 585 587 /* Request the IRQ only after the watchdog is disabled */ 586 588 irq = platform_get_irq(pdev, 0);
+52 -11
drivers/watchdog/sp805_wdt.c
··· 11 11 * warranty of any kind, whether express or implied. 12 12 */ 13 13 14 + #include <linux/acpi.h> 14 15 #include <linux/device.h> 15 16 #include <linux/resource.h> 16 17 #include <linux/amba/bus.h> ··· 23 22 #include <linux/math64.h> 24 23 #include <linux/module.h> 25 24 #include <linux/moduleparam.h> 25 + #include <linux/of.h> 26 26 #include <linux/pm.h> 27 27 #include <linux/slab.h> 28 28 #include <linux/spinlock.h> ··· 44 42 /* control register masks */ 45 43 #define INT_ENABLE (1 << 0) 46 44 #define RESET_ENABLE (1 << 1) 45 + #define ENABLE_MASK (INT_ENABLE | RESET_ENABLE) 47 46 #define WDTINTCLR 0x00C 48 47 #define WDTRIS 0x010 49 48 #define WDTMIS 0x014 ··· 68 65 spinlock_t lock; 69 66 void __iomem *base; 70 67 struct clk *clk; 68 + u64 rate; 71 69 struct amba_device *adev; 72 70 unsigned int load_val; 73 71 }; ··· 78 74 MODULE_PARM_DESC(nowayout, 79 75 "Set to 1 to keep watchdog running after device release"); 80 76 77 + /* returns true if wdt is running; otherwise returns false */ 78 + static bool wdt_is_running(struct watchdog_device *wdd) 79 + { 80 + struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); 81 + u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL); 82 + 83 + return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK; 84 + } 85 + 81 86 /* This routine finds load value that will reset system in required timout */ 82 87 static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) 83 88 { 84 89 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); 85 90 u64 load, rate; 86 91 87 - rate = clk_get_rate(wdt->clk); 92 + rate = wdt->rate; 88 93 89 94 /* 90 95 * sp805 runs counter with given value twice, after the end of first ··· 119 106 static unsigned int wdt_timeleft(struct watchdog_device *wdd) 120 107 { 121 108 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); 122 - u64 load, rate; 123 - 124 - rate = clk_get_rate(wdt->clk); 109 + u64 load; 125 110 126 111 spin_lock(&wdt->lock); 127 112 load = readl_relaxed(wdt->base + WDTVALUE); ··· 129 118 load += wdt->load_val + 1; 130 119 spin_unlock(&wdt->lock); 131 120 132 - return div_u64(load, rate); 121 + return div_u64(load, wdt->rate); 133 122 } 134 123 135 124 static int ··· 239 228 if (IS_ERR(wdt->base)) 240 229 return PTR_ERR(wdt->base); 241 230 242 - wdt->clk = devm_clk_get(&adev->dev, NULL); 243 - if (IS_ERR(wdt->clk)) { 244 - dev_warn(&adev->dev, "Clock not found\n"); 245 - ret = PTR_ERR(wdt->clk); 246 - goto err; 231 + if (adev->dev.of_node) { 232 + wdt->clk = devm_clk_get(&adev->dev, NULL); 233 + if (IS_ERR(wdt->clk)) { 234 + dev_err(&adev->dev, "Clock not found\n"); 235 + return PTR_ERR(wdt->clk); 236 + } 237 + wdt->rate = clk_get_rate(wdt->clk); 238 + } else if (has_acpi_companion(&adev->dev)) { 239 + /* 240 + * When Driver probe with ACPI device, clock devices 241 + * are not available, so watchdog rate get from 242 + * clock-frequency property given in _DSD object. 243 + */ 244 + device_property_read_u64(&adev->dev, "clock-frequency", 245 + &wdt->rate); 246 + if (!wdt->rate) { 247 + dev_err(&adev->dev, "no clock-frequency property\n"); 248 + return -ENODEV; 249 + } 247 250 } 248 251 249 252 wdt->adev = adev; ··· 269 244 watchdog_set_nowayout(&wdt->wdd, nowayout); 270 245 watchdog_set_drvdata(&wdt->wdd, wdt); 271 246 watchdog_set_restart_priority(&wdt->wdd, 128); 272 - wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT); 247 + 248 + /* 249 + * If 'timeout-sec' devicetree property is specified, use that. 250 + * Otherwise, use DEFAULT_TIMEOUT 251 + */ 252 + wdt->wdd.timeout = DEFAULT_TIMEOUT; 253 + watchdog_init_timeout(&wdt->wdd, 0, &adev->dev); 254 + wdt_setload(&wdt->wdd, wdt->wdd.timeout); 255 + 256 + /* 257 + * If HW is already running, enable/reset the wdt and set the running 258 + * bit to tell the wdt subsystem 259 + */ 260 + if (wdt_is_running(&wdt->wdd)) { 261 + wdt_enable(&wdt->wdd); 262 + set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); 263 + } 273 264 274 265 ret = watchdog_register_device(&wdt->wdd); 275 266 if (ret) {
+1 -3
drivers/watchdog/sprd_wdt.c
··· 279 279 280 280 wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 281 281 wdt->base = devm_ioremap_resource(&pdev->dev, wdt_res); 282 - if (IS_ERR(wdt->base)) { 283 - dev_err(&pdev->dev, "failed to map memory resource\n"); 282 + if (IS_ERR(wdt->base)) 284 283 return PTR_ERR(wdt->base); 285 - } 286 284 287 285 wdt->enable = devm_clk_get(&pdev->dev, "enable"); 288 286 if (IS_ERR(wdt->enable)) {
+74 -42
drivers/watchdog/stm32_iwdg.c
··· 11 11 12 12 #include <linux/clk.h> 13 13 #include <linux/delay.h> 14 - #include <linux/kernel.h> 15 - #include <linux/module.h> 16 14 #include <linux/interrupt.h> 17 15 #include <linux/io.h> 18 16 #include <linux/iopoll.h> 17 + #include <linux/kernel.h> 18 + #include <linux/module.h> 19 19 #include <linux/of.h> 20 + #include <linux/of_device.h> 20 21 #include <linux/platform_device.h> 21 22 #include <linux/watchdog.h> 22 23 ··· 55 54 #define TIMEOUT_US 100000 56 55 #define SLEEP_US 1000 57 56 57 + #define HAS_PCLK true 58 + 58 59 struct stm32_iwdg { 59 60 struct watchdog_device wdd; 60 61 void __iomem *regs; 61 - struct clk *clk; 62 + struct clk *clk_lsi; 63 + struct clk *clk_pclk; 62 64 unsigned int rate; 65 + bool has_pclk; 63 66 }; 64 67 65 68 static inline u32 reg_read(void __iomem *base, u32 reg) ··· 138 133 return 0; 139 134 } 140 135 136 + static int stm32_iwdg_clk_init(struct platform_device *pdev, 137 + struct stm32_iwdg *wdt) 138 + { 139 + u32 ret; 140 + 141 + wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi"); 142 + if (IS_ERR(wdt->clk_lsi)) { 143 + dev_err(&pdev->dev, "Unable to get lsi clock\n"); 144 + return PTR_ERR(wdt->clk_lsi); 145 + } 146 + 147 + /* optional peripheral clock */ 148 + if (wdt->has_pclk) { 149 + wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk"); 150 + if (IS_ERR(wdt->clk_pclk)) { 151 + dev_err(&pdev->dev, "Unable to get pclk clock\n"); 152 + return PTR_ERR(wdt->clk_pclk); 153 + } 154 + 155 + ret = clk_prepare_enable(wdt->clk_pclk); 156 + if (ret) { 157 + dev_err(&pdev->dev, "Unable to prepare pclk clock\n"); 158 + return ret; 159 + } 160 + } 161 + 162 + ret = clk_prepare_enable(wdt->clk_lsi); 163 + if (ret) { 164 + dev_err(&pdev->dev, "Unable to prepare lsi clock\n"); 165 + clk_disable_unprepare(wdt->clk_pclk); 166 + return ret; 167 + } 168 + 169 + wdt->rate = clk_get_rate(wdt->clk_lsi); 170 + 171 + return 0; 172 + } 173 + 141 174 static const struct watchdog_info stm32_iwdg_info = { 142 175 .options = WDIOF_SETTIMEOUT | 143 176 WDIOF_MAGICCLOSE | ··· 190 147 .set_timeout = stm32_iwdg_set_timeout, 191 148 }; 192 149 150 + static const struct of_device_id stm32_iwdg_of_match[] = { 151 + { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK }, 152 + { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK }, 153 + { /* end node */ } 154 + }; 155 + MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); 156 + 193 157 static int stm32_iwdg_probe(struct platform_device *pdev) 194 158 { 195 159 struct watchdog_device *wdd; 160 + const struct of_device_id *match; 196 161 struct stm32_iwdg *wdt; 197 162 struct resource *res; 198 - void __iomem *regs; 199 - struct clk *clk; 200 163 int ret; 164 + 165 + match = of_match_device(stm32_iwdg_of_match, &pdev->dev); 166 + if (!match) 167 + return -ENODEV; 168 + 169 + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 170 + if (!wdt) 171 + return -ENOMEM; 172 + 173 + wdt->has_pclk = match->data; 201 174 202 175 /* This is the timer base. */ 203 176 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 204 - regs = devm_ioremap_resource(&pdev->dev, res); 205 - if (IS_ERR(regs)) { 177 + wdt->regs = devm_ioremap_resource(&pdev->dev, res); 178 + if (IS_ERR(wdt->regs)) { 206 179 dev_err(&pdev->dev, "Could not get resource\n"); 207 - return PTR_ERR(regs); 180 + return PTR_ERR(wdt->regs); 208 181 } 209 182 210 - clk = devm_clk_get(&pdev->dev, NULL); 211 - if (IS_ERR(clk)) { 212 - dev_err(&pdev->dev, "Unable to get clock\n"); 213 - return PTR_ERR(clk); 214 - } 215 - 216 - ret = clk_prepare_enable(clk); 217 - if (ret) { 218 - dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk); 183 + ret = stm32_iwdg_clk_init(pdev, wdt); 184 + if (ret) 219 185 return ret; 220 - } 221 - 222 - /* 223 - * Allocate our watchdog driver data, which has the 224 - * struct watchdog_device nested within it. 225 - */ 226 - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 227 - if (!wdt) { 228 - ret = -ENOMEM; 229 - goto err; 230 - } 231 - 232 - /* Initialize struct stm32_iwdg. */ 233 - wdt->regs = regs; 234 - wdt->clk = clk; 235 - wdt->rate = clk_get_rate(clk); 236 186 237 187 /* Initialize struct watchdog_device. */ 238 188 wdd = &wdt->wdd; ··· 253 217 254 218 return 0; 255 219 err: 256 - clk_disable_unprepare(clk); 220 + clk_disable_unprepare(wdt->clk_lsi); 221 + clk_disable_unprepare(wdt->clk_pclk); 257 222 258 223 return ret; 259 224 } ··· 264 227 struct stm32_iwdg *wdt = platform_get_drvdata(pdev); 265 228 266 229 watchdog_unregister_device(&wdt->wdd); 267 - clk_disable_unprepare(wdt->clk); 230 + clk_disable_unprepare(wdt->clk_lsi); 231 + clk_disable_unprepare(wdt->clk_pclk); 268 232 269 233 return 0; 270 234 } 271 - 272 - static const struct of_device_id stm32_iwdg_of_match[] = { 273 - { .compatible = "st,stm32-iwdg" }, 274 - { /* end node */ } 275 - }; 276 - MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); 277 235 278 236 static struct platform_driver stm32_iwdg_driver = { 279 237 .probe = stm32_iwdg_probe, 280 238 .remove = stm32_iwdg_remove, 281 239 .driver = { 282 240 .name = "iwdg", 283 - .of_match_table = stm32_iwdg_of_match, 241 + .of_match_table = of_match_ptr(stm32_iwdg_of_match), 284 242 }, 285 243 }; 286 244 module_platform_driver(stm32_iwdg_driver);
+1 -4
drivers/watchdog/stmp3xxx_rtc_wdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28 3 4 * 4 5 * Author: Wolfram Sang <kernel@pengutronix.de> 5 6 * 6 7 * Copyright (C) 2011-12 Wolfram Sang, Pengutronix 7 - * 8 - * This program is free software; you can redistribute it and/or modify it 9 - * under the terms of the GNU General Public License version 2 as published by 10 - * the Free Software Foundation. 11 8 */ 12 9 #include <linux/kernel.h> 13 10 #include <linux/module.h>