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

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

Pull watchdog updates from Wim Van Sebroeck:

- Add watchdog driver for Lenovo SE30 platform

- Add support for Allwinner A523

- Add i.MX94 support

- watchdog framework: Convert to use device property

- renesas,wdt: Document RZ/G3E support

- Various other fixes and improvemenents

* tag 'linux-watchdog-6.15-rc1' of git://www.linux-watchdog.org/linux-watchdog:
watchdog: sunxi_wdt: Add support for Allwinner A523
dt-bindings: watchdog: sunxi: add Allwinner A523 compatible string
watchdog: aspeed: fix 64-bit division
watchdog: npcm: Remove unnecessary NULL check before clk_prepare_enable/clk_disable_unprepare
dt-bindings: watchdog: renesas,wdt: Document RZ/G3E support
watchdog: Convert to use device property
watchdog: lenovo_se30_wdt: include io.h for devm_ioremap()
dt-bindings: watchdog: fsl-imx7ulp-wdt: Add i.MX94 support
watchdog: nic7018_wdt: tidy up ACPI ID table
watchdog: s3c2410_wdt: Fix PMU register bits for ExynosAutoV920 SoC
watchdog: lenovo_se30_wdt: Watchdog driver for Lenovo SE30 platform
watchdog: Enable RZV2HWDT driver depend on ARCH_RENESAS
watchdog: cros-ec: Add newlines to printks
watchdog: aspeed: Update bootstatus handling

