xref: /openbsd/sys/dev/pci/amdpm.c (revision 891d7ab6)
1 /*	$OpenBSD: amdpm.c,v 1.26 2011/04/09 04:33:40 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 Alexander Yurchenko <grange@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  * Copyright (c) 2002 The NetBSD Foundation, Inc.
21  * All rights reserved.
22  *
23  * This code is derived from software contributed to The NetBSD Foundation
24  * by Enami Tsugutomo.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions
28  * are met:
29  * 1. Redistributions of source code must retain the above copyright
30  *    notice, this list of conditions and the following disclaimer.
31  * 2. Redistributions in binary form must reproduce the above copyright
32  *    notice, this list of conditions and the following disclaimer in the
33  *    documentation and/or other materials provided with the distribution.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
36  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
37  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
39  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45  * POSSIBILITY OF SUCH DAMAGE.
46  */
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/device.h>
51 #include <sys/kernel.h>
52 #include <sys/rwlock.h>
53 #include <sys/timeout.h>
54 #ifdef __HAVE_TIMECOUNTER
55 #include <sys/timetc.h>
56 #endif
57 
58 #include <machine/bus.h>
59 
60 #include <dev/pci/pcivar.h>
61 #include <dev/pci/pcireg.h>
62 #include <dev/pci/pcidevs.h>
63 
64 #include <dev/rndvar.h>
65 #include <dev/i2c/i2cvar.h>
66 
67 #ifdef AMDPM_DEBUG
68 #define DPRINTF(x...) printf(x)
69 #else
70 #define DPRINTF(x...)
71 #endif
72 
73 #define AMDPM_SMBUS_DELAY	100
74 #define AMDPM_SMBUS_TIMEOUT	1
75 
76 #ifdef __HAVE_TIMECOUNTER
77 u_int amdpm_get_timecount(struct timecounter *tc);
78 
79 #ifndef AMDPM_FREQUENCY
80 #define AMDPM_FREQUENCY 3579545
81 #endif
82 
83 static struct timecounter amdpm_timecounter = {
84 	amdpm_get_timecount,	/* get_timecount */
85 	0,			/* no poll_pps */
86 	0xffffff,		/* counter_mask */
87 	AMDPM_FREQUENCY,	/* frequency */
88 	"AMDPM",		/* name */
89 	1000			/* quality */
90 };
91 #endif
92 
93 #define	AMDPM_CONFREG	0x40
94 
95 /* 0x40: General Configuration 1 Register */
96 #define	AMDPM_RNGEN	0x00000080	/* random number generator enable */
97 #define	AMDPM_STOPTMR	0x00000040	/* stop free-running timer */
98 
99 /* 0x41: General Configuration 2 Register */
100 #define	AMDPM_PMIOEN	0x00008000	/* system management IO space enable */
101 #define	AMDPM_TMRRST	0x00004000	/* reset free-running timer */
102 #define	AMDPM_TMR32	0x00000800	/* extended (32 bit) timer enable */
103 
104 /* 0x42: SCI Interrupt Configuration Register */
105 /* 0x43: Previous Power State Register */
106 
107 #define	AMDPM_PMPTR	0x58		/* PMxx System Management IO space
108 					   Pointer */
109 #define NFPM_PMPTR	0x14		/* nForce System Management IO space
110 					   POinter */
111 #define	AMDPM_PMBASE(x)	((x) & 0xff00)	/* PMxx base address */
112 #define	AMDPM_PMSIZE	256		/* PMxx space size */
113 
114 /* Registers in PMxx space */
115 #define	AMDPM_TMR	0x08		/* 24/32 bit timer register */
116 
117 #define	AMDPM_RNGDATA	0xf0		/* 32 bit random data register */
118 #define	AMDPM_RNGSTAT	0xf4		/* RNG status register */
119 #define	AMDPM_RNGDONE	0x00000001	/* Random number generation complete */
120 
121 #define AMDPM_SMB_REGS  0xe0		/* offset of SMB register space */
122 #define AMDPM_SMB_SIZE  0xf		/* size of SMB register space */
123 #define AMDPM_SMBSTAT	0x0		/* SMBus status */
124 #define AMDPM_SMBSTAT_ABRT	(1 << 0)	/* transfer abort */
125 #define AMDPM_SMBSTAT_COL	(1 << 1)	/* collision */
126 #define AMDPM_SMBSTAT_PRERR	(1 << 2)	/* protocol error */
127 #define AMDPM_SMBSTAT_HBSY	(1 << 3)	/* host controller busy */
128 #define AMDPM_SMBSTAT_CYC	(1 << 4)	/* cycle complete */
129 #define AMDPM_SMBSTAT_TO	(1 << 5)	/* timeout */
130 #define AMDPM_SMBSTAT_SNP	(1 << 8)	/* snoop address match */
131 #define AMDPM_SMBSTAT_SLV	(1 << 9)	/* slave address match */
132 #define AMDPM_SMBSTAT_SMBA	(1 << 10)	/* SMBALERT# asserted */
133 #define AMDPM_SMBSTAT_BSY	(1 << 11)	/* bus busy */
134 #define AMDPM_SMBSTAT_BITS	"\020\001ABRT\002COL\003PRERR\004HBSY\005CYC\006TO\011SNP\012SLV\013SMBA\014BSY"
135 #define AMDPM_SMBCTL	0x2		/* SMBus control */
136 #define AMDPM_SMBCTL_CMD_QUICK	0		/* QUICK command */
137 #define AMDPM_SMBCTL_CMD_BYTE	1		/* BYTE command */
138 #define AMDPM_SMBCTL_CMD_BDATA	2		/* BYTE DATA command */
139 #define AMDPM_SMBCTL_CMD_WDATA	3		/* WORD DATA command */
140 #define AMDPM_SMBCTL_CMD_PCALL	4		/* PROCESS CALL command */
141 #define AMDPM_SMBCTL_CMD_BLOCK	5		/* BLOCK command */
142 #define AMDPM_SMBCTL_START	(1 << 3)	/* start transfer */
143 #define AMDPM_SMBCTL_CYCEN	(1 << 4)	/* intr on cycle complete */
144 #define AMDPM_SMBCTL_ABORT	(1 << 5)	/* abort transfer */
145 #define AMDPM_SMBCTL_SNPEN	(1 << 8)	/* intr on snoop addr match */
146 #define AMDPM_SMBCTL_SLVEN	(1 << 9)	/* intr on slave addr match */
147 #define AMDPM_SMBCTL_SMBAEN	(1 << 10)	/* intr on SMBALERT# */
148 #define AMDPM_SMBADDR	0x4		/* SMBus address */
149 #define AMDPM_SMBADDR_READ	(1 << 0)	/* read direction */
150 #define AMDPM_SMBADDR_ADDR(x)	(((x) & 0x7f) << 1) /* 7-bit address */
151 #define AMDPM_SMBDATA	0x6		/* SMBus data */
152 #define AMDPM_SMBCMD	0x8		/* SMBus command */
153 
154 
155 struct amdpm_softc {
156 	struct device sc_dev;
157 
158 	pci_chipset_tag_t sc_pc;
159 	pcitag_t sc_tag;
160 
161 	bus_space_tag_t sc_iot;
162 	bus_space_handle_t sc_ioh;		/* PMxx space */
163 	bus_space_handle_t sc_i2c_ioh;		/* I2C space */
164 	int sc_poll;
165 
166 	struct timeout sc_rnd_ch;
167 
168 	struct i2c_controller sc_i2c_tag;
169 	struct rwlock sc_i2c_lock;
170 	struct {
171 		i2c_op_t op;
172 		void *buf;
173 		size_t len;
174 		int flags;
175 		volatile int error;
176 	} sc_i2c_xfer;
177 };
178 
179 int	amdpm_match(struct device *, void *, void *);
180 void	amdpm_attach(struct device *, struct device *, void *);
181 int	amdpm_activate(struct device *, int);
182 void	amdpm_rnd_callout(void *);
183 
184 int	amdpm_i2c_acquire_bus(void *, int);
185 void	amdpm_i2c_release_bus(void *, int);
186 int	amdpm_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
187 	    void *, size_t, int);
188 
189 int	amdpm_intr(void *);
190 
191 struct cfattach amdpm_ca = {
192 	sizeof(struct amdpm_softc), amdpm_match, amdpm_attach, NULL,
193 	amdpm_activate
194 };
195 
196 struct cfdriver amdpm_cd = {
197 	NULL, "amdpm", DV_DULL
198 };
199 
200 const struct pci_matchid amdpm_ids[] = {
201 	{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_PMC },
202 	{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_766_PMC },
203 	{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC768_PMC },
204 	{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_8111_PMC },
205 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_SMB }
206 };
207 
208 int
209 amdpm_match(struct device *parent, void *match, void *aux)
210 {
211 	return (pci_matchbyid(aux, amdpm_ids,
212 	    sizeof(amdpm_ids) / sizeof(amdpm_ids[0])));
213 }
214 
215 void
216 amdpm_attach(struct device *parent, struct device *self, void *aux)
217 {
218 	struct amdpm_softc *sc = (struct amdpm_softc *) self;
219 	struct pci_attach_args *pa = aux;
220 	struct i2cbus_attach_args iba;
221 	pcireg_t cfg_reg, reg;
222 	int i;
223 
224 	sc->sc_pc = pa->pa_pc;
225 	sc->sc_tag = pa->pa_tag;
226 	sc->sc_iot = pa->pa_iot;
227 	sc->sc_poll = 1; /* XXX */
228 
229 
230 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD)  {
231 		cfg_reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG);
232 		if ((cfg_reg & AMDPM_PMIOEN) == 0) {
233 			printf(": PMxx space isn't enabled\n");
234 			return;
235 		}
236 
237 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_PMPTR);
238 		if (AMDPM_PMBASE(reg) == 0 ||
239 		    bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_PMSIZE,
240 		    0, &sc->sc_ioh)) {
241 			printf("\n");
242 			return;
243 		}
244 		if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, AMDPM_SMB_REGS,
245 		    AMDPM_SMB_SIZE, &sc->sc_i2c_ioh)) {
246 			printf(": failed to map I2C subregion\n");
247 			return;
248 		}
249 
250 #ifdef __HAVE_TIMECOUNTER
251 		if ((cfg_reg & AMDPM_TMRRST) == 0 &&
252 		    (cfg_reg & AMDPM_STOPTMR) == 0 &&
253 		    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC ||
254 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8111_PMC)) {
255 			printf(": %d-bit timer at %dHz",
256 			    (cfg_reg & AMDPM_TMR32) ? 32 : 24,
257 			    amdpm_timecounter.tc_frequency);
258 
259 			amdpm_timecounter.tc_priv = sc;
260 			if (cfg_reg & AMDPM_TMR32)
261 				amdpm_timecounter.tc_counter_mask = 0xffffffffu;
262 			tc_init(&amdpm_timecounter);
263 		}
264 #endif
265 		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC ||
266 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8111_PMC) {
267 			if ((cfg_reg & AMDPM_RNGEN) ==0) {
268 				pci_conf_write(pa->pa_pc, pa->pa_tag,
269 				    AMDPM_CONFREG, cfg_reg | AMDPM_RNGEN);
270 				cfg_reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
271 				    AMDPM_CONFREG);
272 			}
273 			if (cfg_reg & AMDPM_RNGEN) {
274 			/* Check to see if we can read data from the RNG. */
275 				(void) bus_space_read_4(sc->sc_iot, sc->sc_ioh,
276 				    AMDPM_RNGDATA);
277 				for (i = 1000; i--; ) {
278 					if (bus_space_read_1(sc->sc_iot,
279 					    sc->sc_ioh, AMDPM_RNGSTAT) &
280 					    AMDPM_RNGDONE)
281 						break;
282 					DELAY(10);
283 				}
284 				if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
285 				    AMDPM_RNGSTAT) & AMDPM_RNGDONE) {
286 					printf(": rng active");
287 					timeout_set(&sc->sc_rnd_ch,
288 					    amdpm_rnd_callout, sc);
289 					amdpm_rnd_callout(sc);
290 				}
291 			}
292 		}
293 	} else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) {
294 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, NFPM_PMPTR);
295 		if (AMDPM_PMBASE(reg) == 0 ||
296 		    bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_SMB_SIZE, 0,
297 		    &sc->sc_i2c_ioh)) {
298 			printf(": failed to map I2C subregion\n");
299 			return;
300 		}
301 	}
302 	printf("\n");
303 
304 	/* Attach I2C bus */
305 	rw_init(&sc->sc_i2c_lock, "iiclk");
306 	sc->sc_i2c_tag.ic_cookie = sc;
307 	sc->sc_i2c_tag.ic_acquire_bus = amdpm_i2c_acquire_bus;
308 	sc->sc_i2c_tag.ic_release_bus = amdpm_i2c_release_bus;
309 	sc->sc_i2c_tag.ic_exec = amdpm_i2c_exec;
310 
311 	bzero(&iba, sizeof(iba));
312 	iba.iba_name = "iic";
313 	iba.iba_tag = &sc->sc_i2c_tag;
314 	config_found(self, &iba, iicbus_print);
315 }
316 
317 int
318 amdpm_activate(struct device *self, int act)
319 {
320 	struct amdpm_softc *sc = (struct amdpm_softc *)self;
321 
322 	switch (act) {
323 	case DVACT_RESUME:
324 		if (timeout_initialized(&sc->sc_rnd_ch)) {
325 			pcireg_t cfg_reg;
326 
327 			/* Restart the AMD PBC768_PMC/8111_PMC RNG */
328 			cfg_reg = pci_conf_read(sc->sc_pc, sc->sc_tag,
329 			    AMDPM_CONFREG);
330 			pci_conf_write(sc->sc_pc, sc->sc_tag,
331 			    AMDPM_CONFREG, cfg_reg | AMDPM_RNGEN);
332 
333 		}
334 		break;
335 	}
336 	return (0);
337 }
338 
339 void
340 amdpm_rnd_callout(void *v)
341 {
342 	struct amdpm_softc *sc = v;
343 	u_int32_t reg;
344 
345 	if ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) &
346 	    AMDPM_RNGDONE) != 0) {
347 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGDATA);
348 		add_true_randomness(reg);
349 	}
350 	timeout_add(&sc->sc_rnd_ch, 1);
351 }
352 
353 #ifdef __HAVE_TIMECOUNTER
354 u_int
355 amdpm_get_timecount(struct timecounter *tc)
356 {
357 	struct amdpm_softc *sc = tc->tc_priv;
358 	u_int u2;
359 #if 0
360 	u_int u1, u3;
361 #endif
362 
363 	u2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_TMR);
364 #if 0
365 	u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_TMR);
366 	do {
367 		u1 = u2;
368 		u2 = u3;
369 		u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_TMR);
370 	} while (u1 > u2 || u2 > u3);
371 #endif
372 	return (u2);
373 }
374 #endif
375 
376 int
377 amdpm_i2c_acquire_bus(void *cookie, int flags)
378 {
379 	struct amdpm_softc *sc = cookie;
380 
381 	if (cold || sc->sc_poll || (flags & I2C_F_POLL))
382 		return (0);
383 
384 	return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR));
385 }
386 
387 void
388 amdpm_i2c_release_bus(void *cookie, int flags)
389 {
390 	struct amdpm_softc *sc = cookie;
391 
392 	if (cold || sc->sc_poll || (flags & I2C_F_POLL))
393 		return;
394 
395 	rw_exit(&sc->sc_i2c_lock);
396 }
397 
398 int
399 amdpm_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
400     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
401 {
402 	struct amdpm_softc *sc = cookie;
403 	u_int8_t *b;
404 	u_int16_t st, ctl, data;
405 	int retries;
406 
407 	DPRINTF("%s: exec: op %d, addr 0x%02x, cmdlen %d, len %d, "
408 	    "flags 0x%02x\n", sc->sc_dev.dv_xname, op, addr, cmdlen,
409 	    len, flags);
410 
411 	/* Wait for bus to be idle */
412 	for (retries = 100; retries > 0; retries--) {
413 		st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT);
414 		if (!(st & AMDPM_SMBSTAT_BSY))
415 			break;
416 		DELAY(AMDPM_SMBUS_DELAY);
417 	}
418 	DPRINTF("%s: exec: st 0x%b\n", sc->sc_dev.dv_xname, st,
419 	    AMDPM_SMBSTAT_BITS);
420 	if (st & AMDPM_SMBSTAT_BSY)
421 		return (1);
422 
423 	if (cold || sc->sc_poll)
424 		flags |= I2C_F_POLL;
425 
426 	if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2)
427 		return (1);
428 
429 	/* Setup transfer */
430 	sc->sc_i2c_xfer.op = op;
431 	sc->sc_i2c_xfer.buf = buf;
432 	sc->sc_i2c_xfer.len = len;
433 	sc->sc_i2c_xfer.flags = flags;
434 	sc->sc_i2c_xfer.error = 0;
435 
436 	/* Set slave address and transfer direction */
437 	bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBADDR,
438 	    AMDPM_SMBADDR_ADDR(addr) |
439 	    (I2C_OP_READ_P(op) ? AMDPM_SMBADDR_READ : 0));
440 
441 	b = (void *)cmdbuf;
442 	if (cmdlen > 0)
443 		/* Set command byte */
444 		bus_space_write_1(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBCMD, b[0]);
445 
446 	if (I2C_OP_WRITE_P(op)) {
447 		/* Write data */
448 		data = 0;
449 		b = buf;
450 		if (len > 0)
451 			data = b[0];
452 		if (len > 1)
453 			data |= ((u_int16_t)b[1] << 8);
454 		if (len > 0)
455 			bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh,
456 			    AMDPM_SMBDATA, data);
457 	}
458 
459 	/* Set SMBus command */
460 	if (len == 0)
461 		ctl = AMDPM_SMBCTL_CMD_BYTE;
462 	else if (len == 1)
463 		ctl = AMDPM_SMBCTL_CMD_BDATA;
464 	else if (len == 2)
465 		ctl = AMDPM_SMBCTL_CMD_WDATA;
466 
467 	if ((flags & I2C_F_POLL) == 0)
468 		ctl |= AMDPM_SMBCTL_CYCEN;
469 
470 	/* Start transaction */
471 	ctl |= AMDPM_SMBCTL_START;
472 	bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBCTL, ctl);
473 
474 	if (flags & I2C_F_POLL) {
475 		/* Poll for completion */
476 		DELAY(AMDPM_SMBUS_DELAY);
477 		for (retries = 1000; retries > 0; retries--) {
478 			st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh,
479 			    AMDPM_SMBSTAT);
480 			if ((st & AMDPM_SMBSTAT_HBSY) == 0)
481 				break;
482 			DELAY(AMDPM_SMBUS_DELAY);
483 		}
484 		if (st & AMDPM_SMBSTAT_HBSY)
485 			goto timeout;
486 		amdpm_intr(sc);
487 	} else {
488 		/* Wait for interrupt */
489 		if (tsleep(sc, PRIBIO, "amdpm", AMDPM_SMBUS_TIMEOUT * hz))
490 			goto timeout;
491 	}
492 
493 	if (sc->sc_i2c_xfer.error)
494 		return (1);
495 
496 	return (0);
497 
498 timeout:
499 	/*
500 	 * Transfer timeout. Kill the transaction and clear status bits.
501 	 */
502 	printf("%s: exec: op %d, addr 0x%02x, cmdlen %d, len %d, "
503 	    "flags 0x%02x: timeout, status 0x%b\n",
504 	    sc->sc_dev.dv_xname, op, addr, cmdlen, len, flags,
505 	    st, AMDPM_SMBSTAT_BITS);
506 	bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBCTL,
507 	    AMDPM_SMBCTL_ABORT);
508 	DELAY(AMDPM_SMBUS_DELAY);
509 	st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT);
510 	if ((st & AMDPM_SMBSTAT_ABRT) == 0)
511 		printf("%s: abort failed, status 0x%b\n",
512 		    sc->sc_dev.dv_xname, st, AMDPM_SMBSTAT_BITS);
513 	bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT, st);
514 	return (1);
515 }
516 
517 int
518 amdpm_intr(void *arg)
519 {
520 	struct amdpm_softc *sc = arg;
521 	u_int16_t st, data;
522 	u_int8_t *b;
523 	size_t len;
524 
525 	/* Read status */
526 	st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT);
527 	if ((st & AMDPM_SMBSTAT_HBSY) != 0 || (st & (AMDPM_SMBSTAT_ABRT |
528 	    AMDPM_SMBSTAT_COL | AMDPM_SMBSTAT_PRERR | AMDPM_SMBSTAT_CYC |
529 	    AMDPM_SMBSTAT_TO | AMDPM_SMBSTAT_SNP | AMDPM_SMBSTAT_SLV |
530 	    AMDPM_SMBSTAT_SMBA)) == 0)
531 		/* Interrupt was not for us */
532 		return (0);
533 
534 	DPRINTF("%s: intr: st 0x%b\n", sc->sc_dev.dv_xname, st,
535 	    AMDPM_SMBSTAT_BITS);
536 
537 	/* Clear status bits */
538 	bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT, st);
539 
540 	/* Check for errors */
541 	if (st & (AMDPM_SMBSTAT_COL | AMDPM_SMBSTAT_PRERR |
542 	    AMDPM_SMBSTAT_TO)) {
543 		sc->sc_i2c_xfer.error = 1;
544 		goto done;
545 	}
546 
547 	if (st & AMDPM_SMBSTAT_CYC) {
548 		if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op))
549 			goto done;
550 
551 		/* Read data */
552 		b = sc->sc_i2c_xfer.buf;
553 		len = sc->sc_i2c_xfer.len;
554 		if (len > 0) {
555 			data = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh,
556 			    AMDPM_SMBDATA);
557 			b[0] = data & 0xff;
558 		}
559 		if (len > 1)
560 			b[1] = (data >> 8) & 0xff;
561 	}
562 
563 done:
564 	if ((sc->sc_i2c_xfer.flags & I2C_F_POLL) == 0)
565 		wakeup(sc);
566 	return (1);
567 }
568