1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Watchdog timer for PowerPC Book-E systems |
4 | * |
5 | * Author: Matthew McClintock |
6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * |
8 | * Copyright 2005, 2008, 2010-2011 Freescale Semiconductor Inc. |
9 | */ |
10 | |
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
12 | |
13 | #include <linux/module.h> |
14 | #include <linux/smp.h> |
15 | #include <linux/watchdog.h> |
16 | |
17 | #include <asm/reg_booke.h> |
18 | #include <asm/time.h> |
19 | #include <asm/div64.h> |
20 | |
21 | /* If the kernel parameter wdt=1, the watchdog will be enabled at boot. |
22 | * Also, the wdt_period sets the watchdog timer period timeout. |
23 | * For E500 cpus the wdt_period sets which bit changing from 0->1 will |
24 | * trigger a watchdog timeout. This watchdog timeout will occur 3 times, the |
25 | * first time nothing will happen, the second time a watchdog exception will |
26 | * occur, and the final time the board will reset. |
27 | */ |
28 | |
29 | |
30 | #ifdef CONFIG_PPC_E500 |
31 | #define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) |
32 | #define WDTP_MASK (WDTP(0x3f)) |
33 | #else |
34 | #define WDTP(x) (TCR_WP(x)) |
35 | #define WDTP_MASK (TCR_WP_MASK) |
36 | #endif |
37 | |
38 | static bool booke_wdt_enabled; |
39 | module_param(booke_wdt_enabled, bool, 0); |
40 | static int booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; |
41 | module_param(booke_wdt_period, int, 0); |
42 | static bool nowayout = WATCHDOG_NOWAYOUT; |
43 | module_param(nowayout, bool, 0); |
44 | MODULE_PARM_DESC(nowayout, |
45 | "Watchdog cannot be stopped once started (default=" |
46 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")" ); |
47 | |
48 | #ifdef CONFIG_PPC_E500 |
49 | |
50 | /* For the specified period, determine the number of seconds |
51 | * corresponding to the reset time. There will be a watchdog |
52 | * exception at approximately 3/5 of this time. |
53 | * |
54 | * The formula to calculate this is given by: |
55 | * 2.5 * (2^(63-period+1)) / timebase_freq |
56 | * |
57 | * In order to simplify things, we assume that period is |
58 | * at least 1. This will still result in a very long timeout. |
59 | */ |
60 | static unsigned long long period_to_sec(unsigned int period) |
61 | { |
62 | unsigned long long tmp = 1ULL << (64 - period); |
63 | unsigned long tmp2 = ppc_tb_freq; |
64 | |
65 | /* tmp may be a very large number and we don't want to overflow, |
66 | * so divide the timebase freq instead of multiplying tmp |
67 | */ |
68 | tmp2 = tmp2 / 5 * 2; |
69 | |
70 | do_div(tmp, tmp2); |
71 | return tmp; |
72 | } |
73 | |
74 | /* |
75 | * This procedure will find the highest period which will give a timeout |
76 | * greater than the one required. e.g. for a bus speed of 66666666 and |
77 | * a parameter of 2 secs, then this procedure will return a value of 38. |
78 | */ |
79 | static unsigned int sec_to_period(unsigned int secs) |
80 | { |
81 | unsigned int period; |
82 | for (period = 63; period > 0; period--) { |
83 | if (period_to_sec(period) >= secs) |
84 | return period; |
85 | } |
86 | return 0; |
87 | } |
88 | |
89 | #define MAX_WDT_TIMEOUT period_to_sec(1) |
90 | |
91 | #else /* CONFIG_PPC_E500 */ |
92 | |
93 | static unsigned long long period_to_sec(unsigned int period) |
94 | { |
95 | return period; |
96 | } |
97 | |
98 | static unsigned int sec_to_period(unsigned int secs) |
99 | { |
100 | return secs; |
101 | } |
102 | |
103 | #define MAX_WDT_TIMEOUT 3 /* from Kconfig */ |
104 | |
105 | #endif /* !CONFIG_PPC_E500 */ |
106 | |
107 | static void __booke_wdt_set(void *data) |
108 | { |
109 | u32 val; |
110 | struct watchdog_device *wdog = data; |
111 | |
112 | val = mfspr(SPRN_TCR); |
113 | val &= ~WDTP_MASK; |
114 | val |= WDTP(sec_to_period(wdog->timeout)); |
115 | |
116 | mtspr(SPRN_TCR, val); |
117 | } |
118 | |
119 | static void booke_wdt_set(void *data) |
120 | { |
121 | on_each_cpu(func: __booke_wdt_set, info: data, wait: 0); |
122 | } |
123 | |
124 | static void __booke_wdt_ping(void *data) |
125 | { |
126 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); |
127 | } |
128 | |
129 | static int booke_wdt_ping(struct watchdog_device *wdog) |
130 | { |
131 | on_each_cpu(func: __booke_wdt_ping, NULL, wait: 0); |
132 | |
133 | return 0; |
134 | } |
135 | |
136 | static void __booke_wdt_enable(void *data) |
137 | { |
138 | u32 val; |
139 | struct watchdog_device *wdog = data; |
140 | |
141 | /* clear status before enabling watchdog */ |
142 | __booke_wdt_ping(NULL); |
143 | val = mfspr(SPRN_TCR); |
144 | val &= ~WDTP_MASK; |
145 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(sec_to_period(wdog->timeout))); |
146 | |
147 | mtspr(SPRN_TCR, val); |
148 | } |
149 | |
150 | /** |
151 | * __booke_wdt_disable - disable the watchdog on the given CPU |
152 | * |
153 | * This function is called on each CPU. It disables the watchdog on that CPU. |
154 | * |
155 | * TCR[WRC] cannot be changed once it has been set to non-zero, but we can |
156 | * effectively disable the watchdog by setting its period to the maximum value. |
157 | */ |
158 | static void __booke_wdt_disable(void *data) |
159 | { |
160 | u32 val; |
161 | |
162 | val = mfspr(SPRN_TCR); |
163 | val &= ~(TCR_WIE | WDTP_MASK); |
164 | mtspr(SPRN_TCR, val); |
165 | |
166 | /* clear status to make sure nothing is pending */ |
167 | __booke_wdt_ping(NULL); |
168 | |
169 | } |
170 | |
171 | static int booke_wdt_start(struct watchdog_device *wdog) |
172 | { |
173 | on_each_cpu(func: __booke_wdt_enable, info: wdog, wait: 0); |
174 | pr_debug("watchdog enabled (timeout = %u sec)\n" , wdog->timeout); |
175 | |
176 | return 0; |
177 | } |
178 | |
179 | static int booke_wdt_stop(struct watchdog_device *wdog) |
180 | { |
181 | on_each_cpu(func: __booke_wdt_disable, NULL, wait: 0); |
182 | pr_debug("watchdog disabled\n" ); |
183 | |
184 | return 0; |
185 | } |
186 | |
187 | static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, |
188 | unsigned int timeout) |
189 | { |
190 | wdt_dev->timeout = timeout; |
191 | booke_wdt_set(data: wdt_dev); |
192 | |
193 | return 0; |
194 | } |
195 | |
196 | static struct watchdog_info booke_wdt_info __ro_after_init = { |
197 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
198 | .identity = "PowerPC Book-E Watchdog" , |
199 | }; |
200 | |
201 | static const struct watchdog_ops booke_wdt_ops = { |
202 | .owner = THIS_MODULE, |
203 | .start = booke_wdt_start, |
204 | .stop = booke_wdt_stop, |
205 | .ping = booke_wdt_ping, |
206 | .set_timeout = booke_wdt_set_timeout, |
207 | }; |
208 | |
209 | static struct watchdog_device booke_wdt_dev = { |
210 | .info = &booke_wdt_info, |
211 | .ops = &booke_wdt_ops, |
212 | .min_timeout = 1, |
213 | }; |
214 | |
215 | static void __exit booke_wdt_exit(void) |
216 | { |
217 | watchdog_unregister_device(&booke_wdt_dev); |
218 | } |
219 | |
220 | static int __init booke_wdt_init(void) |
221 | { |
222 | int ret = 0; |
223 | |
224 | pr_info("powerpc book-e watchdog driver loaded\n" ); |
225 | booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value; |
226 | booke_wdt_set_timeout(wdt_dev: &booke_wdt_dev, |
227 | timeout: period_to_sec(period: booke_wdt_period)); |
228 | watchdog_set_nowayout(wdd: &booke_wdt_dev, nowayout); |
229 | booke_wdt_dev.max_timeout = MAX_WDT_TIMEOUT; |
230 | if (booke_wdt_enabled) |
231 | booke_wdt_start(wdog: &booke_wdt_dev); |
232 | |
233 | ret = watchdog_register_device(&booke_wdt_dev); |
234 | |
235 | return ret; |
236 | } |
237 | |
238 | module_init(booke_wdt_init); |
239 | module_exit(booke_wdt_exit); |
240 | |
241 | MODULE_ALIAS("booke_wdt" ); |
242 | MODULE_DESCRIPTION("PowerPC Book-E watchdog driver" ); |
243 | MODULE_LICENSE("GPL" ); |
244 | |