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