amdpm.c revision 93040
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 93040 2002-03-23 18:27:16Z nsouch $ 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 device_set_desc(dev, "AMD 756 SMBus interface"); 214 device_printf(dev, "AMD 756 SMBus interface\n"); 215 216 /* Allocate a new smbus device */ 217 amdsmb_sc->smbus = device_add_child(dev, "smbus", -1); 218 if (!amdsmb_sc->smbus) 219 return (EINVAL); 220 221 bus_generic_attach(dev); 222 223 return (0); 224} 225 226static int 227amdsmb_attach(device_t dev) 228{ 229 struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev); 230 231 amdsmb_sc->amdpm = device_get_softc(device_get_parent(dev)); 232 233 /* Probe and attach the smbus */ 234 device_probe_and_attach(amdsmb_sc->smbus); 235 236 return (0); 237} 238 239static int 240amdsmb_smb_callback(device_t dev, int index, caddr_t *data) 241{ 242 int error = 0; 243 244 switch (index) { 245 case SMB_REQUEST_BUS: 246 case SMB_RELEASE_BUS: 247 break; 248 default: 249 error = EINVAL; 250 } 251 252 return (error); 253} 254 255static int 256amdsmb_clear(struct amdsmb_softc *sc) 257{ 258 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); 259 DELAY(10); 260 261 return (0); 262} 263 264#if 0 265static int 266amdsmb_abort(struct amdsmb_softc *sc) 267{ 268 u_short l; 269 270 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 271 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT); 272 273 return (0); 274} 275#endif 276 277static int 278amdsmb_idle(struct amdsmb_softc *sc) 279{ 280 u_short sts; 281 282 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 283 284 AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts)); 285 286 return (~(sts & AMDSMB_GS_HST_STS)); 287} 288 289/* 290 * Poll the SMBus controller 291 */ 292static int 293amdsmb_wait(struct amdsmb_softc *sc) 294{ 295 int count = 10000; 296 u_short sts = 0; 297 int error; 298 299 /* Wait for command to complete (SMBus controller is idle) */ 300 while(count--) { 301 DELAY(10); 302 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 303 if (!(sts & AMDSMB_GS_HST_STS)) 304 break; 305 } 306 307 AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count)); 308 309 error = SMB_ENOERR; 310 311 if (!count) 312 error |= SMB_ETIMEOUT; 313 314 if (sts & AMDSMB_GS_ABRT_STS) 315 error |= SMB_EABORT; 316 317 if (sts & AMDSMB_GS_COL_STS) 318 error |= SMB_ENOACK; 319 320 if (sts & AMDSMB_GS_PRERR_STS) 321 error |= SMB_EBUSERR; 322 323 if (error != SMB_ENOERR) 324 amdsmb_clear(sc); 325 326 return (error); 327} 328 329static int 330amdsmb_smb_quick(device_t dev, u_char slave, int how) 331{ 332 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 333 int error; 334 u_short l; 335 336 amdsmb_clear(sc); 337 if (!amdsmb_idle(sc)) 338 return (EBUSY); 339 340 switch (how) { 341 case SMB_QWRITE: 342 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave)); 343 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 344 break; 345 case SMB_QREAD: 346 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave)); 347 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 348 break; 349 default: 350 panic("%s: unknown QUICK command (%x)!", __func__, how); 351 } 352 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 353 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC); 354 355 error = amdsmb_wait(sc); 356 357 AMDPM_DEBUG(printf(", error=0x%x\n", error)); 358 359 return (error); 360} 361 362static int 363amdsmb_smb_sendb(device_t dev, u_char slave, char byte) 364{ 365 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 366 int error; 367 u_short l; 368 369 amdsmb_clear(sc); 370 if (!amdsmb_idle(sc)) 371 return (SMB_EBUSY); 372 373 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 374 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 375 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 376 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 377 378 error = amdsmb_wait(sc); 379 380 AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 381 382 return (error); 383} 384 385static int 386amdsmb_smb_recvb(device_t dev, u_char slave, char *byte) 387{ 388 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 389 int error; 390 u_short l; 391 392 amdsmb_clear(sc); 393 if (!amdsmb_idle(sc)) 394 return (SMB_EBUSY); 395 396 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 397 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 398 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 399 400 if ((error = amdsmb_wait(sc)) == SMB_ENOERR) 401 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 402 403 AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 404 405 return (error); 406} 407 408static int 409amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) 410{ 411 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 412 int error; 413 u_short l; 414 415 amdsmb_clear(sc); 416 if (!amdsmb_idle(sc)) 417 return (SMB_EBUSY); 418 419 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 420 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 421 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 422 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 423 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 424 425 error = amdsmb_wait(sc); 426 427 AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 428 429 return (error); 430} 431 432static int 433amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) 434{ 435 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 436 int error; 437 u_short l; 438 439 amdsmb_clear(sc); 440 if (!amdsmb_idle(sc)) 441 return (SMB_EBUSY); 442 443 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 444 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 445 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 446 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 447 448 if ((error = amdsmb_wait(sc)) == SMB_ENOERR) 449 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 450 451 AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); 452 453 return (error); 454} 455 456static int 457amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) 458{ 459 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 460 int error; 461 u_short l; 462 463 amdsmb_clear(sc); 464 if (!amdsmb_idle(sc)) 465 return (SMB_EBUSY); 466 467 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 468 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word); 469 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 470 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 471 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 472 473 error = amdsmb_wait(sc); 474 475 AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 476 477 return (error); 478} 479 480static int 481amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) 482{ 483 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 484 int error; 485 u_short l; 486 487 amdsmb_clear(sc); 488 if (!amdsmb_idle(sc)) 489 return (SMB_EBUSY); 490 491 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 492 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 493 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 494 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 495 496 if ((error = amdsmb_wait(sc)) == SMB_ENOERR) 497 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 498 499 AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); 500 501 return (error); 502} 503 504static int 505amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 506{ 507 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 508 u_char remain, len, i; 509 int error = SMB_ENOERR; 510 u_short l; 511 512 amdsmb_clear(sc); 513 if(!amdsmb_idle(sc)) 514 return (SMB_EBUSY); 515 516 remain = count; 517 while (remain) { 518 len = min(remain, 32); 519 520 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 521 522 /* 523 * Do we have to reset the internal 32-byte buffer? 524 * Can't see how to do this from the data sheet. 525 */ 526 527 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, len); 528 529 /* Fill the 32-byte internal buffer */ 530 for (i=0; i<len; i++) { 531 AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[count-remain+i]); 532 DELAY(2); 533 } 534 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 535 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 536 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 537 538 if ((error = amdsmb_wait(sc)) != SMB_ENOERR) 539 goto error; 540 541 remain -= len; 542 } 543 544error: 545 AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 546 547 return (error); 548} 549 550static int 551amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 552{ 553 struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev); 554 u_char remain, len, i; 555 int error = SMB_ENOERR; 556 u_short l; 557 558 amdsmb_clear(sc); 559 if (!amdsmb_idle(sc)) 560 return (SMB_EBUSY); 561 562 remain = count; 563 while (remain) { 564 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 565 566 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 567 568 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 569 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 570 571 if ((error = amdsmb_wait(sc)) != SMB_ENOERR) 572 goto error; 573 574 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 575 576 /* Read the 32-byte internal buffer */ 577 for (i=0; i<len; i++) { 578 buf[count-remain+i] = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO); 579 DELAY(2); 580 } 581 582 remain -= len; 583 } 584error: 585 AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 586 587 return (error); 588} 589 590static devclass_t amdpm_devclass; 591 592static device_method_t amdpm_methods[] = { 593 /* Device interface */ 594 DEVMETHOD(device_probe, amdpm_probe), 595 DEVMETHOD(device_attach, amdpm_attach), 596 597 { 0, 0 } 598}; 599 600static driver_t amdpm_driver = { 601 "amdpm", 602 amdpm_methods, 603 sizeof(struct amdpm_softc), 604}; 605 606static devclass_t amdsmb_devclass; 607 608static device_method_t amdsmb_methods[] = { 609 /* Device interface */ 610 DEVMETHOD(device_probe, amdsmb_probe), 611 DEVMETHOD(device_attach, amdsmb_attach), 612 613 /* Bus interface */ 614 DEVMETHOD(bus_print_child, bus_generic_print_child), 615 616 /* SMBus interface */ 617 DEVMETHOD(smbus_callback, amdsmb_smb_callback), 618 DEVMETHOD(smbus_quick, amdsmb_smb_quick), 619 DEVMETHOD(smbus_sendb, amdsmb_smb_sendb), 620 DEVMETHOD(smbus_recvb, amdsmb_smb_recvb), 621 DEVMETHOD(smbus_writeb, amdsmb_smb_writeb), 622 DEVMETHOD(smbus_readb, amdsmb_smb_readb), 623 DEVMETHOD(smbus_writew, amdsmb_smb_writew), 624 DEVMETHOD(smbus_readw, amdsmb_smb_readw), 625 DEVMETHOD(smbus_bwrite, amdsmb_smb_bwrite), 626 DEVMETHOD(smbus_bread, amdsmb_smb_bread), 627 628 { 0, 0 } 629}; 630 631static driver_t amdsmb_driver = { 632 "amdsmb", 633 amdsmb_methods, 634 sizeof(struct amdsmb_softc), 635}; 636 637DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0); 638DRIVER_MODULE(amdsmb, amdpm, amdsmb_driver, amdsmb_devclass, 0, 0); 639MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 640MODULE_VERSION(amdpm, 1); 641