ramips: disable sdhc for HC5661A
[oweals/openwrt.git] / target / linux / cns3xxx / patches-4.14 / 020-watchdog_support.patch
1 Add a watchdog driver for ARM MPcore processors.
2
3 Signed-off-by: Felix Fietkau <nbd@nbd.name>
4 --- a/drivers/watchdog/Kconfig
5 +++ b/drivers/watchdog/Kconfig
6 @@ -355,6 +355,13 @@ config KS8695_WATCHDOG
7           Watchdog timer embedded into KS8695 processor. This will reboot your
8           system when the timeout is reached.
9  
10 +config MPCORE_WATCHDOG
11 +       tristate "MPcore watchdog"
12 +       depends on HAVE_ARM_TWD
13 +       select WATCHDOG_CORE
14 +       help
15 +         Watchdog timer embedded into the MPcore system
16 +
17  config HAVE_S3C2410_WATCHDOG
18         bool
19         help
20 --- a/drivers/watchdog/Makefile
21 +++ b/drivers/watchdog/Makefile
22 @@ -49,6 +49,7 @@ obj-$(CONFIG_977_WATCHDOG) += wdt977.o
23  obj-$(CONFIG_GEMINI_WATCHDOG) += gemini_wdt.o
24  obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
25  obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
26 +obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
27  obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
28  obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
29  obj-$(CONFIG_SAMA5D4_WATCHDOG) += sama5d4_wdt.o
30 --- /dev/null
31 +++ b/drivers/watchdog/mpcore_wdt.c
32 @@ -0,0 +1,118 @@
33 +/*
34 + * Watchdog driver for ARM MPcore
35 + *
36 + * Copyright (C) 2017 Felix Fietkau <nbd@nbd.name>
37 + */
38 +
39 +#include <linux/export.h>
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 = (twd_timer_get_rate() / 256) * wdt_timeout;
56 +
57 +       /* Reload register needs a different value on each refresh */
58 +       count += perturb;
59 +       perturb = !perturb;
60 +
61 +       iowrite32(count, wdt_base + TWD_WDOG_LOAD);
62 +
63 +       return 0;
64 +}
65 +
66 +static int mpcore_wdt_start(struct watchdog_device *wdd)
67 +{
68 +       mpcore_wdt_keepalive(wdd);
69 +
70 +       /* prescale = 256, mode = 1, enable = 1 */
71 +       iowrite32(0x0000FF09, wdt_base + TWD_WDOG_CONTROL);
72 +
73 +       return 0;
74 +}
75 +
76 +static int mpcore_wdt_stop(struct watchdog_device *wdd)
77 +{
78 +       iowrite32(0x12345678, wdt_base + TWD_WDOG_DISABLE);
79 +       iowrite32(0x87654321, wdt_base + TWD_WDOG_DISABLE);
80 +       iowrite32(0x0, wdt_base + TWD_WDOG_CONTROL);
81 +
82 +       return 0;
83 +}
84 +
85 +static int mpcore_wdt_set_timeout(struct watchdog_device *wdd,
86 +                                unsigned int timeout)
87 +{
88 +       mpcore_wdt_stop(wdd);
89 +       wdt_timeout = timeout;
90 +       mpcore_wdt_start(wdd);
91 +
92 +       return 0;
93 +}
94 +
95 +static const struct watchdog_info mpcore_wdt_info = {
96 +       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
97 +       .identity = "MPcore Watchdog",
98 +};
99 +
100 +static const struct watchdog_ops mpcore_wdt_ops = {
101 +       .owner = THIS_MODULE,
102 +       .start = mpcore_wdt_start,
103 +       .stop  = mpcore_wdt_stop,
104 +       .ping  = mpcore_wdt_keepalive,
105 +       .set_timeout = mpcore_wdt_set_timeout,
106 +};
107 +
108 +static struct watchdog_device mpcore_wdt = {
109 +       .info = &mpcore_wdt_info,
110 +       .ops = &mpcore_wdt_ops,
111 +       .min_timeout = 1,
112 +       .max_timeout = 65535,
113 +};
114 +
115 +static int mpcore_wdt_probe(struct platform_device *pdev)
116 +{
117 +       struct resource *res;
118 +       unsigned long rate = twd_timer_get_rate();
119 +
120 +       pr_info("MPCore WD init. clockrate: %lu prescaler: %u countrate: %lu timeout: %us\n", rate, 256, rate / 256, wdt_timeout);
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");
151 --- a/arch/arm/include/asm/smp_twd.h
152 +++ b/arch/arm/include/asm/smp_twd.h
153 @@ -34,5 +34,6 @@ struct twd_local_timer name __initdata =
154  };
155  
156  int twd_local_timer_register(struct twd_local_timer *);
157 +unsigned long twd_timer_get_rate(void);
158  
159  #endif
160 --- a/arch/arm/kernel/smp_twd.c
161 +++ b/arch/arm/kernel/smp_twd.c
162 @@ -15,6 +15,7 @@
163  #include <linux/delay.h>
164  #include <linux/device.h>
165  #include <linux/err.h>
166 +#include <linux/export.h>
167  #include <linux/smp.h>
168  #include <linux/jiffies.h>
169  #include <linux/clockchips.h>
170 @@ -380,6 +381,14 @@ int __init twd_local_timer_register(stru
171         return twd_local_timer_common_register(NULL);
172  }
173  
174 +/* Needed by mpcore_wdt */
175 +unsigned long twd_timer_get_rate(void)
176 +{
177 +       return twd_timer_rate;
178 +}
179 +EXPORT_SYMBOL_GPL(twd_timer_get_rate);
180 +
181 +
182  #ifdef CONFIG_OF
183  static int __init twd_local_timer_of_register(struct device_node *np)
184  {