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

Pull watchdog updates from Wim Van Sebroeck:

- renesas,wdt: Add support for RZ/T2H and RZ/N2H

- Add SMARC-sAM67 support

- Several small fixes and improvements

* tag 'linux-watchdog-6.18-rc1' of git://www.linux-watchdog.org/linux-watchdog:
watchdog/hpwdt New maintianer
dt-bindings: watchdog: add SMARC-sAM67 support
watchdog: mpc8xxx_wdt: Reload the watchdog timer when enabling the watchdog
watchdog: visconti: don't print superfluous errors
watchdog: rzv2h_wdt: don't print superfluous errors
watchdog: rzg2l_wdt: don't print superfluous errors
watchdog: s3c2410_wdt: exynosautov9: Enable supported features
watchdog: s3c2410_wdt: exynosautov920: Enable QUIRK_HAS_32BIT_CNT
watchdog: s3c2410_wdt: Increase max timeout value of watchdog
watchdog: s3c2410_wdt: Fix max_timeout being calculated larger
watchdog: s3c2410_wdt: Replace hardcoded values with macro definitions
watchdog: rzv2h: Improve error strings and add newlines
watchdog: rzv2h: Add support for RZ/T2H
watchdog: rzv2h: Add support for configurable count clock source
watchdog: rzv2h: Make "oscclk" and reset controller optional
watchdog: rzv2h: Obtain clock-divider and timeout values from OF match data
dt-bindings: watchdog: renesas,wdt: Add support for RZ/T2H and RZ/N2H
watchdog: intel_oc_wdt: Do not try to write into const memory

