Skip to content

Commit e0c50cd

Browse files
AaronDotWim Van Sebroeck
authored andcommitted
watchdog: loongson1: Add Loongson-2k0300 watchdog support
According to the manual, the Loongson-2K0300 watchdog is similar to the Loongson-1, except for some register offsets and inconsistent register bit definitions. Separate definitions via driver_data suffice. Co-developed-by: Xiaochuang Mao <maoxiaochuan@loongson.cn> Signed-off-by: Xiaochuang Mao <maoxiaochuan@loongson.cn> Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> Reviewed-by: Huacai Chen <chenhuacai@loongson.cn> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
1 parent e4948e8 commit e0c50cd

2 files changed

Lines changed: 62 additions & 15 deletions

File tree

drivers/watchdog/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,10 +1984,10 @@ config LANTIQ_WDT
19841984

19851985
config LOONGSON1_WDT
19861986
tristate "Loongson1 SoC hardware watchdog"
1987-
depends on MACH_LOONGSON32 || COMPILE_TEST
1987+
depends on MACH_LOONGSON32 || MACH_LOONGSON64 || COMPILE_TEST
19881988
select WATCHDOG_CORE
19891989
help
1990-
Hardware driver for the Loongson1 SoC Watchdog Timer.
1990+
Hardware driver for the Loongson family Watchdog Timer.
19911991

19921992
config RALINK_WDT
19931993
tristate "Ralink SoC watchdog"

drivers/watchdog/loongson1_wdt.c

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
22
/*
33
* Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
4+
* Copyright (C) 2025 Binbin Zhou <zhoubinbin@loongson.cn>
45
*/
56

67
#include <linux/clk.h>
@@ -10,10 +11,8 @@
1011
#include <linux/platform_device.h>
1112
#include <linux/watchdog.h>
1213

13-
/* Loongson 1 Watchdog Register Definitions */
14+
/* Loongson Watchdog Register Definitions */
1415
#define WDT_EN 0x0
15-
#define WDT_TIMER 0x4
16-
#define WDT_SET 0x8
1716

1817
#define DEFAULT_HEARTBEAT 30
1918

@@ -27,18 +26,37 @@ module_param(heartbeat, uint, 0);
2726
MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
2827
__MODULE_STRING(DEFAULT_HEARTBEAT) ")");
2928

29+
struct ls1x_wdt_pdata {
30+
u32 timer_offset;
31+
u32 set_offset;
32+
u32 wdt_en_bit;
33+
};
34+
35+
static const struct ls1x_wdt_pdata ls1b_wdt_pdata = {
36+
.timer_offset = 0x4,
37+
.set_offset = 0x8,
38+
.wdt_en_bit = BIT(0),
39+
};
40+
41+
static const struct ls1x_wdt_pdata ls2k0300_wdt_pdata = {
42+
.timer_offset = 0x8,
43+
.set_offset = 0x4,
44+
.wdt_en_bit = BIT(1),
45+
};
46+
3047
struct ls1x_wdt_drvdata {
3148
void __iomem *base;
3249
struct clk *clk;
3350
unsigned long clk_rate;
3451
struct watchdog_device wdt;
52+
const struct ls1x_wdt_pdata *pdata;
3553
};
3654

3755
static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
3856
{
3957
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
4058

41-
writel(0x1, drvdata->base + WDT_SET);
59+
writel(0x1, drvdata->base + drvdata->pdata->set_offset);
4260

4361
return 0;
4462
}
@@ -53,7 +71,7 @@ static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
5371
wdt_dev->timeout = timeout;
5472

5573
counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
56-
writel(counts, drvdata->base + WDT_TIMER);
74+
writel(counts, drvdata->base + drvdata->pdata->timer_offset);
5775

5876
return 0;
5977
}
@@ -62,16 +80,18 @@ static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
6280
{
6381
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
6482

65-
writel(0x1, drvdata->base + WDT_EN);
83+
writel(drvdata->pdata->wdt_en_bit, drvdata->base + WDT_EN);
6684

6785
return 0;
6886
}
6987

