projects/linux·blob master · refs

596 lines · 14.3 KiB

1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * ACPI Hardware Watchdog (WDAT) driver.
4 *
5 * Copyright (C) 2016, Intel Corporation
6 * Author: Mika Westerberg <[email protected]>
7 */
8
9#include <linux/acpi.h>
10#include <linux/io.h>
11#include <linux/ioport.h>
12#include <linux/mm.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/pm.h>
16#include <linux/watchdog.h>
17
18#define MAX_WDAT_ACTIONS ACPI_WDAT_ACTION_RESERVED
19
20/**
21 * struct wdat_instruction - Single ACPI WDAT instruction
22 * @entry: Copy of the ACPI table instruction
23 * @reg: Register the instruction is accessing
24 * @node: Next instruction in action sequence
25 */
26struct wdat_instruction {
27 struct acpi_wdat_entry entry;
28 void __iomem *reg;
29 struct list_head node;
30};
31
32/**
33 * struct wdat_wdt - ACPI WDAT watchdog device
34 * @pdev: Parent platform device
35 * @wdd: Watchdog core device
36 * @period: How long is one watchdog period in ms
37 * @stopped_in_sleep: Is this watchdog stopped by the firmware in S1-S5
38 * @stopped: Was the watchdog stopped by the driver in suspend
39 * @instructions: An array of instruction lists indexed by an action number from
40 * the WDAT table. There can be %NULL entries for not implemented
41 * actions.
42 */
43struct wdat_wdt {
44 struct platform_device *pdev;
45 struct watchdog_device wdd;
46 unsigned int period;
47 bool stopped_in_sleep;
48 bool stopped;
49 struct list_head *instructions[MAX_WDAT_ACTIONS];
50};
51
52#define to_wdat_wdt(wdd) container_of(wdd, struct wdat_wdt, wdd)
53
54static bool nowayout = WATCHDOG_NOWAYOUT;
55module_param(nowayout, bool, 0);
56MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
57 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
58
59#define WDAT_DEFAULT_TIMEOUT 30
60
61static int timeout = WDAT_DEFAULT_TIMEOUT;
62module_param(timeout, int, 0);
63MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
64 __MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")");
65
66static int wdat_wdt_read(struct wdat_wdt *wdat,
67 const struct wdat_instruction *instr, u32 *value)
68{
69 const struct acpi_generic_address *gas = &instr->entry.register_region;
70
71 switch (gas->access_width) {
72 case 1:
73 *value = ioread8(instr->reg);
74 break;
75 case 2:
76 *value = ioread16(instr->reg);
77 break;
78 case 3:
79 *value = ioread32(instr->reg);
80 break;
81 default:
82 return -EINVAL;
83 }
84
85 dev_dbg(&wdat->pdev->dev, "Read %#x from 0x%08llx\n", *value,
86 gas->address);
87
88 return 0;
89}
90
91static int wdat_wdt_write(struct wdat_wdt *wdat,
92 const struct wdat_instruction *instr, u32 value)
93{
94 const struct acpi_generic_address *gas = &instr->entry.register_region;
95
96 switch (gas->access_width) {
97 case 1:
98 iowrite8((u8)value, instr->reg);
99 break;
100 case 2:
101 iowrite16((u16)value, instr->reg);
102 break;
103 case 3:
104 iowrite32(value, instr->reg);
105 break;
106 default:
107 return -EINVAL;
108 }
109
110 dev_dbg(&wdat->pdev->dev, "Wrote %#x to 0x%08llx\n", value,
111 gas->address);
112
113 return 0;
114}
115
116static int wdat_wdt_run_action(struct wdat_wdt *wdat, unsigned int action,
117 u32 param, u32 *retval)
118{
119 struct wdat_instruction *instr;
120
121 if (action >= ARRAY_SIZE(wdat->instructions))
122 return -EINVAL;
123
124 if (!wdat->instructions[action])
125 return -EOPNOTSUPP;
126
127 dev_dbg(&wdat->pdev->dev, "Running action %#x\n", action);
128
129 /* Run each instruction sequentially */
130 list_for_each_entry(instr, wdat->instructions[action], node) {
131 const struct acpi_wdat_entry *entry = &instr->entry;
132 const struct acpi_generic_address *gas;
133 u32 flags, value, mask, x, y;
134 bool preserve;
135 int ret;
136
137 gas = &entry->register_region;
138
139 preserve = entry->instruction & ACPI_WDAT_PRESERVE_REGISTER;
140 flags = entry->instruction & ~ACPI_WDAT_PRESERVE_REGISTER;
141 value = entry->value;
142 mask = entry->mask;
143
144 switch (flags) {
145 case ACPI_WDAT_READ_VALUE:
146 ret = wdat_wdt_read(wdat, instr, &x);
147 if (ret)
148 return ret;
149 x >>= gas->bit_offset;
150 x &= mask;
151 if (retval)
152 *retval = x == value;
153 break;
154
155 case ACPI_WDAT_READ_COUNTDOWN:
156 ret = wdat_wdt_read(wdat, instr, &x);
157 if (ret)
158 return ret;
159 x >>= gas->bit_offset;
160 x &= mask;
161 if (retval)
162 *retval = x;
163 break;
164
165 case ACPI_WDAT_WRITE_VALUE:
166 x = value & mask;
167 x <<= gas->bit_offset;
168 if (preserve) {
169 ret = wdat_wdt_read(wdat, instr, &y);
170 if (ret)
171 return ret;
172 y = y & ~(mask << gas->bit_offset);
173 x |= y;
174 }
175 ret = wdat_wdt_write(wdat, instr, x);
176 if (ret)
177 return ret;
178 break;
179
180 case ACPI_WDAT_WRITE_COUNTDOWN:
181 x = param;
182 x &= mask;
183 x <<= gas->bit_offset;
184 if (preserve) {
185 ret = wdat_wdt_read(wdat, instr, &y);
186 if (ret)
187 return ret;
188 y = y & ~(mask << gas->bit_offset);
189 x |= y;
190 }
191 ret = wdat_wdt_write(wdat, instr, x);
192 if (ret)
193 return ret;
194 break;
195
196 default:
197 dev_err(&wdat->pdev->dev, "Unknown instruction: %u\n",
198 flags);
199 return -EINVAL;
200 }
201 }
202
203 return 0;
204}
205
206static int wdat_wdt_enable_reboot(struct wdat_wdt *wdat)
207{
208 int ret;
209
210 /*
211 * WDAT specification says that the watchdog is required to reboot
212 * the system when it fires. However, it also states that it is
213 * recommended to make it configurable through hardware register. We
214 * enable reboot now if it is configurable, just in case.
215 */
216 ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL);
217 if (ret && ret != -EOPNOTSUPP) {
218 dev_err(&wdat->pdev->dev,
219 "Failed to enable reboot when watchdog triggers\n");
220 return ret;
221 }
222
223 return 0;
224}
225
226static void wdat_wdt_boot_status(struct wdat_wdt *wdat)
227{
228 u32 boot_status = 0;
229 int ret;
230
231 ret = wdat_wdt_run_action(wdat, ACPI_WDAT_GET_STATUS, 0, &boot_status);
232 if (ret && ret != -EOPNOTSUPP) {
233 dev_err(&wdat->pdev->dev, "Failed to read boot status\n");
234 return;
235 }
236
237 if (boot_status)
238 wdat->wdd.bootstatus = WDIOF_CARDRESET;
239
240 /* Clear the boot status in case BIOS did not do it */
241 ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_STATUS, 0, NULL);
242 if (ret && ret != -EOPNOTSUPP)
243 dev_err(&wdat->pdev->dev, "Failed to clear boot status\n");
244}
245
246static void wdat_wdt_set_running(struct wdat_wdt *wdat)
247{
248 u32 running = 0;
249 int ret;
250
251 ret = wdat_wdt_run_action(wdat, ACPI_WDAT_GET_RUNNING_STATE, 0,
252 &running);
253 if (ret && ret != -EOPNOTSUPP)
254 dev_err(&wdat->pdev->dev, "Failed to read running state\n");
255
256 if (running)
257 set_bit(WDOG_HW_RUNNING, &wdat->wdd.status);
258}
259
260static int wdat_wdt_start(struct watchdog_device *wdd)
261{
262 return wdat_wdt_run_action(to_wdat_wdt(wdd),
263 ACPI_WDAT_SET_RUNNING_STATE, 0, NULL);
264}
265
266static int wdat_wdt_stop(struct watchdog_device *wdd)
267{
268 return wdat_wdt_run_action(to_wdat_wdt(wdd),
269 ACPI_WDAT_SET_STOPPED_STATE, 0, NULL);
270}
271
272static int wdat_wdt_ping(struct watchdog_device *wdd)
273{
274 return wdat_wdt_run_action(to_wdat_wdt(wdd), ACPI_WDAT_RESET, wdd->timeout, NULL);
275}
276
277static int wdat_wdt_set_timeout(struct watchdog_device *wdd,
278 unsigned int timeout)
279{
280 struct wdat_wdt *wdat = to_wdat_wdt(wdd);
281 unsigned int periods;
282 int ret;
283
284 periods = timeout * 1000 / wdat->period;
285 ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_COUNTDOWN, periods, NULL);
286 if (!ret)
287 wdd->timeout = timeout;
288 return ret;
289}
290
291static unsigned int wdat_wdt_get_timeleft(struct watchdog_device *wdd)
292{
293 struct wdat_wdt *wdat = to_wdat_wdt(wdd);
294 u32 periods = 0;
295
296 wdat_wdt_run_action(wdat, ACPI_WDAT_GET_CURRENT_COUNTDOWN, 0, &periods);
297 return periods * wdat->period / 1000;
298}
299
300static const struct watchdog_info wdat_wdt_info = {
301 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
302 .firmware_version = 0,
303 .identity = "wdat_wdt",
304};
305
306static struct watchdog_ops wdat_wdt_ops = {
307 .owner = THIS_MODULE,
308 .start = wdat_wdt_start,
309 .stop = wdat_wdt_stop,
310 .ping = wdat_wdt_ping,
311 .set_timeout = wdat_wdt_set_timeout,
312};
313
314static void __iomem *wdat_wdt_map_mem(struct device *dev, struct resource *res)
315{
316 resource_size_t size = resource_size(res);
317 void *addr;
318
319 /* Map memory region without reserving it if it falls inside ACPI NVS */
320 if (region_intersects(res->start, size, IORESOURCE_MEM,
321 IORES_DESC_ACPI_NV_STORAGE) == REGION_INTERSECTS) {
322 dev_warn(dev, "%pR is inside ACPI NVS, mapping without reservation\n",
323 res);
324
325 addr = devm_memremap(dev, res->start, size, MEMREMAP_WB);
326 if (IS_ERR(addr)) {
327 dev_err(dev, "failed to map resource %pR\n", res);
328 return IOMEM_ERR_PTR(PTR_ERR(addr));
329 }
330
331 return (void __iomem __force *)addr;
332 }
333
334 return devm_ioremap_resource(dev, res);
335}
336
337static int wdat_wdt_probe(struct platform_device *pdev)
338{
339 struct device *dev = &pdev->dev;
340 const struct acpi_wdat_entry *entries;
341 const struct acpi_table_wdat *tbl;
342 struct wdat_wdt *wdat;
343 struct resource *res;
344 void __iomem **regs;
345 acpi_status status;
346 int i, ret;
347
348 status = acpi_get_table(ACPI_SIG_WDAT, 0,
349 (struct acpi_table_header **)&tbl);
350 if (ACPI_FAILURE(status))
351 return -ENODEV;
352
353 wdat = devm_kzalloc(dev, sizeof(*wdat), GFP_KERNEL);
354 if (!wdat) {
355 ret = -ENOMEM;
356 goto out_put_table;
357 }
358
359 regs = devm_kcalloc(dev, pdev->num_resources, sizeof(*regs),
360 GFP_KERNEL);
361 if (!regs) {
362 ret = -ENOMEM;
363 goto out_put_table;
364 }
365
366 /* WDAT specification wants to have >= 1ms period */
367 if (tbl->timer_period < 1) {
368 ret = -EINVAL;
369 goto out_put_table;
370 }
371 if (tbl->min_count > tbl->max_count) {
372 ret = -EINVAL;
373 goto out_put_table;
374 }
375
376 wdat->period = tbl->timer_period;
377 wdat->wdd.min_timeout = DIV_ROUND_UP(wdat->period * tbl->min_count, 1000);
378 wdat->wdd.max_timeout = wdat->period * tbl->max_count / 1000;
379 wdat->stopped_in_sleep = tbl->flags & ACPI_WDAT_STOPPED;
380 wdat->wdd.info = &wdat_wdt_info;
381 wdat->wdd.ops = &wdat_wdt_ops;
382 wdat->pdev = pdev;
383
384 /* Request and map all resources */
385 for (i = 0; i < pdev->num_resources; i++) {
386 void __iomem *reg;
387
388 res = &pdev->resource[i];
389 if (resource_type(res) == IORESOURCE_MEM) {
390 reg = wdat_wdt_map_mem(dev, res);
391 if (IS_ERR(reg)) {
392 ret = PTR_ERR(reg);
393 goto out_put_table;
394 }
395 } else if (resource_type(res) == IORESOURCE_IO) {
396 reg = devm_ioport_map(dev, res->start, 1);
397 if (!reg) {
398 ret = -ENOMEM;
399 goto out_put_table;
400 }
401 } else {
402 dev_err(dev, "Unsupported resource\n");
403 ret = -EINVAL;
404 goto out_put_table;
405 }
406
407 regs[i] = reg;
408 }
409
410 entries = (struct acpi_wdat_entry *)(tbl + 1);
411 for (i = 0; i < tbl->entries; i++) {
412 const struct acpi_generic_address *gas;
413 struct wdat_instruction *instr;
414 struct list_head *instructions;
415 unsigned int action;
416 struct resource r;
417 int j;
418
419 action = entries[i].action;
420 if (action >= MAX_WDAT_ACTIONS) {
421 dev_dbg(dev, "Skipping unknown action: %u\n", action);
422 continue;
423 }
424
425 instr = devm_kzalloc(dev, sizeof(*instr), GFP_KERNEL);
426 if (!instr) {
427 ret = -ENOMEM;
428 goto out_put_table;
429 }
430
431 INIT_LIST_HEAD(&instr->node);
432 instr->entry = entries[i];
433
434 gas = &entries[i].register_region;
435
436 memset(&r, 0, sizeof(r));
437 r.start = gas->address;
438 r.end = r.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
439 if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
440 r.flags = IORESOURCE_MEM;
441 } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
442 r.flags = IORESOURCE_IO;
443 } else {
444 dev_dbg(dev, "Unsupported address space: %d\n",
445 gas->space_id);
446 continue;
447 }
448
449 /* Find the matching resource */
450 for (j = 0; j < pdev->num_resources; j++) {
451 res = &pdev->resource[j];
452 if (resource_contains(res, &r)) {
453 instr->reg = regs[j] + r.start - res->start;
454 break;
455 }
456 }
457
458 if (!instr->reg) {
459 dev_err(dev, "I/O resource not found\n");
460 ret = -EINVAL;
461 goto out_put_table;
462 }
463
464 instructions = wdat->instructions[action];
465 if (!instructions) {
466 instructions = devm_kzalloc(dev,
467 sizeof(*instructions),
468 GFP_KERNEL);
469 if (!instructions) {
470 ret = -ENOMEM;
471 goto out_put_table;
472 }
473
474 INIT_LIST_HEAD(instructions);
475 wdat->instructions[action] = instructions;
476 }
477
478 list_add_tail(&instr->node, instructions);
479 }
480
481 if (wdat->instructions[ACPI_WDAT_GET_CURRENT_COUNTDOWN])
482 wdat_wdt_ops.get_timeleft = wdat_wdt_get_timeleft;
483
484 wdat_wdt_boot_status(wdat);
485 wdat_wdt_set_running(wdat);
486
487 ret = wdat_wdt_enable_reboot(wdat);
488 if (ret)
489 goto out_put_table;
490
491 platform_set_drvdata(pdev, wdat);
492
493 /*
494 * Set initial timeout so that userspace has time to configure the
495 * watchdog properly after it has opened the device. In some cases
496 * the BIOS default is too short and causes immediate reboot.
497 */
498 if (watchdog_timeout_invalid(&wdat->wdd, timeout)) {
499 dev_warn(dev, "Invalid timeout %d given, using %d\n",
500 timeout, WDAT_DEFAULT_TIMEOUT);
501 timeout = WDAT_DEFAULT_TIMEOUT;
502 }
503
504 ret = wdat_wdt_set_timeout(&wdat->wdd, timeout);
505 if (ret)
506 goto out_put_table;
507
508 watchdog_set_nowayout(&wdat->wdd, nowayout);
509 watchdog_stop_on_reboot(&wdat->wdd);
510 watchdog_stop_on_unregister(&wdat->wdd);
511 ret = devm_watchdog_register_device(dev, &wdat->wdd);
512
513out_put_table:
514 acpi_put_table((struct acpi_table_header *)tbl);
515 return ret;
516}
517
518static int wdat_wdt_suspend_noirq(struct device *dev)
519{
520 struct wdat_wdt *wdat = dev_get_drvdata(dev);
521 int ret;
522
523 if (!watchdog_active(&wdat->wdd))
524 return 0;
525
526 /*
527 * We need to stop the watchdog if firmware is not doing it or if we
528 * are going suspend to idle (where firmware is not involved). If
529 * firmware is stopping the watchdog we kick it here one more time
530 * to give it some time.
531 */
532 wdat->stopped = false;
533 if (acpi_target_system_state() == ACPI_STATE_S0 ||
534 !wdat->stopped_in_sleep) {
535 ret = wdat_wdt_stop(&wdat->wdd);
536 if (!ret)
537 wdat->stopped = true;
538 } else {
539 ret = wdat_wdt_ping(&wdat->wdd);
540 }
541
542 return ret;
543}
544
545static int wdat_wdt_resume_noirq(struct device *dev)
546{
547 struct wdat_wdt *wdat = dev_get_drvdata(dev);
548 int ret;
549
550 if (!watchdog_active(&wdat->wdd))
551 return 0;
552
553 if (!wdat->stopped) {
554 /*
555 * Looks like the boot firmware reinitializes the watchdog
556 * before it hands off to the OS on resume from sleep so we
557 * stop and reprogram the watchdog here.
558 */
559 ret = wdat_wdt_stop(&wdat->wdd);
560 if (ret)
561 return ret;
562
563 ret = wdat_wdt_set_timeout(&wdat->wdd, wdat->wdd.timeout);
564 if (ret)
565 return ret;
566
567 ret = wdat_wdt_enable_reboot(wdat);
568 if (ret)
569 return ret;
570
571 ret = wdat_wdt_ping(&wdat->wdd);
572 if (ret)
573 return ret;
574 }
575
576 return wdat_wdt_start(&wdat->wdd);
577}
578
579static const struct dev_pm_ops wdat_wdt_pm_ops = {
580 NOIRQ_SYSTEM_SLEEP_PM_OPS(wdat_wdt_suspend_noirq, wdat_wdt_resume_noirq)
581};
582
583static struct platform_driver wdat_wdt_driver = {
584 .probe = wdat_wdt_probe,
585 .driver = {
586 .name = "wdat_wdt",
587 .pm = pm_sleep_ptr(&wdat_wdt_pm_ops),
588 },
589};
590
591module_platform_driver(wdat_wdt_driver);
592
593MODULE_AUTHOR("Mika Westerberg <[email protected]>");
594MODULE_DESCRIPTION("ACPI Hardware Watchdog (WDAT) driver");
595MODULE_LICENSE("GPL v2");
596MODULE_ALIAS("platform:wdat_wdt");