+206 -47
+33 -3
Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml
··· 81 - renesas,r9a09g056-wdt # RZ/V2N 82 - const: renesas,r9a09g057-wdt # RZ/V2H(P) 83 84 - - const: renesas,r9a09g057-wdt # RZ/V2H(P) 85 86 reg: 87 - maxItems: 1 88 89 interrupts: 90 minItems: 1 ··· 139 compatible: 140 contains: 141 enum: 142 - renesas,rza-wdt 143 - renesas,rzn1-wdt 144 then: ··· 191 properties: 192 compatible: 193 contains: 194 - const: renesas,r9a09g057-wdt 195 then: 196 properties: 197 interrupts: false ··· 201 else: 202 required: 203 - interrupts 204 205 additionalProperties: false 206
··· 81 - renesas,r9a09g056-wdt # RZ/V2N 82 - const: renesas,r9a09g057-wdt # RZ/V2H(P) 83 84 + - enum: 85 + - renesas,r9a09g057-wdt # RZ/V2H(P) 86 + - renesas,r9a09g077-wdt # RZ/T2H 87 + 88 + - items: 89 + - const: renesas,r9a09g087-wdt # RZ/N2H 90 + - const: renesas,r9a09g077-wdt # RZ/T2H 91 92 reg: 93 + minItems: 1 94 + maxItems: 2 95 96 interrupts: 97 minItems: 1 ··· 132 compatible: 133 contains: 134 enum: 135 + - renesas,r9a09g077-wdt 136 - renesas,rza-wdt 137 - renesas,rzn1-wdt 138 then: ··· 183 properties: 184 compatible: 185 contains: 186 + enum: 187 + - renesas,r9a09g057-wdt 188 + - renesas,r9a09g077-wdt 189 then: 190 properties: 191 interrupts: false ··· 191 else: 192 required: 193 - interrupts 194 + 195 + - if: 196 + properties: 197 + compatible: 198 + contains: 199 + const: renesas,r9a09g077-wdt 200 + then: 201 + properties: 202 + resets: false 203 + clock-names: 204 + maxItems: 1 205 + reg: 206 + minItems: 2 207 + required: 208 + - clock-names 209 + - power-domains 210 + else: 211 + properties: 212 + reg: 213 + maxItems: 1 214 215 additionalProperties: false 216
+1 -1
MAINTAINERS
··· 10961 F: drivers/misc/hpilo.[ch] 10962 10963 HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER 10964 - M: Jerry Hoemann <jerry.hoemann@hpe.com> 10965 S: Supported 10966 F: Documentation/watchdog/hpwdt.rst 10967 F: drivers/watchdog/hpwdt.c
··· 10961 F: drivers/misc/hpilo.[ch] 10962 10963 HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER 10964 + M: Craig Lamparter <craig.lamparter@hpe.com> 10965 S: Supported 10966 F: Documentation/watchdog/hpwdt.rst 10967 F: drivers/watchdog/hpwdt.c
+4 -4
drivers/watchdog/intel_oc_wdt.c
··· 41 struct intel_oc_wdt { 42 struct watchdog_device wdd; 43 struct resource *ctrl_res; 44 bool locked; 45 }; 46 ··· 116 117 static int intel_oc_wdt_setup(struct intel_oc_wdt *oc_wdt) 118 { 119 - struct watchdog_info *info; 120 unsigned long val; 121 122 val = inl(INTEL_OC_WDT_CTRL_REG(oc_wdt)); ··· 134 set_bit(WDOG_HW_RUNNING, &oc_wdt->wdd.status); 135 136 if (oc_wdt->locked) { 137 - info = (struct watchdog_info *)&intel_oc_wdt_info; 138 /* 139 * Set nowayout unconditionally as we cannot stop 140 * the watchdog. ··· 144 * and inform the core we can't change it. 145 */ 146 oc_wdt->wdd.timeout = (val & INTEL_OC_WDT_TOV) + 1; 147 - info->options &= ~WDIOF_SETTIMEOUT; 148 149 dev_info(oc_wdt->wdd.parent, 150 "Register access locked, heartbeat fixed at: %u s\n", ··· 192 wdd->min_timeout = INTEL_OC_WDT_MIN_TOV; 193 wdd->max_timeout = INTEL_OC_WDT_MAX_TOV; 194 wdd->timeout = INTEL_OC_WDT_DEF_TOV; 195 - wdd->info = &intel_oc_wdt_info; 196 wdd->ops = &intel_oc_wdt_ops; 197 wdd->parent = dev; 198
··· 41 struct intel_oc_wdt { 42 struct watchdog_device wdd; 43 struct resource *ctrl_res; 44 + struct watchdog_info info; 45 bool locked; 46 }; 47 ··· 115 116 static int intel_oc_wdt_setup(struct intel_oc_wdt *oc_wdt) 117 { 118 unsigned long val; 119 120 val = inl(INTEL_OC_WDT_CTRL_REG(oc_wdt)); ··· 134 set_bit(WDOG_HW_RUNNING, &oc_wdt->wdd.status); 135 136 if (oc_wdt->locked) { 137 /* 138 * Set nowayout unconditionally as we cannot stop 139 * the watchdog. ··· 145 * and inform the core we can't change it. 146 */ 147 oc_wdt->wdd.timeout = (val & INTEL_OC_WDT_TOV) + 1; 148 + oc_wdt->info.options &= ~WDIOF_SETTIMEOUT; 149 150 dev_info(oc_wdt->wdd.parent, 151 "Register access locked, heartbeat fixed at: %u s\n", ··· 193 wdd->min_timeout = INTEL_OC_WDT_MIN_TOV; 194 wdd->max_timeout = INTEL_OC_WDT_MAX_TOV; 195 wdd->timeout = INTEL_OC_WDT_DEF_TOV; 196 + oc_wdt->info = intel_oc_wdt_info; 197 + wdd->info = &oc_wdt->info; 198 wdd->ops = &intel_oc_wdt_ops; 199 wdd->parent = dev; 200
+2
drivers/watchdog/mpc8xxx_wdt.c
··· 100 ddata->swtc = tmp >> 16; 101 set_bit(WDOG_HW_RUNNING, &ddata->wdd.status); 102 103 return 0; 104 } 105
··· 100 ddata->swtc = tmp >> 16; 101 set_bit(WDOG_HW_RUNNING, &ddata->wdd.status); 102 103 + mpc8xxx_wdt_keepalive(ddata); 104 + 105 return 0; 106 } 107
+1 -3
drivers/watchdog/rzg2l_wdt.c
··· 310 watchdog_set_nowayout(&priv->wdev, nowayout); 311 watchdog_stop_on_unregister(&priv->wdev); 312 313 - ret = watchdog_init_timeout(&priv->wdev, 0, dev); 314 - if (ret) 315 - dev_warn(dev, "Specified timeout invalid, using default"); 316 317 return devm_watchdog_register_device(&pdev->dev, &priv->wdev); 318 }
··· 310 watchdog_set_nowayout(&priv->wdev, nowayout); 311 watchdog_stop_on_unregister(&priv->wdev); 312 313 + watchdog_init_timeout(&priv->wdev, 0, dev); 314 315 return devm_watchdog_register_device(&pdev->dev, &priv->wdev); 316 }
+131 -19
drivers/watchdog/rzv2h_wdt.c
··· 21 #define WDTSR 0x04 /* WDT Status Register RW, 16 */ 22 #define WDTRCR 0x06 /* WDT Reset Control Register RW, 8 */ 23 24 #define WDTCR_TOPS_1024 0x00 25 #define WDTCR_TOPS_16384 0x03 26 27 #define WDTCR_CKS_CLK_1 0x00 28 #define WDTCR_CKS_CLK_256 0x50 29 30 #define WDTCR_RPES_0 0x300 31 #define WDTCR_RPES_75 0x000 ··· 41 42 #define WDTRCR_RSTIRQS BIT(7) 43 44 - #define MAX_TIMEOUT_CYCLES 16384 45 - #define CLOCK_DIV_BY_256 256 46 47 #define WDT_DEFAULT_TIMEOUT 60U 48 ··· 50 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 51 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 52 53 struct rzv2h_wdt_priv { 54 void __iomem *base; 55 struct clk *pclk; 56 struct clk *oscclk; 57 struct reset_control *rstc; 58 struct watchdog_device wdev; 59 }; 60 61 static int rzv2h_wdt_ping(struct watchdog_device *wdev) ··· 87 writeb(0xFF, priv->base + WDTRR); 88 89 return 0; 90 } 91 92 static void rzv2h_wdt_setup(struct watchdog_device *wdev, u16 wdtcr) ··· 120 static int rzv2h_wdt_start(struct watchdog_device *wdev) 121 { 122 struct rzv2h_wdt_priv *priv = watchdog_get_drvdata(wdev); 123 int ret; 124 125 ret = pm_runtime_resume_and_get(wdev->parent); ··· 138 139 /* 140 * WDTCR 141 - * - CKS[7:4] - Clock Division Ratio Select - 0101b: oscclk/256 142 * - RPSS[13:12] - Window Start Position Select - 11b: 100% 143 * - RPES[9:8] - Window End Position Select - 11b: 0% 144 - * - TOPS[1:0] - Timeout Period Select - 11b: 16384 cycles (3FFFh) 145 */ 146 - rzv2h_wdt_setup(wdev, WDTCR_CKS_CLK_256 | WDTCR_RPSS_100 | 147 - WDTCR_RPES_0 | WDTCR_TOPS_16384); 148 149 /* 150 * Down counting starts after writing the sequence 00h -> FFh to the ··· 170 ret = reset_control_assert(priv->rstc); 171 if (ret) 172 return ret; 173 174 ret = pm_runtime_put(wdev->parent); 175 if (ret < 0) ··· 226 227 /* 228 * WDTCR 229 - * - CKS[7:4] - Clock Division Ratio Select - 0000b: oscclk/1 230 * - RPSS[13:12] - Window Start Position Select - 00b: 25% 231 * - RPES[9:8] - Window End Position Select - 00b: 75% 232 * - TOPS[1:0] - Timeout Period Select - 00b: 1024 cycles (03FFh) 233 */ 234 - rzv2h_wdt_setup(wdev, WDTCR_CKS_CLK_1 | WDTCR_RPSS_25 | 235 WDTCR_RPES_75 | WDTCR_TOPS_1024); 236 237 rzv2h_wdt_ping(wdev); 238 ··· 255 .restart = rzv2h_wdt_restart, 256 }; 257 258 static int rzv2h_wdt_probe(struct platform_device *pdev) 259 { 260 struct device *dev = &pdev->dev; 261 struct rzv2h_wdt_priv *priv; 262 int ret; 263 264 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 265 if (!priv) 266 return -ENOMEM; 267 268 priv->base = devm_platform_ioremap_resource(pdev, 0); 269 if (IS_ERR(priv->base)) ··· 296 297 priv->pclk = devm_clk_get_prepared(dev, "pclk"); 298 if (IS_ERR(priv->pclk)) 299 - return dev_err_probe(dev, PTR_ERR(priv->pclk), "no pclk"); 300 301 - priv->oscclk = devm_clk_get_prepared(dev, "oscclk"); 302 if (IS_ERR(priv->oscclk)) 303 - return dev_err_probe(dev, PTR_ERR(priv->oscclk), "no oscclk"); 304 305 - priv->rstc = devm_reset_control_get_exclusive(dev, NULL); 306 if (IS_ERR(priv->rstc)) 307 return dev_err_probe(dev, PTR_ERR(priv->rstc), 308 - "failed to get cpg reset"); 309 310 - priv->wdev.max_hw_heartbeat_ms = (MILLI * MAX_TIMEOUT_CYCLES * CLOCK_DIV_BY_256) / 311 - clk_get_rate(priv->oscclk); 312 dev_dbg(dev, "max hw timeout of %dms\n", priv->wdev.max_hw_heartbeat_ms); 313 314 ret = devm_pm_runtime_enable(dev); 315 if (ret) 316 return ret; 317 318 priv->wdev.min_timeout = 1; 319 priv->wdev.timeout = WDT_DEFAULT_TIMEOUT; ··· 341 watchdog_set_nowayout(&priv->wdev, nowayout); 342 watchdog_stop_on_unregister(&priv->wdev); 343 344 - ret = watchdog_init_timeout(&priv->wdev, 0, dev); 345 - if (ret) 346 - dev_warn(dev, "Specified timeout invalid, using default"); 347 348 return devm_watchdog_register_device(dev, &priv->wdev); 349 } 350 351 static const struct of_device_id rzv2h_wdt_ids[] = { 352 - { .compatible = "renesas,r9a09g057-wdt", }, 353 { /* sentinel */ } 354 }; 355 MODULE_DEVICE_TABLE(of, rzv2h_wdt_ids);
··· 21 #define WDTSR 0x04 /* WDT Status Register RW, 16 */ 22 #define WDTRCR 0x06 /* WDT Reset Control Register RW, 8 */ 23 24 + /* This register is only available on RZ/T2H and RZ/N2H SoCs */ 25 + #define WDTDCR 0x00 /* WDT Debug Control Register RW, 32 */ 26 + 27 #define WDTCR_TOPS_1024 0x00 28 + #define WDTCR_TOPS_4096 0x01 29 #define WDTCR_TOPS_16384 0x03 30 31 #define WDTCR_CKS_CLK_1 0x00 32 + #define WDTCR_CKS_CLK_4 0x10 33 #define WDTCR_CKS_CLK_256 0x50 34 + #define WDTCR_CKS_CLK_8192 0x80 35 36 #define WDTCR_RPES_0 0x300 37 #define WDTCR_RPES_75 0x000 ··· 35 36 #define WDTRCR_RSTIRQS BIT(7) 37 38 + #define WDTDCR_WDTSTOPCTRL BIT(0) 39 40 #define WDT_DEFAULT_TIMEOUT 60U 41 ··· 45 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 46 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 47 48 + enum rzv2h_wdt_count_source { 49 + COUNT_SOURCE_LOCO, 50 + COUNT_SOURCE_PCLK, 51 + }; 52 + 53 + struct rzv2h_of_data { 54 + u8 cks_min; 55 + u8 cks_max; 56 + u16 cks_div; 57 + u8 tops; 58 + u16 timeout_cycles; 59 + enum rzv2h_wdt_count_source count_source; 60 + bool wdtdcr; 61 + }; 62 + 63 struct rzv2h_wdt_priv { 64 void __iomem *base; 65 + void __iomem *wdtdcr; 66 struct clk *pclk; 67 struct clk *oscclk; 68 struct reset_control *rstc; 69 struct watchdog_device wdev; 70 + const struct rzv2h_of_data *of_data; 71 }; 72 73 static int rzv2h_wdt_ping(struct watchdog_device *wdev) ··· 65 writeb(0xFF, priv->base + WDTRR); 66 67 return 0; 68 + } 69 + 70 + static void rzt2h_wdt_wdtdcr_count_stop(struct rzv2h_wdt_priv *priv) 71 + { 72 + u32 reg = readl(priv->wdtdcr + WDTDCR); 73 + 74 + writel(reg | WDTDCR_WDTSTOPCTRL, priv->wdtdcr + WDTDCR); 75 + } 76 + 77 + static void rzt2h_wdt_wdtdcr_count_start(struct rzv2h_wdt_priv *priv) 78 + { 79 + u32 reg = readl(priv->wdtdcr + WDTDCR); 80 + 81 + writel(reg & ~WDTDCR_WDTSTOPCTRL, priv->wdtdcr + WDTDCR); 82 } 83 84 static void rzv2h_wdt_setup(struct watchdog_device *wdev, u16 wdtcr) ··· 84 static int rzv2h_wdt_start(struct watchdog_device *wdev) 85 { 86 struct rzv2h_wdt_priv *priv = watchdog_get_drvdata(wdev); 87 + const struct rzv2h_of_data *of_data = priv->of_data; 88 int ret; 89 90 ret = pm_runtime_resume_and_get(wdev->parent); ··· 101 102 /* 103 * WDTCR 104 + * - CKS[7:4] - Clock Division Ratio Select 105 + * - 0101b: oscclk/256 for RZ/V2H(P) 106 + * - 1000b: pclkl/8192 for RZ/T2H 107 * - RPSS[13:12] - Window Start Position Select - 11b: 100% 108 * - RPES[9:8] - Window End Position Select - 11b: 0% 109 + * - TOPS[1:0] - Timeout Period Select 110 + * - 11b: 16384 cycles (3FFFh) for RZ/V2H(P) 111 + * - 01b: 4096 cycles (0FFFh) for RZ/T2H 112 */ 113 + rzv2h_wdt_setup(wdev, of_data->cks_max | WDTCR_RPSS_100 | 114 + WDTCR_RPES_0 | of_data->tops); 115 + 116 + if (priv->of_data->wdtdcr) 117 + rzt2h_wdt_wdtdcr_count_start(priv); 118 119 /* 120 * Down counting starts after writing the sequence 00h -> FFh to the ··· 126 ret = reset_control_assert(priv->rstc); 127 if (ret) 128 return ret; 129 + 130 + if (priv->of_data->wdtdcr) 131 + rzt2h_wdt_wdtdcr_count_stop(priv); 132 133 ret = pm_runtime_put(wdev->parent); 134 if (ret < 0) ··· 179 180 /* 181 * WDTCR 182 + * - CKS[7:4] - Clock Division Ratio Select 183 + * - 0000b: oscclk/1 for RZ/V2H(P) 184 + * - 0100b: pclkl/4 for RZ/T2H 185 * - RPSS[13:12] - Window Start Position Select - 00b: 25% 186 * - RPES[9:8] - Window End Position Select - 00b: 75% 187 * - TOPS[1:0] - Timeout Period Select - 00b: 1024 cycles (03FFh) 188 */ 189 + rzv2h_wdt_setup(wdev, priv->of_data->cks_min | WDTCR_RPSS_25 | 190 WDTCR_RPES_75 | WDTCR_TOPS_1024); 191 + 192 + if (priv->of_data->wdtdcr) 193 + rzt2h_wdt_wdtdcr_count_start(priv); 194 195 rzv2h_wdt_ping(wdev); 196 ··· 203 .restart = rzv2h_wdt_restart, 204 }; 205 206 + static int rzt2h_wdt_wdtdcr_init(struct platform_device *pdev, 207 + struct rzv2h_wdt_priv *priv) 208 + { 209 + int ret; 210 + 211 + priv->wdtdcr = devm_platform_ioremap_resource(pdev, 1); 212 + if (IS_ERR(priv->wdtdcr)) 213 + return PTR_ERR(priv->wdtdcr); 214 + 215 + ret = pm_runtime_resume_and_get(&pdev->dev); 216 + if (ret) 217 + return ret; 218 + 219 + rzt2h_wdt_wdtdcr_count_stop(priv); 220 + 221 + ret = pm_runtime_put(&pdev->dev); 222 + if (ret < 0) 223 + return ret; 224 + 225 + return 0; 226 + } 227 + 228 static int rzv2h_wdt_probe(struct platform_device *pdev) 229 { 230 struct device *dev = &pdev->dev; 231 struct rzv2h_wdt_priv *priv; 232 + struct clk *count_clk; 233 int ret; 234 235 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 236 if (!priv) 237 return -ENOMEM; 238 + 239 + priv->of_data = of_device_get_match_data(dev); 240 241 priv->base = devm_platform_ioremap_resource(pdev, 0); 242 if (IS_ERR(priv->base)) ··· 219 220 priv->pclk = devm_clk_get_prepared(dev, "pclk"); 221 if (IS_ERR(priv->pclk)) 222 + return dev_err_probe(dev, PTR_ERR(priv->pclk), "Failed to get pclk\n"); 223 224 + priv->oscclk = devm_clk_get_optional_prepared(dev, "oscclk"); 225 if (IS_ERR(priv->oscclk)) 226 + return dev_err_probe(dev, PTR_ERR(priv->oscclk), "Failed to get oscclk\n"); 227 228 + priv->rstc = devm_reset_control_get_optional_exclusive(dev, NULL); 229 if (IS_ERR(priv->rstc)) 230 return dev_err_probe(dev, PTR_ERR(priv->rstc), 231 + "Failed to get cpg reset\n"); 232 233 + switch (priv->of_data->count_source) { 234 + case COUNT_SOURCE_LOCO: 235 + count_clk = priv->oscclk; 236 + break; 237 + case COUNT_SOURCE_PCLK: 238 + count_clk = priv->pclk; 239 + break; 240 + default: 241 + return dev_err_probe(dev, -EINVAL, "Invalid count source\n"); 242 + } 243 + 244 + priv->wdev.max_hw_heartbeat_ms = (MILLI * priv->of_data->timeout_cycles * 245 + priv->of_data->cks_div) / clk_get_rate(count_clk); 246 dev_dbg(dev, "max hw timeout of %dms\n", priv->wdev.max_hw_heartbeat_ms); 247 248 ret = devm_pm_runtime_enable(dev); 249 if (ret) 250 return ret; 251 + 252 + if (priv->of_data->wdtdcr) { 253 + ret = rzt2h_wdt_wdtdcr_init(pdev, priv); 254 + if (ret) 255 + return dev_err_probe(dev, ret, "WDTDCR init failed\n"); 256 + } 257 258 priv->wdev.min_timeout = 1; 259 priv->wdev.timeout = WDT_DEFAULT_TIMEOUT; ··· 247 watchdog_set_nowayout(&priv->wdev, nowayout); 248 watchdog_stop_on_unregister(&priv->wdev); 249 250 + watchdog_init_timeout(&priv->wdev, 0, dev); 251 252 return devm_watchdog_register_device(dev, &priv->wdev); 253 } 254 255 + static const struct rzv2h_of_data rzt2h_wdt_of_data = { 256 + .cks_min = WDTCR_CKS_CLK_4, 257 + .cks_max = WDTCR_CKS_CLK_8192, 258 + .cks_div = 8192, 259 + .tops = WDTCR_TOPS_4096, 260 + .timeout_cycles = 4096, 261 + .count_source = COUNT_SOURCE_PCLK, 262 + .wdtdcr = true, 263 + }; 264 + 265 + static const struct rzv2h_of_data rzv2h_wdt_of_data = { 266 + .cks_min = WDTCR_CKS_CLK_1, 267 + .cks_max = WDTCR_CKS_CLK_256, 268 + .cks_div = 256, 269 + .tops = WDTCR_TOPS_16384, 270 + .timeout_cycles = 16384, 271 + .count_source = COUNT_SOURCE_LOCO, 272 + }; 273 + 274 static const struct of_device_id rzv2h_wdt_ids[] = { 275 + { .compatible = "renesas,r9a09g057-wdt", .data = &rzv2h_wdt_of_data }, 276 + { .compatible = "renesas,r9a09g077-wdt", .data = &rzt2h_wdt_of_data }, 277 { /* sentinel */ } 278 }; 279 MODULE_DEVICE_TABLE(of, rzv2h_wdt_ids);
+33 -13
drivers/watchdog/s3c2410_wdt.c
··· 27 #include <linux/mfd/syscon.h> 28 #include <linux/regmap.h> 29 #include <linux/delay.h> 30 31 #define S3C2410_WTCON 0x00 32 #define S3C2410_WTDAT 0x04 33 #define S3C2410_WTCNT 0x08 34 #define S3C2410_WTCLRINT 0x0c 35 36 - #define S3C2410_WTCNT_MAXCNT 0xffff 37 38 #define S3C2410_WTCON_RSTEN BIT(0) 39 #define S3C2410_WTCON_INTEN BIT(2) ··· 125 * %QUIRK_HAS_DBGACK_BIT: WTCON register has DBGACK_MASK bit. Setting the 126 * DBGACK_MASK bit disables the watchdog outputs when the SoC is in debug mode. 127 * Debug mode is determined by the DBGACK CPU signal. 128 */ 129 #define QUIRK_HAS_WTCLRINT_REG BIT(0) 130 #define QUIRK_HAS_PMU_MASK_RESET BIT(1) ··· 136 #define QUIRK_HAS_PMU_AUTO_DISABLE BIT(3) 137 #define QUIRK_HAS_PMU_CNT_EN BIT(4) 138 #define QUIRK_HAS_DBGACK_BIT BIT(5) 139 140 /* These quirks require that we have a PMU register map */ 141 #define QUIRKS_HAVE_PMUREG \ ··· 205 struct notifier_block freq_transition; 206 const struct s3c2410_wdt_variant *drv_data; 207 struct regmap *pmureg; 208 }; 209 210 static const struct s3c2410_wdt_variant drv_data_s3c2410 = { ··· 306 .cnt_en_reg = EXYNOS850_CLUSTER0_NONCPU_OUT, 307 .cnt_en_bit = 7, 308 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 309 - QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN, 310 }; 311 312 static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = { ··· 319 .cnt_en_reg = EXYNOSAUTOV9_CLUSTER1_NONCPU_OUT, 320 .cnt_en_bit = 7, 321 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 322 - QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN, 323 }; 324 325 static const struct s3c2410_wdt_variant drv_data_gs101_cl0 = { ··· 359 .cnt_en_bit = 8, 360 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 361 QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 362 - QUIRK_HAS_DBGACK_BIT, 363 }; 364 365 static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = { ··· 372 .cnt_en_bit = 8, 373 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 374 QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 375 - QUIRK_HAS_DBGACK_BIT, 376 }; 377 378 static const struct of_device_id s3c2410_wdt_match[] = { ··· 420 static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt) 421 { 422 const unsigned long freq = s3c2410wdt_get_freq(wdt); 423 424 - return S3C2410_WTCNT_MAXCNT / (freq / (S3C2410_WTCON_PRESCALE_MAX + 1) 425 - / S3C2410_WTCON_MAXDIV); 426 } 427 428 static int s3c2410wdt_disable_wdt_reset(struct s3c2410_wdt *wdt, bool mask) ··· 581 { 582 struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); 583 unsigned long freq = s3c2410wdt_get_freq(wdt); 584 - unsigned int count; 585 unsigned int divisor = 1; 586 unsigned long wtcon; 587 ··· 591 freq = DIV_ROUND_UP(freq, 128); 592 count = timeout * freq; 593 594 - dev_dbg(wdt->dev, "Heartbeat: count=%d, timeout=%d, freq=%lu\n", 595 count, timeout, freq); 596 597 /* if the count is bigger than the watchdog register, ··· 599 actually make this value 600 */ 601 602 - if (count >= 0x10000) { 603 - divisor = DIV_ROUND_UP(count, 0xffff); 604 605 - if (divisor > 0x100) { 606 dev_err(wdt->dev, "timeout %d too big\n", timeout); 607 return -EINVAL; 608 } 609 } 610 611 - dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%d (%08x)\n", 612 timeout, divisor, count, DIV_ROUND_UP(count, divisor)); 613 614 count = DIV_ROUND_UP(count, divisor); ··· 815 wdt->src_clk = devm_clk_get_optional_enabled(dev, "watchdog_src"); 816 if (IS_ERR(wdt->src_clk)) 817 return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n"); 818 819 wdt->wdt_device.min_timeout = 1; 820 wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt);
··· 27 #include <linux/mfd/syscon.h> 28 #include <linux/regmap.h> 29 #include <linux/delay.h> 30 + #include <linux/math64.h> 31 32 #define S3C2410_WTCON 0x00 33 #define S3C2410_WTDAT 0x04 34 #define S3C2410_WTCNT 0x08 35 #define S3C2410_WTCLRINT 0x0c 36 37 + #define S3C2410_WTCNT_MAXCNT_16 0xffff 38 + #define S3C2410_WTCNT_MAXCNT_32 0xffffffff 39 40 #define S3C2410_WTCON_RSTEN BIT(0) 41 #define S3C2410_WTCON_INTEN BIT(2) ··· 123 * %QUIRK_HAS_DBGACK_BIT: WTCON register has DBGACK_MASK bit. Setting the 124 * DBGACK_MASK bit disables the watchdog outputs when the SoC is in debug mode. 125 * Debug mode is determined by the DBGACK CPU signal. 126 + * 127 + * %QUIRK_HAS_32BIT_CNT: WTDAT and WTCNT are 32-bit registers. With these 128 + * 32-bit registers, larger values will be set, which means that larger timeouts 129 + * value can be set. 130 */ 131 #define QUIRK_HAS_WTCLRINT_REG BIT(0) 132 #define QUIRK_HAS_PMU_MASK_RESET BIT(1) ··· 130 #define QUIRK_HAS_PMU_AUTO_DISABLE BIT(3) 131 #define QUIRK_HAS_PMU_CNT_EN BIT(4) 132 #define QUIRK_HAS_DBGACK_BIT BIT(5) 133 + #define QUIRK_HAS_32BIT_CNT BIT(6) 134 135 /* These quirks require that we have a PMU register map */ 136 #define QUIRKS_HAVE_PMUREG \ ··· 198 struct notifier_block freq_transition; 199 const struct s3c2410_wdt_variant *drv_data; 200 struct regmap *pmureg; 201 + u32 max_cnt; 202 }; 203 204 static const struct s3c2410_wdt_variant drv_data_s3c2410 = { ··· 298 .cnt_en_reg = EXYNOS850_CLUSTER0_NONCPU_OUT, 299 .cnt_en_bit = 7, 300 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 301 + QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 302 + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_CNT, 303 }; 304 305 static const struct s3c2410_wdt_variant drv_data_exynosautov9_cl1 = { ··· 310 .cnt_en_reg = EXYNOSAUTOV9_CLUSTER1_NONCPU_OUT, 311 .cnt_en_bit = 7, 312 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 313 + QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 314 + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_CNT, 315 }; 316 317 static const struct s3c2410_wdt_variant drv_data_gs101_cl0 = { ··· 349 .cnt_en_bit = 8, 350 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 351 QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 352 + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_CNT, 353 }; 354 355 static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = { ··· 362 .cnt_en_bit = 8, 363 .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | 364 QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | 365 + QUIRK_HAS_DBGACK_BIT | QUIRK_HAS_32BIT_CNT, 366 }; 367 368 static const struct of_device_id s3c2410_wdt_match[] = { ··· 410 static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt) 411 { 412 const unsigned long freq = s3c2410wdt_get_freq(wdt); 413 + const u64 n_max = (u64)(S3C2410_WTCON_PRESCALE_MAX + 1) * 414 + S3C2410_WTCON_MAXDIV * wdt->max_cnt; 415 + u64 t_max = div64_ul(n_max, freq); 416 417 + if (t_max > UINT_MAX) 418 + t_max = UINT_MAX; 419 + 420 + return t_max; 421 } 422 423 static int s3c2410wdt_disable_wdt_reset(struct s3c2410_wdt *wdt, bool mask) ··· 566 { 567 struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); 568 unsigned long freq = s3c2410wdt_get_freq(wdt); 569 + unsigned long count; 570 unsigned int divisor = 1; 571 unsigned long wtcon; 572 ··· 576 freq = DIV_ROUND_UP(freq, 128); 577 count = timeout * freq; 578 579 + dev_dbg(wdt->dev, "Heartbeat: count=%lu, timeout=%d, freq=%lu\n", 580 count, timeout, freq); 581 582 /* if the count is bigger than the watchdog register, ··· 584 actually make this value 585 */ 586 587 + if (count > wdt->max_cnt) { 588 + divisor = DIV_ROUND_UP(count, wdt->max_cnt); 589 590 + if (divisor > S3C2410_WTCON_PRESCALE_MAX + 1) { 591 dev_err(wdt->dev, "timeout %d too big\n", timeout); 592 return -EINVAL; 593 } 594 } 595 596 + dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%lu (%08lx)\n", 597 timeout, divisor, count, DIV_ROUND_UP(count, divisor)); 598 599 count = DIV_ROUND_UP(count, divisor); ··· 800 wdt->src_clk = devm_clk_get_optional_enabled(dev, "watchdog_src"); 801 if (IS_ERR(wdt->src_clk)) 802 return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n"); 803 + 804 + if (wdt->drv_data->quirks & QUIRK_HAS_32BIT_CNT) 805 + wdt->max_cnt = S3C2410_WTCNT_MAXCNT_32; 806 + else 807 + wdt->max_cnt = S3C2410_WTCNT_MAXCNT_16; 808 809 wdt->wdt_device.min_timeout = 1; 810 wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt);
+1 -4
drivers/watchdog/visconti_wdt.c
··· 118 struct visconti_wdt_priv *priv; 119 struct device *dev = &pdev->dev; 120 struct clk *clk; 121 - int ret; 122 unsigned long clk_freq; 123 124 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ··· 152 watchdog_stop_on_unregister(wdev); 153 154 /* This overrides the default timeout only if DT configuration was found */ 155 - ret = watchdog_init_timeout(wdev, 0, dev); 156 - if (ret) 157 - dev_warn(dev, "Specified timeout value invalid, using default\n"); 158 159 return devm_watchdog_register_device(dev, wdev); 160 }
··· 118 struct visconti_wdt_priv *priv; 119 struct device *dev = &pdev->dev; 120 struct clk *clk; 121 unsigned long clk_freq; 122 123 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ··· 153 watchdog_stop_on_unregister(wdev); 154 155 /* This overrides the default timeout only if DT configuration was found */ 156 + watchdog_init_timeout(wdev, 0, dev); 157 158 return devm_watchdog_register_device(dev, wdev); 159 }