amdpm.c revision 142398
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 31/* 32 * Power management function/SMBus function support for the AMD 756 chip. 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD: head/sys/pci/amdpm.c 142398 2005-02-24 21:32:56Z imp $"); 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 <dev/pci/pcivar.h> 53#include <dev/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#define AMDPM_DEVICEID_AMD766PM 0x7413 70#define AMDPM_DEVICEID_AMD768PM 0x7443 71#define AMDPM_DEVICEID_AMD8111PM 0x746A 72 73/* nVidia nForce chipset */ 74#define AMDPM_VENDORID_NVIDIA 0x10de 75#define AMDPM_DEVICEID_NF_SMB 0x01b4 76 77/* PCI Configuration space registers */ 78#define AMDPCI_PMBASE 0x58 79#define NFPCI_PMBASE 0x14 80 81#define AMDPCI_GEN_CONFIG_PM 0x41 82#define AMDPCI_PMIOEN (1<<7) 83 84#define AMDPCI_SCIINT_CONFIG_PM 0x42 85#define AMDPCI_SCISEL_IRQ11 11 86 87#define AMDPCI_REVID 0x08 88 89/* 90 * I/O registers. 91 * Base address programmed via AMDPCI_PMBASE. 92 */ 93 94#define AMDSMB_GLOBAL_STATUS (0x00) 95#define AMDSMB_GS_TO_STS (1<<5) 96#define AMDSMB_GS_HCYC_STS (1<<4) 97#define AMDSMB_GS_HST_STS (1<<3) 98#define AMDSMB_GS_PRERR_STS (1<<2) 99#define AMDSMB_GS_COL_STS (1<<1) 100#define AMDSMB_GS_ABRT_STS (1<<0) 101#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) 102 103#define AMDSMB_GLOBAL_ENABLE (0x02) 104#define AMDSMB_GE_ABORT (1<<5) 105#define AMDSMB_GE_HCYC_EN (1<<4) 106#define AMDSMB_GE_HOST_STC (1<<3) 107#define AMDSMB_GE_CYC_QUICK 0 108#define AMDSMB_GE_CYC_BYTE 1 109#define AMDSMB_GE_CYC_BDATA 2 110#define AMDSMB_GE_CYC_WDATA 3 111#define AMDSMB_GE_CYC_PROCCALL 4 112#define AMDSMB_GE_CYC_BLOCK 5 113 114#define AMDSMB_HSTADDR (0x04) 115#define AMDSMB_HSTDATA (0x06) 116#define AMDSMB_HSTCMD (0x08) 117#define AMDSMB_HSTDFIFO (0x09) 118#define AMDSMB_HSLVDATA (0x0A) 119#define AMDSMB_HSLVDA (0x0C) 120#define AMDSMB_HSLVDDR (0x0E) 121#define AMDSMB_SNPADDR (0x0F) 122 123struct amdpm_softc { 124 int base; 125 int rid; 126 struct resource *res; 127 bus_space_tag_t smbst; 128 bus_space_handle_t smbsh; 129 130 device_t smbus; 131}; 132 133#define AMDPM_SMBINB(amdpm,register) \ 134 (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register)) 135#define AMDPM_SMBOUTB(amdpm,register,value) \ 136 (bus_space_write_1(amdpm->smbst, amdpm->smbsh, register, value)) 137#define AMDPM_SMBINW(amdpm,register) \ 138 (bus_space_read_2(amdpm->smbst, amdpm->smbsh, register)) 139#define AMDPM_SMBOUTW(amdpm,register,value) \ 140 (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value)) 141 142static int 143amdpm_probe(device_t dev) 144{ 145 u_long base; 146 u_int16_t vid; 147 u_int16_t did; 148 149 vid = pci_get_vendor(dev); 150 did = pci_get_device(dev); 151 if ((vid == AMDPM_VENDORID_AMD) && 152 ((did == AMDPM_DEVICEID_AMD756PM) || 153 (did == AMDPM_DEVICEID_AMD766PM) || 154 (did == AMDPM_DEVICEID_AMD768PM) || 155 (did == AMDPM_DEVICEID_AMD8111PM))) { 156 device_set_desc(dev, "AMD 756/766/768/8111 Power Management Controller"); 157 158 /* 159 * We have to do this, since the BIOS won't give us the 160 * resource info (not mine, anyway). 161 */ 162 base = pci_read_config(dev, AMDPCI_PMBASE, 4); 163 base &= 0xff00; 164 bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, 165 base+0xe0, 32); 166 return (BUS_PROBE_DEFAULT); 167 } 168 169 if ((vid == AMDPM_VENDORID_NVIDIA) && 170 (did == AMDPM_DEVICEID_NF_SMB)) { 171 device_set_desc(dev, "nForce SMBus Controller"); 172 173 /* 174 * We have to do this, since the BIOS won't give us the 175 * resource info (not mine, anyway). 176 */ 177 base = pci_read_config(dev, NFPCI_PMBASE, 4); 178 base &= 0xff00; 179 bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE, 180 base, 32); 181 182 return (BUS_PROBE_DEFAULT); 183 } 184 185 return ENXIO; 186} 187 188static int 189amdpm_attach(device_t dev) 190{ 191 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 192 u_char val_b; 193 194 /* Enable I/O block access */ 195 val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1); 196 pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1); 197 198 /* Allocate I/O space */ 199 if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD) 200 amdpm_sc->rid = AMDPCI_PMBASE; 201 else 202 amdpm_sc->rid = NFPCI_PMBASE; 203 amdpm_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 204 &amdpm_sc->rid, RF_ACTIVE); 205 206 if (amdpm_sc->res == NULL) { 207 device_printf(dev, "could not map i/o space\n"); 208 return (ENXIO); 209 } 210 211 amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res); 212 amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res); 213 214 /* Allocate a new smbus device */ 215 amdpm_sc->smbus = device_add_child(dev, "smbus", -1); 216 if (!amdpm_sc->smbus) 217 return (EINVAL); 218 219 bus_generic_attach(dev); 220 221 return (0); 222} 223 224static int 225amdpm_detach(device_t dev) 226{ 227 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 228 229 if (amdpm_sc->smbus) { 230 device_delete_child(dev, amdpm_sc->smbus); 231 amdpm_sc->smbus = NULL; 232 } 233 234 if (amdpm_sc->res) 235 bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid, 236 amdpm_sc->res); 237 238 return (0); 239} 240 241static int 242amdpm_callback(device_t dev, int index, caddr_t *data) 243{ 244 int error = 0; 245 246 switch (index) { 247 case SMB_REQUEST_BUS: 248 case SMB_RELEASE_BUS: 249 break; 250 default: 251 error = EINVAL; 252 } 253 254 return (error); 255} 256 257static int 258amdpm_clear(struct amdpm_softc *sc) 259{ 260 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); 261 DELAY(10); 262 263 return (0); 264} 265 266#if 0 267static int 268amdpm_abort(struct amdpm_softc *sc) 269{ 270 u_short l; 271 272 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 273 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT); 274 275 return (0); 276} 277#endif 278 279static int 280amdpm_idle(struct amdpm_softc *sc) 281{ 282 u_short sts; 283 284 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 285 286 AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts)); 287 288 return (~(sts & AMDSMB_GS_HST_STS)); 289} 290 291/* 292 * Poll the SMBus controller 293 */ 294static int 295amdpm_wait(struct amdpm_softc *sc) 296{ 297 int count = 10000; 298 u_short sts = 0; 299 int error; 300 301 /* Wait for command to complete (SMBus controller is idle) */ 302 while(count--) { 303 DELAY(10); 304 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 305 if (!(sts & AMDSMB_GS_HST_STS)) 306 break; 307 } 308 309 AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count)); 310 311 error = SMB_ENOERR; 312 313 if (!count) 314 error |= SMB_ETIMEOUT; 315 316 if (sts & AMDSMB_GS_ABRT_STS) 317 error |= SMB_EABORT; 318 319 if (sts & AMDSMB_GS_COL_STS) 320 error |= SMB_ENOACK; 321 322 if (sts & AMDSMB_GS_PRERR_STS) 323 error |= SMB_EBUSERR; 324 325 if (error != SMB_ENOERR) 326 amdpm_clear(sc); 327 328 return (error); 329} 330 331static int 332amdpm_quick(device_t dev, u_char slave, int how) 333{ 334 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 335 int error; 336 u_short l; 337 338 amdpm_clear(sc); 339 if (!amdpm_idle(sc)) 340 return (EBUSY); 341 342 switch (how) { 343 case SMB_QWRITE: 344 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave)); 345 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 346 break; 347 case SMB_QREAD: 348 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave)); 349 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 350 break; 351 default: 352 panic("%s: unknown QUICK command (%x)!", __func__, how); 353 } 354 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 355 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC); 356 357 error = amdpm_wait(sc); 358 359 AMDPM_DEBUG(printf(", error=0x%x\n", error)); 360 361 return (error); 362} 363 364static int 365amdpm_sendb(device_t dev, u_char slave, char byte) 366{ 367 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 368 int error; 369 u_short l; 370 371 amdpm_clear(sc); 372 if (!amdpm_idle(sc)) 373 return (SMB_EBUSY); 374 375 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 376 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 377 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 378 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 379 380 error = amdpm_wait(sc); 381 382 AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 383 384 return (error); 385} 386 387static int 388amdpm_recvb(device_t dev, u_char slave, char *byte) 389{ 390 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 391 int error; 392 u_short l; 393 394 amdpm_clear(sc); 395 if (!amdpm_idle(sc)) 396 return (SMB_EBUSY); 397 398 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 399 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 400 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 401 402 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 403 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 404 405 AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 406 407 return (error); 408} 409 410static int 411amdpm_writeb(device_t dev, u_char slave, char cmd, char byte) 412{ 413 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 414 int error; 415 u_short l; 416 417 amdpm_clear(sc); 418 if (!amdpm_idle(sc)) 419 return (SMB_EBUSY); 420 421 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 422 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 423 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 424 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 425 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 426 427 error = amdpm_wait(sc); 428 429 AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 430 431 return (error); 432} 433 434static int 435amdpm_readb(device_t dev, u_char slave, char cmd, char *byte) 436{ 437 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 438 int error; 439 u_short l; 440 441 amdpm_clear(sc); 442 if (!amdpm_idle(sc)) 443 return (SMB_EBUSY); 444 445 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 446 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 447 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 448 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 449 450 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 451 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 452 453 AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); 454 455 return (error); 456} 457 458static int 459amdpm_writew(device_t dev, u_char slave, char cmd, short word) 460{ 461 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 462 int error; 463 u_short l; 464 465 amdpm_clear(sc); 466 if (!amdpm_idle(sc)) 467 return (SMB_EBUSY); 468 469 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 470 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word); 471 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 472 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 473 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 474 475 error = amdpm_wait(sc); 476 477 AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 478 479 return (error); 480} 481 482static int 483amdpm_readw(device_t dev, u_char slave, char cmd, short *word) 484{ 485 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 486 int error; 487 u_short l; 488 489 amdpm_clear(sc); 490 if (!amdpm_idle(sc)) 491 return (SMB_EBUSY); 492 493 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 494 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 495 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 496 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 497 498 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 499 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 500 501 AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); 502 503 return (error); 504} 505 506static int 507amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 508{ 509 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 510 u_char remain, len, i; 511 int error = SMB_ENOERR; 512 u_short l; 513 514 amdpm_clear(sc); 515 if(!amdpm_idle(sc)) 516 return (SMB_EBUSY); 517 518 remain = count; 519 while (remain) { 520 len = min(remain, 32); 521 522 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 523 524 /* 525 * Do we have to reset the internal 32-byte buffer? 526 * Can't see how to do this from the data sheet. 527 */ 528 529 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, len); 530 531 /* Fill the 32-byte internal buffer */ 532 for (i=0; i<len; i++) { 533 AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[count-remain+i]); 534 DELAY(2); 535 } 536 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 537 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 538 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 539 540 if ((error = amdpm_wait(sc)) != SMB_ENOERR) 541 goto error; 542 543 remain -= len; 544 } 545 546error: 547 AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 548 549 return (error); 550} 551 552static int 553amdpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) 554{ 555 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 556 u_char remain, len, i; 557 int error = SMB_ENOERR; 558 u_short l; 559 560 amdpm_clear(sc); 561 if (!amdpm_idle(sc)) 562 return (SMB_EBUSY); 563 564 remain = count; 565 while (remain) { 566 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 567 568 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 569 570 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 571 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 572 573 if ((error = amdpm_wait(sc)) != SMB_ENOERR) 574 goto error; 575 576 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 577 578 /* Read the 32-byte internal buffer */ 579 for (i=0; i<len; i++) { 580 buf[count-remain+i] = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO); 581 DELAY(2); 582 } 583 584 remain -= len; 585 } 586error: 587 AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 588 589 return (error); 590} 591 592static devclass_t amdpm_devclass; 593 594static device_method_t amdpm_methods[] = { 595 /* Device interface */ 596 DEVMETHOD(device_probe, amdpm_probe), 597 DEVMETHOD(device_attach, amdpm_attach), 598 DEVMETHOD(device_detach, amdpm_detach), 599 600 /* SMBus interface */ 601 DEVMETHOD(smbus_callback, amdpm_callback), 602 DEVMETHOD(smbus_quick, amdpm_quick), 603 DEVMETHOD(smbus_sendb, amdpm_sendb), 604 DEVMETHOD(smbus_recvb, amdpm_recvb), 605 DEVMETHOD(smbus_writeb, amdpm_writeb), 606 DEVMETHOD(smbus_readb, amdpm_readb), 607 DEVMETHOD(smbus_writew, amdpm_writew), 608 DEVMETHOD(smbus_readw, amdpm_readw), 609 DEVMETHOD(smbus_bwrite, amdpm_bwrite), 610 DEVMETHOD(smbus_bread, amdpm_bread), 611 612 { 0, 0 } 613}; 614 615static driver_t amdpm_driver = { 616 "amdpm", 617 amdpm_methods, 618 sizeof(struct amdpm_softc), 619}; 620 621DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0); 622 623MODULE_DEPEND(amdpm, pci, 1, 1, 1); 624MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 625MODULE_VERSION(amdpm, 1); 626 627