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