1/*-
2 * Copyright (c) 2011 Sandvine Incorporated ULC.
3 * Copyright (c) 2012 iXsystems, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27/*
28 * Support for Winbond watchdog.
29 *
30 * With minor abstractions it might be possible to add support for other
31 * different Winbond Super I/O chips as well.  Winbond seems to have four
32 * different types of chips, four different ways to get into extended config
33 * mode.
34 *
35 * Note: there is no serialization between the debugging sysctl handlers and
36 * the watchdog functions and possibly others poking the registers at the same
37 * time.  For that at least possibly interfering sysctls are hidden by default.
38 */
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD$");
42
43#include <sys/param.h>
44#include <sys/kernel.h>
45#include <sys/systm.h>
46#include <sys/bus.h>
47#include <sys/eventhandler.h>
48#include <sys/lock.h>
49#include <sys/module.h>
50#include <sys/rman.h>
51#include <sys/sbuf.h>
52#include <sys/sysctl.h>
53#include <sys/watchdog.h>
54
55#include <isa/isavar.h>
56
57#include <machine/bus.h>
58#include <machine/resource.h>
59
60/*
61 * Global registers.
62 */
63#define	WB_DEVICE_ID_REG	0x20	/* Device ID */
64#define	WB_DEVICE_REV_REG	0x21	/* Device revision */
65#define	WB_CR26			0x26	/* Bit6: HEFRAS (base port selector) */
66
67/* LDN selection. */
68#define	WB_LDN_REG		0x07
69#define	WB_LDN_REG_LDN8		0x08	/* GPIO 2, Watchdog */
70
71/*
72 * LDN8 (GPIO 2, Watchdog) specific registers and options.
73 */
74/* CR30: LDN8 activation control. */
75#define	WB_LDN8_CR30		0x30
76#define	WB_LDN8_CR30_ACTIVE	0x01	/* 1: LD active */
77
78/* CRF5: Watchdog scale, P20. Mapped to reg_1. */
79#define	WB_LDN8_CRF5		0xF5
80#define	WB_LDN8_CRF5_SCALE	0x08	/* 0: 1s, 1: 60s */
81#define	WB_LDN8_CRF5_KEYB_P20	0x04	/* 1: keyb P20 forces timeout */
82#define	WB_LDN8_CRF5_KBRST	0x02	/* 1: timeout causes pin60 kbd reset */
83
84/* CRF6: Watchdog Timeout (0 == off). Mapped to reg_timeout. */
85#define	WB_LDN8_CRF6		0xF6
86
87/* CRF7: Watchdog mouse, keyb, force, .. Mapped to reg_2. */
88#define	WB_LDN8_CRF7		0xF7
89#define	WB_LDN8_CRF7_MOUSE	0x80	/* 1: mouse irq resets wd timer */
90#define	WB_LDN8_CRF7_KEYB	0x40	/* 1: keyb irq resets wd timer */
91#define	WB_LDN8_CRF7_FORCE	0x20	/* 1: force timeout (self-clear) */
92#define	WB_LDN8_CRF7_TS		0x10	/* 0: counting, 1: fired */
93#define	WB_LDN8_CRF7_IRQS	0x0f	/* irq source for watchdog, 2 == SMI */
94#define	WB_LDN8_CRF7_CLEAR_MASK	\
95    (WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_KEYB|WB_LDN8_CRF7_TS|WB_LDN8_CRF7_IRQS)
96
97struct wb_softc {
98	device_t		dev;
99	struct resource		*portres;
100	bus_space_tag_t		bst;
101	bus_space_handle_t	bsh;
102	int			rid;
103	eventhandler_tag	ev_tag;
104	int			(*ext_cfg_enter_f)(struct wb_softc *, u_short);
105	void			(*ext_cfg_exit_f)(struct wb_softc *, u_short);
106	int			debug_verbose;
107
108	/*
109	 * Special feature to let the watchdog fire at a different
110	 * timeout as set by watchdog(4) but still use that API to
111	 * re-load it periodically.
112	 */
113	unsigned int		timeout_override;
114
115	/*
116	 * Space to save current state temporary and for sysctls.
117	 * We want to know the timeout value and usually need two
118	 * additional registers for options. Do not name them by
119	 * register as these might be different by chip.
120	 */
121	uint8_t			reg_timeout;
122	uint8_t			reg_1;
123	uint8_t			reg_2;
124};
125
126static int	ext_cfg_enter_0x87_0x87(struct wb_softc *, u_short);
127static void	ext_cfg_exit_0xaa(struct wb_softc *, u_short);
128
129struct winbond_superio_cfg {
130	uint8_t			efer;	/* and efir */
131	int			(*ext_cfg_enter_f)(struct wb_softc *, u_short);
132	void			(*ext_cfg_exit_f)(struct wb_softc *, u_short);
133} probe_addrs[] = {
134	{
135		.efer			= 0x2e,
136		.ext_cfg_enter_f	= ext_cfg_enter_0x87_0x87,
137		.ext_cfg_exit_f		= ext_cfg_exit_0xaa,
138	},
139	{
140		.efer			= 0x4e,
141		.ext_cfg_enter_f	= ext_cfg_enter_0x87_0x87,
142		.ext_cfg_exit_f		= ext_cfg_exit_0xaa,
143	},
144};
145
146struct winbond_vendor_device_id {
147	uint16_t		vendor_id;
148	uint8_t			device_id;
149	uint8_t			device_rev;
150	const char *		descr;
151} wb_devs[] = {
152	{
153		.vendor_id	= 0x5ca3,
154		.device_id	= 0x52,
155		.device_rev	= 0x17,
156		.descr		= "Winbond 83627HF/F/HG/G Rev. G",
157	},
158	{
159		.vendor_id	= 0x5ca3,
160		.device_id	= 0x52,
161		.device_rev	= 0x3a,
162		.descr		= "Winbond 83627HF/F/HG/G Rev. J",
163	},
164	{
165		.vendor_id	= 0x5ca3,
166		.device_id	= 0x52,
167		.device_rev	= 0x41,
168		.descr		= "Winbond 83627HF/F/HG/G Rev. UD-A",
169	},
170	{
171		.vendor_id	= 0x5ca3,
172		.device_id	= 0xa0,
173		.device_rev	= 0x25,
174		.descr		= "Winbond 83627DHG IC ver. 5",
175	},
176	{
177		.vendor_id	= 0x5ca3,
178		.device_id	= 0xb0,
179		.device_rev	= 0x73,
180		.descr		= "Winbond 83627DHG-P",
181	},
182	{
183		.vendor_id	= 0x5ca3,
184		.device_id	= 0xc3,
185		.device_rev	= 0x33,
186		.descr		= "Nuvoton WPCM450RA0BX",
187	},
188};
189
190static void
191write_efir_1(struct wb_softc *sc, u_short baseport, uint8_t value)
192{
193
194	MPASS(sc != NULL || baseport != 0);
195	if (sc != NULL)
196		bus_space_write_1((sc)->bst, (sc)->bsh, 0, (value));
197	else
198		outb(baseport, value);
199}
200
201static uint8_t __unused
202read_efir_1(struct wb_softc *sc, u_short baseport)
203{
204
205	MPASS(sc != NULL || baseport != 0);
206	if (sc != NULL)
207		return (bus_space_read_1((sc)->bst, (sc)->bsh, 0));
208	else
209		return (inb(baseport));
210}
211
212static void
213write_efdr_1(struct wb_softc *sc, u_short baseport, uint8_t value)
214{
215
216	MPASS(sc != NULL || baseport != 0);
217	if (sc != NULL)
218		bus_space_write_1((sc)->bst, (sc)->bsh, 1, (value));
219	else
220		outb(baseport + 1, value);
221}
222
223static uint8_t
224read_efdr_1(struct wb_softc *sc, u_short baseport)
225{
226
227	MPASS(sc != NULL || baseport != 0);
228	if (sc != NULL)
229		return (bus_space_read_1((sc)->bst, (sc)->bsh, 1));
230	else
231		return (inb(baseport + 1));
232}
233
234/*
235 * Return the watchdog related registers as we last read them.  This will
236 * usually not give the current timeout or state on whether the watchdog
237 * fired.
238 */
239static int
240sysctl_wb_debug(SYSCTL_HANDLER_ARGS)
241{
242	struct wb_softc *sc;
243	struct sbuf sb;
244	int error;
245
246	sc = arg1;
247
248	sbuf_new_for_sysctl(&sb, NULL, 64, req);
249
250	sbuf_printf(&sb, "LDN8 (GPIO2, Watchdog): ");
251	sbuf_printf(&sb, "CRF5 0x%02x ", sc->reg_1);
252	sbuf_printf(&sb, "CRF6 0x%02x ", sc->reg_timeout);
253	sbuf_printf(&sb, "CRF7 0x%02x", sc->reg_2);
254
255	error = sbuf_finish(&sb);
256	sbuf_delete(&sb);
257	return (error);
258}
259
260/*
261 * Read the current values before returning them.  Given this might poke
262 * the registers the same time as the watchdog, this sysctl handler should
263 * be marked CTLFLAG_SKIP to not show up by default.
264 */
265static int
266sysctl_wb_debug_current(SYSCTL_HANDLER_ARGS)
267{
268	struct wb_softc *sc;
269
270	sc = arg1;
271
272	/*
273	 * Enter extended function mode in case someone else has been
274	 * poking on the registers.  We will not leave it though.
275	 */
276	if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
277		return (ENXIO);
278
279	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
280	write_efir_1(sc, 0, WB_LDN_REG);
281	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
282
283	write_efir_1(sc, 0, WB_LDN8_CRF5);
284	sc->reg_1 = read_efdr_1(sc, 0);
285	write_efir_1(sc, 0, WB_LDN8_CRF6);
286	sc->reg_timeout = read_efdr_1(sc, 0);
287	write_efir_1(sc, 0, WB_LDN8_CRF7);
288	sc->reg_2 = read_efdr_1(sc, 0);
289
290	return (sysctl_wb_debug(oidp, arg1, arg2, req));
291}
292
293/*
294 * Sysctl handlers to force a watchdog timeout or to test the NMI functionality
295 * works as expetced.
296 * For testing we could set a test_nmi flag in the softc that, in case of NMI, a
297 * callback function from trap.c could check whether we fired and not report the
298 * timeout but clear the flag for the sysctl again.  This is interesting given a
299 * lot of boards have jumpers to change the action on watchdog timeout or
300 * disable the watchdog completely.
301 * XXX-BZ notyet: currently no general infrastructure exists to do this.
302 */
303static int
304sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS)
305{
306	struct wb_softc *sc;
307	int error, test, val;
308
309	sc = arg1;
310	test = arg2;
311
312#ifdef notyet
313	val = sc->test_nmi;
314#else
315	val = 0;
316#endif
317	error = sysctl_handle_int(oidp, &val, 0, req);
318        if (error || !req->newptr)
319                return (error);
320
321#ifdef notyet
322	/* Manually clear the test for a value of 0 and do nothing else. */
323	if (test && val == 0) {
324		sc->test_nmi = 0;
325		return (0);
326	}
327#endif
328
329	/*
330	 * Enter extended function mode in case someone else has been
331	 * poking on the registers.  We will not leave it though.
332	 */
333	if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
334		return (ENXIO);
335
336#ifdef notyet
337	/*
338	 * If we are testing the NMI functionality, set the flag before
339	 * forcing the timeout.
340	 */
341	if (test)
342		sc->test_nmi = 1;
343#endif
344
345	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
346	write_efir_1(sc, 0, WB_LDN_REG);
347	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
348
349	/* Force watchdog to fire. */
350	write_efir_1(sc, 0, WB_LDN8_CRF7);
351	sc->reg_2 = read_efdr_1(sc, 0);
352	sc->reg_2 |= WB_LDN8_CRF7_FORCE;
353
354	write_efir_1(sc, 0, WB_LDN8_CRF7);
355	write_efdr_1(sc, 0, sc->reg_2);
356
357	return (0);
358}
359
360/*
361 * Print current watchdog state.
362 *
363 * Note: it is the responsibility of the caller to update the registers
364 * upfront.
365 */
366static void
367wb_print_state(struct wb_softc *sc, const char *msg)
368{
369
370	device_printf(sc->dev, "%s%sWatchdog %sabled. %s"
371	    "Scaling by %ds, timer at %d (%s=%ds%s). "
372	    "CRF5 0x%02x CRF7 0x%02x\n",
373	    (msg != NULL) ? msg : "", (msg != NULL) ? ": " : "",
374	    (sc->reg_timeout > 0x00) ? "en" : "dis",
375	    (sc->reg_2 & WB_LDN8_CRF7_TS) ? "Watchdog fired. " : "",
376	    (sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1,
377	    sc->reg_timeout,
378	    (sc->reg_timeout > 0x00) ? "<" : "",
379	    sc->reg_timeout * ((sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1),
380	    (sc->reg_timeout > 0x00) ? " left" : "",
381	    sc->reg_1, sc->reg_2);
382}
383
384/*
385 * Functions to enter and exit extended function mode.  Possibly shared
386 * between different chips.
387 */
388static int
389ext_cfg_enter_0x87_0x87(struct wb_softc *sc, u_short baseport)
390{
391
392	/*
393	 * Enable extended function mode.
394	 * Winbond does not allow us to validate so always return success.
395	 */
396	write_efir_1(sc, baseport, 0x87);
397	write_efir_1(sc, baseport, 0x87);
398
399	return (0);
400}
401
402static void
403ext_cfg_exit_0xaa(struct wb_softc *sc, u_short baseport)
404{
405
406	write_efir_1(sc, baseport, 0xaa);
407}
408
409/*
410 * (Re)load the watchdog counter depending on timeout.  A timeout of 0 will
411 * disable the watchdog.
412 */
413static int
414wb_set_watchdog(struct wb_softc *sc, unsigned int timeout)
415{
416
417	if (sc->debug_verbose)
418		wb_print_state(sc, "Before watchdog counter (re)load");
419
420	/*
421	 * Enter extended function mode in case someone else has been
422	 * poking on the registers.  We will not leave it though.
423	 */
424	if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
425		return (ENXIO);
426
427	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */
428	write_efir_1(sc, 0, WB_LDN_REG);
429	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
430
431	/* Disable and validate or arm/reset watchdog. */
432	if (timeout == 0) {
433		/* Disable watchdog. */
434		write_efir_1(sc, 0, WB_LDN8_CRF6);
435		write_efdr_1(sc, 0, 0x00);
436
437		/* Re-check. */
438		write_efir_1(sc, 0, WB_LDN8_CRF6);
439		sc->reg_timeout = read_efdr_1(sc, 0);
440
441		if (sc->reg_timeout != 0x00) {
442			device_printf(sc->dev, "Failed to disable watchdog: "
443			    "0x%02x.\n", sc->reg_timeout);
444			return (EIO);
445		}
446
447	} else {
448		/*
449		 * In case an override is set, let it override.  It may lead
450		 * to strange results as we do not check the input of the sysctl.
451		 */
452		if (sc->timeout_override > 0)
453			timeout = sc->timeout_override;
454
455		/* Make sure we support the requested timeout. */
456		if (timeout > 255 * 60)
457			return (EINVAL);
458
459		/* Read current scaling factor. */
460		write_efir_1(sc, 0, WB_LDN8_CRF5);
461		sc->reg_1 = read_efdr_1(sc, 0);
462
463		if (timeout > 255) {
464			/* Set scaling factor to 60s. */
465			sc->reg_1 |= WB_LDN8_CRF5_SCALE;
466			sc->reg_timeout = (timeout / 60);
467			if (timeout % 60)
468				sc->reg_timeout++;
469		} else {
470			/* Set scaling factor to 1s. */
471			sc->reg_1 &= ~WB_LDN8_CRF5_SCALE;
472			sc->reg_timeout = timeout;
473		}
474
475		/* In case we fired before we need to clear to fire again. */
476		write_efir_1(sc, 0, WB_LDN8_CRF7);
477		sc->reg_2 = read_efdr_1(sc, 0);
478		if (sc->reg_2 & WB_LDN8_CRF7_TS) {
479			sc->reg_2 &= ~WB_LDN8_CRF7_TS;
480			write_efir_1(sc, 0, WB_LDN8_CRF7);
481			write_efdr_1(sc, 0, sc->reg_2);
482		}
483
484		/* Write back scaling factor. */
485		write_efir_1(sc, 0, WB_LDN8_CRF5);
486		write_efdr_1(sc, 0, sc->reg_1);
487
488		/* Set timer and arm/reset the watchdog. */
489		write_efir_1(sc, 0, WB_LDN8_CRF6);
490		write_efdr_1(sc, 0, sc->reg_timeout);
491	}
492
493	if (sc->debug_verbose)
494		wb_print_state(sc, "After watchdog counter (re)load");
495
496	return (0);
497}
498
499/*
500 * watchdog(9) EVENTHANDLER function implementation to (re)load the counter
501 * with the given timeout or disable the watchdog.
502 */
503static void
504wb_watchdog_fn(void *private, u_int cmd, int *error)
505{
506	struct wb_softc *sc;
507	unsigned int timeout;
508	int e;
509
510	sc = private;
511	KASSERT(sc != NULL, ("%s: watchdog handler function called without "
512	    "softc.", __func__));
513
514	cmd &= WD_INTERVAL;
515	if (cmd > 0 && cmd <= 63) {
516		/* Reset (and arm) watchdog. */
517		timeout = ((uint64_t)1 << cmd) / 1000000000;
518		if (timeout == 0)
519			timeout = 1;
520		e = wb_set_watchdog(sc, timeout);
521		if (e == 0) {
522			if (error != NULL)
523				*error = 0;
524		} else {
525			/* On error, try to make sure the WD is disabled. */
526			wb_set_watchdog(sc, 0);
527		}
528
529	} else {
530		/* Disable watchdog. */
531		e = wb_set_watchdog(sc, 0);
532		if (e != 0 && cmd == 0 && error != NULL) {
533			/* Failed to disable watchdog. */
534			*error = EOPNOTSUPP;
535		}
536	}
537}
538
539/*
540 * Probe/attach the Winbond Super I/O chip.
541 *
542 * Initial abstraction to possibly support more chips:
543 * - Iterate over the well known base ports, try to enable extended function
544 *   mode and read and match the device ID and device revision.  Unfortunately
545 *   the Vendor ID is in the hardware monitoring section accessible by different
546 *   base ports only.
547 * - Also HEFRAS, which would tell use the base port, is only accessible after
548 *   entering extended function mode, for which the base port is needed.
549 *   At least check HEFRAS to match the current base port we are probing.
550 * - On match set the description, remember functions to enter/exit extended
551 *   function mode as well as the base port.
552 */
553static int
554wb_probe_enable(device_t dev, int probe)
555{
556	struct wb_softc *sc;
557	int error, found, i, j;
558	uint8_t dev_id, dev_rev, cr26;
559
560	if (dev == NULL)
561		sc = NULL;
562	else {
563		sc = device_get_softc(dev);
564		bzero(sc, sizeof(*sc));
565		sc->dev = dev;
566	}
567
568	error = ENXIO;
569	for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) {
570
571		if (sc != NULL) {
572			/* Allocate bus resources for IO index/data register access. */
573			sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
574			    probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE);
575			if (sc->portres == NULL)
576				continue;
577			sc->bst = rman_get_bustag(sc->portres);
578			sc->bsh = rman_get_bushandle(sc->portres);
579		}
580
581		found = 0;
582		error = (*probe_addrs[i].ext_cfg_enter_f)(sc, probe_addrs[i].efer);
583		if (error != 0)
584			goto cleanup;
585
586		/* Identify the SuperIO chip. */
587		write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_ID_REG);
588		dev_id = read_efdr_1(sc, probe_addrs[i].efer);
589		write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_REV_REG);
590		dev_rev = read_efdr_1(sc, probe_addrs[i].efer);
591		write_efir_1(sc, probe_addrs[i].efer, WB_CR26);
592		cr26 = read_efdr_1(sc, probe_addrs[i].efer);
593
594		/* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */
595		if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) ||
596		    ((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) {
597			if (dev != NULL)
598				device_printf(dev, "HEFRAS and EFER do not "
599				    "align: EFER 0x%02x DevID 0x%02x DevRev "
600				    "0x%02x CR26 0x%02x\n",
601				    probe_addrs[i].efer, dev_id, dev_rev, cr26);
602			goto cleanup;
603		}
604
605		if (dev_id == 0xff && dev_rev == 0xff)
606			goto cleanup;
607
608		for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) {
609			if (wb_devs[j].device_id == dev_id &&
610			    wb_devs[j].device_rev == dev_rev) {
611				if (probe && dev != NULL)
612					device_set_desc(dev, wb_devs[j].descr);
613				found++;
614				break;
615			}
616		}
617
618		if (!found) {
619			if (probe && dev != NULL) {
620				device_set_desc(dev, "Unknown Winbond/Nuvoton model");
621				device_printf(dev, "DevID 0x%02x DevRev 0x%02x, "
622				    "please report this.\n", dev_id, dev_rev);
623			}
624			found++;
625		}
626
627		if (probe && found && bootverbose && dev != NULL)
628			device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x"
629			     " CR26 0x%02x (probing)\n", device_get_desc(dev),
630			     probe_addrs[i].efer, dev_id, dev_rev, cr26);
631cleanup:
632		if (probe || !found) {
633			(*probe_addrs[i].ext_cfg_exit_f)(sc, probe_addrs[i].efer);
634
635			if (sc != NULL)
636				(void) bus_release_resource(dev, SYS_RES_IOPORT,
637				    sc->rid, sc->portres);
638		}
639
640		/*
641		 * Stop probing if have successfully identified the SuperIO.
642		 * Remember the extended function mode enter/exit functions
643		 * for operations.
644		 */
645		if (found) {
646			if (sc != NULL) {
647				sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f;
648				sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f;
649			}
650			error = BUS_PROBE_DEFAULT;
651			break;
652		} else
653			error = ENXIO;
654	}
655
656	return (error);
657}
658
659static void
660wb_identify(driver_t *driver, device_t parent)
661{
662	device_t dev;
663
664	if ((dev = device_find_child(parent, driver->name, 0)) == NULL) {
665		if (wb_probe_enable(dev, 1) != BUS_PROBE_DEFAULT) {
666			if (bootverbose)
667				device_printf(dev, "can not find compatible Winbond chip.\n");
668		} else
669			dev = BUS_ADD_CHILD(parent, 0, driver->name, 0);
670		return;
671	}
672}
673
674static int
675wb_probe(device_t dev)
676{
677
678	/* Make sure we do not claim some ISA PNP device. */
679	if (isa_get_logicalid(dev) != 0)
680		return (ENXIO);
681
682	return (wb_probe_enable(dev, 1));
683}
684
685static int
686wb_attach(device_t dev)
687{
688	struct wb_softc *sc;
689	struct sysctl_ctx_list *sctx;
690	struct sysctl_oid *soid;
691	unsigned long timeout;
692	int error;
693
694	error = wb_probe_enable(dev, 0);
695	if (error > 0)
696		return (ENXIO);
697
698	sc = device_get_softc(dev);
699	KASSERT(sc->ext_cfg_enter_f != NULL && sc->ext_cfg_exit_f != NULL,
700	    ("%s: successfull probe result but not setup correctly", __func__));
701
702	/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
703	write_efir_1(sc, 0, WB_LDN_REG);
704	write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
705
706	/* Make sure LDN8 is enabled (Do we need to? Also affects GPIO). */
707	write_efir_1(sc, 0, WB_LDN8_CR30);
708	write_efdr_1(sc, 0, WB_LDN8_CR30_ACTIVE);
709
710	/* Read the current watchdog configuration. */
711	write_efir_1(sc, 0, WB_LDN8_CRF5);
712	sc->reg_1 = read_efdr_1(sc, 0);
713	write_efir_1(sc, 0, WB_LDN8_CRF6);
714	sc->reg_timeout = read_efdr_1(sc, 0);
715	write_efir_1(sc, 0, WB_LDN8_CRF7);
716	sc->reg_2 = read_efdr_1(sc, 0);
717
718	/* Print current state if bootverbose or watchdog already enabled. */
719	if (bootverbose || (sc->reg_timeout > 0x00))
720		wb_print_state(sc, "Before watchdog attach");
721
722	/*
723	 * Clear a previous watchdog timeout event (if (still) set).
724	 * Disable all all interrupt reset sources (defaults).
725	 */
726	sc->reg_1 &= ~(WB_LDN8_CRF5_KEYB_P20);
727	sc->reg_1 |= WB_LDN8_CRF5_KBRST;
728	write_efir_1(sc, 0, WB_LDN8_CRF5);
729	write_efdr_1(sc, 0, sc->reg_1);
730
731	sc->reg_2 &= ~WB_LDN8_CRF7_CLEAR_MASK;
732	write_efir_1(sc, 0, WB_LDN8_CRF7);
733	write_efdr_1(sc, 0, sc->reg_2);
734
735	/* Read global timeout override tunable, Add per device sysctls. */
736	if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) {
737		if (timeout > 0)
738			sc->timeout_override = timeout;
739	}
740	sctx = device_get_sysctl_ctx(dev);
741	soid = device_get_sysctl_tree(dev);
742        SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
743	    "timeout_override", CTLFLAG_RW, &sc->timeout_override, 0,
744            "Timeout in seconds overriding default watchdog timeout");
745        SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
746	    "debug_verbose", CTLFLAG_RW, &sc->debug_verbose, 0,
747            "Enables extra debugging information");
748        SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug",
749	    CTLTYPE_STRING|CTLFLAG_RD, sc, 0, sysctl_wb_debug, "A",
750            "Selected register information from last change by driver");
751        SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug_current",
752	    CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_SKIP, sc, 0,
753	     sysctl_wb_debug_current, "A",
754	     "Selected register information (may interfere)");
755	SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "force_timeout",
756	    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_SKIP, sc, 0,
757	    sysctl_wb_force_test_nmi, "I", "Enable to force watchdog to fire.");
758
759	/* Register watchdog. */
760	sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, wb_watchdog_fn, sc,
761	    0);
762
763	if (bootverbose)
764		wb_print_state(sc, "After watchdog attach");
765
766	return (0);
767}
768
769static int
770wb_detach(device_t dev)
771{
772	struct wb_softc *sc;
773
774	sc = device_get_softc(dev);
775
776	/* Unregister and stop the watchdog if running. */
777	if (sc->ev_tag)
778		EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag);
779	wb_set_watchdog(sc, 0);
780
781	/* Disable extended function mode. */
782	(*sc->ext_cfg_exit_f)(sc, 0);
783
784	/* Cleanup resources. */
785	(void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
786
787	/* Bus subroutines take care of sysctls already. */
788
789	return (0);
790}
791
792static device_method_t wb_methods[] = {
793	/* Device interface */
794	DEVMETHOD(device_identify,	wb_identify),
795	DEVMETHOD(device_probe,		wb_probe),
796	DEVMETHOD(device_attach,	wb_attach),
797	DEVMETHOD(device_detach,	wb_detach),
798
799	DEVMETHOD_END
800};
801
802static driver_t wb_isa_driver = {
803	"wbwd",
804	wb_methods,
805	sizeof(struct wb_softc)
806};
807
808static devclass_t wb_devclass;
809
810DRIVER_MODULE(wb, isa, wb_isa_driver, wb_devclass, NULL, NULL);
811