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