amdpm.c revision 83553
1/*- 2 * Copyright (c) 2000 Matthew C. Forman 3 * 4 * Based (heavily) on alpm.c which is: 5 * 6 * Copyright (c) 1998, 1999 Nicolas Souchu 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD: head/sys/pci/amdpm.c 83553 2001-09-16 22:35:07Z murray $ 31 * 32 */ 33 34/* 35 * Power management function/SMBus function support for the AMD 756 chip. 36 */ 37 38#include <sys/param.h> 39#include <sys/kernel.h> 40#include <sys/systm.h> 41#include <sys/module.h> 42#include <sys/bus.h> 43#include <sys/uio.h> 44 45#include <machine/bus_pio.h> 46#include <machine/bus_memio.h> 47#include <machine/bus.h> 48#include <machine/clock.h> 49#include <machine/resource.h> 50#include <sys/rman.h> 51 52#include <pci/pcivar.h> 53#include <pci/pcireg.h> 54 55#include <dev/iicbus/iiconf.h> 56#include <dev/smbus/smbconf.h> 57#include "smbus_if.h" 58 59#define AMDPM_DEBUG(x) if (amdpm_debug) (x) 60 61#ifdef DEBUG 62static int amdpm_debug = 1; 63#else 64static int amdpm_debug = 0; 65#endif 66 67#define AMDPM_VENDORID_AMD 0x1022 68#define AMDPM_DEVICEID_AMD756PM 0x740b 69 70/* PCI Configuration space registers */ 71#define AMDPCI_PMBASE 0x58 72 73#define AMDPCI_GEN_CONFIG_PM 0x41 74#define AMDPCI_PMIOEN (1<<7) 75 76#define AMDPCI_SCIINT_CONFIG_PM 0x42 77#define AMDPCI_SCISEL_IRQ11 11 78 79#define AMDPCI_REVID 0x08 80 81/* 82 * I/O registers. 83 * Base address programmed via AMDPCI_PMBASE. 84 */ 85#define AMDSMB_GLOBAL_STATUS 0xE0 86#define AMDSMB_GS_TO_STS (1<<5) 87#define AMDSMB_GS_HCYC_STS (1<<4) 88#define AMDSMB_GS_HST_STS (1<<3) 89#define AMDSMB_GS_PRERR_STS (1<<2) 90#define AMDSMB_GS_COL_STS (1<<1) 91#define AMDSMB_GS_ABRT_STS (1<<0) 92#define AMDSMB_GS_CLEAR_STS (AMDSMB_GS_TO_STS|AMDSMB_GS_HCYC_STS|AMDSMB_GS_PRERR_STS|AMDSMB_GS_COL_STS|AMDSMB_GS_ABRT_STS) 93 94#define AMDSMB_GLOBAL_ENABLE 0xE2 95#define AMDSMB_GE_ABORT (1<<5) 96#define AMDSMB_GE_HCYC_EN (1<<4) 97#define AMDSMB_GE_HOST_STC (1<<3) 98#define AMDSMB_GE_CYC_QUICK 0 99#define AMDSMB_GE_CYC_BYTE 1 100#define AMDSMB_GE_CYC_BDATA 2 101#define AMDSMB_GE_CYC_WDATA 3 102#define AMDSMB_GE_CYC_PROCCALL 4 103#define AMDSMB_GE_CYC_BLOCK 5 104 105#define AMDSMB_HSTADDR 0xE4 106#define AMDSMB_HSTDATA 0xE6 107#define AMDSMB_HSTCMD 0xE8 108#define AMDSMB_HSTDFIFO 0xE9 109#define AMDSMB_HSLVDATA 0xEA 110#define AMDSMB_HSLVDA 0xEC 111#define AMDSMB_HSLVDDR 0xEE 112#define AMDSMB_SNPADDR 0xEF 113 114struct amdpm_softc { 115 int base; 116 int rid; 117 struct resource *res; 118 bus_space_tag_t smbst; 119 bus_space_handle_t smbsh; 120}; 121 122struct amdsmb_softc { 123 int base; 124 device_t smbus; 125 struct amdpm_softc *amdpm; 126}; 127 128#define AMDPM_SMBINB(amdsmb,register) \ 129 (bus_space_read_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register)) 130#define AMDPM_SMBOUTB(amdsmb,register,value) \ 131 (bus_space_write_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value)) 132#define AMDPM_SMBINW(amdsmb,register) \ 133 (bus_space_read_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register)) 134#define AMDPM_SMBOUTW(amdsmb,register,value) \ 135 (bus_space_write_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value)) 136 137static int amdsmb_probe(device_t); 138static int amdsmb_attach(device_t); 139static int amdsmb_smb_callback(device_t, int, caddr_t *); 140static int amdsmb_smb_quick(device_t dev, u_char slave, int how); 141static int amdsmb_smb_sendb(device_t dev, u_char slave, char byte); 142static int amdsmb_smb_recvb(device_t dev, u_char slave, char *byte); 143static int amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte); 144static int amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte); 145static int amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word); 146static int amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word); 147static int amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 148static int amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte); 149 150static int amdpm_probe(device_t); 151static int amdpm_attach(device_t); 152 153 154static int 155amdpm_probe(device_t dev) 156{ 157 u_long base; 158 159 if ((pci_get_vendor(dev) == AMDPM_VENDORID_AMD) && 160 (pci_get_device(dev) == AMDPM_DEVICEID_AMD756PM)) { 161 device_set_desc(dev, "AMD 756 Power Management Controller"); 162 163 /* 164 * We have to do this, since the BIOS won't give us the 165 * resource info (not mine, anyway). 166 */ 167 base = pci_read_config(dev, AMDPCI_PMBASE, 4); 168 base &= 0xff00; 169 bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, base, 256); 170 return (0); 171 } 172 return ENXIO; 173} 174 175static int 176amdpm_attach(device_t dev) 177{ 178 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 179 u_char val_b; 180 int unit = device_get_unit(dev); 181 device_t smbinterface; 182 183 /* Enable I/O block access */ 184 val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1); 185 pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1); 186 187 /* Allocate I/O space */ 188 amdpm_sc->rid = AMDPCI_PMBASE; 189 amdpm_sc->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &amdpm_sc->rid, 0, ~0, 1, RF_ACTIVE); 190 191 if (amdpm_sc->res == NULL) { 192 device_printf(dev, "could not map i/o space\n"); 193 return (ENXIO); 194 } 195 196 amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res); 197 amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res); 198 199 smbinterface = device_add_child(dev, "amdsmb", unit); 200 if (!smbinterface) 201 device_printf(dev, "could not add SMBus device\n"); 202 else 203 device_probe_and_attach(smbinterface); 204 205 return (0); 206} 207 208static int 209amdsmb_probe(device_t dev) 210{ 211 struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev); 212 213 /* Allocate a new smbus device */ 214 amdsmb_sc->smbus = smbus_alloc_bus(dev); 215 if (!amdsmb_sc->smbus) 216 return (EINVAL); 217 218 device_set_desc(dev, "AMD 756 SMBus interface"); 219 device_printf(dev, "AMD 756 SMBus interface\n"); 220 221 return (0); 222} 223 224static int 225amdsmb_attach(device_t dev) 226{ 227 struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev); 228 229 amdsmb_sc->amdpm = device_get_softc(device_get_parent(dev)); 230 231 /* Probe and attach the smbus */ 232 device_probe_and_attach(amdsmb_sc->smbus); 233 234 return (0); 235} 236 237static int 238amdsmb_smb_callback(device_t dev, int index, caddr_t *data) 239{ 240 int error = 0; 241 242 switch (index) { 243 case SMB_REQUEST_BUS: 244 case SMB_RELEASE_BUS: 245 break; 246 default: 247 error = EINVAL; 248 } 249 250 return (error); 251} 252 253static int 254amdsmb_clear(struct amdsmb_softc *sc) 255{ 256 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); 257 DELAY(10); 258 259 return (0); 260} 261 262static int 263amdsmb_abort(struct amdsmb_softc *sc) 264{ 265 u_short l; 266 267 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 268 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT); 269 270 return (0); 271} 272 273static int 274amdsmb_idle(struct amdsmb_softc *sc) 275{ 276 u_short sts; 277 278 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 279 280 AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts)); 281 282 return (~(sts & AMDSMB_GS_HST_STS)); 283} 284 285/* 286 * Poll the SMBus controller 287 */ 288static int 289amdsmb_wait(struct amdsmb_softc *sc) 290{ 291 int count = 10000; 292 u_short sts = 0; 293 int error; 294 295 /* Wait for command to complete (SMBus controller is idle) */ 296 while(count--) { 297 DELAY(10); 298 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 299 if (!(sts & AMDSMB_GS_HST_STS)) 300 break; 301 } 302 303 AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count)); 304 305 error = SMB_ENOERR; 306 307 if (!count) 308 error |= SMB_ETIMEOUT; 309 310 if (sts & AMDSMB_GS_ABRT_STS) 311 error |= SMB_EABORT; 312 313 if (sts & AMDSMB_GS_COL_STS) 314 error |= SMB_ENOACK; 315 316 if (sts & AMDSMB_GS_PRERR_STS) 317 error |= SMB_EBUSERR; 318 319 if (error != SMB_ENOERR) 320 amdsmb_clear(sc); 321 322 return (error); 323} 324 325static int 326amdsmb_smb_quick(device_t dev, u_char slave, int how) 327{ 328 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 329 int error; 330 u_short l; 331 332 amdsmb_clear(sc); 333 if (!amdsmb_idle(sc)) 334 return (EBUSY); 335 336 switch (how) { 337 case SMB_QWRITE: 338 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave)); 339 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 340 break; 341 case SMB_QREAD: 342 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave)); 343 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 344 break; 345 default: 346 panic("%s: unknown QUICK command (%x)!", __FUNCTION__, how); 347 } 348 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 349 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC); 350 351 error = amdsmb_wait(sc); 352 353 AMDPM_DEBUG(printf(", error=0x%x\n", error)); 354 355 return (error); 356} 357 358static int 359amdsmb_smb_sendb(device_t dev, u_char slave, char byte) 360{ 361 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 362 int error; 363 u_short l; 364 365 amdsmb_clear(sc); 366 if (!amdsmb_idle(sc)) 367 return (SMB_EBUSY); 368 369 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 370 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 371 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 372 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 373 374 error = amdsmb_wait(sc); 375 376 AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 377 378 return (error); 379} 380 381static int 382amdsmb_smb_recvb(device_t dev, u_char slave, char *byte) 383{ 384 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 385 int error; 386 u_short l; 387 388 amdsmb_clear(sc); 389 if (!amdsmb_idle(sc)) 390 return (SMB_EBUSY); 391 392 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 393 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 394 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 395 396 if ((error = amdsmb_wait(sc)) == SMB_ENOERR) 397 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 398 399 AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 400 401 return (error); 402} 403 404static int 405amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) 406{ 407 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 408 int error; 409 u_short l; 410 411 amdsmb_clear(sc); 412 if (!amdsmb_idle(sc)) 413 return (SMB_EBUSY); 414 415 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 416 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 417 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 418 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 419 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 420 421 error = amdsmb_wait(sc); 422 423 AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 424 425 return (error); 426} 427 428static int 429amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) 430{ 431 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 432 int error; 433 u_short l; 434 435 amdsmb_clear(sc); 436 if (!amdsmb_idle(sc)) 437 return (SMB_EBUSY); 438 439 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 440 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 441 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 442 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 443 444 if ((error = amdsmb_wait(sc)) == SMB_ENOERR) 445 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 446 447 AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); 448 449 return (error); 450} 451 452static int 453amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) 454{ 455 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 456 int error; 457 u_short l; 458 459 amdsmb_clear(sc); 460 if (!amdsmb_idle(sc)) 461 return (SMB_EBUSY); 462 463 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 464 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word); 465 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 466 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 467 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 468 469 error = amdsmb_wait(sc); 470 471 AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 472 473 return (error); 474} 475 476static int 477amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) 478{ 479 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 480 int error; 481 u_short l; 482 483 amdsmb_clear(sc); 484 if (!amdsmb_idle(sc)) 485 return (SMB_EBUSY); 486 487 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 488 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 489 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 490 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 491 492 if ((error = amdsmb_wait(sc)) == SMB_ENOERR) 493 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 494 495 AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); 496 497 return (error); 498} 499 500static int 501amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 502{ 503 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 504 u_char remain, len, i; 505 int error = SMB_ENOERR; 506 u_short l; 507 508 amdsmb_clear(sc); 509 if(!amdsmb_idle(sc)) 510 return (SMB_EBUSY); 511 512 remain = count; 513 while (remain) { 514 len = min(remain, 32); 515 516 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 517 518 /* 519 * Do we have to reset the internal 32-byte buffer? 520 * Can't see how to do this from the data sheet. 521 */ 522 523 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, len); 524 525 /* Fill the 32-byte internal buffer */ 526 for (i=0; i<len; i++) { 527 AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[count-remain+i]); 528 DELAY(2); 529 } 530 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 531 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 532 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 533 534 if ((error = amdsmb_wait(sc)) != SMB_ENOERR) 535 goto error; 536 537 remain -= len; 538 } 539 540error: 541 AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 542 543 return (error); 544} 545 546static int 547amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 548{ 549 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 550 u_char remain, len, i; 551 int error = SMB_ENOERR; 552 u_short l; 553 554 amdsmb_clear(sc); 555 if (!amdsmb_idle(sc)) 556 return (SMB_EBUSY); 557 558 remain = count; 559 while (remain) { 560 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 561 562 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 563 564 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 565 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 566 567 if ((error = amdsmb_wait(sc)) != SMB_ENOERR) 568 goto error; 569 570 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 571 572 /* Read the 32-byte internal buffer */ 573 for (i=0; i<len; i++) { 574 buf[count-remain+i] = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO); 575 DELAY(2); 576 } 577 578 remain -= len; 579 } 580error: 581 AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 582 583 return (error); 584} 585 586static devclass_t amdpm_devclass; 587 588static device_method_t amdpm_methods[] = { 589 /* Device interface */ 590 DEVMETHOD(device_probe, amdpm_probe), 591 DEVMETHOD(device_attach, amdpm_attach), 592 593 { 0, 0 } 594}; 595 596static driver_t amdpm_driver = { 597 "amdpm", 598 amdpm_methods, 599 sizeof(struct amdpm_softc), 600}; 601 602static devclass_t amdsmb_devclass; 603 604static device_method_t amdsmb_methods[] = { 605 /* Device interface */ 606 DEVMETHOD(device_probe, amdsmb_probe), 607 DEVMETHOD(device_attach, amdsmb_attach), 608 609 /* Bus interface */ 610 DEVMETHOD(bus_print_child, bus_generic_print_child), 611 612 /* SMBus interface */ 613 DEVMETHOD(smbus_callback, amdsmb_smb_callback), 614 DEVMETHOD(smbus_quick, amdsmb_smb_quick), 615 DEVMETHOD(smbus_sendb, amdsmb_smb_sendb), 616 DEVMETHOD(smbus_recvb, amdsmb_smb_recvb), 617 DEVMETHOD(smbus_writeb, amdsmb_smb_writeb), 618 DEVMETHOD(smbus_readb, amdsmb_smb_readb), 619 DEVMETHOD(smbus_writew, amdsmb_smb_writew), 620 DEVMETHOD(smbus_readw, amdsmb_smb_readw), 621 DEVMETHOD(smbus_bwrite, amdsmb_smb_bwrite), 622 DEVMETHOD(smbus_bread, amdsmb_smb_bread), 623 624 { 0, 0 } 625}; 626 627static driver_t amdsmb_driver = { 628 "amdsmb", 629 amdsmb_methods, 630 sizeof(struct amdsmb_softc), 631}; 632 633DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0); 634DRIVER_MODULE(amdsmb, amdpm, amdsmb_driver, amdsmb_devclass, 0, 0); 635