]>
Commit | Line | Data |
---|---|---|
053fce84 SR |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Ralink / Mediatek RT288x/RT3xxx/MT76xx built-in hardware watchdog timer | |
4 | * | |
5 | * Copyright (C) 2018 Stefan Roese <[email protected]> | |
6 | * | |
7 | * Based on the Linux driver version which is: | |
8 | * Copyright (C) 2011 Gabor Juhos <[email protected]> | |
9 | * Copyright (C) 2013 John Crispin <[email protected]> | |
10 | */ | |
11 | ||
12 | #include <common.h> | |
13 | #include <dm.h> | |
14 | #include <wdt.h> | |
401d1c4f | 15 | #include <asm/global_data.h> |
cd93d625 | 16 | #include <linux/bitops.h> |
053fce84 SR |
17 | #include <linux/io.h> |
18 | ||
19 | DECLARE_GLOBAL_DATA_PTR; | |
20 | ||
21 | struct mt762x_wdt { | |
22 | void __iomem *regs; | |
23 | }; | |
24 | ||
25 | #define TIMER_REG_TMRSTAT 0x00 | |
26 | #define TIMER_REG_TMR1CTL 0x20 | |
27 | #define TIMER_REG_TMR1LOAD 0x24 | |
28 | ||
29 | #define TMR1CTL_ENABLE BIT(7) | |
30 | #define TMR1CTL_RESTART BIT(9) | |
31 | #define TMR1CTL_PRESCALE_SHIFT 16 | |
32 | ||
33 | static int mt762x_wdt_ping(struct mt762x_wdt *priv) | |
34 | { | |
35 | writel(TMR1CTL_RESTART, priv->regs + TIMER_REG_TMRSTAT); | |
36 | ||
37 | return 0; | |
38 | } | |
39 | ||
40 | static int mt762x_wdt_start(struct udevice *dev, u64 ms, ulong flags) | |
41 | { | |
42 | struct mt762x_wdt *priv = dev_get_priv(dev); | |
43 | ||
44 | /* set the prescaler to 1ms == 1000us */ | |
45 | writel(1000 << TMR1CTL_PRESCALE_SHIFT, priv->regs + TIMER_REG_TMR1CTL); | |
46 | writel(ms, priv->regs + TIMER_REG_TMR1LOAD); | |
47 | ||
48 | setbits_le32(priv->regs + TIMER_REG_TMR1CTL, TMR1CTL_ENABLE); | |
49 | ||
50 | return 0; | |
51 | } | |
52 | ||
53 | static int mt762x_wdt_stop(struct udevice *dev) | |
54 | { | |
55 | struct mt762x_wdt *priv = dev_get_priv(dev); | |
56 | ||
57 | mt762x_wdt_ping(priv); | |
58 | ||
59 | clrbits_le32(priv->regs + TIMER_REG_TMR1CTL, TMR1CTL_ENABLE); | |
60 | ||
61 | return 0; | |
62 | } | |
63 | ||
64 | static int mt762x_wdt_reset(struct udevice *dev) | |
65 | { | |
66 | struct mt762x_wdt *priv = dev_get_priv(dev); | |
67 | ||
68 | mt762x_wdt_ping(priv); | |
69 | ||
70 | return 0; | |
71 | } | |
72 | ||
73 | static int mt762x_wdt_probe(struct udevice *dev) | |
74 | { | |
75 | struct mt762x_wdt *priv = dev_get_priv(dev); | |
76 | ||
77 | priv->regs = dev_remap_addr(dev); | |
78 | if (!priv->regs) | |
79 | return -EINVAL; | |
80 | ||
81 | mt762x_wdt_stop(dev); | |
82 | ||
83 | return 0; | |
84 | } | |
85 | ||
86 | static const struct wdt_ops mt762x_wdt_ops = { | |
87 | .start = mt762x_wdt_start, | |
88 | .reset = mt762x_wdt_reset, | |
89 | .stop = mt762x_wdt_stop, | |
90 | }; | |
91 | ||
92 | static const struct udevice_id mt762x_wdt_ids[] = { | |
93 | { .compatible = "mediatek,mt7621-wdt" }, | |
94 | {} | |
95 | }; | |
96 | ||
97 | U_BOOT_DRIVER(mt762x_wdt) = { | |
98 | .name = "mt762x_wdt", | |
99 | .id = UCLASS_WDT, | |
100 | .of_match = mt762x_wdt_ids, | |
101 | .probe = mt762x_wdt_probe, | |
41575d8e | 102 | .priv_auto = sizeof(struct mt762x_wdt), |
053fce84 SR |
103 | .ops = &mt762x_wdt_ops, |
104 | }; |