xref: /openbsd/sys/dev/isa/sch311x.c (revision 471aeecf)
1 /*	$OpenBSD: sch311x.c,v 1.18 2022/04/06 18:59:29 naddy Exp $	*/
2 /*
3  * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org>
4  * Copyright (c) 2009 Michael Knudsen <mk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * SMSC SCH3112, SCH3114, and SCH3116 LPC Super I/O driver.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/device.h>
25 #include <sys/kernel.h>
26 #include <sys/systm.h>
27 #include <sys/sensors.h>
28 
29 #include <machine/bus.h>
30 
31 #include <dev/isa/isavar.h>
32 
33 /* Device identifiers */
34 #define SCHSIO_ID_SCH3112	0x7c
35 #define SCHSIO_ID_SCH3114	0x7d
36 #define SCHSIO_ID_SCH3116	0x7f
37 
38 #define SCHSIO_IOSIZE 0x02
39 #define SCHSIO_PORT_CONFIG	0x00
40 
41 /* These are used in configuration mode */
42 #define SCHSIO_PORT_INDEX	0x00
43 #define SCHSIO_PORT_DATA	0x01
44 
45 #define SCHSIO_CONFIG_ENTER	0x55
46 #define SCHSIO_CONFIG_LEAVE	0xaa
47 
48 /* Register definitions */
49 #define SCHSIO_IDX_LDEVSEL	0x07 /* Logical device select */
50 #define SCHSIO_IDX_DEVICE	0x20 /* Device ID */
51 #define SCHSIO_IDX_REV		0x21 /* Device revision */
52 
53 #define SCHSIO_IDX_BASE_HI	0x60 /* Configuration base address */
54 #define SCHSIO_IDX_BASE_LO	0x61
55 
56 /* Logical devices */
57 #define SCHSIO_LDEV_RUNTIME	0x0a /* holds wdog and sensors */
58 #define SCHSIO_LDEV_RUNTIME_SZ	0x100
59 
60 /* Hardware monitor */
61 #define SCHSIO_HWM_INTERVAL	5 /* seconds */
62 
63 /* Register access */
64 #define SCHSIO_HWM_INDEX	0x70
65 #define SCHSIO_HWM_DATA		0x71
66 
67 /* Sensor definitions */
68 /* Voltage */
69 #define SCHSIO_HWM_VOLT1	0x20
70 #define SCHSIO_HWM_VOLT2	0x21
71 #define SCHSIO_HWM_VOLT3	0x22
72 #define SCHSIO_HWM_VOLT4	0x23
73 #define SCHSIO_HWM_VOLT5	0x24
74 #define SCHSIO_HWM_VOLT6	0x99
75 #define SCHSIO_HWM_VOLT7	0x9a
76 
77 /* Temperature */
78 #define SCHSIO_HWM_TEMP1	0x26
79 #define SCHSIO_HWM_TEMP2	0x25
80 #define SCHSIO_HWM_TEMP3	0x27
81 
82 /* Fan speed */
83 #define SCHSIO_HWM_TACH1_L	0x28
84 #define SCHSIO_HWM_TACH1_U	0x29
85 #define SCHSIO_HWM_TACH2_L	0x2a
86 #define SCHSIO_HWM_TACH2_U	0x2b
87 #define SCHSIO_HWM_TACH3_L	0x2c
88 #define SCHSIO_HWM_TACH3_U	0x2d
89 
90 /* 11111 = 90kHz * 10^9 */
91 #define SCHSIO_FAN_RPM(x)	(1000000000 / ((x) * 11111) * 60)
92 
93 #define SCHSIO_CONV_VOLT1	66400
94 #define SCHSIO_CONV_VOLT2	20000
95 #define SCHSIO_CONV_VOLT3	43800
96 #define SCHSIO_CONV_VOLT4	66400
97 #define SCHSIO_CONV_VOLT5	160000
98 #define SCHSIO_CONV_VOLT6	43800
99 #define SCHSIO_CONV_VOLT7	43800
100 #define SCHSIO_VOLT_MUV(x, k)	(1000000 * (x) / 2560000 * (k))
101 
102 #define SCHSIO_TEMP_MUK(x)	(((x) + 273) * 1000000)
103 
104 #define SCHSIO_SENSORS		13
105 
106 #define SCHSIO_SENSOR_FAN1	0
107 #define SCHSIO_SENSOR_FAN2	1
108 #define SCHSIO_SENSOR_FAN3	2
109 
110 #define SCHSIO_SENSOR_VOLT1	3
111 #define SCHSIO_SENSOR_VOLT2	4
112 #define SCHSIO_SENSOR_VOLT3	5
113 #define SCHSIO_SENSOR_VOLT4	6
114 #define SCHSIO_SENSOR_VOLT5	7
115 #define SCHSIO_SENSOR_VOLT6	8
116 #define SCHSIO_SENSOR_VOLT7	9
117 
118 #define SCHSIO_SENSOR_TEMP1	10
119 #define SCHSIO_SENSOR_TEMP2	11
120 #define SCHSIO_SENSOR_TEMP3	12
121 
122 
123 /* Watchdog */
124 
125 /* Register access */
126 #define SCHSIO_WDT_GPIO		0x47
127 #define SCHSIO_WDT_TIMEOUT	0x65
128 #define SCHSIO_WDT_VAL		0x66
129 #define SCHSIO_WDT_CFG		0x67
130 #define SCHSIO_WDT_CTRL		0x68
131 
132 /* Bits */
133 #define SCHSIO_WDT_GPIO_MASK	0x0f
134 #define SCHSIO_WDT_GPIO_OUT	0x0e
135 
136 #define SCHSIO_WDT_TO_SECONDS		(1 << 7)
137 
138 #define SCHSIO_WDT_CTRL_TRIGGERED	(1 << 0)
139 #define SCHSIO_WDT_CFG_KBDEN		(1 << 1)
140 #define SCHSIO_WDT_CFG_MSEN		(1 << 2)
141 
142 /* autoconf(9) flags etc. */
143 #define SCHSIO_CFFLAGS_WDTEN	(1 << 0)
144 
145 #define DEVNAME(x) ((x)->sc_dev.dv_xname)
146 
147 struct schsio_softc {
148 	struct device		sc_dev;
149 
150 	bus_space_tag_t		sc_iot;
151 	bus_space_handle_t	sc_ioh;
152 
153 	bus_space_handle_t	sc_ioh_rr;
154 
155 	struct ksensordev	sc_sensordev;
156 	struct ksensor		sc_sensor[SCHSIO_SENSORS];
157 };
158 
159 int	schsio_probe(struct device *, void *, void *);
160 void	schsio_attach(struct device *, struct device *, void *);
161 int	schsio_activate(struct device *, int);
162 
163 static __inline void schsio_config_enable(bus_space_tag_t iot,
164     bus_space_handle_t ioh);
165 static __inline void schsio_config_disable(bus_space_tag_t iot,
166     bus_space_handle_t ioh);
167 
168 u_int8_t schsio_config_read(bus_space_tag_t iot, bus_space_handle_t ioh,
169     u_int8_t reg);
170 void schsio_config_write(bus_space_tag_t iot, bus_space_handle_t ioh,
171     u_int8_t reg, u_int8_t val);
172 
173 /* HWM prototypes */
174 void schsio_hwm_init(struct schsio_softc *sc);
175 void schsio_hwm_update(void *arg);
176 u_int8_t schsio_hwm_read(struct schsio_softc *sc, u_int8_t reg);
177 
178 /* Watchdog prototypes */
179 
180 void schsio_wdt_init(struct schsio_softc *sc);
181 int schsio_wdt_cb(void *arg, int period);
182 
183 const struct cfattach schsio_ca = {
184 	sizeof(struct schsio_softc),
185 	schsio_probe,
186 	schsio_attach,
187 	NULL,
188 	schsio_activate
189 };
190 
191 struct cfdriver schsio_cd = {
192 	NULL, "schsio", DV_DULL
193 };
194 
195 static __inline void
schsio_config_enable(bus_space_tag_t iot,bus_space_handle_t ioh)196 schsio_config_enable(bus_space_tag_t iot, bus_space_handle_t ioh)
197 {
198 	bus_space_write_1(iot, ioh, SCHSIO_PORT_CONFIG, SCHSIO_CONFIG_ENTER);
199 }
200 
201 static __inline void
schsio_config_disable(bus_space_tag_t iot,bus_space_handle_t ioh)202 schsio_config_disable(bus_space_tag_t iot, bus_space_handle_t ioh)
203 {
204 	bus_space_write_1(iot, ioh, SCHSIO_PORT_CONFIG, SCHSIO_CONFIG_LEAVE);
205 }
206 
207 u_int8_t
schsio_config_read(bus_space_tag_t iot,bus_space_handle_t ioh,u_int8_t reg)208 schsio_config_read(bus_space_tag_t iot, bus_space_handle_t ioh,
209     u_int8_t reg)
210 {
211 	bus_space_write_1(iot, ioh, SCHSIO_PORT_INDEX, reg);
212 	return (bus_space_read_1(iot, ioh, SCHSIO_PORT_DATA));
213 }
214 
215 void
schsio_config_write(bus_space_tag_t iot,bus_space_handle_t ioh,u_int8_t reg,u_int8_t val)216 schsio_config_write(bus_space_tag_t iot, bus_space_handle_t ioh,
217     u_int8_t reg, u_int8_t val)
218 {
219 	bus_space_write_1(iot, ioh, SCHSIO_PORT_INDEX, reg);
220 	bus_space_write_1(iot, ioh, SCHSIO_PORT_DATA, val);
221 }
222 
223 int
schsio_probe(struct device * parent,void * match,void * aux)224 schsio_probe(struct device *parent, void *match, void *aux)
225 {
226 	struct isa_attach_args *ia = aux;
227 	bus_space_tag_t iot;
228 	bus_space_handle_t ioh;
229 	u_int8_t reg;
230 
231 	/* Match by device ID */
232 	iot = ia->ia_iot;
233 	if (bus_space_map(iot, ia->ipa_io[0].base, SCHSIO_IOSIZE, 0, &ioh))
234 		return (0);
235 
236 	schsio_config_enable(iot, ioh);
237 	reg = schsio_config_read(iot, ioh, SCHSIO_IDX_DEVICE);
238 	schsio_config_disable(iot, ioh);
239 
240 	bus_space_unmap(iot, ia->ipa_io[0].base, SCHSIO_IOSIZE);
241 
242 	switch (reg) {
243 	case SCHSIO_ID_SCH3112:
244 	case SCHSIO_ID_SCH3114:
245 	case SCHSIO_ID_SCH3116:
246 		ia->ipa_nio = 1;
247 		ia->ipa_io[0].length = SCHSIO_IOSIZE;
248 		ia->ipa_nmem = 0;
249 		ia->ipa_nirq = 0;
250 		ia->ipa_ndrq = 0;
251 		ia->ia_aux = (void *)(u_long) reg;
252 
253 		return (1);
254 		break;
255 	}
256 
257 	return (0);
258 }
259 
260 void
schsio_attach(struct device * parent,struct device * self,void * aux)261 schsio_attach(struct device *parent, struct device *self, void *aux)
262 {
263 	struct schsio_softc *sc = (void *)self;
264 	struct isa_attach_args *ia = aux;
265 	u_int16_t iobase;
266 	u_int8_t reg0, reg1;
267 
268 	/* Map ISA I/O space */
269 	sc->sc_iot = ia->ia_iot;
270 	if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base,
271 	    SCHSIO_IOSIZE, 0, &sc->sc_ioh)) {
272 		printf(": can't map i/o space\n");
273 		return;
274 	}
275 
276 	/* Enter configuration mode */
277 	schsio_config_enable(sc->sc_iot, sc->sc_ioh);
278 
279 	/* Check device ID */
280 	reg0 = (u_int8_t)(u_long) ia->ia_aux;
281 	switch (reg0) {
282 	case SCHSIO_ID_SCH3112:
283 		printf(": SCH3112");
284 		break;
285 	case SCHSIO_ID_SCH3114:
286 		printf(": SCH3114");
287 		break;
288 	case SCHSIO_ID_SCH3116:
289 		printf(": SCH3116");
290 		break;
291 	}
292 
293 	/* Read device revision */
294 	reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_REV);
295 	printf(" rev 0x%02x", reg0);
296 
297 	/* Select runtime registers logical device */
298 	schsio_config_write(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_LDEVSEL,
299 	    SCHSIO_LDEV_RUNTIME);
300 
301 	reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh,
302 	    SCHSIO_IDX_BASE_HI);
303 	reg1 = schsio_config_read(sc->sc_iot, sc->sc_ioh,
304 	    SCHSIO_IDX_BASE_LO);
305 	iobase = (reg0 << 8) | reg1;
306 
307 	if (bus_space_map(sc->sc_iot, iobase, SCHSIO_LDEV_RUNTIME_SZ,
308 	    0, &sc->sc_ioh_rr)) {
309 		printf(": can't map i/o space\n");
310 		return;
311 	}
312 
313 	schsio_wdt_init(sc);
314 	schsio_hwm_init(sc);
315 
316 	printf("\n");
317 
318 	/* Escape from configuration mode */
319 	schsio_config_disable(sc->sc_iot, sc->sc_ioh);
320 }
321 
322 int
schsio_activate(struct device * self,int act)323 schsio_activate(struct device *self, int act)
324 {
325 	switch (act) {
326 	case DVACT_POWERDOWN:
327 		wdog_shutdown(self);
328 		break;
329 	}
330 
331 	return (0);
332 }
333 
334 void
schsio_hwm_init(struct schsio_softc * sc)335 schsio_hwm_init(struct schsio_softc *sc)
336 {
337 	int i;
338 
339 	/* Set up sensors */
340 	for (i = SCHSIO_SENSOR_FAN1; i < SCHSIO_SENSOR_FAN3 + 1; i++)
341 		sc->sc_sensor[i].type = SENSOR_FANRPM;
342 
343 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT1].desc, "+2.5V",
344 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT1].desc));
345 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT2].desc, "+1.5V (Vccp)",
346 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT2].desc));
347 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT3].desc, "+3.3V (VCC)",
348 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT3].desc));
349 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT4].desc, "+5V",
350 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT4].desc));
351 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT5].desc, "+12V",
352 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT5].desc));
353 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT6].desc, "+3.3V (VTR)",
354 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT6].desc));
355 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT7].desc, "+3V (Vbat)",
356 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT7].desc));
357 	for (i = SCHSIO_SENSOR_VOLT1; i < SCHSIO_SENSOR_VOLT7 + 1; i++)
358 		sc->sc_sensor[i].type = SENSOR_VOLTS_DC;
359 
360 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP1].desc, "Internal",
361 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP1].desc));
362 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP2].desc, "Remote",
363 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP2].desc));
364 	strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP3].desc, "Remote",
365 	    sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP3].desc));
366 	for (i = SCHSIO_SENSOR_TEMP1; i < SCHSIO_SENSOR_TEMP3 + 1; i++)
367 		sc->sc_sensor[i].type = SENSOR_TEMP;
368 
369 	strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
370 	    sizeof(sc->sc_sensordev.xname));
371 
372 	for (i = 0; i < SCHSIO_SENSORS; i++)
373 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
374 
375 	if (sensor_task_register(sc, schsio_hwm_update,
376 	    SCHSIO_HWM_INTERVAL) == NULL) {
377 		printf(": unable to register update task");
378 		return;
379 	}
380 	sensordev_install(&sc->sc_sensordev);
381 }
382 
383 void
schsio_hwm_update(void * arg)384 schsio_hwm_update(void *arg)
385 {
386 	struct schsio_softc *sc;
387 	u_int16_t tach;
388 	int8_t temp;
389 	u_int8_t volt;
390 	u_int8_t reg0, reg1;
391 
392 	sc = (struct schsio_softc *)arg;
393 
394 	reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_L);
395 	reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_U);
396 	tach = (reg1 << 8) | reg0;
397 	sc->sc_sensor[SCHSIO_SENSOR_FAN1].value = SCHSIO_FAN_RPM(tach);
398 	sc->sc_sensor[SCHSIO_SENSOR_FAN1].flags =
399 	    (tach == 0xffff) ? SENSOR_FINVALID : 0;
400 
401 	reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH2_L);
402 	reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH2_U);
403 	tach = (reg1 << 8) | reg0;
404 	sc->sc_sensor[SCHSIO_SENSOR_FAN2].value = SCHSIO_FAN_RPM(tach);
405 	sc->sc_sensor[SCHSIO_SENSOR_FAN2].flags =
406 	    (tach == 0xffff) ? SENSOR_FINVALID : 0;
407 
408 	reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH3_L);
409 	reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH3_U);
410 	tach = (reg1 << 8) | reg0;
411 	sc->sc_sensor[SCHSIO_SENSOR_FAN3].value = SCHSIO_FAN_RPM(tach);
412 	sc->sc_sensor[SCHSIO_SENSOR_FAN3].flags =
413 	    (tach == 0xffff) ? SENSOR_FINVALID : 0;
414 
415 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT1);
416 	sc->sc_sensor[SCHSIO_SENSOR_VOLT1].value =
417 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT1);
418 
419 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT2);
420 	sc->sc_sensor[SCHSIO_SENSOR_VOLT2].value =
421 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT2);
422 
423 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT3);
424 	sc->sc_sensor[SCHSIO_SENSOR_VOLT3].value =
425 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT3);
426 
427 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT4);
428 	sc->sc_sensor[SCHSIO_SENSOR_VOLT4].value =
429 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT4);
430 
431 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT5);
432 	sc->sc_sensor[SCHSIO_SENSOR_VOLT5].value =
433 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT5);
434 
435 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT6);
436 	sc->sc_sensor[SCHSIO_SENSOR_VOLT6].value =
437 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT6);
438 
439 	volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT7);
440 	sc->sc_sensor[SCHSIO_SENSOR_VOLT7].value =
441 	    SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT7);
442 
443 	temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP1);
444 	sc->sc_sensor[SCHSIO_SENSOR_TEMP1].value = SCHSIO_TEMP_MUK(temp);
445 	sc->sc_sensor[SCHSIO_SENSOR_TEMP1].flags =
446 	    ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
447 
448 	temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP2);
449 	sc->sc_sensor[SCHSIO_SENSOR_TEMP2].value = SCHSIO_TEMP_MUK(temp);
450 	sc->sc_sensor[SCHSIO_SENSOR_TEMP2].flags =
451 	    ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
452 
453 	temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP3);
454 	sc->sc_sensor[SCHSIO_SENSOR_TEMP3].value = SCHSIO_TEMP_MUK(temp);
455 	sc->sc_sensor[SCHSIO_SENSOR_TEMP3].flags =
456 	    ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
457 
458 }
459 
460 u_int8_t
schsio_hwm_read(struct schsio_softc * sc,u_int8_t reg)461 schsio_hwm_read(struct schsio_softc *sc, u_int8_t reg)
462 {
463 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_INDEX, reg);
464 	return (bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_DATA));
465 }
466 
467 void
schsio_wdt_init(struct schsio_softc * sc)468 schsio_wdt_init(struct schsio_softc *sc)
469 {
470 	u_int8_t reg;
471 
472 	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO);
473 	if ((reg & SCHSIO_WDT_GPIO_MASK) != SCHSIO_WDT_GPIO_OUT) {
474 		if (sc->sc_dev.dv_cfdata->cf_flags & SCHSIO_CFFLAGS_WDTEN) {
475 			reg &= ~0x0f;
476 			reg |= SCHSIO_WDT_GPIO_OUT;
477 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
478 			    SCHSIO_WDT_GPIO, reg);
479 		}
480 		else {
481 			printf(", watchdog disabled");
482 			return;
483 		}
484 	}
485 
486 	/* First of all, make sure the wdt is disabled */
487 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, 0);
488 
489 	/* Clear triggered status */
490 	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CTRL);
491 	if (reg & SCHSIO_WDT_CTRL_TRIGGERED) {
492 		printf(", warning: watchdog triggered");
493 		reg &= ~SCHSIO_WDT_CTRL_TRIGGERED;
494 		bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
495 		    SCHSIO_WDT_CTRL, reg);
496 	}
497 
498 	/* Disable wdt reset by mouse and kbd */
499 	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG);
500 	reg &= ~(SCHSIO_WDT_CFG_MSEN | SCHSIO_WDT_CFG_KBDEN);
501 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG, reg);
502 
503 	wdog_register(schsio_wdt_cb, sc);
504 }
505 
506 int
schsio_wdt_cb(void * arg,int period)507 schsio_wdt_cb(void *arg, int period)
508 {
509 	struct schsio_softc *sc;
510 	uint8_t val, minute, reg;
511 
512 	sc = (struct schsio_softc *)arg;
513 
514 	if (period > 255) {
515 		val = period / 60;
516 		minute = 1;
517 	} else {
518 		val = period;
519 		minute = 0;
520 	}
521 
522 	/* Set unit */
523 	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr,
524 	    SCHSIO_WDT_TIMEOUT);
525 	if (!minute)
526 		reg |= SCHSIO_WDT_TO_SECONDS;
527 	else
528 		reg &= ~SCHSIO_WDT_TO_SECONDS;
529 
530 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_TIMEOUT,
531 	    reg);
532 
533 	/* Set value */
534 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, val);
535 
536 	if (!minute)
537 		return val;
538 	else
539 		return val * 60;
540 }
541 
542