watchdog: w83627hf: Auto-detect IO address and supported chips
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / watchdog / w83627hf_wdt.c
1 /*
2  *      w83627hf/thf WDT driver
3  *
4  *      (c) Copyright 2013 Guenter Roeck
5  *              converted to watchdog infrastructure
6  *
7  *      (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
8  *              added support for W83627THF.
9  *
10  *      (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
11  *
12  *      Based on advantechwdt.c which is based on wdt.c.
13  *      Original copyright messages:
14  *
15  *      (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
16  *
17  *      (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
18  *                                              All Rights Reserved.
19  *
20  *      This program is free software; you can redistribute it and/or
21  *      modify it under the terms of the GNU General Public License
22  *      as published by the Free Software Foundation; either version
23  *      2 of the License, or (at your option) any later version.
24  *
25  *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
26  *      warranty for any of this software. This material is provided
27  *      "AS-IS" and at no charge.
28  *
29  *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
30  */
31
32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/types.h>
37 #include <linux/watchdog.h>
38 #include <linux/ioport.h>
39 #include <linux/notifier.h>
40 #include <linux/reboot.h>
41 #include <linux/init.h>
42 #include <linux/io.h>
43
44 #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
45 #define WATCHDOG_TIMEOUT 60             /* 60 sec default timeout */
46
47 static int wdt_io;
48
49 enum chips { w83627hf, w83627s, w83637hf, w83627thf, w83687thf,
50              w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p, w83667hg_b,
51              nct6775, nct6776, nct6779 };
52
53 static int timeout;                     /* in seconds */
54 module_param(timeout, int, 0);
55 MODULE_PARM_DESC(timeout,
56                 "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
57                                 __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
58
59 static bool nowayout = WATCHDOG_NOWAYOUT;
60 module_param(nowayout, bool, 0);
61 MODULE_PARM_DESC(nowayout,
62                 "Watchdog cannot be stopped once started (default="
63                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
64
65 /*
66  *      Kernel methods.
67  */
68
69 #define WDT_EFER (wdt_io+0)   /* Extended Function Enable Registers */
70 #define WDT_EFIR (wdt_io+0)   /* Extended Function Index Register
71                                                         (same as EFER) */
72 #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
73
74 #define W83627HF_LD_WDT         0x08
75
76 #define W83627HF_ID             0x52
77 #define W83627S_ID              0x59
78 #define W83637HF_ID             0x70
79 #define W83627THF_ID            0x82
80 #define W83687THF_ID            0x85
81 #define W83627EHF_ID            0x88
82 #define W83627DHG_ID            0xa0
83 #define W83627UHG_ID            0xa2
84 #define W83667HG_ID             0xa5
85 #define W83627DHG_P_ID          0xb0
86 #define W83667HG_B_ID           0xb3
87 #define NCT6775_ID              0xb4
88 #define NCT6776_ID              0xc3
89 #define NCT6779_ID              0xc5
90
91 static void superio_outb(int reg, int val)
92 {
93         outb(reg, WDT_EFER);
94         outb(val, WDT_EFDR);
95 }
96
97 static inline int superio_inb(int reg)
98 {
99         outb(reg, WDT_EFER);
100         return inb(WDT_EFDR);
101 }
102
103 static int superio_enter(void)
104 {
105         if (!request_muxed_region(wdt_io, 2, WATCHDOG_NAME))
106                 return -EBUSY;
107
108         outb_p(0x87, WDT_EFER); /* Enter extended function mode */
109         outb_p(0x87, WDT_EFER); /* Again according to manual */
110
111         return 0;
112 }
113
114 static void superio_select(int ld)
115 {
116         superio_outb(0x07, ld);
117 }
118
119 static void superio_exit(void)
120 {
121         outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
122         release_region(wdt_io, 2);
123 }
124
125 static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
126 {
127         int ret;
128         unsigned char t;
129
130         ret = superio_enter();
131         if (ret)
132                 return ret;
133
134         superio_select(W83627HF_LD_WDT);
135
136         /* set CR30 bit 0 to activate GPIO2 */
137         t = superio_inb(0x30);
138         if (!(t & 0x01))
139                 superio_outb(0x30, t | 0x01);
140
141         switch (chip) {
142         case w83627hf:
143         case w83627s:
144                 t = superio_inb(0x2B) & ~0x10;
145                 superio_outb(0x2B, t); /* set GPIO24 to WDT0 */
146                 break;
147         case w83627thf:
148                 t = (superio_inb(0x2B) & ~0x08) | 0x04;
149                 superio_outb(0x2B, t); /* set GPIO3 to WDT0 */
150                 break;
151         case w83627dhg:
152         case w83627dhg_p:
153                 t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */
154                 superio_outb(0x2D, t); /* set GPIO5 to WDT0 */
155                 t = superio_inb(0xF5);
156                 t |= 0x02;      /* enable the WDTO# output low pulse
157                                  * to the KBRST# pin */
158                 superio_outb(0xF5, t);
159                 break;
160         case w83637hf:
161                 break;
162         case w83687thf:
163                 t = superio_inb(0x2C) & ~0x80; /* PIN47 -> WDT0# */
164                 superio_outb(0x2C, t);
165                 break;
166         case w83627ehf:
167         case w83627uhg:
168         case w83667hg:
169         case w83667hg_b:
170         case nct6775:
171         case nct6776:
172         case nct6779:
173                 /*
174                  * These chips have a fixed WDTO# output pin (W83627UHG),
175                  * or support more than one WDTO# output pin.
176                  * Don't touch its configuration, and hope the BIOS
177                  * does the right thing.
178                  */
179                 t = superio_inb(0xF5);
180                 t |= 0x02;      /* enable the WDTO# output low pulse
181                                  * to the KBRST# pin */
182                 superio_outb(0xF5, t);
183                 break;
184         default:
185                 break;
186         }
187
188         t = superio_inb(0xF6);
189         if (t != 0) {
190                 pr_info("Watchdog already running. Resetting timeout to %d sec\n",
191                         wdog->timeout);
192                 superio_outb(0xF6, wdog->timeout);
193         }
194
195         /* set second mode & disable keyboard turning off watchdog */
196         t = superio_inb(0xF5) & ~0x0C;
197         superio_outb(0xF5, t);
198
199         /* disable keyboard & mouse turning off watchdog */
200         t = superio_inb(0xF7) & ~0xC0;
201         superio_outb(0xF7, t);
202
203         superio_exit();
204
205         return 0;
206 }
207
208 static int wdt_set_time(unsigned int timeout)
209 {
210         int ret;
211
212         ret = superio_enter();
213         if (ret)
214                 return ret;
215
216         superio_select(W83627HF_LD_WDT);
217         superio_outb(0xF6, timeout);
218         superio_exit();
219
220         return 0;
221 }
222
223 static int wdt_start(struct watchdog_device *wdog)
224 {
225         return wdt_set_time(wdog->timeout);
226 }
227
228 static int wdt_stop(struct watchdog_device *wdog)
229 {
230         return wdt_set_time(0);
231 }
232
233 static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
234 {
235         wdog->timeout = timeout;
236
237         return 0;
238 }
239
240 static unsigned int wdt_get_time(struct watchdog_device *wdog)
241 {
242         unsigned int timeleft;
243         int ret;
244
245         ret = superio_enter();
246         if (ret)
247                 return 0;
248
249         superio_select(W83627HF_LD_WDT);
250         timeleft = superio_inb(0xF6);
251         superio_exit();
252
253         return timeleft;
254 }
255
256 /*
257  *      Notifier for system down
258  */
259 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
260         void *unused)
261 {
262         if (code == SYS_DOWN || code == SYS_HALT)
263                 wdt_set_time(0);        /* Turn the WDT off */
264
265         return NOTIFY_DONE;
266 }
267
268 /*
269  *      Kernel Interfaces
270  */
271
272 static struct watchdog_info wdt_info = {
273         .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
274         .identity = "W83627HF Watchdog",
275 };
276
277 static struct watchdog_ops wdt_ops = {
278         .owner = THIS_MODULE,
279         .start = wdt_start,
280         .stop = wdt_stop,
281         .set_timeout = wdt_set_timeout,
282         .get_timeleft = wdt_get_time,
283 };
284
285 static struct watchdog_device wdt_dev = {
286         .info = &wdt_info,
287         .ops = &wdt_ops,
288         .timeout = WATCHDOG_TIMEOUT,
289         .min_timeout = 1,
290         .max_timeout = 255,
291 };
292
293 /*
294  *      The WDT needs to learn about soft shutdowns in order to
295  *      turn the timebomb registers off.
296  */
297
298 static struct notifier_block wdt_notifier = {
299         .notifier_call = wdt_notify_sys,
300 };
301
302 static int wdt_find(int addr)
303 {
304         u8 val;
305         int ret;
306
307         ret = superio_enter();
308         if (ret)
309                 return ret;
310         superio_select(W83627HF_LD_WDT);
311         val = superio_inb(0x20);
312         switch (val) {
313         case W83627HF_ID:
314                 ret = w83627hf;
315                 break;
316         case W83627S_ID:
317                 ret = w83627s;
318                 break;
319         case W83637HF_ID:
320                 ret = w83637hf;
321                 break;
322         case W83627THF_ID:
323                 ret = w83627thf;
324                 break;
325         case W83687THF_ID:
326                 ret = w83687thf;
327                 break;
328         case W83627EHF_ID:
329                 ret = w83627ehf;
330                 break;
331         case W83627DHG_ID:
332                 ret = w83627dhg;
333                 break;
334         case W83627DHG_P_ID:
335                 ret = w83627dhg_p;
336                 break;
337         case W83627UHG_ID:
338                 ret = w83627uhg;
339                 break;
340         case W83667HG_ID:
341                 ret = w83667hg;
342                 break;
343         case W83667HG_B_ID:
344                 ret = w83667hg_b;
345                 break;
346         case NCT6775_ID:
347                 ret = nct6775;
348                 break;
349         case NCT6776_ID:
350                 ret = nct6776;
351                 break;
352         case NCT6779_ID:
353                 ret = nct6779;
354                 break;
355         case 0xff:
356                 ret = -ENODEV;
357                 break;
358         default:
359                 ret = -ENODEV;
360                 pr_err("Unsupported chip ID: 0x%02x\n", val);
361                 break;
362         }
363         superio_exit();
364         return ret;
365 }
366
367 static int __init wdt_init(void)
368 {
369         int ret;
370         int chip;
371         const char * const chip_name[] = {
372                 "W83627HF",
373                 "W83627S",
374                 "W83637HF",
375                 "W83627THF",
376                 "W83687THF",
377                 "W83627EHF",
378                 "W83627DHG",
379                 "W83627UHG",
380                 "W83667HG",
381                 "W83667DHG-P",
382                 "W83667HG-B",
383                 "NCT6775",
384                 "NCT6776",
385                 "NCT6779",
386         };
387
388         wdt_io = 0x2e;
389         chip = wdt_find(0x2e);
390         if (chip < 0) {
391                 wdt_io = 0x4e;
392                 chip = wdt_find(0x4e);
393                 if (chip < 0)
394                         return chip;
395         }
396
397         pr_info("WDT driver for %s Super I/O chip initialising\n",
398                 chip_name[chip]);
399
400         watchdog_init_timeout(&wdt_dev, timeout, NULL);
401         watchdog_set_nowayout(&wdt_dev, nowayout);
402
403         ret = w83627hf_init(&wdt_dev, chip);
404         if (ret) {
405                 pr_err("failed to initialize watchdog (err=%d)\n", ret);
406                 return ret;
407         }
408
409         ret = register_reboot_notifier(&wdt_notifier);
410         if (ret != 0) {
411                 pr_err("cannot register reboot notifier (err=%d)\n", ret);
412                 return ret;
413         }
414
415         ret = watchdog_register_device(&wdt_dev);
416         if (ret)
417                 goto unreg_reboot;
418
419         pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
420                 wdt_dev.timeout, nowayout);
421
422         return ret;
423
424 unreg_reboot:
425         unregister_reboot_notifier(&wdt_notifier);
426         return ret;
427 }
428
429 static void __exit wdt_exit(void)
430 {
431         watchdog_unregister_device(&wdt_dev);
432         unregister_reboot_notifier(&wdt_notifier);
433 }
434
435 module_init(wdt_init);
436 module_exit(wdt_exit);
437
438 MODULE_LICENSE("GPL");
439 MODULE_AUTHOR("Pádraig  Brady <P@draigBrady.com>");
440 MODULE_DESCRIPTION("w83627hf/thf WDT driver");