2 * drivers/watchdog/orion_wdt.c
4 * Watchdog driver for Orion/Kirkwood processors
6 * Author: Sylver Bruneau <sylver.bruneau@googlemail.com>
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/platform_device.h>
20 #include <linux/watchdog.h>
21 #include <linux/interrupt.h>
23 #include <linux/clk.h>
24 #include <linux/err.h>
26 #include <linux/of_device.h>
28 /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
29 #define ORION_RSTOUT_MASK_OFFSET 0x20108
31 /* Internal registers can be configured at any 1 MiB aligned address */
32 #define INTERNAL_REGS_MASK ~(SZ_1M - 1)
35 * Watchdog timer block registers.
37 #define TIMER_CTRL 0x0000
38 #define TIMER_A370_STATUS 0x04
40 #define WDT_MAX_CYCLE_COUNT 0xffffffff
42 #define WDT_A370_RATIO_MASK(v) ((v) << 16)
43 #define WDT_A370_RATIO_SHIFT 5
44 #define WDT_A370_RATIO (1 << WDT_A370_RATIO_SHIFT)
46 #define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
47 #define WDT_A370_EXPIRED BIT(31)
49 static bool nowayout
= WATCHDOG_NOWAYOUT
;
50 static int heartbeat
= -1; /* module parameter (seconds) */
52 struct orion_watchdog
;
54 struct orion_watchdog_data
{
55 int wdt_counter_offset
;
57 int rstout_enable_bit
;
59 int (*clock_init
)(struct platform_device
*,
60 struct orion_watchdog
*);
61 int (*enabled
)(struct orion_watchdog
*);
62 int (*start
)(struct watchdog_device
*);
63 int (*stop
)(struct watchdog_device
*);
66 struct orion_watchdog
{
67 struct watchdog_device wdt
;
70 void __iomem
*rstout_mask
;
71 unsigned long clk_rate
;
73 const struct orion_watchdog_data
*data
;
76 static int orion_wdt_clock_init(struct platform_device
*pdev
,
77 struct orion_watchdog
*dev
)
81 dev
->clk
= clk_get(&pdev
->dev
, NULL
);
83 return PTR_ERR(dev
->clk
);
84 ret
= clk_prepare_enable(dev
->clk
);
90 dev
->clk_rate
= clk_get_rate(dev
->clk
);
94 static int armada370_wdt_clock_init(struct platform_device
*pdev
,
95 struct orion_watchdog
*dev
)
99 dev
->clk
= clk_get(&pdev
->dev
, NULL
);
100 if (IS_ERR(dev
->clk
))
101 return PTR_ERR(dev
->clk
);
102 ret
= clk_prepare_enable(dev
->clk
);
108 /* Setup watchdog input clock */
109 atomic_io_modify(dev
->reg
+ TIMER_CTRL
,
110 WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT
),
111 WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT
));
113 dev
->clk_rate
= clk_get_rate(dev
->clk
) / WDT_A370_RATIO
;
117 static int armada375_wdt_clock_init(struct platform_device
*pdev
,
118 struct orion_watchdog
*dev
)
122 dev
->clk
= of_clk_get_by_name(pdev
->dev
.of_node
, "fixed");
123 if (!IS_ERR(dev
->clk
)) {
124 ret
= clk_prepare_enable(dev
->clk
);
130 atomic_io_modify(dev
->reg
+ TIMER_CTRL
,
131 WDT_AXP_FIXED_ENABLE_BIT
,
132 WDT_AXP_FIXED_ENABLE_BIT
);
133 dev
->clk_rate
= clk_get_rate(dev
->clk
);
138 /* Mandatory fallback for proper devicetree backward compatibility */
139 dev
->clk
= clk_get(&pdev
->dev
, NULL
);
140 if (IS_ERR(dev
->clk
))
141 return PTR_ERR(dev
->clk
);
143 ret
= clk_prepare_enable(dev
->clk
);
149 atomic_io_modify(dev
->reg
+ TIMER_CTRL
,
150 WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT
),
151 WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT
));
152 dev
->clk_rate
= clk_get_rate(dev
->clk
) / WDT_A370_RATIO
;
157 static int armadaxp_wdt_clock_init(struct platform_device
*pdev
,
158 struct orion_watchdog
*dev
)
162 dev
->clk
= of_clk_get_by_name(pdev
->dev
.of_node
, "fixed");
163 if (IS_ERR(dev
->clk
))
164 return PTR_ERR(dev
->clk
);
165 ret
= clk_prepare_enable(dev
->clk
);
171 /* Enable the fixed watchdog clock input */
172 atomic_io_modify(dev
->reg
+ TIMER_CTRL
,
173 WDT_AXP_FIXED_ENABLE_BIT
,
174 WDT_AXP_FIXED_ENABLE_BIT
);
176 dev
->clk_rate
= clk_get_rate(dev
->clk
);
180 static int orion_wdt_ping(struct watchdog_device
*wdt_dev
)
182 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
183 /* Reload watchdog duration */
184 writel(dev
->clk_rate
* wdt_dev
->timeout
,
185 dev
->reg
+ dev
->data
->wdt_counter_offset
);
189 static int armada375_start(struct watchdog_device
*wdt_dev
)
191 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
194 /* Set watchdog duration */
195 writel(dev
->clk_rate
* wdt_dev
->timeout
,
196 dev
->reg
+ dev
->data
->wdt_counter_offset
);
198 /* Clear the watchdog expiration bit */
199 atomic_io_modify(dev
->reg
+ TIMER_A370_STATUS
, WDT_A370_EXPIRED
, 0);
201 /* Enable watchdog timer */
202 atomic_io_modify(dev
->reg
+ TIMER_CTRL
, dev
->data
->wdt_enable_bit
,
203 dev
->data
->wdt_enable_bit
);
205 /* Enable reset on watchdog */
206 reg
= readl(dev
->rstout
);
207 reg
|= dev
->data
->rstout_enable_bit
;
208 writel(reg
, dev
->rstout
);
210 atomic_io_modify(dev
->rstout_mask
, dev
->data
->rstout_mask_bit
, 0);
214 static int armada370_start(struct watchdog_device
*wdt_dev
)
216 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
219 /* Set watchdog duration */
220 writel(dev
->clk_rate
* wdt_dev
->timeout
,
221 dev
->reg
+ dev
->data
->wdt_counter_offset
);
223 /* Clear the watchdog expiration bit */
224 atomic_io_modify(dev
->reg
+ TIMER_A370_STATUS
, WDT_A370_EXPIRED
, 0);
226 /* Enable watchdog timer */
227 atomic_io_modify(dev
->reg
+ TIMER_CTRL
, dev
->data
->wdt_enable_bit
,
228 dev
->data
->wdt_enable_bit
);
230 /* Enable reset on watchdog */
231 reg
= readl(dev
->rstout
);
232 reg
|= dev
->data
->rstout_enable_bit
;
233 writel(reg
, dev
->rstout
);
237 static int orion_start(struct watchdog_device
*wdt_dev
)
239 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
241 /* Set watchdog duration */
242 writel(dev
->clk_rate
* wdt_dev
->timeout
,
243 dev
->reg
+ dev
->data
->wdt_counter_offset
);
245 /* Enable watchdog timer */
246 atomic_io_modify(dev
->reg
+ TIMER_CTRL
, dev
->data
->wdt_enable_bit
,
247 dev
->data
->wdt_enable_bit
);
249 /* Enable reset on watchdog */
250 atomic_io_modify(dev
->rstout
, dev
->data
->rstout_enable_bit
,
251 dev
->data
->rstout_enable_bit
);
256 static int orion_wdt_start(struct watchdog_device
*wdt_dev
)
258 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
260 /* There are some per-SoC quirks to handle */
261 return dev
->data
->start(wdt_dev
);
264 static int orion_stop(struct watchdog_device
*wdt_dev
)
266 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
268 /* Disable reset on watchdog */
269 atomic_io_modify(dev
->rstout
, dev
->data
->rstout_enable_bit
, 0);
271 /* Disable watchdog timer */
272 atomic_io_modify(dev
->reg
+ TIMER_CTRL
, dev
->data
->wdt_enable_bit
, 0);
277 static int armada375_stop(struct watchdog_device
*wdt_dev
)
279 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
282 /* Disable reset on watchdog */
283 atomic_io_modify(dev
->rstout_mask
, dev
->data
->rstout_mask_bit
,
284 dev
->data
->rstout_mask_bit
);
285 reg
= readl(dev
->rstout
);
286 reg
&= ~dev
->data
->rstout_enable_bit
;
287 writel(reg
, dev
->rstout
);
289 /* Disable watchdog timer */
290 atomic_io_modify(dev
->reg
+ TIMER_CTRL
, dev
->data
->wdt_enable_bit
, 0);
295 static int armada370_stop(struct watchdog_device
*wdt_dev
)
297 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
300 /* Disable reset on watchdog */
301 reg
= readl(dev
->rstout
);
302 reg
&= ~dev
->data
->rstout_enable_bit
;
303 writel(reg
, dev
->rstout
);
305 /* Disable watchdog timer */
306 atomic_io_modify(dev
->reg
+ TIMER_CTRL
, dev
->data
->wdt_enable_bit
, 0);
311 static int orion_wdt_stop(struct watchdog_device
*wdt_dev
)
313 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
315 return dev
->data
->stop(wdt_dev
);
318 static int orion_enabled(struct orion_watchdog
*dev
)
320 bool enabled
, running
;
322 enabled
= readl(dev
->rstout
) & dev
->data
->rstout_enable_bit
;
323 running
= readl(dev
->reg
+ TIMER_CTRL
) & dev
->data
->wdt_enable_bit
;
325 return enabled
&& running
;
328 static int armada375_enabled(struct orion_watchdog
*dev
)
330 bool masked
, enabled
, running
;
332 masked
= readl(dev
->rstout_mask
) & dev
->data
->rstout_mask_bit
;
333 enabled
= readl(dev
->rstout
) & dev
->data
->rstout_enable_bit
;
334 running
= readl(dev
->reg
+ TIMER_CTRL
) & dev
->data
->wdt_enable_bit
;
336 return !masked
&& enabled
&& running
;
339 static int orion_wdt_enabled(struct watchdog_device
*wdt_dev
)
341 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
343 return dev
->data
->enabled(dev
);
346 static unsigned int orion_wdt_get_timeleft(struct watchdog_device
*wdt_dev
)
348 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
349 return readl(dev
->reg
+ dev
->data
->wdt_counter_offset
) / dev
->clk_rate
;
352 static int orion_wdt_set_timeout(struct watchdog_device
*wdt_dev
,
353 unsigned int timeout
)
355 wdt_dev
->timeout
= timeout
;
359 static const struct watchdog_info orion_wdt_info
= {
360 .options
= WDIOF_SETTIMEOUT
| WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
,
361 .identity
= "Orion Watchdog",
364 static const struct watchdog_ops orion_wdt_ops
= {
365 .owner
= THIS_MODULE
,
366 .start
= orion_wdt_start
,
367 .stop
= orion_wdt_stop
,
368 .ping
= orion_wdt_ping
,
369 .set_timeout
= orion_wdt_set_timeout
,
370 .get_timeleft
= orion_wdt_get_timeleft
,
373 static irqreturn_t
orion_wdt_irq(int irq
, void *devid
)
375 panic("Watchdog Timeout");
380 * The original devicetree binding for this driver specified only
381 * one memory resource, so in order to keep DT backwards compatibility
382 * we try to fallback to a hardcoded register address, if the resource
383 * is missing from the devicetree.
385 static void __iomem
*orion_wdt_ioremap_rstout(struct platform_device
*pdev
,
386 phys_addr_t internal_regs
)
388 struct resource
*res
;
391 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
393 return devm_ioremap(&pdev
->dev
, res
->start
,
396 rstout
= internal_regs
+ ORION_RSTOUT_MASK_OFFSET
;
398 WARN(1, FW_BUG
"falling back to harcoded RSTOUT reg %pa\n", &rstout
);
399 return devm_ioremap(&pdev
->dev
, rstout
, 0x4);
402 static const struct orion_watchdog_data orion_data
= {
403 .rstout_enable_bit
= BIT(1),
404 .wdt_enable_bit
= BIT(4),
405 .wdt_counter_offset
= 0x24,
406 .clock_init
= orion_wdt_clock_init
,
407 .enabled
= orion_enabled
,
408 .start
= orion_start
,
412 static const struct orion_watchdog_data armada370_data
= {
413 .rstout_enable_bit
= BIT(8),
414 .wdt_enable_bit
= BIT(8),
415 .wdt_counter_offset
= 0x34,
416 .clock_init
= armada370_wdt_clock_init
,
417 .enabled
= orion_enabled
,
418 .start
= armada370_start
,
419 .stop
= armada370_stop
,
422 static const struct orion_watchdog_data armadaxp_data
= {
423 .rstout_enable_bit
= BIT(8),
424 .wdt_enable_bit
= BIT(8),
425 .wdt_counter_offset
= 0x34,
426 .clock_init
= armadaxp_wdt_clock_init
,
427 .enabled
= orion_enabled
,
428 .start
= armada370_start
,
429 .stop
= armada370_stop
,
432 static const struct orion_watchdog_data armada375_data
= {
433 .rstout_enable_bit
= BIT(8),
434 .rstout_mask_bit
= BIT(10),
435 .wdt_enable_bit
= BIT(8),
436 .wdt_counter_offset
= 0x34,
437 .clock_init
= armada375_wdt_clock_init
,
438 .enabled
= armada375_enabled
,
439 .start
= armada375_start
,
440 .stop
= armada375_stop
,
443 static const struct orion_watchdog_data armada380_data
= {
444 .rstout_enable_bit
= BIT(8),
445 .rstout_mask_bit
= BIT(10),
446 .wdt_enable_bit
= BIT(8),
447 .wdt_counter_offset
= 0x34,
448 .clock_init
= armadaxp_wdt_clock_init
,
449 .enabled
= armada375_enabled
,
450 .start
= armada375_start
,
451 .stop
= armada375_stop
,
454 static const struct of_device_id orion_wdt_of_match_table
[] = {
456 .compatible
= "marvell,orion-wdt",
460 .compatible
= "marvell,armada-370-wdt",
461 .data
= &armada370_data
,
464 .compatible
= "marvell,armada-xp-wdt",
465 .data
= &armadaxp_data
,
468 .compatible
= "marvell,armada-375-wdt",
469 .data
= &armada375_data
,
472 .compatible
= "marvell,armada-380-wdt",
473 .data
= &armada380_data
,
477 MODULE_DEVICE_TABLE(of
, orion_wdt_of_match_table
);
479 static int orion_wdt_get_regs(struct platform_device
*pdev
,
480 struct orion_watchdog
*dev
)
482 struct device_node
*node
= pdev
->dev
.of_node
;
483 struct resource
*res
;
485 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
488 dev
->reg
= devm_ioremap(&pdev
->dev
, res
->start
,
493 /* Each supported compatible has some RSTOUT register quirk */
494 if (of_device_is_compatible(node
, "marvell,orion-wdt")) {
496 dev
->rstout
= orion_wdt_ioremap_rstout(pdev
, res
->start
&
501 } else if (of_device_is_compatible(node
, "marvell,armada-370-wdt") ||
502 of_device_is_compatible(node
, "marvell,armada-xp-wdt")) {
504 /* Dedicated RSTOUT register, can be requested. */
505 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
506 dev
->rstout
= devm_ioremap_resource(&pdev
->dev
, res
);
507 if (IS_ERR(dev
->rstout
))
508 return PTR_ERR(dev
->rstout
);
510 } else if (of_device_is_compatible(node
, "marvell,armada-375-wdt") ||
511 of_device_is_compatible(node
, "marvell,armada-380-wdt")) {
513 /* Dedicated RSTOUT register, can be requested. */
514 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
515 dev
->rstout
= devm_ioremap_resource(&pdev
->dev
, res
);
516 if (IS_ERR(dev
->rstout
))
517 return PTR_ERR(dev
->rstout
);
519 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 2);
522 dev
->rstout_mask
= devm_ioremap(&pdev
->dev
, res
->start
,
524 if (!dev
->rstout_mask
)
534 static int orion_wdt_probe(struct platform_device
*pdev
)
536 struct orion_watchdog
*dev
;
537 const struct of_device_id
*match
;
538 unsigned int wdt_max_duration
; /* (seconds) */
541 dev
= devm_kzalloc(&pdev
->dev
, sizeof(struct orion_watchdog
),
546 match
= of_match_device(orion_wdt_of_match_table
, &pdev
->dev
);
548 /* Default legacy match */
549 match
= &orion_wdt_of_match_table
[0];
551 dev
->wdt
.info
= &orion_wdt_info
;
552 dev
->wdt
.ops
= &orion_wdt_ops
;
553 dev
->wdt
.min_timeout
= 1;
554 dev
->data
= match
->data
;
556 ret
= orion_wdt_get_regs(pdev
, dev
);
560 ret
= dev
->data
->clock_init(pdev
, dev
);
562 dev_err(&pdev
->dev
, "cannot initialize clock\n");
566 wdt_max_duration
= WDT_MAX_CYCLE_COUNT
/ dev
->clk_rate
;
568 dev
->wdt
.timeout
= wdt_max_duration
;
569 dev
->wdt
.max_timeout
= wdt_max_duration
;
570 dev
->wdt
.parent
= &pdev
->dev
;
571 watchdog_init_timeout(&dev
->wdt
, heartbeat
, &pdev
->dev
);
573 platform_set_drvdata(pdev
, &dev
->wdt
);
574 watchdog_set_drvdata(&dev
->wdt
, dev
);
577 * Let's make sure the watchdog is fully stopped, unless it's
578 * explicitly enabled. This may be the case if the module was
579 * removed and re-insterted, or if the bootloader explicitly
580 * set a running watchdog before booting the kernel.
582 if (!orion_wdt_enabled(&dev
->wdt
))
583 orion_wdt_stop(&dev
->wdt
);
585 /* Request the IRQ only after the watchdog is disabled */
586 irq
= platform_get_irq(pdev
, 0);
589 * Not all supported platforms specify an interrupt for the
590 * watchdog, so let's make it optional.
592 ret
= devm_request_irq(&pdev
->dev
, irq
, orion_wdt_irq
, 0,
595 dev_err(&pdev
->dev
, "failed to request IRQ\n");
600 watchdog_set_nowayout(&dev
->wdt
, nowayout
);
601 ret
= watchdog_register_device(&dev
->wdt
);
605 pr_info("Initial timeout %d sec%s\n",
606 dev
->wdt
.timeout
, nowayout
? ", nowayout" : "");
610 clk_disable_unprepare(dev
->clk
);
615 static int orion_wdt_remove(struct platform_device
*pdev
)
617 struct watchdog_device
*wdt_dev
= platform_get_drvdata(pdev
);
618 struct orion_watchdog
*dev
= watchdog_get_drvdata(wdt_dev
);
620 watchdog_unregister_device(wdt_dev
);
621 clk_disable_unprepare(dev
->clk
);
626 static void orion_wdt_shutdown(struct platform_device
*pdev
)
628 struct watchdog_device
*wdt_dev
= platform_get_drvdata(pdev
);
629 orion_wdt_stop(wdt_dev
);
632 static struct platform_driver orion_wdt_driver
= {
633 .probe
= orion_wdt_probe
,
634 .remove
= orion_wdt_remove
,
635 .shutdown
= orion_wdt_shutdown
,
638 .of_match_table
= orion_wdt_of_match_table
,
642 module_platform_driver(orion_wdt_driver
);
644 MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
645 MODULE_DESCRIPTION("Orion Processor Watchdog");
647 module_param(heartbeat
, int, 0);
648 MODULE_PARM_DESC(heartbeat
, "Initial watchdog heartbeat in seconds");
650 module_param(nowayout
, bool, 0);
651 MODULE_PARM_DESC(nowayout
, "Watchdog cannot be stopped once started (default="
652 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
654 MODULE_LICENSE("GPL");
655 MODULE_ALIAS("platform:orion_wdt");