xref: /openbsd-src/sys/dev/pci/viapm.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: viapm.c,v 1.14 2011/04/10 20:27:02 shadchin Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Mark Kettenis <kettenis@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 /*	$NetBSD: viaenv.c,v 1.9 2002/10/02 16:51:59 thorpej Exp $	*/
20 
21 /*
22  * Copyright (c) 2000 Johan Danielsson
23  * All rights reserved.
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions
27  * are met:
28  *
29  * 1. Redistributions of source code must retain the above copyright
30  *    notice, this list of conditions and the following disclaimer.
31  *
32  * 2. Redistributions in binary form must reproduce the above copyright
33  *    notice, this list of conditions and the following disclaimer in the
34  *    documentation and/or other materials provided with the distribution.
35  *
36  * 3. Neither the name of author nor the names of any contributors may
37  *    be used to endorse or promote products derived from this
38  *    software without specific prior written permission.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
41  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
45  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
46  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50  * POSSIBILITY OF SUCH DAMAGE.
51  */
52 
53 /*
54  * Driver for the SMBus controller and power management timer
55  * in the VIA VT82C596[B], VT82C686A, VT8231, VT8233[A], VT8235, VT8237[A,S],
56  * VT8251, CX700, VX800 and VX855 South Bridges.
57  * Also for the hardware monitoring part of the VIA VT82C686A and VT8231.
58  */
59 
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/device.h>
63 #include <sys/kernel.h>
64 #include <sys/rwlock.h>
65 #include <sys/sensors.h>
66 #include <sys/timeout.h>
67 #ifdef __HAVE_TIMECOUNTER
68 #include <sys/timetc.h>
69 #endif
70 
71 #include <machine/bus.h>
72 
73 #include <dev/pci/pcidevs.h>
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcivar.h>
76 
77 #include <dev/i2c/i2cvar.h>
78 
79 /*
80  * Register definitions.
81  */
82 
83 /* PCI configuration registers */
84 #define VIAPM_PM_CFG1		0x40	/* general configuration */
85 #define VIAPM_PM_CFG2		0x80
86 #define VIAPM_PM_CFG_TMR32	(1 << 11)	/* 32-bit PM timer */
87 #define VIAPM_PM_CFG_PMEN	(1 << 15)	/* enable PM I/O space */
88 #define VIAPM_PM_BASE1		0x48	/* power management I/O base address */
89 #define VIAPM_PM_BASE2		0x88
90 #define VIAPM_PM_BASE_MASK	0xff80
91 
92 #define VIAPM_HWMON_BASE	0x70	/* HWMon I/O base address */
93 #define VIAPM_HWMON_BASE_MASK	0xff80
94 #define VIAPM_HWMON_CFG		0x74	/* HWMon control register */
95 #define VIAPM_HWMON_CFG_HWEN	(1 << 0)	/* enable HWMon I/O space */
96 
97 #define VIAPM_SMB_BASE1		0x90	/* SMBus I/O base address */
98 #define VIAPM_SMB_BASE2		0x80
99 #define VIAPM_SMB_BASE3		0xd0
100 #define VIAPM_SMB_BASE_MASK	0xfff0
101 #define VIAPM_SMB_CFG1		0xd2	/* host configuration */
102 #define VIAPM_SMB_CFG2		0x84
103 #define VIAPM_SMB_CFG_HSTEN	(1 << 0)	/* enable SMBus I/O space */
104 #define VIAPM_SMB_CFG_INTEN	(1 << 1)	/* enable SCI/SMI */
105 #define VIAPM_SMB_CFG_SCIEN	(1 << 3)	/* interrupt type (SCI/SMI) */
106 
107 #define VIAPM_PM_SIZE		256	/* Power management I/O space size */
108 #define VIAPM_HWMON_SIZE	128	/* HWMon I/O space size */
109 #define VIAPM_SMB_SIZE		16	/* SMBus I/O space size */
110 
111 /* HWMon I/O registers */
112 #define VIAPM_HWMON_TSENS3	0x1f
113 #define VIAPM_HWMON_TSENS1	0x20
114 #define VIAPM_HWMON_TSENS2	0x21
115 #define VIAPM_HWMON_VSENS1	0x22
116 #define VIAPM_HWMON_VSENS2	0x23
117 #define VIAPM_HWMON_VCORE	0x24
118 #define VIAPM_HWMON_VSENS3	0x25
119 #define VIAPM_HWMON_VSENS4	0x26
120 #define VIAPM_HWMON_FAN1	0x29
121 #define VIAPM_HWMON_FAN2	0x2a
122 #define VIAPM_HWMON_FANCONF	0x47	/* fan configuration */
123 #define VIAPM_HWMON_TLOW	0x49	/* temperature low order value */
124 #define VIAPM_HWMON_TIRQ	0x4b	/* temperature interrupt configuration */
125 
126 /* ACPI I/O registers */
127 #define VIAPM_PM_TMR		0x08	/* PM timer */
128 
129 /* SMBus I/O registers */
130 #define VIAPM_SMB_HS		0x00	/* host status */
131 #define VIAPM_SMB_HS_BUSY	(1 << 0)	/* running a command */
132 #define VIAPM_SMB_HS_INTR	(1 << 1)	/* command completed */
133 #define VIAPM_SMB_HS_DEVERR	(1 << 2)	/* command error */
134 #define VIAPM_SMB_HS_BUSERR	(1 << 3)	/* transaction collision */
135 #define VIAPM_SMB_HS_FAILED	(1 << 4)	/* failed bus transaction */
136 #define VIAPM_SMB_HS_INUSE	(1 << 6)	/* bus semaphore */
137 #define VIAPM_SMB_HS_BITS	\
138   "\020\001BUSY\002INTR\003DEVERR\004BUSERR\005FAILED\007INUSE"
139 #define VIAPM_SMB_HC		0x02	/* host control */
140 #define VIAPM_SMB_HC_INTREN	(1 << 0)	/* enable interrupts */
141 #define VIAPM_SMB_HC_KILL	(1 << 1)	/* kill current transaction */
142 #define VIAPM_SMB_HC_CMD_QUICK	(0 << 2)	/* QUICK command */
143 #define VIAPM_SMB_HC_CMD_BYTE	(1 << 2)	/* BYTE command */
144 #define VIAPM_SMB_HC_CMD_BDATA	(2 << 2)	/* BYTE DATA command */
145 #define VIAPM_SMB_HC_CMD_WDATA	(3 << 2)	/* WORD DATA command */
146 #define VIAPM_SMB_HC_CMD_PCALL	(4 << 2)	/* PROCESS CALL command */
147 #define VIAPM_SMB_HC_CMD_BLOCK	(5 << 2)	/* BLOCK command */
148 #define VIAPM_SMB_HC_START	(1 << 6)	/* start transaction */
149 #define VIAPM_SMB_HCMD		0x03	/* host command */
150 #define VIAPM_SMB_TXSLVA	0x04	/* transmit slave address */
151 #define VIAPM_SMB_TXSLVA_READ	(1 << 0)	/* read direction */
152 #define VIAPM_SMB_TXSLVA_ADDR(x) (((x) & 0x7f) << 1) /* 7-bit address */
153 #define VIAPM_SMB_HD0		0x05	/* host data 0 */
154 #define VIAPM_SMB_HD1		0x06	/* host data 1 */
155 #define VIAPM_SMB_HBDB		0x07	/* host block data byte */
156 
157 #ifdef VIAPM_DEBUG
158 #define DPRINTF(x...) printf(x)
159 #else
160 #define DPRINTF(x...)
161 #endif
162 
163 #define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
164 
165 #define VIAPM_SMBUS_DELAY	100
166 #define VIAPM_SMBUS_TIMEOUT	1
167 
168 #define VIAPM_NUM_SENSORS	10	/* three temp, two fan, five voltage */
169 
170 #ifdef __HAVE_TIMECOUNTER
171 u_int	viapm_get_timecount(struct timecounter *tc);
172 
173 #ifndef VIAPM_FREQUENCY
174 #define VIAPM_FREQUENCY 3579545
175 #endif
176 
177 static struct timecounter viapm_timecounter = {
178 	viapm_get_timecount,	/* get_timecount */
179 	0,			/* no poll_pps */
180 	0xffffff,		/* counter_mask */
181 	VIAPM_FREQUENCY,	/* frequency */
182 	"VIAPM",		/* name */
183 	1000			/* quality */
184 };
185 #endif	/* __HAVE_TIMECOUNTER */
186 
187 struct timeout viapm_timeout;
188 
189 struct viapm_softc {
190 	struct device		sc_dev;
191 
192 	bus_space_tag_t		sc_iot;
193 	bus_space_handle_t	sc_pm_ioh;
194 	bus_space_handle_t	sc_smbus_ioh;
195 	bus_space_handle_t	sc_hwmon_ioh;
196 	void *			sc_ih;
197 	int			sc_poll;
198 
199 	int			sc_fan_div[2];	/* fan RPM divisor */
200 
201 	struct ksensor		sc_data[VIAPM_NUM_SENSORS];
202 	struct ksensordev	sc_sensordev;
203 
204 	struct i2c_controller	sc_i2c_tag;
205 	struct rwlock		sc_i2c_lock;
206 	struct {
207 		i2c_op_t     op;
208 		void *       buf;
209 		size_t       len;
210 		int          flags;
211 		volatile int error;
212 	}			sc_i2c_xfer;
213 };
214 
215 int	viapm_match(struct device *, void *, void *);
216 void	viapm_attach(struct device *, struct device *, void *);
217 
218 int	viapm_i2c_acquire_bus(void *, int);
219 void	viapm_i2c_release_bus(void *, int);
220 int	viapm_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
221 	    void *, size_t, int);
222 
223 int	viapm_intr(void *);
224 
225 int	val_to_uK(unsigned int);
226 int	val_to_rpm(unsigned int, int);
227 long	val_to_uV(unsigned int, int);
228 void	viapm_refresh_sensor_data(struct viapm_softc *);
229 void	viapm_refresh(void *);
230 
231 struct cfattach viapm_ca = {
232 	sizeof(struct viapm_softc), viapm_match, viapm_attach
233 };
234 
235 struct cfdriver viapm_cd = {
236 	NULL, "viapm", DV_DULL
237 };
238 
239 const struct pci_matchid viapm_ids[] = {
240 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596 },
241 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596B_PM },
242 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_SMB },
243 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8231_PWR },
244 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8233_ISA },
245 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8233A_ISA },
246 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8235_ISA },
247 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8237_ISA },
248 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8237A_ISA },
249 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8237S_ISA },
250 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8251_ISA },
251 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_CX700_ISA },
252 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VX800_ISA },
253 	{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VX855_ISA }
254 };
255 
256 /*
257  * XXX there doesn't seem to exist much hard documentation on how to
258  * convert the raw values to usable units, this code is more or less
259  * stolen from the Linux driver, but changed to suit our conditions
260  */
261 
262 /*
263  * lookup-table to translate raw values to uK, this is the same table
264  * used by the Linux driver (modulo units); there is a fifth degree
265  * polynomial that supposedly been used to generate this table, but I
266  * haven't been able to figure out how -- it doesn't give the same values
267  */
268 
269 static const long val_to_temp[] = {
270 	20225, 20435, 20645, 20855, 21045, 21245, 21425, 21615, 21785, 21955,
271 	22125, 22285, 22445, 22605, 22755, 22895, 23035, 23175, 23315, 23445,
272 	23565, 23695, 23815, 23925, 24045, 24155, 24265, 24365, 24465, 24565,
273 	24665, 24765, 24855, 24945, 25025, 25115, 25195, 25275, 25355, 25435,
274 	25515, 25585, 25655, 25725, 25795, 25865, 25925, 25995, 26055, 26115,
275 	26175, 26235, 26295, 26355, 26405, 26465, 26515, 26575, 26625, 26675,
276 	26725, 26775, 26825, 26875, 26925, 26975, 27025, 27065, 27115, 27165,
277 	27205, 27255, 27295, 27345, 27385, 27435, 27475, 27515, 27565, 27605,
278 	27645, 27685, 27735, 27775, 27815, 27855, 27905, 27945, 27985, 28025,
279 	28065, 28105, 28155, 28195, 28235, 28275, 28315, 28355, 28405, 28445,
280 	28485, 28525, 28565, 28615, 28655, 28695, 28735, 28775, 28825, 28865,
281 	28905, 28945, 28995, 29035, 29075, 29125, 29165, 29205, 29245, 29295,
282 	29335, 29375, 29425, 29465, 29505, 29555, 29595, 29635, 29685, 29725,
283 	29765, 29815, 29855, 29905, 29945, 29985, 30035, 30075, 30125, 30165,
284 	30215, 30255, 30305, 30345, 30385, 30435, 30475, 30525, 30565, 30615,
285 	30655, 30705, 30755, 30795, 30845, 30885, 30935, 30975, 31025, 31075,
286 	31115, 31165, 31215, 31265, 31305, 31355, 31405, 31455, 31505, 31545,
287 	31595, 31645, 31695, 31745, 31805, 31855, 31905, 31955, 32005, 32065,
288 	32115, 32175, 32225, 32285, 32335, 32395, 32455, 32515, 32575, 32635,
289 	32695, 32755, 32825, 32885, 32955, 33025, 33095, 33155, 33235, 33305,
290 	33375, 33455, 33525, 33605, 33685, 33765, 33855, 33935, 34025, 34115,
291 	34205, 34295, 34395, 34495, 34595, 34695, 34805, 34905, 35015, 35135,
292 	35245, 35365, 35495, 35615, 35745, 35875, 36015, 36145, 36295, 36435,
293 	36585, 36745, 36895, 37065, 37225, 37395, 37575, 37755, 37935, 38125,
294 	38325, 38525, 38725, 38935, 39155, 39375, 39605, 39835, 40075, 40325,
295 	40575, 40835, 41095, 41375, 41655, 41935,
296 };
297 
298 int
299 viapm_match(struct device *parent, void *match, void *aux)
300 {
301 	return (pci_matchbyid(aux, viapm_ids, nitems(viapm_ids)));
302 }
303 
304 void
305 viapm_attach(struct device *parent, struct device *self, void *aux)
306 {
307 	struct viapm_softc *sc = (struct viapm_softc *)self;
308 	struct pci_attach_args *pa = aux;
309 	struct i2cbus_attach_args iba;
310 	pcireg_t conf, iobase;
311 	pci_intr_handle_t ih;
312 	const char *intrstr = NULL;
313 	int basereg, cfgreg;
314 	int i, v;
315 
316 	sc->sc_iot = pa->pa_iot;
317 
318 	/* SMBus */
319 	switch (PCI_PRODUCT(pa->pa_id)) {
320 	case PCI_PRODUCT_VIATECH_VT82C596:
321 	case PCI_PRODUCT_VIATECH_VT82C596B_PM:
322 	case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
323 	case PCI_PRODUCT_VIATECH_VT8231_PWR:
324 		basereg = VIAPM_SMB_BASE1;
325 		break;
326 	default:
327 		basereg = VIAPM_SMB_BASE3;
328 	}
329 
330 	cfgreg = (VIAPM_SMB_CFG1 & (~0x03));	/* XXX 4-byte aligned */
331 
332 	/* Check 2nd address for VT82C596 */
333 	iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, basereg);
334 	if ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT82C596) &&
335 	    ((iobase & 0x0001) == 0)) {
336 		iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAPM_SMB_BASE2);
337 		cfgreg = VIAPM_SMB_CFG2;
338 	}
339 
340 	/* Check if SMBus I/O space is enabled */
341 	conf = pci_conf_read(pa->pa_pc, pa->pa_tag, cfgreg);
342 	if (cfgreg != VIAPM_SMB_CFG2)
343 		conf >>= 16;
344 	DPRINTF(": conf 0x%02x", conf & 0xff);
345 
346 	if ((conf & VIAPM_SMB_CFG_HSTEN) == 0) {
347 		printf(": SMBus disabled\n");
348 		goto nosmb;
349 	}
350 
351 	/* Map SMBus I/O space */
352 	iobase &= VIAPM_SMB_BASE_MASK;
353 	if (iobase == 0 || bus_space_map(sc->sc_iot, iobase,
354 	    VIAPM_SMB_SIZE, 0, &sc->sc_smbus_ioh)) {
355 		printf(": can't map SMBus i/o space\n");
356 		goto nosmb;
357 	}
358 
359 	sc->sc_poll = 1;
360 	if ((conf & VIAPM_SMB_CFG_SCIEN) == 0) {
361 		/* No PCI IRQ */
362 		printf(": SMI");
363 	} else {
364 		/* Install interrupt handler */
365 		if (pci_intr_map(pa, &ih) == 0) {
366 			intrstr = pci_intr_string(pa->pa_pc, ih);
367 			sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
368 			    viapm_intr, sc, DEVNAME(sc));
369 			if (sc->sc_ih != NULL) {
370 				printf(": %s", intrstr);
371 				sc->sc_poll = 0;
372 			}
373 		}
374 		if (sc->sc_poll)
375 			printf(": polling");
376 	}
377 
378 	printf("\n");
379 
380 	/* Attach I2C bus */
381 	rw_init(&sc->sc_i2c_lock, "iiclk");
382 	sc->sc_i2c_tag.ic_cookie = sc;
383 	sc->sc_i2c_tag.ic_acquire_bus = viapm_i2c_acquire_bus;
384 	sc->sc_i2c_tag.ic_release_bus = viapm_i2c_release_bus;
385 	sc->sc_i2c_tag.ic_exec = viapm_i2c_exec;
386 
387 	bzero(&iba, sizeof iba);
388 	iba.iba_name = "iic";
389 	iba.iba_tag = &sc->sc_i2c_tag;
390 	config_found(self, &iba, iicbus_print);
391 
392 nosmb:
393 
394 #ifdef __HAVE_TIMECOUNTER
395 	/* Power management */
396 	switch (PCI_PRODUCT(pa->pa_id)) {
397 	case PCI_PRODUCT_VIATECH_VT82C596:
398 	case PCI_PRODUCT_VIATECH_VT82C596B_PM:
399 	case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
400 	case PCI_PRODUCT_VIATECH_VT8231_PWR:
401 		basereg = VIAPM_PM_BASE1;
402 		cfgreg = VIAPM_PM_CFG1;
403 		break;
404 	default:
405 		basereg = VIAPM_PM_BASE2;
406 		cfgreg = VIAPM_PM_CFG2;
407 	}
408 
409 	/* Check if power management I/O space is enabled */
410 	conf = pci_conf_read(pa->pa_pc, pa->pa_tag, cfgreg);
411 	if ((conf & VIAPM_PM_CFG_PMEN) == 0) {
412 		printf("%s: PM disabled\n", DEVNAME(sc));
413 		goto nopm;
414 	}
415 
416 	/* Map power management I/O space */
417 	iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, basereg);
418 	iobase &= VIAPM_PM_BASE_MASK;
419 	if (iobase == 0 || bus_space_map(sc->sc_iot, iobase,
420 	    VIAPM_PM_SIZE, 0, &sc->sc_pm_ioh)) {
421 		/* XXX can't map PM i/o space if ACPI mode */
422 		DPRINTF("%s: can't map PM i/o space\n", DEVNAME(sc));
423 		goto nopm;
424 	}
425 
426 	/* Check for 32-bit PM timer */
427 	if (conf & VIAPM_PM_CFG_TMR32)
428 		viapm_timecounter.tc_counter_mask = 0xffffffff;
429 
430 	/* Register new timecounter */
431 	viapm_timecounter.tc_priv = sc;
432 	tc_init(&viapm_timecounter);
433 
434 	printf("%s: %s-bit timer at %lluHz\n", DEVNAME(sc),
435 	    (viapm_timecounter.tc_counter_mask == 0xffffffff ? "32" : "24"),
436 	    (unsigned long long)viapm_timecounter.tc_frequency);
437 
438 nopm:
439 #endif	/* __HAVE_TIMECOUNTER */
440 
441 	/* HWMon */
442 	switch (PCI_PRODUCT(pa->pa_id)) {
443 	case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
444 	case PCI_PRODUCT_VIATECH_VT8231_PWR:
445 		break;
446 	default:
447 		return;
448 	}
449 
450 	/* Check if HWMon I/O space is enabled */
451 	conf = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAPM_HWMON_CFG);
452 	if ((conf & VIAPM_HWMON_CFG_HWEN) == 0) {
453 		printf("%s: HWM disabled\n", DEVNAME(sc));
454 		return;
455 	}
456 
457 	/* Map HWMon I/O space */
458 	iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAPM_HWMON_BASE);
459 	iobase &= VIAPM_HWMON_BASE_MASK;
460 	if (iobase == 0 || bus_space_map(sc->sc_iot, iobase,
461 	    VIAPM_HWMON_SIZE, 0, &sc->sc_hwmon_ioh)) {
462 		printf("%s: can't map HWM i/o space\n", DEVNAME(sc));
463 		return;
464 	}
465 
466 	v = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh, VIAPM_HWMON_FANCONF);
467 
468 	sc->sc_fan_div[0] = 1 << ((v >> 4) & 0x3);
469 	sc->sc_fan_div[1] = 1 << ((v >> 6) & 0x3);
470 
471 	for (i = 0; i <= 2; i++)
472 		sc->sc_data[i].type = SENSOR_TEMP;
473 	for (i = 3; i <= 4; i++)
474 		sc->sc_data[i].type = SENSOR_FANRPM;
475 	for (i = 5; i <= 9; ++i)
476 		sc->sc_data[i].type = SENSOR_VOLTS_DC;
477 
478 	strlcpy(sc->sc_data[5].desc, "VSENS1",
479 	    sizeof(sc->sc_data[5].desc));	/* CPU core (2V) */
480 	strlcpy(sc->sc_data[6].desc, "VSENS2",
481 	    sizeof(sc->sc_data[6].desc));	/* NB core? (2.5V) */
482 	strlcpy(sc->sc_data[7].desc, "Vcore",
483 	    sizeof(sc->sc_data[7].desc));	/* Vcore (3.3V) */
484 	strlcpy(sc->sc_data[8].desc, "VSENS3",
485 	    sizeof(sc->sc_data[8].desc));	/* VSENS3 (5V) */
486 	strlcpy(sc->sc_data[9].desc, "VSENS4",
487 	    sizeof(sc->sc_data[9].desc));	/* VSENS4 (12V) */
488 
489 	/* Get initial set of sensor values. */
490 	viapm_refresh_sensor_data(sc);
491 
492 	/* Register sensors with sysctl */
493 	strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
494 	    sizeof(sc->sc_sensordev.xname));
495 	for (i = 0; i < VIAPM_NUM_SENSORS; ++i)
496 		sensor_attach(&sc->sc_sensordev, &sc->sc_data[i]);
497 	sensordev_install(&sc->sc_sensordev);
498 
499 	/* Refresh sensors data every 1.5 seconds */
500 	timeout_set(&viapm_timeout, viapm_refresh, sc);
501 	timeout_add_msec(&viapm_timeout, 1500);
502 }
503 
504 int
505 viapm_i2c_acquire_bus(void *cookie, int flags)
506 {
507 	struct viapm_softc *sc = cookie;
508 
509 	if (cold || sc->sc_poll || (flags & I2C_F_POLL))
510 		return (0);
511 
512 	return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR));
513 }
514 
515 void
516 viapm_i2c_release_bus(void *cookie, int flags)
517 {
518 	struct viapm_softc *sc = cookie;
519 
520 	if (cold || sc->sc_poll || (flags & I2C_F_POLL))
521 		return;
522 
523 	rw_exit(&sc->sc_i2c_lock);
524 }
525 
526 int
527 viapm_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
528     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
529 {
530 	struct viapm_softc *sc = cookie;
531 	u_int8_t *b;
532 	u_int8_t ctl, st;
533 	int retries;
534 
535 	/* Check if there's a transfer already running */
536 	st = bus_space_read_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HS);
537 	DPRINTF("%s: exec op %d, addr 0x%x, cmdlen %d, len %d, "
538 	    "flags 0x%x, status 0x%b\n", DEVNAME(sc), op, addr,
539 	    cmdlen, len, flags, st, VIAPM_SMB_HS_BITS);
540 	if (st & VIAPM_SMB_HS_BUSY)
541 		return (1);
542 
543 	if (cold || sc->sc_poll)
544 		flags |= I2C_F_POLL;
545 
546 	if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2)
547 		return (1);
548 
549 	/* Setup transfer */
550 	sc->sc_i2c_xfer.op = op;
551 	sc->sc_i2c_xfer.buf = buf;
552 	sc->sc_i2c_xfer.len = len;
553 	sc->sc_i2c_xfer.flags = flags;
554 	sc->sc_i2c_xfer.error = 0;
555 
556 	/* Set slave address and transfer direction */
557 	bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_TXSLVA,
558 	    VIAPM_SMB_TXSLVA_ADDR(addr) |
559 	    (I2C_OP_READ_P(op) ? VIAPM_SMB_TXSLVA_READ : 0));
560 
561 	b = (void *)cmdbuf;
562 	if (cmdlen > 0)
563 		/* Set command byte */
564 		bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh,
565 		    VIAPM_SMB_HCMD, b[0]);
566 
567 	if (I2C_OP_WRITE_P(op)) {
568 		/* Write data */
569 		b = buf;
570 		if (len > 0)
571 			bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh,
572 			    VIAPM_SMB_HD0, b[0]);
573 		if (len > 1)
574 			bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh,
575 			    VIAPM_SMB_HD1, b[1]);
576 	}
577 
578 	/* Set SMBus command */
579 	if (len == 0)
580 		ctl = VIAPM_SMB_HC_CMD_BYTE;
581 	else if (len == 1)
582 		ctl = VIAPM_SMB_HC_CMD_BDATA;
583 	else if (len == 2)
584 		ctl = VIAPM_SMB_HC_CMD_WDATA;
585 
586 	if ((flags & I2C_F_POLL) == 0)
587 		ctl |= VIAPM_SMB_HC_INTREN;
588 
589 	/* Start transaction */
590 	ctl |= VIAPM_SMB_HC_START;
591 	bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HC, ctl);
592 
593 	if (flags & I2C_F_POLL) {
594 		/* Poll for completion */
595 		DELAY(VIAPM_SMBUS_DELAY);
596 		for (retries = 1000; retries > 0; retries--) {
597 			st = bus_space_read_1(sc->sc_iot, sc->sc_smbus_ioh,
598 			    VIAPM_SMB_HS);
599 			if ((st & VIAPM_SMB_HS_BUSY) == 0)
600 				break;
601 			DELAY(VIAPM_SMBUS_DELAY);
602 		}
603 		if (st & VIAPM_SMB_HS_BUSY)
604 			goto timeout;
605 		viapm_intr(sc);
606 	} else {
607 		/* Wait for interrupt */
608 		if (tsleep(sc, PRIBIO, "iicexec", VIAPM_SMBUS_TIMEOUT * hz))
609 			goto timeout;
610 	}
611 
612 	if (sc->sc_i2c_xfer.error)
613 		return (1);
614 
615 	return (0);
616 
617 timeout:
618 	/*
619 	 * Transfer timeout. Kill the transaction and clear status bits.
620 	 */
621 	printf("%s: timeout, status 0x%b\n", DEVNAME(sc), st,
622 	    VIAPM_SMB_HS_BITS);
623 	bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HC,
624 	    VIAPM_SMB_HC_KILL);
625 	DELAY(VIAPM_SMBUS_DELAY);
626 	st = bus_space_read_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HS);
627 	if ((st & VIAPM_SMB_HS_FAILED) == 0)
628 		printf("%s: transaction abort failed, status 0x%b\n",
629 		    DEVNAME(sc), st, VIAPM_SMB_HS_BITS);
630 	bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HS, st);
631 	return (1);
632 }
633 
634 int
635 viapm_intr(void *arg)
636 {
637 	struct viapm_softc *sc = arg;
638 	u_int8_t st;
639 	u_int8_t *b;
640 	size_t len;
641 
642 	/* Read status */
643 	st = bus_space_read_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HS);
644 	if ((st & VIAPM_SMB_HS_BUSY) != 0 || (st & (VIAPM_SMB_HS_INTR |
645 	    VIAPM_SMB_HS_DEVERR | VIAPM_SMB_HS_BUSERR |
646 	    VIAPM_SMB_HS_FAILED)) == 0)
647 		/* Interrupt was not for us */
648 		return (0);
649 
650 	DPRINTF("%s: intr st 0x%b\n", DEVNAME(sc), st, VIAPM_SMB_HS_BITS);
651 
652 	/* Clear status bits */
653 	bus_space_write_1(sc->sc_iot, sc->sc_smbus_ioh, VIAPM_SMB_HS, st);
654 
655 	/* Check for errors */
656 	if (st & (VIAPM_SMB_HS_DEVERR | VIAPM_SMB_HS_BUSERR |
657 	    VIAPM_SMB_HS_FAILED)) {
658 		sc->sc_i2c_xfer.error = 1;
659 		goto done;
660 	}
661 
662 	if (st & VIAPM_SMB_HS_INTR) {
663 		if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op))
664 			goto done;
665 
666 		/* Read data */
667 		b = sc->sc_i2c_xfer.buf;
668 		len = sc->sc_i2c_xfer.len;
669 		if (len > 0)
670 			b[0] = bus_space_read_1(sc->sc_iot, sc->sc_smbus_ioh,
671 			    VIAPM_SMB_HD0);
672 		if (len > 1)
673 			b[1] = bus_space_read_1(sc->sc_iot, sc->sc_smbus_ioh,
674 			    VIAPM_SMB_HD1);
675 	}
676 
677 done:
678 	if ((sc->sc_i2c_xfer.flags & I2C_F_POLL) == 0)
679 		wakeup(sc);
680 	return (1);
681 }
682 
683 int
684 val_to_uK(unsigned int val)
685 {
686 	int i = val / 4;
687 	int j = val % 4;
688 
689 	KASSERT(i >= 0 && i <= 255);
690 
691 	if (j == 0 || i == 255)
692 		return val_to_temp[i] * 10000;
693 
694 	/* is linear interpolation ok? */
695 	return (val_to_temp[i] * (4 - j) +
696 	    val_to_temp[i + 1] * j) * 2500 /* really: / 4 * 10000 */ ;
697 }
698 
699 int
700 val_to_rpm(unsigned int val, int div)
701 {
702 	if (val == 0)
703 		return 0;
704 
705 	return 1350000 / val / div;
706 }
707 
708 long
709 val_to_uV(unsigned int val, int index)
710 {
711 	static const long mult[] =
712 	    {1250000, 1250000, 1670000, 2600000, 6300000};
713 
714 	KASSERT(index >= 0 && index <= 4);
715 
716 	return (25LL * val + 133) * mult[index] / 2628;
717 }
718 
719 void
720 viapm_refresh_sensor_data(struct viapm_softc *sc)
721 {
722 	int i;
723 	u_int8_t v, v2;
724 
725 	/* temperature */
726 	v = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh, VIAPM_HWMON_TIRQ);
727 	v2 = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh, VIAPM_HWMON_TSENS1);
728 	DPRINTF("%s: TSENS1 = %d\n", DEVNAME(sc), (v2 << 2) | (v >> 6));
729 	sc->sc_data[0].value = val_to_uK((v2 << 2) | (v >> 6));
730 
731 	v = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh, VIAPM_HWMON_TLOW);
732 	v2 = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh, VIAPM_HWMON_TSENS2);
733 	DPRINTF("%s: TSENS2 = %d\n", DEVNAME(sc), (v2 << 2) | ((v >> 4) & 0x3));
734 	sc->sc_data[1].value = val_to_uK((v2 << 2) | ((v >> 4) & 0x3));
735 
736 	v2 = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh, VIAPM_HWMON_TSENS3);
737 	DPRINTF("%s: TSENS3 = %d\n", DEVNAME(sc), (v2 << 2) | (v >> 6));
738 	sc->sc_data[2].value = val_to_uK((v2 << 2) | (v >> 6));
739 
740 	/* fan */
741 	for (i = 3; i <= 4; i++) {
742 		v = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh,
743 		    VIAPM_HWMON_FAN1 + i - 3);
744 		DPRINTF("%s: FAN%d = %d / %d\n", DEVNAME(sc), i - 3, v,
745 		    sc->sc_fan_div[i - 3]);
746 		sc->sc_data[i].value = val_to_rpm(v, sc->sc_fan_div[i - 3]);
747 	}
748 
749 	/* voltage */
750 	for (i = 5; i <= 9; i++) {
751 		v = bus_space_read_1(sc->sc_iot, sc->sc_hwmon_ioh,
752 		    VIAPM_HWMON_VSENS1 + i - 5);
753 		DPRINTF("%s: V%d = %d\n", DEVNAME(sc), i - 5, v);
754 		sc->sc_data[i].value = val_to_uV(v, i - 5);
755 	}
756 }
757 
758 void
759 viapm_refresh(void *arg)
760 {
761 	struct viapm_softc *sc = (struct viapm_softc *)arg;
762 
763 	viapm_refresh_sensor_data(sc);
764 	timeout_add_msec(&viapm_timeout, 1500);
765 }
766 
767 #ifdef __HAVE_TIMECOUNTER
768 u_int
769 viapm_get_timecount(struct timecounter *tc)
770 {
771 	struct viapm_softc *sc = tc->tc_priv;
772 	u_int u1, u2, u3;
773 
774 	u2 = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, VIAPM_PM_TMR);
775 	u3 = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, VIAPM_PM_TMR);
776 	do {
777 		u1 = u2;
778 		u2 = u3;
779 		u3 = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, VIAPM_PM_TMR);
780 	} while (u1 > u2 || u2 > u3);
781 
782 	return (u2);
783 }
784 #endif	/* __HAVE_TIMECOUNTER */
785