Line data Source code
1 : /* $OpenBSD: it.c,v 1.46 2015/03/14 03:38:47 jsg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2007-2008 Oleg Safiullin <form@pdp-11.org.ru>
5 : * Copyright (c) 2006-2007 Juan Romero Pardines <juan@xtrarom.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 LIMITED 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 LIMITED 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 : #include <sys/param.h>
31 : #include <sys/systm.h>
32 : #include <sys/device.h>
33 : #include <sys/sensors.h>
34 :
35 : #include <machine/bus.h>
36 :
37 : #include <dev/isa/isavar.h>
38 : #include <dev/isa/itvar.h>
39 :
40 :
41 : #if defined(ITDEBUG)
42 : #define DPRINTF(x) do { printf x; } while (0)
43 : #else
44 : #define DPRINTF(x)
45 : #endif
46 :
47 :
48 : int it_match(struct device *, void *, void *);
49 : void it_attach(struct device *, struct device *, void *);
50 : int it_activate(struct device *, int);
51 : u_int8_t it_readreg(bus_space_tag_t, bus_space_handle_t, int);
52 : void it_writereg(bus_space_tag_t, bus_space_handle_t, int, u_int8_t);
53 : void it_enter(bus_space_tag_t, bus_space_handle_t, int);
54 : void it_exit(bus_space_tag_t, bus_space_handle_t);
55 :
56 : u_int8_t it_ec_readreg(struct it_softc *, int);
57 : void it_ec_writereg(struct it_softc *, int, u_int8_t);
58 : void it_ec_refresh(void *arg);
59 :
60 : int it_wdog_cb(void *, int);
61 :
62 : /*
63 : * IT87-compatible chips can typically measure voltages up to 4.096 V.
64 : * To measure higher voltages the input is attenuated with (external)
65 : * resistors. Negative voltages are measured using a reference
66 : * voltage. So we have to convert the sensor values back to real
67 : * voltages by applying the appropriate resistor factor.
68 : */
69 : #define RFACT_NONE 10000
70 : #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
71 :
72 :
73 : struct {
74 : enum sensor_type type;
75 : const char *desc;
76 : } it_sensors[IT_EC_NUMSENSORS] = {
77 : #define IT_TEMP_BASE 0
78 : #define IT_TEMP_COUNT 3
79 : { SENSOR_TEMP, NULL },
80 : { SENSOR_TEMP, NULL },
81 : { SENSOR_TEMP, NULL },
82 :
83 : #define IT_FAN_BASE 3
84 : #define IT_FAN_COUNT 5
85 : { SENSOR_FANRPM, NULL },
86 : { SENSOR_FANRPM, NULL },
87 : { SENSOR_FANRPM, NULL },
88 : { SENSOR_FANRPM, NULL },
89 : { SENSOR_FANRPM, NULL },
90 :
91 : #define IT_VOLT_BASE 8
92 : #define IT_VOLT_COUNT 9
93 : { SENSOR_VOLTS_DC, "VCORE_A" },
94 : { SENSOR_VOLTS_DC, "VCORE_B" },
95 : { SENSOR_VOLTS_DC, "+3.3V" },
96 : { SENSOR_VOLTS_DC, "+5V" },
97 : { SENSOR_VOLTS_DC, "+12V" },
98 : { SENSOR_VOLTS_DC, "-12V" },
99 : { SENSOR_VOLTS_DC, "-5V" },
100 : { SENSOR_VOLTS_DC, "+5VSB" },
101 : { SENSOR_VOLTS_DC, "VBAT" }
102 : };
103 :
104 : /* rfact values for voltage sensors */
105 : int it_vrfact[IT_VOLT_COUNT] = {
106 : RFACT_NONE, /* VCORE_A */
107 : RFACT_NONE, /* VCORE_A */
108 : RFACT_NONE, /* +3.3V */
109 : RFACT(68, 100), /* +5V */
110 : RFACT(30, 10), /* +12V */
111 : RFACT(83, 20), /* -12V */
112 : RFACT(21, 10), /* -5V */
113 : RFACT(68, 100), /* +5VSB */
114 : RFACT_NONE /* VBAT */
115 : };
116 :
117 : int it_fan_regs[] = {
118 : IT_EC_FAN_TAC1, IT_EC_FAN_TAC2, IT_EC_FAN_TAC3,
119 : IT_EC_FAN_TAC4_LSB, IT_EC_FAN_TAC5_LSB
120 : };
121 :
122 : int it_fan_ext_regs[] = {
123 : IT_EC_FAN_EXT_TAC1, IT_EC_FAN_EXT_TAC2, IT_EC_FAN_EXT_TAC3,
124 : IT_EC_FAN_TAC4_MSB, IT_EC_FAN_TAC5_MSB
125 : };
126 :
127 : LIST_HEAD(, it_softc) it_softc_list = LIST_HEAD_INITIALIZER(it_softc_list);
128 :
129 :
130 : int
131 0 : it_match(struct device *parent, void *match, void *aux)
132 : {
133 0 : struct isa_attach_args *ia = aux;
134 : struct it_softc *sc;
135 0 : bus_space_handle_t ioh;
136 : int ec_iobase, found = 0;
137 : u_int16_t cr;
138 :
139 0 : if (ia->ipa_io[0].base != IO_IT1 && ia->ipa_io[0].base != IO_IT2)
140 0 : return (0);
141 :
142 : /* map i/o space */
143 0 : if (bus_space_map(ia->ia_iot, ia->ipa_io[0].base, 2, 0, &ioh) != 0) {
144 : DPRINTF(("it_match: can't map i/o space"));
145 0 : return (0);
146 : }
147 :
148 : /* enter MB PnP mode */
149 0 : it_enter(ia->ia_iot, ioh, ia->ipa_io[0].base);
150 :
151 : /*
152 : * SMSC or similar SuperIO chips use 0x55 magic to enter PnP mode
153 : * and 0xaa to exit. These chips also enter PnP mode via ITE
154 : * `enter MB PnP mode' sequence, so force chip to exit PnP mode
155 : * if this is the case.
156 : */
157 0 : bus_space_write_1(ia->ia_iot, ioh, IT_IO_ADDR, 0xaa);
158 :
159 : /* get chip id */
160 0 : cr = it_readreg(ia->ia_iot, ioh, IT_CHIPID1) << 8;
161 0 : cr |= it_readreg(ia->ia_iot, ioh, IT_CHIPID2);
162 :
163 0 : switch (cr) {
164 : case IT_ID_8705:
165 : case IT_ID_8712:
166 : case IT_ID_8716:
167 : case IT_ID_8718:
168 : case IT_ID_8720:
169 : case IT_ID_8721:
170 : case IT_ID_8726:
171 : case IT_ID_8728:
172 : case IT_ID_8772:
173 : /* get environment controller base address */
174 0 : it_writereg(ia->ia_iot, ioh, IT_LDN, IT_EC_LDN);
175 0 : ec_iobase = it_readreg(ia->ia_iot, ioh, IT_EC_MSB) << 8;
176 0 : ec_iobase |= it_readreg(ia->ia_iot, ioh, IT_EC_LSB);
177 :
178 : /* check if device already attached */
179 0 : LIST_FOREACH(sc, &it_softc_list, sc_list)
180 0 : if (sc->sc_ec_iobase == ec_iobase)
181 : break;
182 :
183 0 : if (sc == NULL) {
184 0 : ia->ipa_nio = 1;
185 0 : ia->ipa_io[0].length = 2;
186 0 : ia->ipa_nmem = ia->ipa_nirq = ia->ipa_ndrq = 0;
187 : found++;
188 0 : }
189 :
190 : break;
191 : }
192 :
193 : /* exit MB PnP mode */
194 0 : it_exit(ia->ia_iot, ioh);
195 :
196 : /* unmap i/o space */
197 0 : bus_space_unmap(ia->ia_iot, ioh, 2);
198 :
199 0 : return (found);
200 0 : }
201 :
202 : void
203 0 : it_attach(struct device *parent, struct device *self, void *aux)
204 : {
205 0 : struct it_softc *sc = (void *)self;
206 0 : struct isa_attach_args *ia = aux;
207 : int i;
208 :
209 0 : sc->sc_iot = ia->ia_iot;
210 0 : sc->sc_iobase = ia->ipa_io[0].base;
211 0 : if (bus_space_map(sc->sc_iot, sc->sc_iobase, 2, 0, &sc->sc_ioh) != 0) {
212 0 : printf(": can't map i/o space\n");
213 0 : return;
214 : }
215 :
216 : /* enter MB PnP mode */
217 0 : it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase);
218 :
219 : /* get chip id and rev */
220 0 : sc->sc_chipid = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID1) << 8;
221 0 : sc->sc_chipid |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID2);
222 0 : sc->sc_chiprev = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPREV) & 0x0f;
223 :
224 : /* get environment controller base address */
225 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_EC_LDN);
226 0 : sc->sc_ec_iobase = it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_MSB) << 8;
227 0 : sc->sc_ec_iobase |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_LSB);
228 :
229 : /* initialize watchdog timer */
230 0 : if (sc->sc_chipid != IT_ID_8705) {
231 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN);
232 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_CSR, 0x00);
233 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 0x00);
234 0 : wdog_register(it_wdog_cb, sc);
235 0 : }
236 :
237 : /* exit MB PnP mode and unmap */
238 0 : it_exit(sc->sc_iot, sc->sc_ioh);
239 :
240 0 : LIST_INSERT_HEAD(&it_softc_list, sc, sc_list);
241 0 : printf(": IT%xF rev %X", sc->sc_chipid, sc->sc_chiprev);
242 :
243 0 : if (sc->sc_ec_iobase == 0) {
244 0 : printf(", EC disabled\n");
245 0 : return;
246 : }
247 :
248 0 : printf(", EC port 0x%x\n", sc->sc_ec_iobase);
249 :
250 : /* map environment controller i/o space */
251 0 : sc->sc_ec_iot = ia->ia_iot;
252 0 : if (bus_space_map(sc->sc_ec_iot, sc->sc_ec_iobase, 8, 0,
253 0 : &sc->sc_ec_ioh) != 0) {
254 0 : printf("%s: can't map EC i/o space\n", sc->sc_dev.dv_xname);
255 0 : return;
256 : }
257 :
258 : /* initialize sensor structures */
259 0 : for (i = 0; i < IT_EC_NUMSENSORS; i++) {
260 0 : sc->sc_sensors[i].type = it_sensors[i].type;
261 :
262 0 : if (it_sensors[i].desc != NULL)
263 0 : strlcpy(sc->sc_sensors[i].desc, it_sensors[i].desc,
264 : sizeof(sc->sc_sensors[i].desc));
265 : }
266 :
267 : /* register sensor update task */
268 0 : if (sensor_task_register(sc, it_ec_refresh, IT_EC_INTERVAL) == NULL) {
269 0 : printf("%s: unable to register update task\n",
270 0 : sc->sc_dev.dv_xname);
271 0 : bus_space_unmap(sc->sc_ec_iot, sc->sc_ec_ioh, 8);
272 0 : return;
273 : }
274 :
275 : /* use 16-bit FAN tachometer registers for newer chips */
276 0 : if (sc->sc_chipid != IT_ID_8705 && sc->sc_chipid != IT_ID_8712)
277 0 : it_ec_writereg(sc, IT_EC_FAN_ECER,
278 0 : it_ec_readreg(sc, IT_EC_FAN_ECER) | 0x07);
279 :
280 : /* activate monitoring */
281 0 : it_ec_writereg(sc, IT_EC_CFG,
282 0 : it_ec_readreg(sc, IT_EC_CFG) | IT_EC_CFG_START | IT_EC_CFG_INTCLR);
283 :
284 : /* initialize sensors */
285 0 : strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
286 : sizeof(sc->sc_sensordev.xname));
287 0 : for (i = 0; i < IT_EC_NUMSENSORS; i++)
288 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
289 0 : sensordev_install(&sc->sc_sensordev);
290 0 : }
291 :
292 : int
293 0 : it_activate(struct device *self, int act)
294 : {
295 0 : switch (act) {
296 : case DVACT_POWERDOWN:
297 0 : wdog_shutdown(self);
298 0 : break;
299 : }
300 :
301 0 : return (0);
302 : }
303 :
304 : u_int8_t
305 0 : it_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int r)
306 : {
307 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, r);
308 0 : return (bus_space_read_1(iot, ioh, IT_IO_DATA));
309 : }
310 :
311 : void
312 0 : it_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int r, u_int8_t v)
313 : {
314 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, r);
315 0 : bus_space_write_1(iot, ioh, IT_IO_DATA, v);
316 0 : }
317 :
318 : void
319 0 : it_enter(bus_space_tag_t iot, bus_space_handle_t ioh, int iobase)
320 : {
321 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x87);
322 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x01);
323 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55);
324 0 : if (iobase == IO_IT1)
325 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55);
326 : else
327 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, 0xaa);
328 0 : }
329 :
330 : void
331 0 : it_exit(bus_space_tag_t iot, bus_space_handle_t ioh)
332 : {
333 0 : bus_space_write_1(iot, ioh, IT_IO_ADDR, IT_CCR);
334 0 : bus_space_write_1(iot, ioh, IT_IO_DATA, 0x02);
335 0 : }
336 :
337 : u_int8_t
338 0 : it_ec_readreg(struct it_softc *sc, int r)
339 : {
340 0 : bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_ADDR, r);
341 0 : return (bus_space_read_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_DATA));
342 : }
343 :
344 : void
345 0 : it_ec_writereg(struct it_softc *sc, int r, u_int8_t v)
346 : {
347 0 : bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_ADDR, r);
348 0 : bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_DATA, v);
349 0 : }
350 :
351 : void
352 0 : it_ec_refresh(void *arg)
353 : {
354 0 : struct it_softc *sc = arg;
355 : int i, sdata, divisor, odivisor, ndivisor;
356 : u_int8_t cr, ecr;
357 :
358 : /* refresh temp sensors */
359 0 : cr = it_ec_readreg(sc, IT_EC_ADC_TEMPER);
360 :
361 0 : for (i = 0; i < IT_TEMP_COUNT; i++) {
362 0 : sc->sc_sensors[IT_TEMP_BASE + i].flags &=
363 : SENSOR_FINVALID;
364 :
365 0 : if (!(cr & (1 << i)) && !(cr & (1 << (i + 3)))) {
366 0 : sc->sc_sensors[IT_TEMP_BASE + i].flags |=
367 : SENSOR_FINVALID;
368 0 : continue;
369 : }
370 :
371 0 : sdata = it_ec_readreg(sc, IT_EC_TEMPBASE + i);
372 : /* convert to degF */
373 0 : sc->sc_sensors[IT_TEMP_BASE + i].value =
374 0 : sdata * 1000000 + 273150000;
375 0 : }
376 :
377 : /* refresh volt sensors */
378 0 : cr = it_ec_readreg(sc, IT_EC_ADC_VINER);
379 :
380 0 : for (i = 0; i < IT_VOLT_COUNT; i++) {
381 0 : sc->sc_sensors[IT_VOLT_BASE + i].flags &=
382 : SENSOR_FINVALID;
383 :
384 0 : if ((i < 8) && !(cr & (1 << i))) {
385 0 : sc->sc_sensors[IT_VOLT_BASE + i].flags |=
386 : SENSOR_FINVALID;
387 0 : continue;
388 : }
389 :
390 0 : sdata = it_ec_readreg(sc, IT_EC_VOLTBASE + i);
391 : /* voltage returned as (mV >> 4) */
392 0 : sc->sc_sensors[IT_VOLT_BASE + i].value = sdata << 4;
393 : /* these two values are negative and formula is different */
394 0 : if (i == 5 || i == 6)
395 0 : sc->sc_sensors[IT_VOLT_BASE + i].value -= IT_EC_VREF;
396 : /* rfact is (factor * 10^4) */
397 0 : sc->sc_sensors[IT_VOLT_BASE + i].value *= it_vrfact[i];
398 : /* division by 10 gets us back to uVDC */
399 0 : sc->sc_sensors[IT_VOLT_BASE + i].value /= 10;
400 0 : if (i == 5 || i == 6)
401 0 : sc->sc_sensors[IT_VOLT_BASE + i].value +=
402 : IT_EC_VREF * 1000;
403 : }
404 :
405 : /* refresh fan sensors */
406 0 : cr = it_ec_readreg(sc, IT_EC_FAN_MCR);
407 :
408 0 : if (sc->sc_chipid != IT_ID_8705 && sc->sc_chipid != IT_ID_8712) {
409 : /* use 16-bit FAN tachometer registers */
410 0 : ecr = it_ec_readreg(sc, IT_EC_FAN_ECER);
411 :
412 0 : for (i = 0; i < IT_FAN_COUNT; i++) {
413 0 : sc->sc_sensors[IT_FAN_BASE + i].flags &=
414 : ~SENSOR_FINVALID;
415 :
416 0 : if (i < 3 && !(cr & (1 << (i + 4)))) {
417 0 : sc->sc_sensors[IT_FAN_BASE + i].flags |=
418 : SENSOR_FINVALID;
419 0 : continue;
420 0 : } else if (i > 2 && !(ecr & (1 << (i + 1)))) {
421 0 : sc->sc_sensors[IT_FAN_BASE + i].flags |=
422 : SENSOR_FINVALID;
423 0 : continue;
424 : }
425 :
426 0 : sdata = it_ec_readreg(sc, it_fan_regs[i]);
427 0 : sdata |= it_ec_readreg(sc, it_fan_ext_regs[i]) << 8;
428 :
429 0 : if (sdata == 0 || sdata == 0xffff)
430 0 : sc->sc_sensors[IT_FAN_BASE + i].value = 0;
431 : else
432 0 : sc->sc_sensors[IT_FAN_BASE + i].value =
433 0 : 675000 / sdata;
434 : }
435 : } else {
436 : /* use 8-bit FAN tachometer & FAN divisor registers */
437 : odivisor = ndivisor = divisor =
438 0 : it_ec_readreg(sc, IT_EC_FAN_DIV);
439 :
440 0 : for (i = 0; i < IT_FAN_COUNT; i++) {
441 0 : if (i > 2 || !(cr & (1 << (i + 4)))) {
442 0 : sc->sc_sensors[IT_FAN_BASE + i].flags |=
443 : SENSOR_FINVALID;
444 0 : continue;
445 : }
446 :
447 0 : sc->sc_sensors[IT_FAN_BASE + i].flags &=
448 : ~SENSOR_FINVALID;
449 :
450 0 : sdata = it_ec_readreg(sc, it_fan_regs[i]);
451 :
452 0 : if (sdata == 0xff) {
453 0 : sc->sc_sensors[IT_FAN_BASE + i].value = 0;
454 :
455 0 : if (i == 2)
456 0 : ndivisor ^= 0x40;
457 : else {
458 0 : ndivisor &= ~(7 << (i * 3));
459 0 : ndivisor |= ((divisor + 1) & 7) <<
460 : (i * 3);
461 : }
462 0 : } else if (sdata != 0) {
463 0 : if (i == 2)
464 0 : divisor = divisor & 1 ? 3 : 1;
465 0 : sc->sc_sensors[IT_FAN_BASE + i].value =
466 0 : 1350000 / (sdata << (divisor & 7));
467 0 : } else
468 0 : sc->sc_sensors[IT_FAN_BASE + i].value = 0;
469 : }
470 :
471 0 : if (ndivisor != odivisor)
472 0 : it_ec_writereg(sc, IT_EC_FAN_DIV, ndivisor);
473 : }
474 0 : }
475 :
476 : int
477 0 : it_wdog_cb(void *arg, int period)
478 : {
479 0 : struct it_softc *sc = arg;
480 : int minutes = 0;
481 :
482 : /* enter MB PnP mode and select WDT device */
483 0 : it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase);
484 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN);
485 :
486 : /* disable watchdog timer */
487 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 0x00);
488 :
489 : /* 1000s should be enough for everyone */
490 0 : if (period > 1000)
491 0 : period = 1000;
492 0 : else if (period < 0)
493 0 : period = 0;
494 :
495 0 : if (period > 0) {
496 : /*
497 : * Older IT8712F chips have 8-bit timeout counter.
498 : * Use minutes for 16-bit values for these chips.
499 : */
500 0 : if (sc->sc_chipid == IT_ID_8712 && sc->sc_chiprev < 0x8 &&
501 0 : period > 0xff) {
502 0 : if (period % 60 >= 30)
503 0 : period += 60;
504 0 : period /= 60;
505 : minutes++;
506 0 : }
507 :
508 : /* set watchdog timeout (low byte) */
509 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TMO_LSB,
510 0 : period & 0xff);
511 :
512 0 : if (minutes) {
513 : /* enable watchdog timer */
514 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR,
515 : IT_WDT_TCR_KRST | IT_WDT_TCR_PWROK);
516 :
517 0 : period *= 60;
518 0 : } else {
519 : /* set watchdog timeout (high byte) */
520 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TMO_MSB,
521 0 : period >> 8);
522 :
523 : /* enable watchdog timer */
524 0 : it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR,
525 : IT_WDT_TCR_SECS | IT_WDT_TCR_KRST |
526 : IT_WDT_TCR_PWROK);
527 : }
528 : }
529 :
530 : /* exit MB PnP mode */
531 0 : it_exit(sc->sc_iot, sc->sc_ioh);
532 :
533 0 : return (period);
534 : }
535 :
536 :
537 : struct cfattach it_ca = {
538 : sizeof(struct it_softc),
539 : it_match,
540 : it_attach,
541 : NULL,
542 : it_activate
543 : };
544 :
545 : struct cfdriver it_cd = {
546 : NULL, "it", DV_DULL
547 : };
|