Skip to content

Commit b611996

Browse files
committed
Merge tag 'linux-watchdog-6.2-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: - Add Advantech EC watchdog driver - Add support for MT6795 Helio X10 watchdog and toprgu - Add support for MT8188 watchdog device - Remove #ifdef guards for PM related functions - Other fixes and improvements * tag 'linux-watchdog-6.2-rc1' of git://www.linux-watchdog.org/linux-watchdog: watchdog: aspeed: Enable pre-timeout interrupt watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running watchdog: rn5t618: add support for read out bootstatus watchdog: kempld: Remove #ifdef guards for PM related functions watchdog: omap: Remove #ifdef guards for PM related functions watchdog: twl4030: Remove #ifdef guards for PM related functions watchdog: at91rm9200: Remove #ifdef guards for PM related functions watchdog: Add Advantech EC watchdog driver dt-bindings: watchdog: mediatek,mtk-wdt: Add compatible for MT8173 dt-bindings: watchdog: mediatek,mtk-wdt: Add compatible for MT6795 dt-bindings: watchdog: mediatek: Convert mtk-wdt to json-schema watchdog: mediatek: mt8188: add wdt support dt-bindings: reset: mt8188: add toprgu reset-controller header file dt-bindings: watchdog: Add compatible for MediaTek MT8188 watchdog: mtk_wdt: Add support for MT6795 Helio X10 watchdog and toprgu
2 parents 75caf59 + 9ec0b7e commit b611996

File tree

16 files changed

+474
-106
lines changed

16 files changed

+474
-106
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/watchdog/mediatek,mtk-wdt.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: MediaTek SoCs Watchdog timer
8+
9+
maintainers:
10+
- Matthias Brugger <[email protected]>
11+
12+
description:
13+
The watchdog supports a pre-timeout interrupt that fires
14+
timeout-sec/2 before the expiry.
15+
16+
allOf:
17+
- $ref: watchdog.yaml#
18+
19+
properties:
20+
compatible:
21+
oneOf:
22+
- enum:
23+
- mediatek,mt2712-wdt
24+
- mediatek,mt6589-wdt
25+
- mediatek,mt6795-wdt
26+
- mediatek,mt7986-wdt
27+
- mediatek,mt8183-wdt
28+
- mediatek,mt8186-wdt
29+
- mediatek,mt8188-wdt
30+
- mediatek,mt8192-wdt
31+
- mediatek,mt8195-wdt
32+
- items:
33+
- enum:
34+
- mediatek,mt2701-wdt
35+
- mediatek,mt6582-wdt
36+
- mediatek,mt6797-wdt
37+
- mediatek,mt7622-wdt
38+
- mediatek,mt7623-wdt
39+
- mediatek,mt7629-wdt
40+
- mediatek,mt8173-wdt
41+
- mediatek,mt8516-wdt
42+
- const: mediatek,mt6589-wdt
43+
44+
reg:
45+
maxItems: 1
46+
47+
interrupts:
48+
items:
49+
- description: Watchdog pre-timeout (bark) interrupt
50+
51+
mediatek,disable-extrst:
52+
description: Disable sending output reset signal
53+
type: boolean
54+
55+
'#reset-cells':
56+
const: 1
57+
58+
required:
59+
- compatible
60+
- reg
61+
62+
unevaluatedProperties: false
63+
64+
examples:
65+
- |
66+
#include <dt-bindings/interrupt-controller/arm-gic.h>
67+
68+
soc {
69+
#address-cells = <2>;
70+
#size-cells = <2>;
71+
72+
watchdog: watchdog@10007000 {
73+
compatible = "mediatek,mt8183-wdt";
74+
reg = <0 0x10007000 0 0x100>;
75+
interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
76+
mediatek,disable-extrst;
77+
timeout-sec = <10>;
78+
#reset-cells = <1>;
79+
};
80+
};

Documentation/devicetree/bindings/watchdog/mtk-wdt.txt

Lines changed: 0 additions & 42 deletions
This file was deleted.

drivers/watchdog/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,13 @@ config ADVANTECH_WDT
10551055
feature. More information can be found at
10561056
<https://www.advantech.com.tw/products/>
10571057

1058+
config ADVANTECH_EC_WDT
1059+
tristate "Advantech Embedded Controller Watchdog Timer"
1060+
depends on X86
1061+
help
1062+
This driver supports Advantech products with ITE based Embedded Controller.
1063+
It does not support Advantech products with other ECs or without EC.
1064+
10581065
config ALIM1535_WDT
10591066
tristate "ALi M1535 PMU Watchdog Timer"
10601067
depends on X86 && PCI

