1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Watchdog driver for the K3 RTI module 4 * 5 * (c) Copyright 2019-2020 Texas Instruments Inc. 6 * All rights reserved. 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/device.h> 11 #include <linux/err.h> 12 #include <linux/io.h> 13 #include <linux/kernel.h> 14 #include <linux/mod_devicetable.h> 15 #include <linux/module.h> 16 #include <linux/moduleparam.h> 17 #include <linux/of.h> 18 #include <linux/of_address.h> 19 #include <linux/platform_device.h> 20 #include <linux/pm_runtime.h> 21 #include <linux/types.h> 22 #include <linux/watchdog.h> 23 24 #define DEFAULT_HEARTBEAT 60 25 26 /* Max heartbeat is calculated at 32kHz source clock */ 27 #define MAX_HEARTBEAT 1000 28 29 /* Timer register set definition */ 30 #define RTIDWDCTRL 0x90 31 #define RTIDWDPRLD 0x94 32 #define RTIWDSTATUS 0x98 33 #define RTIWDKEY 0x9c 34 #define RTIDWDCNTR 0xa0 35 #define RTIWWDRXCTRL 0xa4 36 #define RTIWWDSIZECTRL 0xa8 37 38 #define RTIWWDRX_NMI 0xa 39 40 #define RTIWWDSIZE_50P 0x50 41 #define RTIWWDSIZE_25P 0x500 42 #define RTIWWDSIZE_12P5 0x5000 43 #define RTIWWDSIZE_6P25 0x50000 44 #define RTIWWDSIZE_3P125 0x500000 45 46 #define WDENABLE_KEY 0xa98559da 47 48 #define WDKEY_SEQ0 0xe51a 49 #define WDKEY_SEQ1 0xa35c 50 51 #define WDT_PRELOAD_SHIFT 13 52 53 #define WDT_PRELOAD_MAX 0xfff 54 55 #define DWDST BIT(1) 56 57 #define PON_REASON_SOF_NUM 0xBBBBCCCC 58 #define PON_REASON_MAGIC_NUM 0xDDDDDDDD 59 #define PON_REASON_EOF_NUM 0xCCCCBBBB 60 #define RESERVED_MEM_MIN_SIZE 12 61 62 #define MAX_HW_ERROR 250 63 64 static int heartbeat = DEFAULT_HEARTBEAT; 65 66 /* 67 * struct to hold data for each WDT device 68 * @base - base io address of WD device 69 * @freq - source clock frequency of WDT 70 * @wdd - hold watchdog device as is in WDT core 71 */ 72 struct rti_wdt_device { 73 void __iomem *base; 74 unsigned long freq; 75 struct watchdog_device wdd; 76 }; 77 78 static int rti_wdt_start(struct watchdog_device *wdd) 79 { 80 u32 timer_margin; 81 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd); 82 int ret; 83 84 ret = pm_runtime_resume_and_get(wdd->parent); 85 if (ret) 86 return ret; 87 88 /* set timeout period */ 89 timer_margin = (u64)wdd->timeout * wdt->freq; 90 timer_margin >>= WDT_PRELOAD_SHIFT; 91 if (timer_margin > WDT_PRELOAD_MAX) 92 timer_margin = WDT_PRELOAD_MAX; 93 writel_relaxed(timer_margin, wdt->base + RTIDWDPRLD); 94 95 /* 96 * RTI only supports a windowed mode, where the watchdog can only 97 * be petted during the open window; not too early or not too late. 98 * The HW configuration options only allow for the open window size 99 * to be 50% or less than that; we obviouly want to configure the open 100 * window as large as possible so we select the 50% option. 101 */ 102 wdd->min_hw_heartbeat_ms = 520 * wdd->timeout + MAX_HW_ERROR; 103 104 /* Generate NMI when wdt expires */ 105 writel_relaxed(RTIWWDRX_NMI, wdt->base + RTIWWDRXCTRL); 106 107 /* Open window size 50%; this is the largest window size available */ 108 writel_relaxed(RTIWWDSIZE_50P, wdt->base + RTIWWDSIZECTRL); 109 110 readl_relaxed(wdt->base + RTIWWDSIZECTRL); 111 112 /* enable watchdog */ 113 writel_relaxed(WDENABLE_KEY, wdt->base + RTIDWDCTRL); 114 return 0; 115 } 116 117 static int rti_wdt_ping(struct watchdog_device *wdd) 118 { 119 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd); 120 121 /* put watchdog in service state */ 122 writel_relaxed(WDKEY_SEQ0, wdt->base + RTIWDKEY); 123 /* put watchdog in active state */ 124 writel_relaxed(WDKEY_SEQ1, wdt->base + RTIWDKEY); 125 126 return 0; 127 } 128 129 static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd, u32 wsize) 130 { 131 /* 132 * RTI only supports a windowed mode, where the watchdog can only 133 * be petted during the open window; not too early or not too late. 134 * The HW configuration options only allow for the open window size 135 * to be 50% or less than that. 136 * To avoid any glitches, we accommodate 2% + max hardware error 137 * safety margin. 138 */ 139 switch (wsize) { 140 case RTIWWDSIZE_50P: 141 /* 50% open window => 52% min heartbeat */ 142 wdd->min_hw_heartbeat_ms = 520 * heartbeat + MAX_HW_ERROR; 143 break; 144 145 case RTIWWDSIZE_25P: 146 /* 25% open window => 77% min heartbeat */ 147 wdd->min_hw_heartbeat_ms = 770 * heartbeat + MAX_HW_ERROR; 148 break; 149 150 case RTIWWDSIZE_12P5: 151 /* 12.5% open window => 89.5% min heartbeat */ 152 wdd->min_hw_heartbeat_ms = 895 * heartbeat + MAX_HW_ERROR; 153 break; 154 155 case RTIWWDSIZE_6P25: 156 /* 6.5% open window => 95.5% min heartbeat */ 157 wdd->min_hw_heartbeat_ms = 955 * heartbeat + MAX_HW_ERROR; 158 break; 159 160 case RTIWWDSIZE_3P125: 161 /* 3.125% open window => 98.9% min heartbeat */ 162 wdd->min_hw_heartbeat_ms = 989 * heartbeat + MAX_HW_ERROR; 163 break; 164 165 default: 166 return -EINVAL; 167 } 168 169 return 0; 170 } 171 172 static unsigned int rti_wdt_get_timeleft_ms(struct watchdog_device *wdd) 173 { 174 u64 timer_counter; 175 u32 val; 176 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd); 177 178 /* if timeout has occurred then return 0 */ 179 val = readl_relaxed(wdt->base + RTIWDSTATUS); 180 if (val & DWDST) 181 return 0; 182 183 timer_counter = readl_relaxed(wdt->base + RTIDWDCNTR); 184 185 timer_counter *= 1000; 186 187 do_div(timer_counter, wdt->freq); 188 189 return timer_counter; 190 } 191 192 static unsigned int rti_wdt_get_timeleft(struct watchdog_device *wdd) 193 { 194 return rti_wdt_get_timeleft_ms(wdd) / 1000; 195 } 196 197 static const struct watchdog_info rti_wdt_info = { 198 .options = WDIOF_KEEPALIVEPING, 199 .identity = "K3 RTI Watchdog", 200 }; 201 202 static const struct watchdog_ops rti_wdt_ops = { 203 .owner = THIS_MODULE, 204 .start = rti_wdt_start, 205 .ping = rti_wdt_ping, 206 .get_timeleft = rti_wdt_get_timeleft, 207 }; 208 209 static int rti_wdt_probe(struct platform_device *pdev) 210 { 211 int ret = 0; 212 struct device *dev = &pdev->dev; 213 struct watchdog_device *wdd; 214 struct rti_wdt_device *wdt; 215 struct clk *clk; 216 u32 last_ping = 0; 217 struct device_node *node; 218 u32 reserved_mem_size; 219 struct resource res; 220 u32 *vaddr; 221 u64 paddr; 222 223 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); 224 if (!wdt) 225 return -ENOMEM; 226 227 clk = clk_get(dev, NULL); 228 if (IS_ERR(clk)) 229 return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n"); 230 231 wdt->freq = clk_get_rate(clk); 232 233 clk_put(clk); 234 235 if (!wdt->freq) { 236 dev_err(dev, "Failed to get fck rate.\n"); 237 return -EINVAL; 238 } 239 240 pm_runtime_enable(dev); 241 ret = pm_runtime_resume_and_get(dev); 242 if (ret < 0) { 243 pm_runtime_disable(&pdev->dev); 244 return dev_err_probe(dev, ret, "runtime pm failed\n"); 245 } 246 247 platform_set_drvdata(pdev, wdt); 248 249 wdd = &wdt->wdd; 250 wdd->info = &rti_wdt_info; 251 wdd->ops = &rti_wdt_ops; 252 wdd->min_timeout = 1; 253 wdd->max_hw_heartbeat_ms = (WDT_PRELOAD_MAX << WDT_PRELOAD_SHIFT) / 254 wdt->freq * 1000; 255 wdd->parent = dev; 256 257 watchdog_set_drvdata(wdd, wdt); 258 watchdog_set_nowayout(wdd, 1); 259 watchdog_set_restart_priority(wdd, 128); 260 261 wdt->base = devm_platform_ioremap_resource(pdev, 0); 262 if (IS_ERR(wdt->base)) { 263 ret = PTR_ERR(wdt->base); 264 goto err_iomap; 265 } 266 267 if (readl(wdt->base + RTIDWDCTRL) == WDENABLE_KEY) { 268 int preset_heartbeat; 269 u32 time_left_ms; 270 u64 heartbeat_ms; 271 u32 wsize; 272 273 set_bit(WDOG_HW_RUNNING, &wdd->status); 274 time_left_ms = rti_wdt_get_timeleft_ms(wdd); 275 heartbeat_ms = readl(wdt->base + RTIDWDPRLD); 276 heartbeat_ms <<= WDT_PRELOAD_SHIFT; 277 heartbeat_ms *= 1000; 278 do_div(heartbeat_ms, wdt->freq); 279 preset_heartbeat = heartbeat_ms + 500; 280 preset_heartbeat /= 1000; 281 if (preset_heartbeat != heartbeat) 282 dev_warn(dev, "watchdog already running, ignoring heartbeat config!\n"); 283 284 heartbeat = preset_heartbeat; 285 286 wsize = readl(wdt->base + RTIWWDSIZECTRL); 287 ret = rti_wdt_setup_hw_hb(wdd, wsize); 288 if (ret) { 289 dev_err(dev, "bad window size.\n"); 290 goto err_iomap; 291 } 292 293 last_ping = heartbeat_ms - time_left_ms; 294 if (time_left_ms > heartbeat_ms) { 295 dev_warn(dev, "time_left > heartbeat? Assuming last ping just before now.\n"); 296 last_ping = 0; 297 } 298 } 299 300 node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); 301 if (node) { 302 ret = of_address_to_resource(node, 0, &res); 303 if (ret) { 304 dev_err(dev, "No memory address assigned to the region.\n"); 305 goto err_iomap; 306 } 307 308 /* 309 * If reserved memory is defined for watchdog reset cause. 310 * Readout the Power-on(PON) reason and pass to bootstatus. 311 */ 312 paddr = res.start; 313 reserved_mem_size = resource_size(&res); 314 if (reserved_mem_size < RESERVED_MEM_MIN_SIZE) { 315 dev_err(dev, "The size of reserved memory is too small.\n"); 316 ret = -EINVAL; 317 goto err_iomap; 318 } 319 320 vaddr = memremap(paddr, reserved_mem_size, MEMREMAP_WB); 321 if (!vaddr) { 322 dev_err(dev, "Failed to map memory-region.\n"); 323 ret = -ENOMEM; 324 goto err_iomap; 325 } 326 327 if (vaddr[0] == PON_REASON_SOF_NUM && 328 vaddr[1] == PON_REASON_MAGIC_NUM && 329 vaddr[2] == PON_REASON_EOF_NUM) { 330 wdd->bootstatus |= WDIOF_CARDRESET; 331 } 332 memset(vaddr, 0, reserved_mem_size); 333 memunmap(vaddr); 334 } 335 336 watchdog_init_timeout(wdd, heartbeat, dev); 337 338 ret = watchdog_register_device(wdd); 339 if (ret) { 340 dev_err(dev, "cannot register watchdog device\n"); 341 goto err_iomap; 342 } 343 344 if (last_ping) 345 watchdog_set_last_hw_keepalive(wdd, last_ping); 346 347 if (!watchdog_hw_running(wdd)) 348 pm_runtime_put_sync(&pdev->dev); 349 350 return 0; 351 352 err_iomap: 353 pm_runtime_put_sync(&pdev->dev); 354 pm_runtime_disable(&pdev->dev); 355 356 return ret; 357 } 358 359 static void rti_wdt_remove(struct platform_device *pdev) 360 { 361 struct rti_wdt_device *wdt = platform_get_drvdata(pdev); 362 363 watchdog_unregister_device(&wdt->wdd); 364 365 if (!pm_runtime_suspended(&pdev->dev)) 366 pm_runtime_put(&pdev->dev); 367 368 pm_runtime_disable(&pdev->dev); 369 } 370 371 static const struct of_device_id rti_wdt_of_match[] = { 372 { .compatible = "ti,j7-rti-wdt", }, 373 {}, 374 }; 375 MODULE_DEVICE_TABLE(of, rti_wdt_of_match); 376 377 static struct platform_driver rti_wdt_driver = { 378 .driver = { 379 .name = "rti-wdt", 380 .of_match_table = rti_wdt_of_match, 381 }, 382 .probe = rti_wdt_probe, 383 .remove_new = rti_wdt_remove, 384 }; 385 386 module_platform_driver(rti_wdt_driver); 387 388 MODULE_AUTHOR("Tero Kristo <t-kristo@ti.com>"); 389 MODULE_DESCRIPTION("K3 RTI Watchdog Driver"); 390 391 module_param(heartbeat, int, 0); 392 MODULE_PARM_DESC(heartbeat, 393 "Watchdog heartbeat period in seconds from 1 to " 394 __MODULE_STRING(MAX_HEARTBEAT) ", default " 395 __MODULE_STRING(DEFAULT_HEARTBEAT)); 396 397 MODULE_LICENSE("GPL"); 398 MODULE_ALIAS("platform:rti-wdt"); 399