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: src/sys/pci/amdpm.c,v 1.10 2003/09/06 13:56:56 dfr Exp $ 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 #include <sys/rman.h> 45 46 #include <machine/clock.h> 47 48 #include <bus/pci/pcivar.h> 49 #include <bus/pci/pcireg.h> 50 51 #include <bus/iicbus/iiconf.h> 52 #include <bus/smbus/smbconf.h> 53 #include "smbus_if.h" 54 55 #define AMDPM_DEBUG(x) if (amdpm_debug) (x) 56 57 #ifdef DEBUG 58 static int amdpm_debug = 1; 59 #else 60 static int amdpm_debug = 0; 61 #endif 62 63 #define AMDPM_VENDORID_AMD 0x1022 64 #define AMDPM_DEVICEID_AMD756PM 0x740b 65 #define AMDPM_DEVICEID_AMD766PM 0x7413 66 #define AMDPM_DEVICEID_AMD768PM 0x7443 67 68 /* nVidia nForce chipset */ 69 #define AMDPM_VENDORID_NVIDIA 0x10de 70 #define AMDPM_DEVICEID_NF_SMB 0x01b4 71 72 73 /* PCI Configuration space registers */ 74 #define AMDPCI_PMBASE 0x58 75 #define NFPCI_PMBASE 0x14 76 77 #define AMDPCI_GEN_CONFIG_PM 0x41 78 #define AMDPCI_PMIOEN (1<<7) 79 80 #define AMDPCI_SCIINT_CONFIG_PM 0x42 81 #define AMDPCI_SCISEL_IRQ11 11 82 83 #define AMDPCI_REVID 0x08 84 85 /* 86 * I/O registers. 87 * Base address programmed via AMDPCI_PMBASE. 88 */ 89 90 #define AMDSMB_GLOBAL_STATUS (0x00) 91 #define AMDSMB_GS_TO_STS (1<<5) 92 #define AMDSMB_GS_HCYC_STS (1<<4) 93 #define AMDSMB_GS_HST_STS (1<<3) 94 #define AMDSMB_GS_PRERR_STS (1<<2) 95 #define AMDSMB_GS_COL_STS (1<<1) 96 #define AMDSMB_GS_ABRT_STS (1<<0) 97 #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) 98 99 #define AMDSMB_GLOBAL_ENABLE (0x02) 100 #define AMDSMB_GE_ABORT (1<<5) 101 #define AMDSMB_GE_HCYC_EN (1<<4) 102 #define AMDSMB_GE_HOST_STC (1<<3) 103 #define AMDSMB_GE_CYC_QUICK 0 104 #define AMDSMB_GE_CYC_BYTE 1 105 #define AMDSMB_GE_CYC_BDATA 2 106 #define AMDSMB_GE_CYC_WDATA 3 107 #define AMDSMB_GE_CYC_PROCCALL 4 108 #define AMDSMB_GE_CYC_BLOCK 5 109 110 #define AMDSMB_HSTADDR (0x04) 111 #define AMDSMB_HSTDATA (0x06) 112 #define AMDSMB_HSTCMD (0x08) 113 #define AMDSMB_HSTDFIFO (0x09) 114 #define AMDSMB_HSLVDATA (0x0A) 115 #define AMDSMB_HSLVDA (0x0C) 116 #define AMDSMB_HSLVDDR (0x0E) 117 #define AMDSMB_SNPADDR (0x0F) 118 119 struct amdpm_softc { 120 int base; 121 int rid; 122 struct resource *res; 123 bus_space_tag_t smbst; 124 bus_space_handle_t smbsh; 125 126 device_t smbus; 127 }; 128 129 #define AMDPM_SMBINB(amdpm,register) \ 130 (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register)) 131 #define AMDPM_SMBOUTB(amdpm,register,value) \ 132 (bus_space_write_1(amdpm->smbst, amdpm->smbsh, register, value)) 133 #define AMDPM_SMBINW(amdpm,register) \ 134 (bus_space_read_2(amdpm->smbst, amdpm->smbsh, register)) 135 #define AMDPM_SMBOUTW(amdpm,register,value) \ 136 (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value)) 137 138 static int 139 amdpm_probe(device_t dev) 140 { 141 u_long base; 142 u_int16_t vid; 143 u_int16_t did; 144 145 vid = pci_get_vendor(dev); 146 did = pci_get_device(dev); 147 if ((vid == AMDPM_VENDORID_AMD) && 148 ((did == AMDPM_DEVICEID_AMD756PM) || 149 (did == AMDPM_DEVICEID_AMD766PM) || 150 (did == AMDPM_DEVICEID_AMD768PM))) { 151 device_set_desc(dev, "AMD 756/766/768 Power Management Controller"); 152 153 /* 154 * We have to do this, since the BIOS won't give us the 155 * resource info (not mine, anyway). 156 */ 157 base = pci_read_config(dev, AMDPCI_PMBASE, 4); 158 base &= 0xff00; 159 bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, 160 base+0xe0, 32); 161 return (0); 162 } 163 164 if ((vid == AMDPM_VENDORID_NVIDIA) && 165 (did == AMDPM_DEVICEID_NF_SMB)) { 166 device_set_desc(dev, "nForce SMBus Controller"); 167 168 /* 169 * We have to do this, since the BIOS won't give us the 170 * resource info (not mine, anyway). 171 */ 172 base = pci_read_config(dev, NFPCI_PMBASE, 4); 173 base &= 0xff00; 174 bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE, 175 base, 32); 176 177 return (0); 178 } 179 180 return ENXIO; 181 } 182 183 static int 184 amdpm_attach(device_t dev) 185 { 186 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 187 u_char val_b; 188 189 /* Enable I/O block access */ 190 val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1); 191 pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1); 192 193 /* Allocate I/O space */ 194 if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD) 195 amdpm_sc->rid = AMDPCI_PMBASE; 196 else 197 amdpm_sc->rid = NFPCI_PMBASE; 198 amdpm_sc->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &amdpm_sc->rid, 0, ~0, 1, RF_ACTIVE); 199 200 if (amdpm_sc->res == NULL) { 201 device_printf(dev, "could not map i/o space\n"); 202 return (ENXIO); 203 } 204 205 amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res); 206 amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res); 207 208 /* Allocate a new smbus device */ 209 amdpm_sc->smbus = device_add_child(dev, "smbus", -1); 210 if (!amdpm_sc->smbus) 211 return (EINVAL); 212 213 bus_generic_attach(dev); 214 215 return (0); 216 } 217 218 static int 219 amdpm_detach(device_t dev) 220 { 221 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 222 223 if (amdpm_sc->smbus) { 224 device_delete_child(dev, amdpm_sc->smbus); 225 amdpm_sc->smbus = NULL; 226 } 227 228 if (amdpm_sc->res) 229 bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid, 230 amdpm_sc->res); 231 232 return (0); 233 } 234 235 static int 236 amdpm_callback(device_t dev, int index, caddr_t *data) 237 { 238 int error = 0; 239 240 switch (index) { 241 case SMB_REQUEST_BUS: 242 case SMB_RELEASE_BUS: 243 break; 244 default: 245 error = EINVAL; 246 } 247 248 return (error); 249 } 250 251 static int 252 amdpm_clear(struct amdpm_softc *sc) 253 { 254 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); 255 DELAY(10); 256 257 return (0); 258 } 259 260 #if 0 261 static int 262 amdpm_abort(struct amdpm_softc *sc) 263 { 264 u_short l; 265 266 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 267 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT); 268 269 return (0); 270 } 271 #endif 272 273 static int 274 amdpm_idle(struct amdpm_softc *sc) 275 { 276 u_short sts; 277 278 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 279 280 AMDPM_DEBUG(kprintf("amdpm: busy? STS=0x%x\n", sts)); 281 282 return (~(sts & AMDSMB_GS_HST_STS)); 283 } 284 285 /* 286 * Poll the SMBus controller 287 */ 288 static int 289 amdpm_wait(struct amdpm_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(kprintf("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 amdpm_clear(sc); 321 322 return (error); 323 } 324 325 static int 326 amdpm_quick(device_t dev, u_char slave, int how) 327 { 328 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 329 int error; 330 u_short l; 331 332 amdpm_clear(sc); 333 if (!amdpm_idle(sc)) 334 return (EBUSY); 335 336 switch (how) { 337 case SMB_QWRITE: 338 AMDPM_DEBUG(kprintf("amdpm: QWRITE to 0x%x", slave)); 339 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 340 break; 341 case SMB_QREAD: 342 AMDPM_DEBUG(kprintf("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)!", __func__, 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 = amdpm_wait(sc); 352 353 AMDPM_DEBUG(kprintf(", error=0x%x\n", error)); 354 355 return (error); 356 } 357 358 static int 359 amdpm_sendb(device_t dev, u_char slave, char byte) 360 { 361 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 362 int error; 363 u_short l; 364 365 amdpm_clear(sc); 366 if (!amdpm_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 = amdpm_wait(sc); 375 376 AMDPM_DEBUG(kprintf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 377 378 return (error); 379 } 380 381 static int 382 amdpm_recvb(device_t dev, u_char slave, char *byte) 383 { 384 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 385 int error; 386 u_short l; 387 388 amdpm_clear(sc); 389 if (!amdpm_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 = amdpm_wait(sc)) == SMB_ENOERR) 397 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 398 399 AMDPM_DEBUG(kprintf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 400 401 return (error); 402 } 403 404 static int 405 amdpm_writeb(device_t dev, u_char slave, char cmd, char byte) 406 { 407 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 408 int error; 409 u_short l; 410 411 amdpm_clear(sc); 412 if (!amdpm_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 = amdpm_wait(sc); 422 423 AMDPM_DEBUG(kprintf("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 428 static int 429 amdpm_readb(device_t dev, u_char slave, char cmd, char *byte) 430 { 431 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 432 int error; 433 u_short l; 434 435 amdpm_clear(sc); 436 if (!amdpm_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 = amdpm_wait(sc)) == SMB_ENOERR) 445 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 446 447 AMDPM_DEBUG(kprintf("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 452 static int 453 amdpm_writew(device_t dev, u_char slave, char cmd, short word) 454 { 455 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 456 int error; 457 u_short l; 458 459 amdpm_clear(sc); 460 if (!amdpm_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 = amdpm_wait(sc); 470 471 AMDPM_DEBUG(kprintf("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 476 static int 477 amdpm_readw(device_t dev, u_char slave, char cmd, short *word) 478 { 479 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 480 int error; 481 u_short l; 482 483 amdpm_clear(sc); 484 if (!amdpm_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 = amdpm_wait(sc)) == SMB_ENOERR) 493 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 494 495 AMDPM_DEBUG(kprintf("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 500 static int 501 amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 502 { 503 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 504 u_char remain, len, i; 505 int error = SMB_ENOERR; 506 u_short l; 507 508 amdpm_clear(sc); 509 if(!amdpm_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 = amdpm_wait(sc)) != SMB_ENOERR) 535 goto error; 536 537 remain -= len; 538 } 539 540 error: 541 AMDPM_DEBUG(kprintf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 542 543 return (error); 544 } 545 546 static int 547 amdpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 548 { 549 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 550 u_char remain, len, i; 551 int error = SMB_ENOERR; 552 u_short l; 553 554 amdpm_clear(sc); 555 if (!amdpm_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 = amdpm_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 } 580 error: 581 AMDPM_DEBUG(kprintf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 582 583 return (error); 584 } 585 586 static devclass_t amdpm_devclass; 587 588 static device_method_t amdpm_methods[] = { 589 /* Device interface */ 590 DEVMETHOD(device_probe, amdpm_probe), 591 DEVMETHOD(device_attach, amdpm_attach), 592 DEVMETHOD(device_detach, amdpm_detach), 593 594 /* SMBus interface */ 595 DEVMETHOD(smbus_callback, amdpm_callback), 596 DEVMETHOD(smbus_quick, amdpm_quick), 597 DEVMETHOD(smbus_sendb, amdpm_sendb), 598 DEVMETHOD(smbus_recvb, amdpm_recvb), 599 DEVMETHOD(smbus_writeb, amdpm_writeb), 600 DEVMETHOD(smbus_readb, amdpm_readb), 601 DEVMETHOD(smbus_writew, amdpm_writew), 602 DEVMETHOD(smbus_readw, amdpm_readw), 603 DEVMETHOD(smbus_bwrite, amdpm_bwrite), 604 DEVMETHOD(smbus_bread, amdpm_bread), 605 606 { 0, 0 } 607 }; 608 609 static driver_t amdpm_driver = { 610 "amdpm", 611 amdpm_methods, 612 sizeof(struct amdpm_softc), 613 }; 614 615 DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0); 616 617 MODULE_DEPEND(amdpm, pci, 1, 1, 1); 618 MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 619 MODULE_VERSION(amdpm, 1); 620