drivers/watchdog/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
102102
# X86 (i386 + ia64 + x86_64) Architecture
103103
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
104104
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
105+
obj-$(CONFIG_ADVANTECH_EC_WDT) += advantech_ec_wdt.o
105106
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
106107
obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
107108
obj-$(CONFIG_EBC_C384_WDT) += ebc-c384_wdt.o

drivers/watchdog/advantech_ec_wdt.c

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Advantech Embedded Controller Watchdog Driver
4+
*
5+
* This driver supports Advantech products with ITE based Embedded Controller.
6+
* It does not support Advantech products with other ECs or without EC.
7+
*
8+
* Copyright (C) 2022 Advantech Europe B.V.
9+
*/
10+
11+
#include <linux/delay.h>
12+
#include <linux/io.h>
13+
#include <linux/isa.h>
14+
#include <linux/kernel.h>
15+
#include <linux/module.h>
16+
#include <linux/moduleparam.h>
17+
#include <linux/watchdog.h>
18+
19+
#define DRIVER_NAME "advantech_ec_wdt"
20+
21+
/* EC IO region */
22+
#define EC_BASE_ADDR 0x299
23+
#define EC_ADDR_EXTENT 2
24+
25+
/* EC minimum IO access delay in ms */
26+
#define EC_MIN_DELAY 10
27+
28+
/* EC interface definitions */
29+
#define EC_ADDR_CMD (EC_BASE_ADDR + 1)
30+
#define EC_ADDR_DATA EC_BASE_ADDR
31+
#define EC_CMD_EC_PROBE 0x30
32+
#define EC_CMD_COMM 0x89
33+
#define EC_CMD_WDT_START 0x28
34+
#define EC_CMD_WDT_STOP 0x29
35+
#define EC_CMD_WDT_RESET 0x2A
36+
#define EC_DAT_EN_DLY_H 0x58
37+
#define EC_DAT_EN_DLY_L 0x59
38+
#define EC_DAT_RST_DLY_H 0x5E
39+
#define EC_DAT_RST_DLY_L 0x5F
40+
#define EC_MAGIC 0x95
41+
42+
/* module parameters */
43+
#define MIN_TIME 1
44+
#define MAX_TIME 6000 /* 100 minutes */
45+
#define DEFAULT_TIME 60
46+
47+
static unsigned int timeout;
48+
static ktime_t ec_timestamp;
49+
50+
module_param(timeout, uint, 0);
51+
MODULE_PARM_DESC(timeout,
52+
"Default Watchdog timer setting (" __MODULE_STRING(DEFAULT_TIME) "s). The range is from " __MODULE_STRING(MIN_TIME) " to " __MODULE_STRING(MAX_TIME) ".");
53+
54+
static void adv_ec_wdt_timing_gate(void)
55+
{
56+
ktime_t time_cur, time_delta;
57+
58+
/* ensure minimum delay between IO accesses*/
59+
time_cur = ktime_get();
60+
time_delta = ktime_to_ms(ktime_sub(time_cur, ec_timestamp));
61+
if (time_delta < EC_MIN_DELAY) {
62+
time_delta = EC_MIN_DELAY - time_delta;
63+
usleep_range(time_delta * 1000, (time_delta + 1) * 1000);
64+
}
65+
ec_timestamp = ktime_get();
66+
}
67+
68+
static void adv_ec_wdt_outb(unsigned char value, unsigned short port)
69+
{
70+
adv_ec_wdt_timing_gate();
71+
outb(value, port);
72+
}
73+
74+
static unsigned char adv_ec_wdt_inb(unsigned short port)
75+
{
76+
adv_ec_wdt_timing_gate();
77+
return inb(port);
78+
}
79+
80+
static int adv_ec_wdt_ping(struct watchdog_device *wdd)
81+
{
82+
adv_ec_wdt_outb(EC_CMD_WDT_RESET, EC_ADDR_CMD);
83+
return 0;
84+
}
85+
86+
static int adv_ec_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
87+
{
88+
unsigned int val;
89+
90+
/* scale time to EC 100 ms base */
91+
val = t * 10;
92+
93+
/* reset enable delay, just in case it was set by BIOS etc. */
94+
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
95+
adv_ec_wdt_outb(EC_DAT_EN_DLY_H, EC_ADDR_DATA);
96+
adv_ec_wdt_outb(0, EC_ADDR_DATA);
97+
98+
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
99+
adv_ec_wdt_outb(EC_DAT_EN_DLY_L, EC_ADDR_DATA);
100+
adv_ec_wdt_outb(0, EC_ADDR_DATA);
101+
102+
/* set reset delay */
103+
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
104+
adv_ec_wdt_outb(EC_DAT_RST_DLY_H, EC_ADDR_DATA);
105+
adv_ec_wdt_outb(val >> 8, EC_ADDR_DATA);
106+
107+
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
108+
adv_ec_wdt_outb(EC_DAT_RST_DLY_L, EC_ADDR_DATA);
109+
adv_ec_wdt_outb(val & 0xFF, EC_ADDR_DATA);
110+
111+
wdd->timeout = t;
112+
return 0;
113+
}
114+
115+
static int adv_ec_wdt_start(struct watchdog_device *wdd)
116+
{
117+
adv_ec_wdt_set_timeout(wdd, wdd->timeout);
118+
adv_ec_wdt_outb(EC_CMD_WDT_START, EC_ADDR_CMD);
119+
120+
return 0;
121+
}
122+
123+
static int adv_ec_wdt_stop(struct watchdog_device *wdd)
124+
{
125+
adv_ec_wdt_outb(EC_CMD_WDT_STOP, EC_ADDR_CMD);
126+
127+
return 0;
128+
}
129+
130+
static const struct watchdog_info adv_ec_wdt_info = {
131+
.identity = DRIVER_NAME,
132+
.options = WDIOF_SETTIMEOUT |
133+
WDIOF_MAGICCLOSE |
134+
WDIOF_KEEPALIVEPING,
135+
};
136+
137+
static const struct watchdog_ops adv_ec_wdt_ops = {
138+
.owner = THIS_MODULE,
139+
.start = adv_ec_wdt_start,
140+
.stop = adv_ec_wdt_stop,
141+
.ping = adv_ec_wdt_ping,
142+
.set_timeout = adv_ec_wdt_set_timeout,
143+
};
144+
145+
static struct watchdog_device adv_ec_wdt_dev = {
146+
.info = &adv_ec_wdt_info,
147+
.ops = &adv_ec_wdt_ops,
148+
.min_timeout = MIN_TIME,
149+
.max_timeout = MAX_TIME,
150+
.timeout = DEFAULT_TIME,
151+
};
152+
153+
static int adv_ec_wdt_probe(struct device *dev, unsigned int id)
154+
{
155+
if (!devm_request_region(dev, EC_BASE_ADDR, EC_ADDR_EXTENT, dev_name(dev))) {
156+
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
157+
EC_BASE_ADDR, EC_BASE_ADDR + EC_ADDR_EXTENT);
158+
return -EBUSY;
159+
}
160+
161+
watchdog_init_timeout(&adv_ec_wdt_dev, timeout, dev);
162+
watchdog_stop_on_reboot(&adv_ec_wdt_dev);
163+
watchdog_stop_on_unregister(&adv_ec_wdt_dev);
164+
165+
return devm_watchdog_register_device(dev, &adv_ec_wdt_dev);
166+
}
167+
168+
static struct isa_driver adv_ec_wdt_driver = {
169+
.probe = adv_ec_wdt_probe,
170+
.driver = {
171+
.name = DRIVER_NAME,
172+
},
173+
};
174+
175+
static int __init adv_ec_wdt_init(void)
176+
{
177+
unsigned int val;
178+
179+
/* quick probe for EC */
180+
if (!request_region(EC_BASE_ADDR, EC_ADDR_EXTENT, DRIVER_NAME))
181+
return -EBUSY;
182+
183+
adv_ec_wdt_outb(EC_CMD_EC_PROBE, EC_ADDR_CMD);
184+
val = adv_ec_wdt_inb(EC_ADDR_DATA);
185+
release_region(EC_BASE_ADDR, EC_ADDR_EXTENT);
186+
187+
if (val != EC_MAGIC)
188+
return -ENODEV;
189+
190+
return isa_register_driver(&adv_ec_wdt_driver, 1);
191+
}
192+
193+
static void __exit adv_ec_wdt_exit(void)
194+
{
195+
isa_unregister_driver(&adv_ec_wdt_driver);
196+
}
197+
198+
module_init(adv_ec_wdt_init);
199+
module_exit(adv_ec_wdt_exit);
200+
201+
MODULE_AUTHOR("Thomas Kastner <[email protected]>");
202+
MODULE_DESCRIPTION("Advantech Embedded Controller Watchdog Device Driver");
203+
MODULE_LICENSE("GPL");
204+
MODULE_VERSION("20221019");
205+
MODULE_ALIAS("isa:" DRIVER_NAME);

0 commit comments

Comments
 (0)