1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Watchdog driver for Renesas WDT watchdog 4 * 5 * Copyright (C) 2015-17 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> 6 * Copyright (C) 2015-17 Renesas Electronics Corporation 7 */ 8#include <linux/bitops.h> 9#include <linux/clk.h> 10#include <linux/delay.h> 11#include <linux/io.h> 12#include <linux/kernel.h> 13#include <linux/module.h> 14#include <linux/of.h> 15#include <linux/platform_device.h> 16#include <linux/pm_runtime.h> 17#include <linux/smp.h> 18#include <linux/sys_soc.h> 19#include <linux/watchdog.h> 20 21#define RWTCNT 0 22#define RWTCSRA 4 23#define RWTCSRA_WOVF BIT(4) 24#define RWTCSRA_WRFLG BIT(5) 25#define RWTCSRA_TME BIT(7) 26#define RWTCSRB 8 27 28#define RWDT_DEFAULT_TIMEOUT 60U 29 30/* 31 * In probe, clk_rate is checked to be not more than 16 bit * biggest clock 32 * divider (12 bits). d is only a factor to fully utilize the WDT counter and 33 * will not exceed its 16 bits. Thus, no overflow, we stay below 32 bits. 34 */ 35#define MUL_BY_CLKS_PER_SEC(p, d) \ 36 DIV_ROUND_UP((d) * (p)->clk_rate, clk_divs[(p)->cks]) 37 38/* d is 16 bit, clk_divs 12 bit -> no 32 bit overflow */ 39#define DIV_BY_CLKS_PER_SEC(p, d) ((d) * clk_divs[(p)->cks] / (p)->clk_rate) 40 41static const unsigned int clk_divs[] = { 1, 4, 16, 32, 64, 128, 1024, 4096 }; 42 43static bool nowayout = WATCHDOG_NOWAYOUT; 44module_param(nowayout, bool, 0); 45MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 46 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 47 48struct rwdt_priv { 49 void __iomem *base; 50 struct watchdog_device wdev; 51 unsigned long clk_rate; 52 u8 cks; 53}; 54 55static void rwdt_write(struct rwdt_priv *priv, u32 val, unsigned int reg) 56{ 57 if (reg == RWTCNT) 58 val |= 0x5a5a0000; 59 else 60 val |= 0xa5a5a500; 61 62 writel_relaxed(val, priv->base + reg); 63} 64 65static int rwdt_init_timeout(struct watchdog_device *wdev) 66{ 67 struct rwdt_priv *priv = watchdog_get_drvdata(wdev); 68 69 rwdt_write(priv, 65536 - MUL_BY_CLKS_PER_SEC(priv, wdev->timeout), RWTCNT); 70 71 return 0; 72} 73 74static void rwdt_wait_cycles(struct rwdt_priv *priv, unsigned int cycles) 75{ 76 unsigned int delay; 77 78 delay = DIV_ROUND_UP(cycles * 1000000, priv->clk_rate); 79 80 usleep_range(delay, 2 * delay); 81} 82 83static int rwdt_start(struct watchdog_device *wdev) 84{ 85 struct rwdt_priv *priv = watchdog_get_drvdata(wdev); 86 u8 val; 87 88 pm_runtime_get_sync(wdev->parent); 89 90 /* Stop the timer before we modify any register */ 91 val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME; 92 rwdt_write(priv, val, RWTCSRA); 93 /* Delay 2 cycles before setting watchdog counter */ 94 rwdt_wait_cycles(priv, 2); 95 96 rwdt_init_timeout(wdev); 97 rwdt_write(priv, priv->cks, RWTCSRA); 98 rwdt_write(priv, 0, RWTCSRB); 99 100 while (readb_relaxed(priv->base + RWTCSRA) & RWTCSRA_WRFLG) 101 cpu_relax(); 102 103 rwdt_write(priv, priv->cks | RWTCSRA_TME, RWTCSRA); 104 105 return 0; 106} 107 108static int rwdt_stop(struct watchdog_device *wdev) 109{ 110 struct rwdt_priv *priv = watchdog_get_drvdata(wdev); 111 112 rwdt_write(priv, priv->cks, RWTCSRA); 113 /* Delay 3 cycles before disabling module clock */ 114 rwdt_wait_cycles(priv, 3); 115 pm_runtime_put(wdev->parent); 116 117 return 0; 118} 119 120static unsigned int rwdt_get_timeleft(struct watchdog_device *wdev) 121{ 122 struct rwdt_priv *priv = watchdog_get_drvdata(wdev); 123 u16 val = readw_relaxed(priv->base + RWTCNT); 124 125 return DIV_BY_CLKS_PER_SEC(priv, 65536 - val); 126} 127 128static int rwdt_restart(struct watchdog_device *wdev, unsigned long action, 129 void *data) 130{ 131 struct rwdt_priv *priv = watchdog_get_drvdata(wdev); 132 133 rwdt_start(wdev); 134 rwdt_write(priv, 0xffff, RWTCNT); 135 return 0; 136} 137 138static const struct watchdog_info rwdt_ident = { 139 .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 140 WDIOF_CARDRESET, 141 .identity = "Renesas WDT Watchdog", 142}; 143 144static const struct watchdog_ops rwdt_ops = { 145 .owner = THIS_MODULE, 146 .start = rwdt_start, 147 .stop = rwdt_stop, 148 .ping = rwdt_init_timeout, 149 .get_timeleft = rwdt_get_timeleft, 150 .restart = rwdt_restart, 151}; 152 153#if defined(CONFIG_ARCH_RCAR_GEN2) && defined(CONFIG_SMP) 154/* 155 * Watchdog-reset integration is broken on early revisions of R-Car Gen2 SoCs 156 */ 157static const struct soc_device_attribute rwdt_quirks_match[] = { 158 { 159 .soc_id = "r8a7790", 160 .revision = "ES1.*", 161 .data = (void *)1, /* needs single CPU */ 162 }, { 163 .soc_id = "r8a7791", 164 .revision = "ES1.*", 165 .data = (void *)1, /* needs single CPU */ 166 }, { 167 .soc_id = "r8a7792", 168 .data = (void *)0, /* needs SMP disabled */ 169 }, 170 { /* sentinel */ } 171}; 172 173static bool rwdt_blacklisted(struct device *dev) 174{ 175 const struct soc_device_attribute *attr; 176 177 attr = soc_device_match(rwdt_quirks_match); 178 if (attr && setup_max_cpus > (uintptr_t)attr->data) { 179 dev_info(dev, "Watchdog blacklisted on %s %s\n", attr->soc_id, 180 attr->revision); 181 return true; 182 } 183 184 return false; 185} 186#else /* !CONFIG_ARCH_RCAR_GEN2 || !CONFIG_SMP */ 187static inline bool rwdt_blacklisted(struct device *dev) { return false; } 188#endif /* !CONFIG_ARCH_RCAR_GEN2 || !CONFIG_SMP */ 189 190static int rwdt_probe(struct platform_device *pdev) 191{ 192 struct device *dev = &pdev->dev; 193 struct rwdt_priv *priv; 194 struct clk *clk; 195 unsigned long clks_per_sec; 196 int ret, i; 197 u8 csra; 198 199 if (rwdt_blacklisted(dev)) 200 return -ENODEV; 201 202 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 203 if (!priv) 204 return -ENOMEM; 205 206 priv->base = devm_platform_ioremap_resource(pdev, 0); 207 if (IS_ERR(priv->base)) 208 return PTR_ERR(priv->base); 209 210 clk = devm_clk_get(dev, NULL); 211 if (IS_ERR(clk)) 212 return PTR_ERR(clk); 213 214 pm_runtime_enable(dev); 215 pm_runtime_get_sync(dev); 216 priv->clk_rate = clk_get_rate(clk); 217 csra = readb_relaxed(priv->base + RWTCSRA); 218 priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0; 219 pm_runtime_put(dev); 220 221 if (!priv->clk_rate) { 222 ret = -ENOENT; 223 goto out_pm_disable; 224 } 225 226 for (i = ARRAY_SIZE(clk_divs) - 1; i >= 0; i--) { 227 clks_per_sec = priv->clk_rate / clk_divs[i]; 228 if (clks_per_sec && clks_per_sec < 65536) { 229 priv->cks = i; 230 break; 231 } 232 } 233 234 if (i < 0) { 235 dev_err(dev, "Can't find suitable clock divider\n"); 236 ret = -ERANGE; 237 goto out_pm_disable; 238 } 239 240 priv->wdev.info = &rwdt_ident; 241 priv->wdev.ops = &rwdt_ops; 242 priv->wdev.parent = dev; 243 priv->wdev.min_timeout = 1; 244 priv->wdev.max_timeout = DIV_BY_CLKS_PER_SEC(priv, 65536); 245 priv->wdev.timeout = min(priv->wdev.max_timeout, RWDT_DEFAULT_TIMEOUT); 246 247 platform_set_drvdata(pdev, priv); 248 watchdog_set_drvdata(&priv->wdev, priv); 249 watchdog_set_nowayout(&priv->wdev, nowayout); 250 watchdog_set_restart_priority(&priv->wdev, 0); 251 watchdog_stop_on_unregister(&priv->wdev); 252 253 /* This overrides the default timeout only if DT configuration was found */ 254 watchdog_init_timeout(&priv->wdev, 0, dev); 255 256 /* Check if FW enabled the watchdog */ 257 if (csra & RWTCSRA_TME) { 258 /* Ensure properly initialized dividers */ 259 rwdt_start(&priv->wdev); 260 set_bit(WDOG_HW_RUNNING, &priv->wdev.status); 261 } 262 263 ret = watchdog_register_device(&priv->wdev); 264 if (ret < 0) 265 goto out_pm_disable; 266 267 return 0; 268 269 out_pm_disable: 270 pm_runtime_disable(dev); 271 return ret; 272} 273 274static int rwdt_remove(struct platform_device *pdev) 275{ 276 struct rwdt_priv *priv = platform_get_drvdata(pdev); 277 278 watchdog_unregister_device(&priv->wdev); 279 pm_runtime_disable(&pdev->dev); 280 281 return 0; 282} 283 284static int __maybe_unused rwdt_suspend(struct device *dev) 285{ 286 struct rwdt_priv *priv = dev_get_drvdata(dev); 287 288 if (watchdog_active(&priv->wdev)) 289 rwdt_stop(&priv->wdev); 290 291 return 0; 292} 293 294static int __maybe_unused rwdt_resume(struct device *dev) 295{ 296 struct rwdt_priv *priv = dev_get_drvdata(dev); 297 298 if (watchdog_active(&priv->wdev)) 299 rwdt_start(&priv->wdev); 300 301 return 0; 302} 303 304static SIMPLE_DEV_PM_OPS(rwdt_pm_ops, rwdt_suspend, rwdt_resume); 305 306static const struct of_device_id rwdt_ids[] = { 307 { .compatible = "renesas,rcar-gen2-wdt", }, 308 { .compatible = "renesas,rcar-gen3-wdt", }, 309 { /* sentinel */ } 310}; 311MODULE_DEVICE_TABLE(of, rwdt_ids); 312 313static struct platform_driver rwdt_driver = { 314 .driver = { 315 .name = "renesas_wdt", 316 .of_match_table = rwdt_ids, 317 .pm = &rwdt_pm_ops, 318 }, 319 .probe = rwdt_probe, 320 .remove = rwdt_remove, 321}; 322module_platform_driver(rwdt_driver); 323 324MODULE_DESCRIPTION("Renesas WDT Watchdog Driver"); 325MODULE_LICENSE("GPL v2"); 326MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>"); 327