1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas RZ/G2L WDT Watchdog Driver 4 * 5 * Copyright (C) 2021 Renesas Electronics Corporation 6 */ 7 #include <linux/bitops.h> 8 #include <linux/clk.h> 9 #include <linux/delay.h> 10 #include <linux/io.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_domain.h> 16 #include <linux/pm_runtime.h> 17 #include <linux/reset.h> 18 #include <linux/units.h> 19 #include <linux/watchdog.h> 20 21 #define WDTCNT 0x00 22 #define WDTSET 0x04 23 #define WDTTIM 0x08 24 #define WDTINT 0x0C 25 #define PECR 0x10 26 #define PEEN 0x14 27 #define WDTCNT_WDTEN BIT(0) 28 #define WDTINT_INTDISP BIT(0) 29 #define PEEN_FORCE BIT(0) 30 31 #define WDT_DEFAULT_TIMEOUT 60U 32 33 /* Setting period time register only 12 bit set in WDTSET[31:20] */ 34 #define WDTSET_COUNTER_MASK (0xFFF00000) 35 #define WDTSET_COUNTER_VAL(f) ((f) << 20) 36 37 #define F2CYCLE_NSEC(f) (1000000000 / (f)) 38 39 #define RZV2M_A_NSEC 730 40 41 static bool nowayout = WATCHDOG_NOWAYOUT; 42 module_param(nowayout, bool, 0); 43 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 44 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 45 46 enum rz_wdt_type { 47 WDT_RZG2L, 48 WDT_RZV2M, 49 }; 50 51 struct rzg2l_wdt_priv { 52 void __iomem *base; 53 struct watchdog_device wdev; 54 struct reset_control *rstc; 55 unsigned long osc_clk_rate; 56 unsigned long delay; 57 struct clk *pclk; 58 struct clk *osc_clk; 59 enum rz_wdt_type devtype; 60 }; 61 62 static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv) 63 { 64 /* delay timer when change the setting register */ 65 ndelay(priv->delay); 66 } 67 68 static u32 rzg2l_wdt_get_cycle_usec(unsigned long cycle, u32 wdttime) 69 { 70 u64 timer_cycle_us = 1024 * 1024ULL * (wdttime + 1) * MICRO; 71 72 return div64_ul(timer_cycle_us, cycle); 73 } 74 75 static void rzg2l_wdt_write(struct rzg2l_wdt_priv *priv, u32 val, unsigned int reg) 76 { 77 if (reg == WDTSET) 78 val &= WDTSET_COUNTER_MASK; 79 80 writel_relaxed(val, priv->base + reg); 81 /* Registers other than the WDTINT is always synchronized with WDT_CLK */ 82 if (reg != WDTINT) 83 rzg2l_wdt_wait_delay(priv); 84 } 85 86 static void rzg2l_wdt_init_timeout(struct watchdog_device *wdev) 87 { 88 struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); 89 u32 time_out; 90 91 /* Clear Lapsed Time Register and clear Interrupt */ 92 rzg2l_wdt_write(priv, WDTINT_INTDISP, WDTINT); 93 /* 2 consecutive overflow cycle needed to trigger reset */ 94 time_out = (wdev->timeout * (MICRO / 2)) / 95 rzg2l_wdt_get_cycle_usec(priv->osc_clk_rate, 0); 96 rzg2l_wdt_write(priv, WDTSET_COUNTER_VAL(time_out), WDTSET); 97 } 98 99 static int rzg2l_wdt_start(struct watchdog_device *wdev) 100 { 101 struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); 102 int ret; 103 104 ret = pm_runtime_resume_and_get(wdev->parent); 105 if (ret) 106 return ret; 107 108 ret = reset_control_deassert(priv->rstc); 109 if (ret) { 110 pm_runtime_put(wdev->parent); 111 return ret; 112 } 113 114 /* Initialize time out */ 115 rzg2l_wdt_init_timeout(wdev); 116 117 /* Initialize watchdog counter register */ 118 rzg2l_wdt_write(priv, 0, WDTTIM); 119 120 /* Enable watchdog timer*/ 121 rzg2l_wdt_write(priv, WDTCNT_WDTEN, WDTCNT); 122 123 return 0; 124 } 125 126 static int rzg2l_wdt_stop(struct watchdog_device *wdev) 127 { 128 struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); 129 int ret; 130 131 ret = reset_control_assert(priv->rstc); 132 if (ret) 133 return ret; 134 135 pm_runtime_put(wdev->parent); 136 137 return 0; 138 } 139 140 static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout) 141 { 142 int ret = 0; 143 144 wdev->timeout = timeout; 145 146 /* 147 * If the watchdog is active, reset the module for updating the WDTSET 148 * register by calling rzg2l_wdt_stop() (which internally calls reset_control_reset() 149 * to reset the module) so that it is updated with new timeout values. 150 */ 151 if (watchdog_active(wdev)) { 152 ret = rzg2l_wdt_stop(wdev); 153 if (ret) 154 return ret; 155 156 ret = rzg2l_wdt_start(wdev); 157 } 158 159 return ret; 160 } 161 162 static int rzg2l_wdt_restart(struct watchdog_device *wdev, 163 unsigned long action, void *data) 164 { 165 struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); 166 int ret; 167 168 /* 169 * In case of RZ/G3S the watchdog device may be part of an IRQ safe power 170 * domain that is currently powered off. In this case we need to power 171 * it on before accessing registers. Along with this the clocks will be 172 * enabled. We don't undo the pm_runtime_resume_and_get() as the device 173 * need to be on for the reboot to happen. 174 * 175 * For the rest of SoCs not registering a watchdog IRQ safe power 176 * domain it is safe to call pm_runtime_resume_and_get() as the 177 * irq_safe_dev_in_sleep_domain() call in genpd_runtime_resume() 178 * returns non zero value and the genpd_lock() is avoided, thus, there 179 * will be no invalid wait context reported by lockdep. 180 */ 181 ret = pm_runtime_resume_and_get(wdev->parent); 182 if (ret) 183 return ret; 184 185 if (priv->devtype == WDT_RZG2L) { 186 ret = reset_control_deassert(priv->rstc); 187 if (ret) 188 return ret; 189 190 /* Generate Reset (WDTRSTB) Signal on parity error */ 191 rzg2l_wdt_write(priv, 0, PECR); 192 193 /* Force parity error */ 194 rzg2l_wdt_write(priv, PEEN_FORCE, PEEN); 195 } else { 196 /* RZ/V2M doesn't have parity error registers */ 197 ret = reset_control_reset(priv->rstc); 198 if (ret) 199 return ret; 200 201 wdev->timeout = 0; 202 203 /* Initialize time out */ 204 rzg2l_wdt_init_timeout(wdev); 205 206 /* Initialize watchdog counter register */ 207 rzg2l_wdt_write(priv, 0, WDTTIM); 208 209 /* Enable watchdog timer*/ 210 rzg2l_wdt_write(priv, WDTCNT_WDTEN, WDTCNT); 211 212 /* Wait 2 consecutive overflow cycles for reset */ 213 mdelay(DIV_ROUND_UP(2 * 0xFFFFF * 1000, priv->osc_clk_rate)); 214 } 215 216 return 0; 217 } 218 219 static const struct watchdog_info rzg2l_wdt_ident = { 220 .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, 221 .identity = "Renesas RZ/G2L WDT Watchdog", 222 }; 223 224 static int rzg2l_wdt_ping(struct watchdog_device *wdev) 225 { 226 struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); 227 228 rzg2l_wdt_write(priv, WDTINT_INTDISP, WDTINT); 229 230 return 0; 231 } 232 233 static const struct watchdog_ops rzg2l_wdt_ops = { 234 .owner = THIS_MODULE, 235 .start = rzg2l_wdt_start, 236 .stop = rzg2l_wdt_stop, 237 .ping = rzg2l_wdt_ping, 238 .set_timeout = rzg2l_wdt_set_timeout, 239 .restart = rzg2l_wdt_restart, 240 }; 241 242 static void rzg2l_wdt_pm_disable(void *data) 243 { 244 struct watchdog_device *wdev = data; 245 246 pm_runtime_disable(wdev->parent); 247 } 248 249 static int rzg2l_wdt_probe(struct platform_device *pdev) 250 { 251 struct device *dev = &pdev->dev; 252 struct rzg2l_wdt_priv *priv; 253 unsigned long pclk_rate; 254 int ret; 255 256 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 257 if (!priv) 258 return -ENOMEM; 259 260 priv->base = devm_platform_ioremap_resource(pdev, 0); 261 if (IS_ERR(priv->base)) 262 return PTR_ERR(priv->base); 263 264 /* Get watchdog main clock */ 265 priv->osc_clk = devm_clk_get(&pdev->dev, "oscclk"); 266 if (IS_ERR(priv->osc_clk)) 267 return dev_err_probe(&pdev->dev, PTR_ERR(priv->osc_clk), "no oscclk"); 268 269 priv->osc_clk_rate = clk_get_rate(priv->osc_clk); 270 if (!priv->osc_clk_rate) 271 return dev_err_probe(&pdev->dev, -EINVAL, "oscclk rate is 0"); 272 273 /* Get Peripheral clock */ 274 priv->pclk = devm_clk_get(&pdev->dev, "pclk"); 275 if (IS_ERR(priv->pclk)) 276 return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk), "no pclk"); 277 278 pclk_rate = clk_get_rate(priv->pclk); 279 if (!pclk_rate) 280 return dev_err_probe(&pdev->dev, -EINVAL, "pclk rate is 0"); 281 282 priv->delay = F2CYCLE_NSEC(priv->osc_clk_rate) * 6 + F2CYCLE_NSEC(pclk_rate) * 9; 283 284 priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 285 if (IS_ERR(priv->rstc)) 286 return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc), 287 "failed to get cpg reset"); 288 289 priv->devtype = (uintptr_t)of_device_get_match_data(dev); 290 291 pm_runtime_irq_safe(&pdev->dev); 292 pm_runtime_enable(&pdev->dev); 293 294 priv->wdev.info = &rzg2l_wdt_ident; 295 priv->wdev.ops = &rzg2l_wdt_ops; 296 priv->wdev.parent = dev; 297 priv->wdev.min_timeout = 1; 298 priv->wdev.max_timeout = rzg2l_wdt_get_cycle_usec(priv->osc_clk_rate, 0xfff) / 299 USEC_PER_SEC; 300 priv->wdev.timeout = WDT_DEFAULT_TIMEOUT; 301 302 watchdog_set_drvdata(&priv->wdev, priv); 303 dev_set_drvdata(dev, priv); 304 ret = devm_add_action_or_reset(&pdev->dev, rzg2l_wdt_pm_disable, &priv->wdev); 305 if (ret) 306 return ret; 307 308 watchdog_set_nowayout(&priv->wdev, nowayout); 309 watchdog_stop_on_unregister(&priv->wdev); 310 311 watchdog_init_timeout(&priv->wdev, 0, dev); 312 313 return devm_watchdog_register_device(&pdev->dev, &priv->wdev); 314 } 315 316 static const struct of_device_id rzg2l_wdt_ids[] = { 317 { .compatible = "renesas,rzg2l-wdt", .data = (void *)WDT_RZG2L }, 318 { .compatible = "renesas,rzv2m-wdt", .data = (void *)WDT_RZV2M }, 319 { /* sentinel */ } 320 }; 321 MODULE_DEVICE_TABLE(of, rzg2l_wdt_ids); 322 323 static int rzg2l_wdt_suspend_late(struct device *dev) 324 { 325 struct rzg2l_wdt_priv *priv = dev_get_drvdata(dev); 326 327 if (!watchdog_active(&priv->wdev)) 328 return 0; 329 330 return rzg2l_wdt_stop(&priv->wdev); 331 } 332 333 static int rzg2l_wdt_resume_early(struct device *dev) 334 { 335 struct rzg2l_wdt_priv *priv = dev_get_drvdata(dev); 336 337 if (!watchdog_active(&priv->wdev)) 338 return 0; 339 340 return rzg2l_wdt_start(&priv->wdev); 341 } 342 343 static const struct dev_pm_ops rzg2l_wdt_pm_ops = { 344 LATE_SYSTEM_SLEEP_PM_OPS(rzg2l_wdt_suspend_late, rzg2l_wdt_resume_early) 345 }; 346 347 static struct platform_driver rzg2l_wdt_driver = { 348 .driver = { 349 .name = "rzg2l_wdt", 350 .of_match_table = rzg2l_wdt_ids, 351 .pm = &rzg2l_wdt_pm_ops, 352 }, 353 .probe = rzg2l_wdt_probe, 354 }; 355 module_platform_driver(rzg2l_wdt_driver); 356 357 MODULE_DESCRIPTION("Renesas RZ/G2L WDT Watchdog Driver"); 358 MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); 359 MODULE_LICENSE("GPL v2"); 360