aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/orion_wdt.c62
1 files changed, 43 insertions, 19 deletions
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 9d3a5b97845b..b220e34285d1 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -24,6 +24,7 @@
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/of.h> 26#include <linux/of.h>
27#include <linux/of_device.h>
27 28
28/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */ 29/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
29#define ORION_RSTOUT_MASK_OFFSET 0x20108 30#define ORION_RSTOUT_MASK_OFFSET 0x20108
@@ -35,29 +36,33 @@
35 * Watchdog timer block registers. 36 * Watchdog timer block registers.
36 */ 37 */
37#define TIMER_CTRL 0x0000 38#define TIMER_CTRL 0x0000
38#define WDT_EN 0x0010
39#define WDT_VAL 0x0024
40 39
41#define WDT_MAX_CYCLE_COUNT 0xffffffff 40#define WDT_MAX_CYCLE_COUNT 0xffffffff
42 41
43#define WDT_RESET_OUT_EN BIT(1)
44
45static bool nowayout = WATCHDOG_NOWAYOUT; 42static bool nowayout = WATCHDOG_NOWAYOUT;
46static int heartbeat = -1; /* module parameter (seconds) */ 43static int heartbeat = -1; /* module parameter (seconds) */
47 44
45struct orion_watchdog_data {
46 int wdt_counter_offset;
47 int wdt_enable_bit;
48 int rstout_enable_bit;
49};
50
48struct orion_watchdog { 51struct orion_watchdog {
49 struct watchdog_device wdt; 52 struct watchdog_device wdt;
50 void __iomem *reg; 53 void __iomem *reg;
51 void __iomem *rstout; 54 void __iomem *rstout;
52 unsigned long clk_rate; 55 unsigned long clk_rate;
53 struct clk *clk; 56 struct clk *clk;
57 const struct orion_watchdog_data *data;
54}; 58};
55 59
56static int orion_wdt_ping(struct watchdog_device *wdt_dev) 60static int orion_wdt_ping(struct watchdog_device *wdt_dev)
57{ 61{
58 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 62 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
59 /* Reload watchdog duration */ 63 /* Reload watchdog duration */
60 writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL); 64 writel(dev->clk_rate * wdt_dev->timeout,
65 dev->reg + dev->data->wdt_counter_offset);
61 return 0; 66 return 0;
62} 67}
63 68
@@ -66,13 +71,16 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
66 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 71 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
67 72
68 /* Set watchdog duration */ 73 /* Set watchdog duration */
69 writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL); 74 writel(dev->clk_rate * wdt_dev->timeout,
75 dev->reg + dev->data->wdt_counter_offset);
70 76
71 /* Enable watchdog timer */ 77 /* Enable watchdog timer */
72 atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, WDT_EN); 78 atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
79 dev->data->wdt_enable_bit);
73 80
74 /* Enable reset on watchdog */ 81 /* Enable reset on watchdog */
75 atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); 82 atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
83 dev->data->rstout_enable_bit);
76 84
77 return 0; 85 return 0;
78} 86}
@@ -82,10 +90,10 @@ static int orion_wdt_stop(struct watchdog_device *wdt_dev)
82 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 90 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
83 91
84 /* Disable reset on watchdog */ 92 /* Disable reset on watchdog */
85 atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, 0); 93 atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0);
86 94
87 /* Disable watchdog timer */ 95 /* Disable watchdog timer */
88 atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, 0); 96 atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
89 97
90 return 0; 98 return 0;
91} 99}
@@ -94,8 +102,8 @@ static int orion_wdt_enabled(struct orion_watchdog *dev)
94{ 102{
95 bool enabled, running; 103 bool enabled, running;
96 104
97 enabled = readl(dev->rstout) & WDT_RESET_OUT_EN; 105 enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
98 running = readl(dev->reg + TIMER_CTRL) & WDT_EN; 106 running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
99 107
100 return enabled && running; 108 return enabled && running;
101} 109}
@@ -103,7 +111,7 @@ static int orion_wdt_enabled(struct orion_watchdog *dev)
103static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) 111static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
104{ 112{
105 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 113 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
106 return readl(dev->reg + WDT_VAL) / dev->clk_rate; 114 return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
107} 115}
108 116
109static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, 117static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
@@ -160,9 +168,25 @@ static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
160 return devm_ioremap(&pdev->dev, rstout, 0x4); 168 return devm_ioremap(&pdev->dev, rstout, 0x4);
161} 169}
162 170
171static const struct orion_watchdog_data orion_data = {
172 .rstout_enable_bit = BIT(1),
173 .wdt_enable_bit = BIT(4),
174 .wdt_counter_offset = 0x24,
175};
176
177static const struct of_device_id orion_wdt_of_match_table[] = {
178 {
179 .compatible = "marvell,orion-wdt",
180 .data = &orion_data,
181 },
182 {},
183};
184MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
185
163static int orion_wdt_probe(struct platform_device *pdev) 186static int orion_wdt_probe(struct platform_device *pdev)
164{ 187{
165 struct orion_watchdog *dev; 188 struct orion_watchdog *dev;
189 const struct of_device_id *match;
166 unsigned int wdt_max_duration; /* (seconds) */ 190 unsigned int wdt_max_duration; /* (seconds) */
167 struct resource *res; 191 struct resource *res;
168 int ret, irq; 192 int ret, irq;
@@ -172,9 +196,15 @@ static int orion_wdt_probe(struct platform_device *pdev)
172 if (!dev) 196 if (!dev)
173 return -ENOMEM; 197 return -ENOMEM;
174 198
199 match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
200 if (!match)
201 /* Default legacy match */
202 match = &orion_wdt_of_match_table[0];
203
175 dev->wdt.info = &orion_wdt_info; 204 dev->wdt.info = &orion_wdt_info;
176 dev->wdt.ops = &orion_wdt_ops; 205 dev->wdt.ops = &orion_wdt_ops;
177 dev->wdt.min_timeout = 1; 206 dev->wdt.min_timeout = 1;
207 dev->data = match->data;
178 208
179 dev->clk = devm_clk_get(&pdev->dev, NULL); 209 dev->clk = devm_clk_get(&pdev->dev, NULL);
180 if (IS_ERR(dev->clk)) { 210 if (IS_ERR(dev->clk)) {
@@ -269,12 +299,6 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
269 orion_wdt_stop(wdt_dev); 299 orion_wdt_stop(wdt_dev);
270} 300}
271 301
272static const struct of_device_id orion_wdt_of_match_table[] = {
273 { .compatible = "marvell,orion-wdt", },
274 {},
275};
276MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
277
278static struct platform_driver orion_wdt_driver = { 302static struct platform_driver orion_wdt_driver = {
279 .probe = orion_wdt_probe, 303 .probe = orion_wdt_probe,
280 .remove = orion_wdt_remove, 304 .remove = orion_wdt_remove,