+535 -28
+2
Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
··· 32 32 - items: 33 33 - const: allwinner,sun20i-d1-wdt-reset 34 34 - const: allwinner,sun20i-d1-wdt 35 + - const: allwinner,sun55i-a523-wdt 35 36 36 37 reg: 37 38 maxItems: 1 ··· 61 60 - allwinner,sun20i-d1-wdt-reset 62 61 - allwinner,sun50i-r329-wdt 63 62 - allwinner,sun50i-r329-wdt-reset 63 + - allwinner,sun55i-a523-wdt 64 64 65 65 then: 66 66 properties:
+4
Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml
··· 22 22 - const: fsl,imx8ulp-wdt 23 23 - const: fsl,imx7ulp-wdt 24 24 - const: fsl,imx93-wdt 25 + - items: 26 + - enum: 27 + - fsl,imx94-wdt 28 + - const: fsl,imx93-wdt 25 29 26 30 reg: 27 31 maxItems: 1
+4
Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml
··· 75 75 - renesas,r8a779h0-wdt # R-Car V4M 76 76 - const: renesas,rcar-gen4-wdt # R-Car Gen4 77 77 78 + - items: 79 + - const: renesas,r9a09g047-wdt # RZ/G3E 80 + - const: renesas,r9a09g057-wdt # RZ/V2H(P) 81 + 78 82 - const: renesas,r9a09g057-wdt # RZ/V2H(P) 79 83 80 84 reg:
+18 -4
drivers/watchdog/Kconfig
··· 279 279 This driver can also be built as a module. If so, the module 280 280 will be called lenovo-se10-wdt. 281 281 282 + config LENOVO_SE30_WDT 283 + tristate "Lenovo SE30 Watchdog" 284 + depends on (X86 && DMI) || COMPILE_TEST 285 + depends on HAS_IOPORT 286 + select WATCHDOG_CORE 287 + help 288 + If you say yes here you get support for the watchdog 289 + functionality for the Lenovo SE30 platform. 290 + 291 + This driver can also be built as a module. If so, the module 292 + will be called lenovo-se30-wdt. 293 + 282 294 config MENF21BMC_WATCHDOG 283 295 tristate "MEN 14F021P00 BMC Watchdog" 284 296 depends on MFD_MENF21BMC || COMPILE_TEST ··· 975 963 Renesas RZ/G2L SoCs. These watchdogs can be used to reset a system. 976 964 977 965 config RENESAS_RZV2HWDT 978 - tristate "Renesas RZ/V2H(P) WDT Watchdog" 979 - depends on ARCH_R9A09G057 || COMPILE_TEST 966 + tristate "Renesas RZ/{G3E,V2H(P)} WDT Watchdog" 967 + depends on ARCH_RENESAS || COMPILE_TEST 980 968 depends on PM || COMPILE_TEST 981 969 select WATCHDOG_CORE 982 970 help 983 971 This driver adds watchdog support for the integrated watchdogs in the 984 - Renesas RZ/V2H(P) SoCs. These watchdogs can be used to reset a system. 972 + Renesas RZ/{G3E,V2H(P)} SoCs. These watchdogs can be used to reset a 973 + system. 985 974 986 975 config ASPEED_WATCHDOG 987 976 tristate "Aspeed BMC watchdog support" ··· 1743 1730 1744 1731 config NIC7018_WDT 1745 1732 tristate "NIC7018 Watchdog" 1746 - depends on X86 && ACPI 1733 + depends on HAS_IOPORT 1734 + depends on ACPI || COMPILE_TEST 1747 1735 select WATCHDOG_CORE 1748 1736 help 1749 1737 Support for National Instruments NIC7018 Watchdog.
+1
drivers/watchdog/Makefile
··· 124 124 obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o 125 125 obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o 126 126 obj-$(CONFIG_LENOVO_SE10_WDT) += lenovo_se10_wdt.o 127 + obj-$(CONFIG_LENOVO_SE30_WDT) += lenovo_se30_wdt.o 127 128 ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) 128 129 obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o 129 130 endif
+79 -2
drivers/watchdog/aspeed_wdt.c
··· 11 11 #include <linux/io.h> 12 12 #include <linux/kernel.h> 13 13 #include <linux/kstrtox.h> 14 + #include <linux/mfd/syscon.h> 14 15 #include <linux/module.h> 15 16 #include <linux/of.h> 16 17 #include <linux/of_irq.h> 17 18 #include <linux/platform_device.h> 19 + #include <linux/regmap.h> 18 20 #include <linux/watchdog.h> 19 21 20 22 static bool nowayout = WATCHDOG_NOWAYOUT; 21 23 module_param(nowayout, bool, 0); 22 24 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 23 25 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 26 + struct aspeed_wdt_scu { 27 + const char *compatible; 28 + u32 reset_status_reg; 29 + u32 wdt_reset_mask; 30 + u32 wdt_reset_mask_shift; 31 + }; 24 32 25 33 struct aspeed_wdt_config { 26 34 u32 ext_pulse_width_mask; 27 35 u32 irq_shift; 28 36 u32 irq_mask; 37 + struct aspeed_wdt_scu scu; 29 38 }; 30 39 31 40 struct aspeed_wdt { ··· 48 39 .ext_pulse_width_mask = 0xff, 49 40 .irq_shift = 0, 50 41 .irq_mask = 0, 42 + .scu = { 43 + .compatible = "aspeed,ast2400-scu", 44 + .reset_status_reg = 0x3c, 45 + .wdt_reset_mask = 0x1, 46 + .wdt_reset_mask_shift = 1, 47 + }, 51 48 }; 52 49 53 50 static const struct aspeed_wdt_config ast2500_config = { 54 51 .ext_pulse_width_mask = 0xfffff, 55 52 .irq_shift = 12, 56 53 .irq_mask = GENMASK(31, 12), 54 + .scu = { 55 + .compatible = "aspeed,ast2500-scu", 56 + .reset_status_reg = 0x3c, 57 + .wdt_reset_mask = 0x1, 58 + .wdt_reset_mask_shift = 2, 59 + }, 57 60 }; 58 61 59 62 static const struct aspeed_wdt_config ast2600_config = { 60 63 .ext_pulse_width_mask = 0xfffff, 61 64 .irq_shift = 0, 62 65 .irq_mask = GENMASK(31, 10), 66 + .scu = { 67 + .compatible = "aspeed,ast2600-scu", 68 + .reset_status_reg = 0x74, 69 + .wdt_reset_mask = 0xf, 70 + .wdt_reset_mask_shift = 16, 71 + }, 63 72 }; 64 73 65 74 static const struct of_device_id aspeed_wdt_of_table[] = { ··· 238 211 mdelay(1000); 239 212 240 213 return 0; 214 + } 215 + 216 + static void aspeed_wdt_update_bootstatus(struct platform_device *pdev, 217 + struct aspeed_wdt *wdt) 218 + { 219 + const struct resource *res; 220 + struct aspeed_wdt_scu scu = wdt->cfg->scu; 221 + struct regmap *scu_base; 222 + u32 reset_mask_width; 223 + u32 reset_mask_shift; 224 + u32 idx = 0; 225 + u32 status; 226 + int ret; 227 + 228 + if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) { 229 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 230 + idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res); 231 + } 232 + 233 + scu_base = syscon_regmap_lookup_by_compatible(scu.compatible); 234 + if (IS_ERR(scu_base)) { 235 + wdt->wdd.bootstatus = WDIOS_UNKNOWN; 236 + return; 237 + } 238 + 239 + ret = regmap_read(scu_base, scu.reset_status_reg, &status); 240 + if (ret) { 241 + wdt->wdd.bootstatus = WDIOS_UNKNOWN; 242 + return; 243 + } 244 + 245 + reset_mask_width = hweight32(scu.wdt_reset_mask); 246 + reset_mask_shift = scu.wdt_reset_mask_shift + 247 + reset_mask_width * idx; 248 + 249 + if (status & (scu.wdt_reset_mask << reset_mask_shift)) 250 + wdt->wdd.bootstatus = WDIOF_CARDRESET; 251 + 252 + /* clear wdt reset event flag */ 253 + if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") || 254 + of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) { 255 + ret = regmap_read(scu_base, scu.reset_status_reg, &status); 256 + if (!ret) { 257 + status &= ~(scu.wdt_reset_mask << reset_mask_shift); 258 + regmap_write(scu_base, scu.reset_status_reg, status); 259 + } 260 + } else { 261 + regmap_write(scu_base, scu.reset_status_reg, 262 + scu.wdt_reset_mask << reset_mask_shift); 263 + } 241 264 } 242 265 243 266 /* access_cs0 shows if cs0 is accessible, hence the reverted bit */ ··· 535 458 writel(duration - 1, wdt->base + WDT_RESET_WIDTH); 536 459 } 537 460 461 + aspeed_wdt_update_bootstatus(pdev, wdt); 462 + 538 463 status = readl(wdt->base + WDT_TIMEOUT_STATUS); 539 464 if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { 540 - wdt->wdd.bootstatus = WDIOF_CARDRESET; 541 - 542 465 if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || 543 466 of_device_is_compatible(np, "aspeed,ast2500-wdt")) 544 467 wdt->wdd.groups = bswitch_groups;
+5 -5
drivers/watchdog/cros_ec_wdt.c
··· 58 58 arg.req.command = EC_HANG_DETECT_CMD_RELOAD; 59 59 ret = cros_ec_wdt_send_cmd(cros_ec, &arg); 60 60 if (ret < 0) 61 - dev_dbg(wdd->parent, "Failed to ping watchdog (%d)", ret); 61 + dev_dbg(wdd->parent, "Failed to ping watchdog (%d)\n", ret); 62 62 63 63 return ret; 64 64 } ··· 74 74 arg.req.reboot_timeout_sec = wdd->timeout; 75 75 ret = cros_ec_wdt_send_cmd(cros_ec, &arg); 76 76 if (ret < 0) 77 - dev_dbg(wdd->parent, "Failed to start watchdog (%d)", ret); 77 + dev_dbg(wdd->parent, "Failed to start watchdog (%d)\n", ret); 78 78 79 79 return ret; 80 80 } ··· 88 88 arg.req.command = EC_HANG_DETECT_CMD_CANCEL; 89 89 ret = cros_ec_wdt_send_cmd(cros_ec, &arg); 90 90 if (ret < 0) 91 - dev_dbg(wdd->parent, "Failed to stop watchdog (%d)", ret); 91 + dev_dbg(wdd->parent, "Failed to stop watchdog (%d)\n", ret); 92 92 93 93 return ret; 94 94 } ··· 136 136 arg.req.command = EC_HANG_DETECT_CMD_GET_STATUS; 137 137 ret = cros_ec_wdt_send_cmd(cros_ec, &arg); 138 138 if (ret < 0) 139 - return dev_err_probe(dev, ret, "Failed to get watchdog bootstatus"); 139 + return dev_err_probe(dev, ret, "Failed to get watchdog bootstatus\n"); 140 140 141 141 wdd->parent = &pdev->dev; 142 142 wdd->info = &cros_ec_wdt_ident; ··· 150 150 arg.req.command = EC_HANG_DETECT_CMD_CLEAR_STATUS; 151 151 ret = cros_ec_wdt_send_cmd(cros_ec, &arg); 152 152 if (ret < 0) 153 - return dev_err_probe(dev, ret, "Failed to clear watchdog bootstatus"); 153 + return dev_err_probe(dev, ret, "Failed to clear watchdog bootstatus\n"); 154 154 155 155 watchdog_stop_on_reboot(wdd); 156 156 watchdog_stop_on_unregister(wdd);
+394
drivers/watchdog/lenovo_se30_wdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * WDT driver for Lenovo SE30 device 4 + */ 5 + 6 + #define dev_fmt(fmt) KBUILD_MODNAME ": " fmt 7 + 8 + #include <linux/io.h> 9 + #include <linux/dmi.h> 10 + #include <linux/delay.h> 11 + #include <linux/iommu.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/moduleparam.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/watchdog.h> 17 + 18 + #define IOREGION_OFFSET 4 /* Use EC port 1 */ 19 + #define IOREGION_LENGTH 4 20 + 21 + #define WATCHDOG_TIMEOUT 60 22 + 23 + #define MIN_TIMEOUT 1 24 + #define MAX_TIMEOUT 255 25 + #define MAX_WAIT 10 26 + 27 + static int timeout; /* in seconds */ 28 + module_param(timeout, int, 0); 29 + MODULE_PARM_DESC(timeout, 30 + "Watchdog timeout in seconds. 1 <= timeout <= 255, default=" 31 + __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 32 + 33 + static bool nowayout = WATCHDOG_NOWAYOUT; 34 + module_param(nowayout, bool, 0); 35 + MODULE_PARM_DESC(nowayout, 36 + "Watchdog cannot be stopped once started (default=" 37 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 38 + 39 + #define LNV_SE30_NAME "lenovo-se30-wdt" 40 + #define LNV_SE30_ID 0x0110 41 + #define CHIPID_MASK 0xFFF0 42 + 43 + #define CHIPID_REG 0x20 44 + #define SIO_REG 0x2e 45 + #define LDN_REG 0x07 46 + #define UNLOCK_KEY 0x87 47 + #define LOCK_KEY 0xAA 48 + #define LD_NUM_SHM 0x0F 49 + #define LD_BASE_ADDR 0xF8 50 + 51 + #define WDT_MODULE 0x10 52 + #define WDT_CFG_INDEX 0x15 /* WD configuration register */ 53 + #define WDT_CNT_INDEX 0x16 /* WD timer count register */ 54 + #define WDT_CFG_RESET 0x2 55 + 56 + /* Host Interface WIN2 offset definition */ 57 + #define SHM_WIN_SIZE 0xFF 58 + #define SHM_WIN_MOD_OFFSET 0x01 59 + #define SHM_WIN_CMD_OFFSET 0x02 60 + #define SHM_WIN_SEL_OFFSET 0x03 61 + #define SHM_WIN_CTL_OFFSET 0x04 62 + #define VAL_SHM_WIN_CTRL_WR 0x40 63 + #define VAL_SHM_WIN_CTRL_RD 0x80 64 + #define SHM_WIN_ID_OFFSET 0x08 65 + #define SHM_WIN_DAT_OFFSET 0x10 66 + 67 + struct nct6692_reg { 68 + unsigned char mod; 69 + unsigned char cmd; 70 + unsigned char sel; 71 + unsigned int idx; 72 + }; 73 + 74 + /* Watchdog is based on NCT6692 device */ 75 + struct lenovo_se30_wdt { 76 + unsigned char __iomem *shm_base_addr; 77 + struct nct6692_reg wdt_cfg; 78 + struct nct6692_reg wdt_cnt; 79 + struct watchdog_device wdt; 80 + }; 81 + 82 + static inline void superio_outb(int ioreg, int reg, int val) 83 + { 84 + outb(reg, ioreg); 85 + outb(val, ioreg + 1); 86 + } 87 + 88 + static inline int superio_inb(int ioreg, int reg) 89 + { 90 + outb(reg, ioreg); 91 + return inb(ioreg + 1); 92 + } 93 + 94 + static inline int superio_enter(int key, int addr, const char *name) 95 + { 96 + if (!request_muxed_region(addr, 2, name)) { 97 + pr_err("I/O address 0x%04x already in use\n", addr); 98 + return -EBUSY; 99 + } 100 + outb(key, addr); /* Enter extended function mode */ 101 + outb(key, addr); /* Again according to manual */ 102 + 103 + return 0; 104 + } 105 + 106 + static inline void superio_exit(int key, int addr) 107 + { 108 + outb(key, addr); /* Leave extended function mode */ 109 + release_region(addr, 2); 110 + } 111 + 112 + static int shm_get_ready(unsigned char __iomem *shm_base_addr, 113 + const struct nct6692_reg *reg) 114 + { 115 + unsigned char pre_id, new_id; 116 + int loop = 0; 117 + 118 + iowrite8(reg->mod, shm_base_addr + SHM_WIN_MOD_OFFSET); 119 + iowrite8(reg->cmd, shm_base_addr + SHM_WIN_CMD_OFFSET); 120 + iowrite8(reg->sel, shm_base_addr + SHM_WIN_SEL_OFFSET); 121 + 122 + pre_id = ioread8(shm_base_addr + SHM_WIN_ID_OFFSET); 123 + iowrite8(VAL_SHM_WIN_CTRL_RD, shm_base_addr + SHM_WIN_CTL_OFFSET); 124 + 125 + /* Loop checking when interface is ready */ 126 + while (loop < MAX_WAIT) { 127 + new_id = ioread8(shm_base_addr + SHM_WIN_ID_OFFSET); 128 + if (new_id != pre_id) 129 + return 0; 130 + loop++; 131 + usleep_range(10, 125); 132 + } 133 + return -ETIMEDOUT; 134 + } 135 + 136 + static int read_shm_win(unsigned char __iomem *shm_base_addr, 137 + const struct nct6692_reg *reg, 138 + unsigned char idx_offset, 139 + unsigned char *data) 140 + { 141 + int err = shm_get_ready(shm_base_addr, reg); 142 + 143 + if (err) 144 + return err; 145 + *data = ioread8(shm_base_addr + SHM_WIN_DAT_OFFSET + reg->idx + idx_offset); 146 + return 0; 147 + } 148 + 149 + static int write_shm_win(unsigned char __iomem *shm_base_addr, 150 + const struct nct6692_reg *reg, 151 + unsigned char idx_offset, 152 + unsigned char val) 153 + { 154 + int err = shm_get_ready(shm_base_addr, reg); 155 + 156 + if (err) 157 + return err; 158 + iowrite8(val, shm_base_addr + SHM_WIN_DAT_OFFSET + reg->idx + idx_offset); 159 + iowrite8(VAL_SHM_WIN_CTRL_WR, shm_base_addr + SHM_WIN_CTL_OFFSET); 160 + err = shm_get_ready(shm_base_addr, reg); 161 + return err; 162 + } 163 + 164 + static int lenovo_se30_wdt_enable(struct lenovo_se30_wdt *data, unsigned int timeout) 165 + { 166 + if (timeout) { 167 + int err = write_shm_win(data->shm_base_addr, &data->wdt_cfg, 0, WDT_CFG_RESET); 168 + 169 + if (err) 170 + return err; 171 + } 172 + return write_shm_win(data->shm_base_addr, &data->wdt_cnt, 0, timeout); 173 + } 174 + 175 + static int lenovo_se30_wdt_start(struct watchdog_device *wdog) 176 + { 177 + struct lenovo_se30_wdt *data = watchdog_get_drvdata(wdog); 178 + 179 + return lenovo_se30_wdt_enable(data, wdog->timeout); 180 + } 181 + 182 + static int lenovo_se30_wdt_stop(struct watchdog_device *wdog) 183 + { 184 + struct lenovo_se30_wdt *data = watchdog_get_drvdata(wdog); 185 + 186 + return lenovo_se30_wdt_enable(data, 0); 187 + } 188 + 189 + static unsigned int lenovo_se30_wdt_get_timeleft(struct watchdog_device *wdog) 190 + { 191 + struct lenovo_se30_wdt *data = watchdog_get_drvdata(wdog); 192 + unsigned char timeleft; 193 + int err; 194 + 195 + err = read_shm_win(data->shm_base_addr, &data->wdt_cnt, 0, &timeleft); 196 + if (err) 197 + return 0; 198 + return timeleft; 199 + } 200 + 201 + static int lenovo_se30_wdt_ping(struct watchdog_device *wdt) 202 + { 203 + struct lenovo_se30_wdt *data = watchdog_get_drvdata(wdt); 204 + int err = 0; 205 + 206 + /* 207 + * Device does not support refreshing WDT_TIMER_REG register when 208 + * the watchdog is active. Need to disable, feed and enable again 209 + */ 210 + err = lenovo_se30_wdt_enable(data, 0); 211 + if (err) 212 + return err; 213 + 214 + err = write_shm_win(data->shm_base_addr, &data->wdt_cnt, 0, wdt->timeout); 215 + if (!err) 216 + err = lenovo_se30_wdt_enable(data, wdt->timeout); 217 + 218 + return err; 219 + } 220 + 221 + static const struct watchdog_info lenovo_se30_wdt_info = { 222 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | 223 + WDIOF_MAGICCLOSE, 224 + .identity = "Lenovo SE30 watchdog", 225 + }; 226 + 227 + static const struct watchdog_ops lenovo_se30_wdt_ops = { 228 + .owner = THIS_MODULE, 229 + .start = lenovo_se30_wdt_start, 230 + .stop = lenovo_se30_wdt_stop, 231 + .ping = lenovo_se30_wdt_ping, 232 + .get_timeleft = lenovo_se30_wdt_get_timeleft, 233 + }; 234 + 235 + static int lenovo_se30_wdt_probe(struct platform_device *pdev) 236 + { 237 + struct device *dev = &pdev->dev; 238 + struct lenovo_se30_wdt *priv; 239 + unsigned long base_phys; 240 + unsigned short val; 241 + int err; 242 + 243 + err = superio_enter(UNLOCK_KEY, SIO_REG, LNV_SE30_NAME); 244 + if (err) 245 + return err; 246 + 247 + val = superio_inb(SIO_REG, CHIPID_REG) << 8; 248 + val |= superio_inb(SIO_REG, CHIPID_REG + 1); 249 + 250 + if ((val & CHIPID_MASK) != LNV_SE30_ID) { 251 + superio_exit(LOCK_KEY, SIO_REG); 252 + return -ENODEV; 253 + } 254 + 255 + superio_outb(SIO_REG, LDN_REG, LD_NUM_SHM); 256 + base_phys = (superio_inb(SIO_REG, LD_BASE_ADDR) | 257 + (superio_inb(SIO_REG, LD_BASE_ADDR + 1) << 8) | 258 + (superio_inb(SIO_REG, LD_BASE_ADDR + 2) << 16) | 259 + (superio_inb(SIO_REG, LD_BASE_ADDR + 3) << 24)) & 260 + 0xFFFFFFFF; 261 + 262 + superio_exit(LOCK_KEY, SIO_REG); 263 + if (base_phys == 0xFFFFFFFF || base_phys == 0) 264 + return -ENODEV; 265 + 266 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 267 + if (!priv) 268 + return -ENOMEM; 269 + 270 + if (!devm_request_mem_region(dev, base_phys, SHM_WIN_SIZE, LNV_SE30_NAME)) 271 + return -EBUSY; 272 + 273 + priv->shm_base_addr = devm_ioremap(dev, base_phys, SHM_WIN_SIZE); 274 + 275 + priv->wdt_cfg.mod = WDT_MODULE; 276 + priv->wdt_cfg.idx = WDT_CFG_INDEX; 277 + priv->wdt_cnt.mod = WDT_MODULE; 278 + priv->wdt_cnt.idx = WDT_CNT_INDEX; 279 + 280 + priv->wdt.ops = &lenovo_se30_wdt_ops; 281 + priv->wdt.info = &lenovo_se30_wdt_info; 282 + priv->wdt.timeout = WATCHDOG_TIMEOUT; /* Set default timeout */ 283 + priv->wdt.min_timeout = MIN_TIMEOUT; 284 + priv->wdt.max_timeout = MAX_TIMEOUT; 285 + priv->wdt.parent = dev; 286 + 287 + watchdog_init_timeout(&priv->wdt, timeout, dev); 288 + watchdog_set_drvdata(&priv->wdt, priv); 289 + watchdog_set_nowayout(&priv->wdt, nowayout); 290 + watchdog_stop_on_reboot(&priv->wdt); 291 + watchdog_stop_on_unregister(&priv->wdt); 292 + 293 + return devm_watchdog_register_device(dev, &priv->wdt); 294 + } 295 + 296 + static struct platform_device *pdev; 297 + 298 + static struct platform_driver lenovo_se30_wdt_driver = { 299 + .driver = { 300 + .name = LNV_SE30_NAME, 301 + }, 302 + .probe = lenovo_se30_wdt_probe, 303 + }; 304 + 305 + static int lenovo_se30_create_platform_device(const struct dmi_system_id *id) 306 + { 307 + int err; 308 + 309 + pdev = platform_device_alloc(LNV_SE30_NAME, -1); 310 + if (!pdev) 311 + return -ENOMEM; 312 + 313 + err = platform_device_add(pdev); 314 + if (err) 315 + platform_device_put(pdev); 316 + 317 + return err; 318 + } 319 + 320 + static const struct dmi_system_id lenovo_se30_wdt_dmi_table[] __initconst = { 321 + { 322 + .ident = "LENOVO-SE30", 323 + .matches = { 324 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 325 + DMI_MATCH(DMI_PRODUCT_NAME, "11NA"), 326 + }, 327 + .callback = lenovo_se30_create_platform_device, 328 + }, 329 + { 330 + .ident = "LENOVO-SE30", 331 + .matches = { 332 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 333 + DMI_MATCH(DMI_PRODUCT_NAME, "11NB"), 334 + }, 335 + .callback = lenovo_se30_create_platform_device, 336 + }, 337 + { 338 + .ident = "LENOVO-SE30", 339 + .matches = { 340 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 341 + DMI_MATCH(DMI_PRODUCT_NAME, "11NC"), 342 + }, 343 + .callback = lenovo_se30_create_platform_device, 344 + }, 345 + { 346 + .ident = "LENOVO-SE30", 347 + .matches = { 348 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 349 + DMI_MATCH(DMI_PRODUCT_NAME, "11NH"), 350 + }, 351 + .callback = lenovo_se30_create_platform_device, 352 + }, 353 + { 354 + .ident = "LENOVO-SE30", 355 + .matches = { 356 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 357 + DMI_MATCH(DMI_PRODUCT_NAME, "11NJ"), 358 + }, 359 + .callback = lenovo_se30_create_platform_device, 360 + }, 361 + { 362 + .ident = "LENOVO-SE30", 363 + .matches = { 364 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 365 + DMI_MATCH(DMI_PRODUCT_NAME, "11NK"), 366 + }, 367 + .callback = lenovo_se30_create_platform_device, 368 + }, 369 + {} 370 + }; 371 + MODULE_DEVICE_TABLE(dmi, lenovo_se30_wdt_dmi_table); 372 + 373 + static int __init lenovo_se30_wdt_init(void) 374 + { 375 + if (!dmi_check_system(lenovo_se30_wdt_dmi_table)) 376 + return -ENODEV; 377 + 378 + return platform_driver_register(&lenovo_se30_wdt_driver); 379 + } 380 + 381 + static void __exit lenovo_se30_wdt_exit(void) 382 + { 383 + if (pdev) 384 + platform_device_unregister(pdev); 385 + platform_driver_unregister(&lenovo_se30_wdt_driver); 386 + } 387 + 388 + module_init(lenovo_se30_wdt_init); 389 + module_exit(lenovo_se30_wdt_exit); 390 + 391 + MODULE_AUTHOR("Mark Pearson <mpearson-lenovo@squebb.ca>"); 392 + MODULE_AUTHOR("David Ober <dober@lenovo.com>"); 393 + MODULE_DESCRIPTION("Lenovo SE30 watchdog driver"); 394 + MODULE_LICENSE("GPL");
+5 -4
drivers/watchdog/nic7018_wdt.c
··· 3 3 * Copyright (C) 2016 National Instruments Corp. 4 4 */ 5 5 6 - #include <linux/acpi.h> 7 6 #include <linux/bitops.h> 8 7 #include <linux/device.h> 9 8 #include <linux/io.h> 9 + #include <linux/mod_devicetable.h> 10 10 #include <linux/module.h> 11 11 #include <linux/platform_device.h> 12 + #include <linux/types.h> 12 13 #include <linux/watchdog.h> 13 14 14 15 #define LOCK 0xA5 ··· 230 229 } 231 230 232 231 static const struct acpi_device_id nic7018_device_ids[] = { 233 - {"NIC7018", 0}, 234 - {"", 0}, 232 + { "NIC7018" }, 233 + { } 235 234 }; 236 235 MODULE_DEVICE_TABLE(acpi, nic7018_device_ids); 237 236 ··· 240 239 .remove = nic7018_remove, 241 240 .driver = { 242 241 .name = KBUILD_MODNAME, 243 - .acpi_match_table = ACPI_PTR(nic7018_device_ids), 242 + .acpi_match_table = nic7018_device_ids, 244 243 }, 245 244 }; 246 245
+3 -6
drivers/watchdog/npcm_wdt.c
··· 68 68 struct npcm_wdt *wdt = to_npcm_wdt(wdd); 69 69 u32 val; 70 70 71 - if (wdt->clk) 72 - clk_prepare_enable(wdt->clk); 71 + clk_prepare_enable(wdt->clk); 73 72 74 73 if (wdd->timeout < 2) 75 74 val = 0x800; ··· 104 105 105 106 writel(0, wdt->reg); 106 107 107 - if (wdt->clk) 108 - clk_disable_unprepare(wdt->clk); 108 + clk_disable_unprepare(wdt->clk); 109 109 110 110 return 0; 111 111 } ··· 154 156 struct npcm_wdt *wdt = to_npcm_wdt(wdd); 155 157 156 158 /* For reset, we start the WDT clock and leave it running. */ 157 - if (wdt->clk) 158 - clk_prepare_enable(wdt->clk); 159 + clk_prepare_enable(wdt->clk); 159 160 160 161 writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, wdt->reg); 161 162 udelay(1000);
+6 -4
drivers/watchdog/s3c2410_wdt.c
··· 72 72 #define EXYNOS850_CLUSTER1_WDTRESET_BIT 23 73 73 #define EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT 25 74 74 #define EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT 24 75 + #define EXYNOSAUTOV920_CLUSTER0_WDTRESET_BIT 0 76 + #define EXYNOSAUTOV920_CLUSTER1_WDTRESET_BIT 1 75 77 76 78 #define GS_CLUSTER0_NONCPU_OUT 0x1220 77 79 #define GS_CLUSTER1_NONCPU_OUT 0x1420 ··· 314 312 .mask_bit = 2, 315 313 .mask_reset_inv = true, 316 314 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, 317 - .rst_stat_bit = EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT, 315 + .rst_stat_bit = EXYNOSAUTOV920_CLUSTER0_WDTRESET_BIT, 318 316 .cnt_en_reg = EXYNOSAUTOV920_CLUSTER0_NONCPU_OUT, 319 - .cnt_en_bit = 7, 317 + .cnt_en_bit = 8, 320 318 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 321 319 QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 322 320 QUIRK_HAS_DBGACK_BIT, ··· 327 325 .mask_bit = 2, 328 326 .mask_reset_inv = true, 329 327 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, 330 - .rst_stat_bit = EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT, 328 + .rst_stat_bit = EXYNOSAUTOV920_CLUSTER1_WDTRESET_BIT, 331 329 .cnt_en_reg = EXYNOSAUTOV920_CLUSTER1_NONCPU_OUT, 332 - .cnt_en_bit = 7, 330 + .cnt_en_bit = 8, 333 331 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 334 332 QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 335 333 QUIRK_HAS_DBGACK_BIT,
+11
drivers/watchdog/sunxi_wdt.c
··· 236 236 .wdt_key_val = 0x16aa0000, 237 237 }; 238 238 239 + static const struct sunxi_wdt_reg sun55i_wdt_reg = { 240 + .wdt_ctrl = 0x0c, 241 + .wdt_cfg = 0x10, 242 + .wdt_mode = 0x14, 243 + .wdt_timeout_shift = 4, 244 + .wdt_reset_mask = 0x03, 245 + .wdt_reset_val = 0x01, 246 + .wdt_key_val = 0x16aa0000, 247 + }; 248 + 239 249 static const struct of_device_id sunxi_wdt_dt_ids[] = { 240 250 { .compatible = "allwinner,sun4i-a10-wdt", .data = &sun4i_wdt_reg }, 241 251 { .compatible = "allwinner,sun6i-a31-wdt", .data = &sun6i_wdt_reg }, 242 252 { .compatible = "allwinner,sun20i-d1-wdt", .data = &sun20i_wdt_reg }, 253 + { .compatible = "allwinner,sun55i-a523-wdt", .data = &sun55i_wdt_reg }, 243 254 { /* sentinel */ } 244 255 }; 245 256 MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
+3 -3
drivers/watchdog/watchdog_core.c
··· 33 33 #include <linux/init.h> /* For __init/__exit/... */ 34 34 #include <linux/idr.h> /* For ida_* macros */ 35 35 #include <linux/err.h> /* For IS_ERR macros */ 36 - #include <linux/of.h> /* For of_get_timeout_sec */ 36 + #include <linux/of.h> /* For of_alias_get_id */ 37 + #include <linux/property.h> /* For device_property_read_u32 */ 37 38 #include <linux/suspend.h> 38 39 39 40 #include "watchdog_core.h" /* For watchdog_dev_register/... */ ··· 138 137 } 139 138 140 139 /* try to get the timeout_sec property */ 141 - if (dev && dev->of_node && 142 - of_property_read_u32(dev->of_node, "timeout-sec", &t) == 0) { 140 + if (dev && device_property_read_u32(dev, "timeout-sec", &t) == 0) { 143 141 if (t && !watchdog_timeout_invalid(wdd, t)) { 144 142 wdd->timeout = t; 145 143 return 0;