Line data Source code
1 : /* $OpenBSD: sch311x.c,v 1.17 2017/09/08 05:36:52 deraadt 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 : 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
196 0 : schsio_config_enable(bus_space_tag_t iot, bus_space_handle_t ioh)
197 : {
198 0 : bus_space_write_1(iot, ioh, SCHSIO_PORT_CONFIG, SCHSIO_CONFIG_ENTER);
199 0 : }
200 :
201 : static __inline void
202 0 : schsio_config_disable(bus_space_tag_t iot, bus_space_handle_t ioh)
203 : {
204 0 : bus_space_write_1(iot, ioh, SCHSIO_PORT_CONFIG, SCHSIO_CONFIG_LEAVE);
205 0 : }
206 :
207 : u_int8_t
208 0 : schsio_config_read(bus_space_tag_t iot, bus_space_handle_t ioh,
209 : u_int8_t reg)
210 : {
211 0 : bus_space_write_1(iot, ioh, SCHSIO_PORT_INDEX, reg);
212 0 : return (bus_space_read_1(iot, ioh, SCHSIO_PORT_DATA));
213 : }
214 :
215 : void
216 0 : schsio_config_write(bus_space_tag_t iot, bus_space_handle_t ioh,
217 : u_int8_t reg, u_int8_t val)
218 : {
219 0 : bus_space_write_1(iot, ioh, SCHSIO_PORT_INDEX, reg);
220 0 : bus_space_write_1(iot, ioh, SCHSIO_PORT_DATA, val);
221 0 : }
222 :
223 : int
224 0 : schsio_probe(struct device *parent, void *match, void *aux)
225 : {
226 0 : struct isa_attach_args *ia = aux;
227 : bus_space_tag_t iot;
228 0 : bus_space_handle_t ioh;
229 : u_int8_t reg;
230 :
231 : /* Match by device ID */
232 0 : iot = ia->ia_iot;
233 0 : if (bus_space_map(iot, ia->ipa_io[0].base, SCHSIO_IOSIZE, 0, &ioh))
234 0 : return (0);
235 :
236 0 : schsio_config_enable(iot, ioh);
237 0 : reg = schsio_config_read(iot, ioh, SCHSIO_IDX_DEVICE);
238 0 : schsio_config_disable(iot, ioh);
239 :
240 0 : bus_space_unmap(iot, ia->ipa_io[0].base, SCHSIO_IOSIZE);
241 :
242 0 : switch (reg) {
243 : case SCHSIO_ID_SCH3112:
244 : case SCHSIO_ID_SCH3114:
245 : case SCHSIO_ID_SCH3116:
246 0 : ia->ipa_nio = 1;
247 0 : ia->ipa_io[0].length = SCHSIO_IOSIZE;
248 0 : ia->ipa_nmem = 0;
249 0 : ia->ipa_nirq = 0;
250 0 : ia->ipa_ndrq = 0;
251 0 : ia->ia_aux = (void *)(u_long) reg;
252 :
253 0 : return (1);
254 : break;
255 : }
256 :
257 0 : return (0);
258 0 : }
259 :
260 : void
261 0 : schsio_attach(struct device *parent, struct device *self, void *aux)
262 : {
263 0 : struct schsio_softc *sc = (void *)self;
264 0 : 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 0 : sc->sc_iot = ia->ia_iot;
270 0 : if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base,
271 0 : SCHSIO_IOSIZE, 0, &sc->sc_ioh)) {
272 0 : printf(": can't map i/o space\n");
273 0 : return;
274 : }
275 :
276 : /* Enter configuration mode */
277 0 : schsio_config_enable(sc->sc_iot, sc->sc_ioh);
278 :
279 : /* Check device ID */
280 0 : reg0 = (u_int8_t)(u_long) ia->ia_aux;
281 0 : switch (reg0) {
282 : case SCHSIO_ID_SCH3112:
283 0 : printf(": SCH3112");
284 0 : break;
285 : case SCHSIO_ID_SCH3114:
286 0 : printf(": SCH3114");
287 0 : break;
288 : case SCHSIO_ID_SCH3116:
289 0 : printf(": SCH3116");
290 0 : break;
291 : }
292 :
293 : /* Read device revision */
294 0 : reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_REV);
295 0 : printf(" rev 0x%02x", reg0);
296 :
297 : /* Select runtime registers logical device */
298 0 : schsio_config_write(sc->sc_iot, sc->sc_ioh, SCHSIO_IDX_LDEVSEL,
299 : SCHSIO_LDEV_RUNTIME);
300 :
301 0 : reg0 = schsio_config_read(sc->sc_iot, sc->sc_ioh,
302 : SCHSIO_IDX_BASE_HI);
303 0 : reg1 = schsio_config_read(sc->sc_iot, sc->sc_ioh,
304 : SCHSIO_IDX_BASE_LO);
305 0 : iobase = (reg0 << 8) | reg1;
306 :
307 0 : if (bus_space_map(sc->sc_iot, iobase, SCHSIO_LDEV_RUNTIME_SZ,
308 0 : 0, &sc->sc_ioh_rr)) {
309 0 : printf(": can't map i/o space\n");
310 0 : return;
311 : }
312 :
313 0 : schsio_wdt_init(sc);
314 0 : schsio_hwm_init(sc);
315 :
316 0 : printf("\n");
317 :
318 : /* Escape from configuration mode */
319 0 : schsio_config_disable(sc->sc_iot, sc->sc_ioh);
320 0 : }
321 :
322 : int
323 0 : schsio_activate(struct device *self, int act)
324 : {
325 0 : switch (act) {
326 : case DVACT_POWERDOWN:
327 0 : wdog_shutdown(self);
328 0 : break;
329 : }
330 :
331 0 : return (0);
332 : }
333 :
334 : void
335 0 : schsio_hwm_init(struct schsio_softc *sc)
336 : {
337 : int i;
338 :
339 : /* Set up sensors */
340 0 : for (i = SCHSIO_SENSOR_FAN1; i < SCHSIO_SENSOR_FAN3 + 1; i++)
341 0 : sc->sc_sensor[i].type = SENSOR_FANRPM;
342 :
343 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT1].desc, "+2.5V",
344 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT1].desc));
345 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT2].desc, "+1.5V (Vccp)",
346 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT2].desc));
347 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT3].desc, "+3.3V (VCC)",
348 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT3].desc));
349 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT4].desc, "+5V",
350 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT4].desc));
351 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT5].desc, "+12V",
352 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT5].desc));
353 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT6].desc, "+3.3V (VTR)",
354 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT6].desc));
355 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_VOLT7].desc, "+3V (Vbat)",
356 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_VOLT7].desc));
357 0 : for (i = SCHSIO_SENSOR_VOLT1; i < SCHSIO_SENSOR_VOLT7 + 1; i++)
358 0 : sc->sc_sensor[i].type = SENSOR_VOLTS_DC;
359 :
360 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP1].desc, "Internal",
361 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP1].desc));
362 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP2].desc, "Remote",
363 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP2].desc));
364 0 : strlcpy(sc->sc_sensor[SCHSIO_SENSOR_TEMP3].desc, "Remote",
365 : sizeof(sc->sc_sensor[SCHSIO_SENSOR_TEMP3].desc));
366 0 : for (i = SCHSIO_SENSOR_TEMP1; i < SCHSIO_SENSOR_TEMP3 + 1; i++)
367 0 : sc->sc_sensor[i].type = SENSOR_TEMP;
368 :
369 0 : strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
370 : sizeof(sc->sc_sensordev.xname));
371 :
372 0 : for (i = 0; i < SCHSIO_SENSORS; i++)
373 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
374 :
375 0 : if (sensor_task_register(sc, schsio_hwm_update,
376 0 : SCHSIO_HWM_INTERVAL) == NULL) {
377 0 : printf(": unable to register update task");
378 0 : return;
379 : }
380 0 : sensordev_install(&sc->sc_sensordev);
381 0 : }
382 :
383 : void
384 0 : 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 0 : sc = (struct schsio_softc *)arg;
393 :
394 0 : reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_L);
395 0 : reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH1_U);
396 0 : tach = (reg1 << 8) | reg0;
397 0 : sc->sc_sensor[SCHSIO_SENSOR_FAN1].value = SCHSIO_FAN_RPM(tach);
398 0 : sc->sc_sensor[SCHSIO_SENSOR_FAN1].flags =
399 0 : (tach == 0xffff) ? SENSOR_FINVALID : 0;
400 :
401 0 : reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH2_L);
402 0 : reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH2_U);
403 0 : tach = (reg1 << 8) | reg0;
404 0 : sc->sc_sensor[SCHSIO_SENSOR_FAN2].value = SCHSIO_FAN_RPM(tach);
405 0 : sc->sc_sensor[SCHSIO_SENSOR_FAN2].flags =
406 0 : (tach == 0xffff) ? SENSOR_FINVALID : 0;
407 :
408 0 : reg0 = schsio_hwm_read(sc, SCHSIO_HWM_TACH3_L);
409 0 : reg1 = schsio_hwm_read(sc, SCHSIO_HWM_TACH3_U);
410 0 : tach = (reg1 << 8) | reg0;
411 0 : sc->sc_sensor[SCHSIO_SENSOR_FAN3].value = SCHSIO_FAN_RPM(tach);
412 0 : sc->sc_sensor[SCHSIO_SENSOR_FAN3].flags =
413 0 : (tach == 0xffff) ? SENSOR_FINVALID : 0;
414 :
415 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT1);
416 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT1].value =
417 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT1);
418 :
419 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT2);
420 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT2].value =
421 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT2);
422 :
423 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT3);
424 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT3].value =
425 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT3);
426 :
427 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT4);
428 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT4].value =
429 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT4);
430 :
431 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT5);
432 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT5].value =
433 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT5);
434 :
435 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT6);
436 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT6].value =
437 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT6);
438 :
439 0 : volt = schsio_hwm_read(sc, SCHSIO_HWM_VOLT7);
440 0 : sc->sc_sensor[SCHSIO_SENSOR_VOLT7].value =
441 0 : SCHSIO_VOLT_MUV(volt, SCHSIO_CONV_VOLT7);
442 :
443 0 : temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP1);
444 0 : sc->sc_sensor[SCHSIO_SENSOR_TEMP1].value = SCHSIO_TEMP_MUK(temp);
445 0 : sc->sc_sensor[SCHSIO_SENSOR_TEMP1].flags =
446 0 : ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
447 :
448 0 : temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP2);
449 0 : sc->sc_sensor[SCHSIO_SENSOR_TEMP2].value = SCHSIO_TEMP_MUK(temp);
450 0 : sc->sc_sensor[SCHSIO_SENSOR_TEMP2].flags =
451 0 : ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
452 :
453 0 : temp = schsio_hwm_read(sc, SCHSIO_HWM_TEMP3);
454 0 : sc->sc_sensor[SCHSIO_SENSOR_TEMP3].value = SCHSIO_TEMP_MUK(temp);
455 0 : sc->sc_sensor[SCHSIO_SENSOR_TEMP3].flags =
456 0 : ((uint8_t)temp == 0x80) ? SENSOR_FINVALID : 0;
457 :
458 0 : }
459 :
460 : u_int8_t
461 0 : schsio_hwm_read(struct schsio_softc *sc, u_int8_t reg)
462 : {
463 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_INDEX, reg);
464 0 : return (bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_HWM_DATA));
465 : }
466 :
467 : void
468 0 : schsio_wdt_init(struct schsio_softc *sc)
469 : {
470 : u_int8_t reg;
471 :
472 0 : reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_GPIO);
473 0 : if ((reg & SCHSIO_WDT_GPIO_MASK) != SCHSIO_WDT_GPIO_OUT) {
474 0 : if (sc->sc_dev.dv_cfdata->cf_flags & SCHSIO_CFFLAGS_WDTEN) {
475 0 : reg &= ~0x0f;
476 0 : reg |= SCHSIO_WDT_GPIO_OUT;
477 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
478 : SCHSIO_WDT_GPIO, reg);
479 : }
480 : else {
481 0 : printf(", watchdog disabled");
482 0 : return;
483 : }
484 0 : }
485 :
486 : /* First of all, make sure the wdt is disabled */
487 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, 0);
488 :
489 : /* Clear triggered status */
490 0 : reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CTRL);
491 0 : if (reg & SCHSIO_WDT_CTRL_TRIGGERED) {
492 0 : printf(", warning: watchdog triggered");
493 0 : reg &= ~SCHSIO_WDT_CTRL_TRIGGERED;
494 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr,
495 : SCHSIO_WDT_CTRL, reg);
496 0 : }
497 :
498 : /* Disable wdt reset by mouse and kbd */
499 0 : reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG);
500 0 : reg &= ~(SCHSIO_WDT_CFG_MSEN | SCHSIO_WDT_CFG_KBDEN);
501 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_CFG, reg);
502 :
503 0 : wdog_register(schsio_wdt_cb, sc);
504 0 : }
505 :
506 : int
507 0 : schsio_wdt_cb(void *arg, int period)
508 : {
509 : struct schsio_softc *sc;
510 : uint8_t val, minute, reg;
511 :
512 0 : sc = (struct schsio_softc *)arg;
513 :
514 0 : if (period > 255) {
515 0 : val = period / 60;
516 : minute = 1;
517 0 : } else {
518 0 : val = period;
519 : minute = 0;
520 : }
521 :
522 : /* Set unit */
523 0 : reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_rr,
524 : SCHSIO_WDT_TIMEOUT);
525 0 : if (!minute)
526 0 : reg |= SCHSIO_WDT_TO_SECONDS;
527 : else
528 0 : reg &= ~SCHSIO_WDT_TO_SECONDS;
529 :
530 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_TIMEOUT,
531 : reg);
532 :
533 : /* Set value */
534 0 : bus_space_write_1(sc->sc_iot, sc->sc_ioh_rr, SCHSIO_WDT_VAL, val);
535 :
536 0 : if (!minute)
537 0 : return val;
538 : else
539 0 : return val * 60;
540 0 : }
541 :
|