7088
static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
7189
{
7290
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
91+
u32 val = readl(drvdata->base + WDT_EN);
7392

74-
writel(0x0, drvdata->base + WDT_EN);
93+
val &= ~(drvdata->pdata->wdt_en_bit);
94+
writel(val, drvdata->base + WDT_EN);
7595

7696
return 0;
7797
}
@@ -81,9 +101,9 @@ static int ls1x_wdt_restart(struct watchdog_device *wdt_dev,
81101
{
82102
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
83103

84-
writel(0x1, drvdata->base + WDT_EN);
85-
writel(0x1, drvdata->base + WDT_TIMER);
86-
writel(0x1, drvdata->base + WDT_SET);
104+
writel(drvdata->pdata->wdt_en_bit, drvdata->base + WDT_EN);
105+
writel(0x1, drvdata->base + drvdata->pdata->timer_offset);
106+
writel(0x1, drvdata->base + drvdata->pdata->set_offset);
87107

88108
return 0;
89109
}
@@ -114,6 +134,8 @@ static int ls1x_wdt_probe(struct platform_device *pdev)
114134
return -ENOMEM;
115135
platform_set_drvdata(pdev, drvdata);
116136

137+
drvdata->pdata = of_device_get_match_data(dev);
138+
117139
drvdata->base = devm_platform_ioremap_resource(pdev, 0);
118140
if (IS_ERR(drvdata->base))
119141
return PTR_ERR(drvdata->base);
@@ -142,9 +164,32 @@ static int ls1x_wdt_probe(struct platform_device *pdev)
142164
return devm_watchdog_register_device(dev, &drvdata->wdt);
143165
}
144166

167+
static int ls1x_wdt_resume(struct device *dev)
168+
{
169+
struct ls1x_wdt_drvdata *data = dev_get_drvdata(dev);
170+
171+
if (watchdog_active(&data->wdt))
172+
ls1x_wdt_start(&data->wdt);
173+
174+
return 0;
175+
}
176+
177+
static int ls1x_wdt_suspend(struct device *dev)
178+
{
179+
struct ls1x_wdt_drvdata *data = dev_get_drvdata(dev);
180+
181+
if (watchdog_active(&data->wdt))
182+
ls1x_wdt_stop(&data->wdt);
183+
184+
return 0;
185+
}
186+
187+
static DEFINE_SIMPLE_DEV_PM_OPS(ls1x_wdt_pm_ops, ls1x_wdt_suspend, ls1x_wdt_resume);
188+
145189
static const struct of_device_id ls1x_wdt_dt_ids[] = {
146-
{ .compatible = "loongson,ls1b-wdt", },
147-
{ .compatible = "loongson,ls1c-wdt", },
190+
{ .compatible = "loongson,ls1b-wdt", .data = &ls1b_wdt_pdata },
191+
{ .compatible = "loongson,ls1c-wdt", .data = &ls1b_wdt_pdata },
192+
{ .compatible = "loongson,ls2k0300-wdt", .data = &ls2k0300_wdt_pdata },
148193
{ /* sentinel */ }
149194
};
150195
MODULE_DEVICE_TABLE(of, ls1x_wdt_dt_ids);
@@ -154,11 +199,13 @@ static struct platform_driver ls1x_wdt_driver = {
154199
.driver = {
155200
.name = "ls1x-wdt",
156201
.of_match_table = ls1x_wdt_dt_ids,
202+
.pm = pm_ptr(&ls1x_wdt_pm_ops),
157203
},
158204
};
159205

160206
module_platform_driver(ls1x_wdt_driver);
161207

162208
MODULE_AUTHOR("Yang Ling <gnaygnil@gmail.com>");
163-
MODULE_DESCRIPTION("Loongson1 Watchdog Driver");
209+
MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
210+
MODULE_DESCRIPTION("Loongson Watchdog Driver");
164211
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)