xref: /netbsd-src/sys/dev/isa/itesio_isa.c (revision bbde328be4e75ea9ad02e9715ea13ca54b797ada)
1 /*	$NetBSD: itesio_isa.c,v 1.18 2010/05/02 18:49:13 jakllsch Exp $ */
2 /*	Derived from $OpenBSD: it.c,v 1.19 2006/04/10 00:57:54 deraadt Exp $	*/
3 
4 /*
5  * Copyright (c) 2006-2007 Juan Romero Pardines <xtraeme@netbsd.org>
6  * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITD TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITD TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * Driver for the iTE IT87xxF Super I/O. Currently supporting
32  * the Environmental Controller to monitor the sensors and the
33  * Watchdog Timer.
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: itesio_isa.c,v 1.18 2010/05/02 18:49:13 jakllsch Exp $");
38 
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/device.h>
42 
43 #include <sys/bus.h>
44 
45 #include <dev/isa/isareg.h>
46 #include <dev/isa/isavar.h>
47 
48 #include <dev/sysmon/sysmonvar.h>
49 
50 #include <dev/isa/itesio_isavar.h>
51 
52 #define IT_VOLTSTART_IDX 	3 	/* voltage start index */
53 #define IT_FANSTART_IDX 	12 	/* fan start index */
54 
55 #if defined(ITESIO_DEBUG)
56 #define DPRINTF(x)		do { printf x; } while (0)
57 #else
58 #define DPRINTF(x)
59 #endif
60 
61 /*
62  * IT87-compatible chips can typically measure voltages up to 4.096 V.
63  * To measure higher voltages the input is attenuated with (external)
64  * resistors.  Negative voltages are measured using a reference
65  * voltage.  So we have to convert the sensor values back to real
66  * voltages by applying the appropriate resistor factor.
67  */
68 #define RFACT_NONE	10000
69 #define RFACT(x, y)	(RFACT_NONE * ((x) + (y)) / (y))
70 
71 /* autoconf(9) functions */
72 static int	itesio_isa_match(device_t, cfdata_t, void *);
73 static void	itesio_isa_attach(device_t, device_t, void *);
74 static int	itesio_isa_detach(device_t, int);
75 
76 CFATTACH_DECL_NEW(itesio, sizeof(struct itesio_softc),
77     itesio_isa_match, itesio_isa_attach, itesio_isa_detach, NULL);
78 
79 /* driver functions */
80 static uint8_t	itesio_ecreadreg(struct itesio_softc *, int);
81 static void	itesio_ecwritereg(struct itesio_softc *, int, int);
82 static uint8_t	itesio_readreg(bus_space_tag_t, bus_space_handle_t, int);
83 static void	itesio_writereg(bus_space_tag_t, bus_space_handle_t, int, int);
84 static void	itesio_enter(bus_space_tag_t, bus_space_handle_t);
85 static void	itesio_exit(bus_space_tag_t, bus_space_handle_t);
86 
87 /* sysmon_envsys(9) glue */
88 static void	itesio_setup_sensors(struct itesio_softc *);
89 static void	itesio_refresh_temp(struct itesio_softc *, envsys_data_t *);
90 static void	itesio_refresh_volts(struct itesio_softc *, envsys_data_t *);
91 static void	itesio_refresh_fans(struct itesio_softc *, envsys_data_t *);
92 static void	itesio_refresh(struct sysmon_envsys *, envsys_data_t *);
93 
94 /* sysmon_wdog glue */
95 static int	itesio_wdt_setmode(struct sysmon_wdog *);
96 static int 	itesio_wdt_tickle(struct sysmon_wdog *);
97 
98 /* rfact values for voltage sensors */
99 static const int itesio_vrfact[] = {
100 	RFACT_NONE,	/* VCORE_A	*/
101 	RFACT_NONE,	/* VCORE_B	*/
102 	RFACT_NONE,	/* +3.3V	*/
103 	RFACT(68, 100),	/* +5V 		*/
104 	RFACT(30, 10),	/* +12V 	*/
105 	RFACT(21, 10),	/* -5V 		*/
106 	RFACT(83, 20),	/* -12V 	*/
107 	RFACT(68, 100),	/* STANDBY	*/
108 	RFACT_NONE	/* VBAT		*/
109 };
110 
111 static int
112 itesio_isa_match(device_t parent, cfdata_t match, void *aux)
113 {
114 	struct isa_attach_args *ia = aux;
115 	bus_space_handle_t ioh;
116 	uint16_t cr;
117 
118 	/* Must supply an address */
119 	if (ia->ia_nio < 1)
120 		return 0;
121 
122 	if (ISA_DIRECT_CONFIG(ia))
123 		return 0;
124 
125 	if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
126 		return 0;
127 
128 	if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh))
129 		return 0;
130 
131 	itesio_enter(ia->ia_iot, ioh);
132 	cr = (itesio_readreg(ia->ia_iot, ioh, ITESIO_CHIPID1) << 8);
133 	cr |= itesio_readreg(ia->ia_iot, ioh, ITESIO_CHIPID2);
134 	itesio_exit(ia->ia_iot, ioh);
135 	bus_space_unmap(ia->ia_iot, ioh, 2);
136 
137 	switch (cr) {
138 	case ITESIO_ID8705:
139 	case ITESIO_ID8712:
140 	case ITESIO_ID8716:
141 	case ITESIO_ID8718:
142 	case ITESIO_ID8726:
143 		ia->ia_nio = 1;
144 		ia->ia_io[0].ir_size = 2;
145 		ia->ia_niomem = 0;
146 		ia->ia_nirq = 0;
147 		ia->ia_ndrq = 0;
148 		return 1;
149 	default:
150 		return 0;
151 	}
152 }
153 
154 static void
155 itesio_isa_attach(device_t parent, device_t self, void *aux)
156 {
157 	struct itesio_softc *sc = device_private(self);
158 	struct isa_attach_args *ia = aux;
159 	int i;
160 	uint8_t cr;
161 
162 	sc->sc_iot = ia->ia_iot;
163 
164 	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, 2, 0,
165 			  &sc->sc_pnp_ioh)) {
166 		aprint_error(": can't map pnp i/o space\n");
167 		return;
168 	}
169 
170 	aprint_naive("\n");
171 
172 	/*
173 	 * Enter to the Super I/O MB PNP mode.
174 	 */
175 	itesio_enter(sc->sc_iot, sc->sc_pnp_ioh);
176 	/*
177 	 * Get info from the Super I/O Global Configuration Registers:
178 	 * Chip IDs and Device Revision.
179 	 */
180 	sc->sc_chipid = (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh,
181 	    ITESIO_CHIPID1) << 8);
182 	sc->sc_chipid |= itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh,
183 	    ITESIO_CHIPID2);
184 	sc->sc_devrev = (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh,
185 	    ITESIO_DEVREV) & 0x0f);
186 	/*
187 	 * Select the EC LDN to get the Base Address.
188 	 */
189 	itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL,
190 	    ITESIO_EC_LDN);
191 	sc->sc_hwmon_baseaddr =
192 	    (itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_EC_MSB) << 8);
193 	sc->sc_hwmon_baseaddr |= itesio_readreg(sc->sc_iot, sc->sc_pnp_ioh,
194 	    ITESIO_EC_LSB);
195 	/*
196 	 * We are done, exit MB PNP mode.
197 	 */
198 	itesio_exit(sc->sc_iot, sc->sc_pnp_ioh);
199 
200 	aprint_normal(": iTE IT%4xF Super I/O (rev %d)\n",
201 	    sc->sc_chipid, sc->sc_devrev);
202 	aprint_normal_dev(self, "Hardware Monitor registers at 0x%x\n",
203 	    sc->sc_hwmon_baseaddr);
204 
205 	if (bus_space_map(sc->sc_iot, sc->sc_hwmon_baseaddr, 8, 0,
206 	    &sc->sc_ec_ioh)) {
207 		aprint_error_dev(self, "cannot map hwmon i/o space\n");
208 		goto out2;
209 	}
210 
211 	sc->sc_hwmon_mapped = true;
212 
213 	/* Activate monitoring */
214 	cr = itesio_ecreadreg(sc, ITESIO_EC_CONFIG);
215 	SET(cr, 0x01);
216 	itesio_ecwritereg(sc, ITESIO_EC_CONFIG, cr);
217 
218 #ifdef notyet
219 	/* Enable beep alarms */
220 	cr = itesio_ecreadreg(sc, ITESIO_EC_BEEPEER);
221 	SET(cr, 0x02);	/* Voltage exceeds limit */
222 	SET(cr, 0x04);	/* Temperature exceeds limit */
223 	itesio_ecwritereg(sc, ITESIO_EC_BEEPEER, cr);
224 #endif
225 
226 	/*
227 	 * Initialize and attach sensors.
228 	 */
229 	itesio_setup_sensors(sc);
230 	sc->sc_sme = sysmon_envsys_create();
231 	for (i = 0; i < IT_NUM_SENSORS; i++) {
232 		if (sysmon_envsys_sensor_attach(sc->sc_sme,
233 						&sc->sc_sensor[i])) {
234 			sysmon_envsys_destroy(sc->sc_sme);
235 			goto out;
236 		}
237 	}
238 	/*
239 	 * Hook into the system monitor.
240 	 */
241 	sc->sc_sme->sme_name = device_xname(self);
242 	sc->sc_sme->sme_cookie = sc;
243 	sc->sc_sme->sme_refresh = itesio_refresh;
244 
245 	if ((i = sysmon_envsys_register(sc->sc_sme))) {
246 		aprint_error_dev(self,
247 		    "unable to register with sysmon (%d)\n", i);
248 		sysmon_envsys_destroy(sc->sc_sme);
249 		goto out;
250 	}
251 	sc->sc_hwmon_enabled = true;
252 
253 	if (!pmf_device_register(self, NULL, NULL))
254 		aprint_error_dev(self, "couldn't establish power handler\n");
255 
256 	/* The IT8705 doesn't support the WDT */
257 	if (sc->sc_chipid == ITESIO_ID8705)
258 		goto out2;
259 
260 	/*
261 	 * Initialize the watchdog timer.
262 	 */
263 	sc->sc_smw.smw_name = device_xname(self);
264 	sc->sc_smw.smw_cookie = sc;
265 	sc->sc_smw.smw_setmode = itesio_wdt_setmode;
266 	sc->sc_smw.smw_tickle = itesio_wdt_tickle;
267 	sc->sc_smw.smw_period = 60;
268 
269 	if (sysmon_wdog_register(&sc->sc_smw)) {
270 		aprint_error_dev(self, "unable to register watchdog timer\n");
271 		goto out2;
272 	}
273 	sc->sc_wdt_enabled = true;
274 	aprint_normal_dev(self, "Watchdog Timer present\n");
275 	return;
276 
277 out:
278 	bus_space_unmap(sc->sc_iot, sc->sc_ec_ioh, 8);
279 out2:
280 	bus_space_unmap(sc->sc_iot, sc->sc_pnp_ioh, 2);
281 }
282 
283 static int
284 itesio_isa_detach(device_t self, int flags)
285 {
286 	struct itesio_softc *sc = device_private(self);
287 
288 	if (sc->sc_hwmon_enabled)
289 		sysmon_envsys_unregister(sc->sc_sme);
290 	if (sc->sc_hwmon_mapped)
291 		bus_space_unmap(sc->sc_iot, sc->sc_ec_ioh, 8);
292 	if (sc->sc_wdt_enabled) {
293 		sysmon_wdog_unregister(&sc->sc_smw);
294 		bus_space_unmap(sc->sc_iot, sc->sc_pnp_ioh, 2);
295 	}
296 
297 	return 0;
298 }
299 
300 /*
301  * Functions to read/write to the Environmental Controller.
302  */
303 static uint8_t
304 itesio_ecreadreg(struct itesio_softc *sc, int reg)
305 {
306 	bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_ADDR, reg);
307 	return bus_space_read_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_DATA);
308 }
309 
310 static void
311 itesio_ecwritereg(struct itesio_softc *sc, int reg, int val)
312 {
313 	bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_ADDR, reg);
314 	bus_space_write_1(sc->sc_iot, sc->sc_ec_ioh, ITESIO_EC_DATA, val);
315 }
316 
317 /*
318  * Functions to enter/exit/read/write to the Super I/O.
319  */
320 static uint8_t
321 itesio_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg)
322 {
323 	bus_space_write_1(iot, ioh, ITESIO_ADDR, reg);
324 	return bus_space_read_1(iot, ioh, ITESIO_DATA);
325 }
326 
327 static void
328 itesio_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, int val)
329 {
330 	bus_space_write_1(iot, ioh, ITESIO_ADDR, reg);
331 	bus_space_write_1(iot, ioh, ITESIO_DATA, val);
332 }
333 
334 static void
335 itesio_enter(bus_space_tag_t iot, bus_space_handle_t ioh)
336 {
337 	bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x87);
338 	bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x01);
339 	bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x55);
340 	bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x55);
341 }
342 
343 static void
344 itesio_exit(bus_space_tag_t iot, bus_space_handle_t ioh)
345 {
346 	bus_space_write_1(iot, ioh, ITESIO_ADDR, 0x02);
347 	bus_space_write_1(iot, ioh, ITESIO_DATA, 0x02);
348 }
349 
350 
351 #define COPYDESCR(x, y)				\
352 	do {					\
353 		strlcpy((x), (y), sizeof(x));	\
354 	} while (0)
355 /*
356  * sysmon_envsys(9) glue.
357  */
358 static void
359 itesio_setup_sensors(struct itesio_softc *sc)
360 {
361 	int i;
362 
363 	/* temperatures */
364 	for (i = 0; i < IT_VOLTSTART_IDX; i++)
365 		sc->sc_sensor[i].units = ENVSYS_STEMP;
366 
367 	COPYDESCR(sc->sc_sensor[0].desc, "CPU Temp");
368 	COPYDESCR(sc->sc_sensor[1].desc, "System Temp");
369 	COPYDESCR(sc->sc_sensor[2].desc, "Aux Temp");
370 
371 	/* voltages */
372 	for (i = IT_VOLTSTART_IDX; i < IT_FANSTART_IDX; i++) {
373 		sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC;
374 		sc->sc_sensor[i].flags = ENVSYS_FCHANGERFACT;
375 	}
376 
377 	COPYDESCR(sc->sc_sensor[3].desc, "VCORE_A");
378 	COPYDESCR(sc->sc_sensor[4].desc, "VCORE_B");
379 	COPYDESCR(sc->sc_sensor[5].desc, "+3.3V");
380 	COPYDESCR(sc->sc_sensor[6].desc, "+5V");
381 	COPYDESCR(sc->sc_sensor[7].desc, "+12V");
382 	COPYDESCR(sc->sc_sensor[8].desc, "-5V");
383 	COPYDESCR(sc->sc_sensor[9].desc, "-12V");
384 	COPYDESCR(sc->sc_sensor[10].desc, "STANDBY");
385 	COPYDESCR(sc->sc_sensor[11].desc, "VBAT");
386 
387 	/* fans */
388 	for (i = IT_FANSTART_IDX; i < IT_NUM_SENSORS; i++)
389 		sc->sc_sensor[i].units = ENVSYS_SFANRPM;
390 
391 	COPYDESCR(sc->sc_sensor[12].desc, "CPU Fan");
392 	COPYDESCR(sc->sc_sensor[13].desc, "System Fan");
393 	COPYDESCR(sc->sc_sensor[14].desc, "Aux Fan");
394 }
395 #undef COPYDESCR
396 
397 static void
398 itesio_refresh_temp(struct itesio_softc *sc, envsys_data_t *edata)
399 {
400 	int sdata;
401 
402 	sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORTEMPBASE + edata->sensor);
403 	/* sensor is not connected or reporting invalid data */
404 	if (sdata == 0 || sdata >= 0xfa) {
405 		edata->state = ENVSYS_SINVALID;
406 		return;
407 	}
408 
409 	DPRINTF(("%s: sdata[temp%d] 0x%x\n", __func__, edata->sensor, sdata));
410 	/* Convert temperature to uK */
411 	edata->value_cur = sdata * 1000000 + 273150000;
412 	edata->state = ENVSYS_SVALID;
413 }
414 
415 static void
416 itesio_refresh_volts(struct itesio_softc *sc, envsys_data_t *edata)
417 {
418 	uint8_t vbatcr = 0;
419 	int i, sdata;
420 
421 	i = edata->sensor - IT_VOLTSTART_IDX;
422 
423 	sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORVOLTBASE + i);
424 	/* not connected */
425 	if (sdata == 0 || sdata == 0xff) {
426 		edata->state = ENVSYS_SINVALID;
427 		return;
428 	}
429 
430 	/*
431 	 * update VBAT voltage reading every time we read it, to get
432 	 * latest value.
433 	 */
434 	if (i == 8) {
435 		vbatcr = itesio_ecreadreg(sc, ITESIO_EC_CONFIG);
436 		SET(vbatcr, ITESIO_EC_UPDATEVBAT);
437 		itesio_ecwritereg(sc, ITESIO_EC_CONFIG, vbatcr);
438 	}
439 
440 	DPRINTF(("%s: sdata[volt%d] 0x%x\n", __func__, i, sdata));
441 
442 	/* voltage returned as (mV << 4) */
443 	edata->value_cur = (sdata << 4);
444 	/* negative values */
445 	if (i == 5 || i == 6)
446 		edata->value_cur -= ITESIO_EC_VREF;
447 	/* rfact is (factor * 10^4) */
448 	edata->value_cur *= itesio_vrfact[i];
449 	if (edata->rfact)
450 		edata->value_cur += edata->rfact;
451 	/* division by 10 gets us back to uVDC */
452 	edata->value_cur /= 10;
453 	if (i == 5 || i == 6)
454 		edata->value_cur += ITESIO_EC_VREF * 1000;
455 
456 	edata->state = ENVSYS_SVALID;
457 }
458 
459 static void
460 itesio_refresh_fans(struct itesio_softc *sc, envsys_data_t *edata)
461 {
462 	uint8_t mode = 0;
463 	uint16_t sdata = 0;
464 	int i, divisor, odivisor, ndivisor;
465 
466 	i = edata->sensor - IT_FANSTART_IDX;
467 	divisor = odivisor = ndivisor = 0;
468 
469 	if (sc->sc_chipid == ITESIO_ID8705 || sc->sc_chipid == ITESIO_ID8712) {
470 		/*
471 		 * Use the Fan Tachometer Divisor Register for
472 		 * IT8705F and IT8712F.
473 		 */
474 		divisor = odivisor = ndivisor =
475 		    itesio_ecreadreg(sc, ITESIO_EC_FAN_TDR);
476 		sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i);
477 		if (sdata == 0xff) {
478 			edata->state = ENVSYS_SINVALID;
479 			if (i == 2)
480 				ndivisor |= 0x40;
481 			else {
482 				ndivisor &= ~(7 << (i * 3));
483 				ndivisor |= ((divisor + 1) & 7) << (i * 3);
484 			}
485 		} else {
486 			if (i == 2)
487 				divisor = divisor & 1 ? 3 : 1;
488 
489 			if ((sdata << (divisor & 7)) == 0)
490 				edata->state = ENVSYS_SINVALID;
491 			else {
492 				edata->value_cur =
493 				    1350000 / (sdata << (divisor & 7));
494 				edata->state = ENVSYS_SVALID;
495 			}
496 		}
497 		DPRINTF(("%s: 8bit sdata[fan%d] 0x%x div: 0x%x\n", __func__,
498 		    i, sdata, divisor));
499 		if (ndivisor != odivisor)
500 			itesio_ecwritereg(sc, ITESIO_EC_FAN_TDR, ndivisor);
501 	} else {
502 		mode = itesio_ecreadreg(sc, ITESIO_EC_FAN16_CER);
503 		sdata = itesio_ecreadreg(sc, ITESIO_EC_SENSORFANBASE + i);
504 		if (mode & (1 << i))
505 			sdata += (itesio_ecreadreg(sc,
506 			    ITESIO_EC_SENSORFANEXTBASE + i) << 8);
507 		edata->state = ENVSYS_SVALID;
508 		if (sdata == 0 ||
509 		    sdata == ((mode & (1 << i)) ? 0xffff : 0xff))
510 			edata->state = ENVSYS_SINVALID;
511 		else {
512 			edata->value_cur = 1350000 / 2 / sdata;
513 			edata->state = ENVSYS_SVALID;
514 		}
515 		DPRINTF(("%s: 16bit sdata[fan%d] 0x%x\n", __func__, i, sdata));
516 	}
517 }
518 
519 static void
520 itesio_refresh(struct sysmon_envsys *sme, struct envsys_data *edata)
521 {
522 	struct itesio_softc *sc = sme->sme_cookie;
523 
524 	if (edata->sensor < IT_VOLTSTART_IDX)
525 		itesio_refresh_temp(sc, edata);
526 	else if (edata->sensor >= IT_VOLTSTART_IDX &&
527 	         edata->sensor < IT_FANSTART_IDX)
528 		itesio_refresh_volts(sc, edata);
529 	else
530 		itesio_refresh_fans(sc, edata);
531 }
532 
533 static int
534 itesio_wdt_setmode(struct sysmon_wdog *smw)
535 {
536 	struct itesio_softc *sc = smw->smw_cookie;
537 	int period = smw->smw_period;
538 
539 	/* Enter MB PNP mode and select the WDT LDN */
540 	itesio_enter(sc->sc_iot, sc->sc_pnp_ioh);
541 	itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL,
542 	    ITESIO_WDT_LDN);
543 
544 	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
545 		/* Disable the watchdog */
546 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CTL, 0);
547 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CNF, 0);
548 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB, 0);
549 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB, 0);
550 	} else {
551 		/* Enable the watchdog */
552 		if (period > ITESIO_WDT_MAXTIMO || period < 1)
553 			period = smw->smw_period = ITESIO_WDT_MAXTIMO;
554 
555 		period *= 2;
556 
557 		/* set the timeout and start the watchdog */
558 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB,
559 		    period >> 8);
560 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB,
561 		    period & 0xff);
562 		itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_CNF,
563 		    ITESIO_WDT_CNF_SECS | ITESIO_WDT_CNF_KRST |
564 		    ITESIO_WDT_CNF_PWROK);
565 	}
566 	/* we are done, exit MB PNP mode */
567 	itesio_exit(sc->sc_iot, sc->sc_pnp_ioh);
568 
569 	return 0;
570 }
571 
572 static int
573 itesio_wdt_tickle(struct sysmon_wdog *smw)
574 {
575 	struct itesio_softc *sc = smw->smw_cookie;
576 	int period = smw->smw_period * 2;
577 
578 	/* refresh timeout value and exit */
579 	itesio_enter(sc->sc_iot, sc->sc_pnp_ioh);
580 	itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_LDNSEL,
581 	    ITESIO_WDT_LDN);
582 	itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_MSB,
583 	    period >> 8);
584 	itesio_writereg(sc->sc_iot, sc->sc_pnp_ioh, ITESIO_WDT_TMO_LSB,
585 	    period & 0xff);
586 	itesio_exit(sc->sc_iot, sc->sc_pnp_ioh);
587 
588 	return 0;
589 }
590