cns3xxx: add back watchdog support
[openwrt/staging/yousong.git] / target / linux / cns3xxx / patches-4.9 / 020-watchdog_support.patch
1 Add a watchdog driver for ARM MPcore processors.
2
3 Signed-off-by: Felix Fietkau <nbd@nbd.name>
4 ---
5 --- a/drivers/watchdog/Kconfig
6 +++ b/drivers/watchdog/Kconfig
7 @@ -324,6 +324,13 @@ config KS8695_WATCHDOG
8 Watchdog timer embedded into KS8695 processor. This will reboot your
9 system when the timeout is reached.
10
11 +config MPCORE_WATCHDOG
12 + tristate "MPcore watchdog"
13 + depends on HAVE_ARM_TWD
14 + select WATCHDOG_CORE
15 + help
16 + Watchdog timer embedded into the MPcore system
17 +
18 config HAVE_S3C2410_WATCHDOG
19 bool
20 help
21 --- a/drivers/watchdog/Makefile
22 +++ b/drivers/watchdog/Makefile
23 @@ -47,6 +47,7 @@ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
24 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
25 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
26 obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
27 +obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
28 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
29 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
30 obj-$(CONFIG_SAMA5D4_WATCHDOG) += sama5d4_wdt.o
31 --- /dev/null
32 +++ b/drivers/watchdog/mpcore_wdt.c
33 @@ -0,0 +1,117 @@
34 +/*
35 + * Watchdog driver for ARM MPcore
36 + *
37 + * Copyright (C) 2017 Felix Fietkau <nbd@nbd.name>
38 + */
39 +
40 +#include <linux/module.h>
41 +#include <linux/kernel.h>
42 +#include <linux/watchdog.h>
43 +#include <linux/platform_device.h>
44 +#include <linux/io.h>
45 +#include <asm/smp_twd.h>
46 +
47 +static void __iomem *wdt_base;
48 +static int wdt_timeout = 60;
49 +
50 +static int mpcore_wdt_keepalive(struct watchdog_device *wdd)
51 +{
52 + static int perturb;
53 + u32 count;
54 +
55 + count = ioread32(wdt_base + TWD_WDOG_COUNTER);
56 + count = (~0U - count) * HZ / 5;
57 + count /= 256; /* prescale */
58 + count *= wdt_timeout;
59 +
60 + /* Reload register needs a different value on each refresh */
61 + count += perturb;
62 + perturb = !perturb;
63 +
64 + iowrite32(count, wdt_base + TWD_WDOG_LOAD);
65 +
66 + return 0;
67 +}
68 +
69 +static int mpcore_wdt_start(struct watchdog_device *wdd)
70 +{
71 + mpcore_wdt_keepalive(wdd);
72 +
73 + /* prescale = 256, mode = 1, enable = 1 */
74 + iowrite32(0x0000FF09, wdt_base + TWD_WDOG_CONTROL);
75 +
76 + return 0;
77 +}
78 +
79 +static int mpcore_wdt_stop(struct watchdog_device *wdd)
80 +{
81 + iowrite32(0x12345678, wdt_base + TWD_WDOG_DISABLE);
82 + iowrite32(0x87654321, wdt_base + TWD_WDOG_DISABLE);
83 + iowrite32(0x0, wdt_base + TWD_WDOG_CONTROL);
84 +
85 + return 0;
86 +}
87 +
88 +static int mpcore_wdt_set_timeout(struct watchdog_device *wdd,
89 + unsigned int timeout)
90 +{
91 + mpcore_wdt_stop(wdd);
92 + wdt_timeout = timeout;
93 + mpcore_wdt_start(wdd);
94 +
95 + return 0;
96 +}
97 +
98 +static const struct watchdog_info mpcore_wdt_info = {
99 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
100 + .identity = "MPcore Watchdog",
101 +};
102 +
103 +static const struct watchdog_ops mpcore_wdt_ops = {
104 + .owner = THIS_MODULE,
105 + .start = mpcore_wdt_start,
106 + .stop = mpcore_wdt_stop,
107 + .ping = mpcore_wdt_keepalive,
108 + .set_timeout = mpcore_wdt_set_timeout,
109 +};
110 +
111 +static struct watchdog_device mpcore_wdt = {
112 + .info = &mpcore_wdt_info,
113 + .ops = &mpcore_wdt_ops,
114 + .min_timeout = 1,
115 + .max_timeout = 65535,
116 +};
117 +
118 +static int mpcore_wdt_probe(struct platform_device *pdev)
119 +{
120 + struct resource *res;
121 +
122 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
123 + if (!res)
124 + return -ENODEV;
125 +
126 + wdt_base = devm_ioremap_resource(&pdev->dev, res);
127 + if (IS_ERR(wdt_base))
128 + return PTR_ERR(wdt_base);
129 +
130 + watchdog_register_device(&mpcore_wdt);
131 + return 0;
132 +}
133 +
134 +static int mpcore_wdt_remove(struct platform_device *dev)
135 +{
136 + watchdog_unregister_device(&mpcore_wdt);
137 + return 0;
138 +}
139 +
140 +static struct platform_driver mpcore_wdt_driver = {
141 + .probe = mpcore_wdt_probe,
142 + .remove = mpcore_wdt_remove,
143 + .driver = {
144 + .name = "mpcore_wdt",
145 + },
146 +};
147 +
148 +module_platform_driver(mpcore_wdt_driver);
149 +MODULE_AUTHOR("Felix Fietkau <nbd@nbd.name>");
150 +MODULE_LICENSE("GPL");