|
14 | 14 | #include <linux/mod_devicetable.h>
|
15 | 15 | #include <linux/module.h>
|
16 | 16 | #include <linux/moduleparam.h>
|
| 17 | +#include <linux/of.h> |
| 18 | +#include <linux/of_address.h> |
17 | 19 | #include <linux/platform_device.h>
|
18 | 20 | #include <linux/pm_runtime.h>
|
19 | 21 | #include <linux/types.h>
|
|
52 | 54 |
|
53 | 55 | #define DWDST BIT(1)
|
54 | 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 | + |
55 | 62 | static int heartbeat = DEFAULT_HEARTBEAT;
|
56 | 63 |
|
57 | 64 | /*
|
@@ -198,6 +205,11 @@ static int rti_wdt_probe(struct platform_device *pdev)
|
198 | 205 | struct rti_wdt_device *wdt;
|
199 | 206 | struct clk *clk;
|
200 | 207 | u32 last_ping = 0;
|
| 208 | + struct device_node *node; |
| 209 | + u32 reserved_mem_size; |
| 210 | + struct resource res; |
| 211 | + u32 *vaddr; |
| 212 | + u64 paddr; |
201 | 213 |
|
202 | 214 | wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
|
203 | 215 | if (!wdt)
|
@@ -284,6 +296,42 @@ static int rti_wdt_probe(struct platform_device *pdev)
|
284 | 296 | }
|
285 | 297 | }
|
286 | 298 |
|
| 299 | + node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); |
| 300 | + if (node) { |
| 301 | + ret = of_address_to_resource(node, 0, &res); |
| 302 | + if (ret) { |
| 303 | + dev_err(dev, "No memory address assigned to the region.\n"); |
| 304 | + goto err_iomap; |
| 305 | + } |
| 306 | + |
| 307 | + /* |
| 308 | + * If reserved memory is defined for watchdog reset cause. |
| 309 | + * Readout the Power-on(PON) reason and pass to bootstatus. |
| 310 | + */ |
| 311 | + paddr = res.start; |
| 312 | + reserved_mem_size = resource_size(&res); |
| 313 | + if (reserved_mem_size < RESERVED_MEM_MIN_SIZE) { |
| 314 | + dev_err(dev, "The size of reserved memory is too small.\n"); |
| 315 | + ret = -EINVAL; |
| 316 | + goto err_iomap; |
| 317 | + } |
| 318 | + |
| 319 | + vaddr = memremap(paddr, reserved_mem_size, MEMREMAP_WB); |
| 320 | + if (!vaddr) { |
| 321 | + dev_err(dev, "Failed to map memory-region.\n"); |
| 322 | + ret = -ENOMEM; |
| 323 | + goto err_iomap; |
| 324 | + } |
| 325 | + |
| 326 | + if (vaddr[0] == PON_REASON_SOF_NUM && |
| 327 | + vaddr[1] == PON_REASON_MAGIC_NUM && |
| 328 | + vaddr[2] == PON_REASON_EOF_NUM) { |
| 329 | + wdd->bootstatus |= WDIOF_CARDRESET; |
| 330 | + } |
| 331 | + memset(vaddr, 0, reserved_mem_size); |
| 332 | + memunmap(vaddr); |
| 333 | + } |
| 334 | + |
287 | 335 | watchdog_init_timeout(wdd, heartbeat, dev);
|
288 | 336 |
|
289 | 337 | ret = watchdog_register_device(wdd);
|
|
0 commit comments