source: src/linux/universal/linux-4.9/drivers/watchdog/cns3xxx_wdt.c @ 31872

Last change on this file since 31872 was 31872, checked in by brainslayer, 2 months ago

change mpcore watchdog driver for laguna

File size: 2.6 KB
Line 
1/*
2 * Watchdog driver for ARM MPcore
3 *
4 * Copyright (C) 2017 Felix Fietkau <nbd@nbd.name>
5 */
6
7#include <linux/export.h>
8#include <linux/module.h>
9#include <linux/kernel.h>
10#include <linux/watchdog.h>
11#include <linux/platform_device.h>
12#include <linux/io.h>
13#include <asm/smp_twd.h>
14
15static void __iomem *wdt_base;
16static int wdt_timeout = 60;
17
18static int mpcore_wdt_keepalive(struct watchdog_device *wdd)
19{
20        static int perturb;
21        u32 count;
22
23        count = (twd_timer_get_rate() / 256) * wdt_timeout;
24
25        /* Reload register needs a different value on each refresh */
26        count += perturb;
27        perturb = !perturb;
28
29        iowrite32(count, wdt_base + TWD_WDOG_LOAD);
30
31        return 0;
32}
33
34static int mpcore_wdt_start(struct watchdog_device *wdd)
35{
36        mpcore_wdt_keepalive(wdd);
37
38        /* prescale = 256, mode = 1, enable = 1 */
39        iowrite32(0x0000FF09, wdt_base + TWD_WDOG_CONTROL);
40
41        return 0;
42}
43
44static int mpcore_wdt_stop(struct watchdog_device *wdd)
45{
46        iowrite32(0x12345678, wdt_base + TWD_WDOG_DISABLE);
47        iowrite32(0x87654321, wdt_base + TWD_WDOG_DISABLE);
48        iowrite32(0x0, wdt_base + TWD_WDOG_CONTROL);
49
50        return 0;
51}
52
53static int mpcore_wdt_set_timeout(struct watchdog_device *wdd,
54                                 unsigned int timeout)
55{
56        mpcore_wdt_stop(wdd);
57        wdt_timeout = timeout;
58        mpcore_wdt_start(wdd);
59
60        return 0;
61}
62
63static const struct watchdog_info mpcore_wdt_info = {
64        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
65        .identity = "MPcore Watchdog",
66};
67
68static const struct watchdog_ops mpcore_wdt_ops = {
69        .owner = THIS_MODULE,
70        .start = mpcore_wdt_start,
71        .stop  = mpcore_wdt_stop,
72        .ping  = mpcore_wdt_keepalive,
73        .set_timeout = mpcore_wdt_set_timeout,
74};
75
76static struct watchdog_device mpcore_wdt = {
77        .info = &mpcore_wdt_info,
78        .ops = &mpcore_wdt_ops,
79        .min_timeout = 1,
80        .max_timeout = 65535,
81};
82
83static int mpcore_wdt_probe(struct platform_device *pdev)
84{
85        struct resource *res;
86        unsigned long rate = twd_timer_get_rate();
87
88        pr_info("MPCore WD init. clockrate: %u prescaler: %u countrate: %u timeout: %us\n", rate, 256, rate / 256, wdt_timeout);
89
90        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
91        if (!res)
92                return -ENODEV;
93
94        wdt_base = devm_ioremap_resource(&pdev->dev, res);
95        if (IS_ERR(wdt_base))
96                return PTR_ERR(wdt_base);
97
98        watchdog_register_device(&mpcore_wdt);
99        return 0;
100}
101
102static int mpcore_wdt_remove(struct platform_device *dev)
103{
104        watchdog_unregister_device(&mpcore_wdt);
105        return 0;
106}
107
108static struct platform_driver mpcore_wdt_driver = {
109        .probe          = mpcore_wdt_probe,
110        .remove         = mpcore_wdt_remove,
111        .driver         = {
112                .name   = "mpcore_wdt",
113        },
114};
115
116module_platform_driver(mpcore_wdt_driver);
117MODULE_AUTHOR("Felix Fietkau <nbd@nbd.name>");
118MODULE_LICENSE("GPL");
Note: See TracBrowser for help on using the repository browser.