1 /*- 2 * Copyright (c) 2001 Alcove - Nicolas Souchu 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 #include "opt_isa.h" 29 30 #include <sys/param.h> 31 #include <sys/bus.h> 32 #include <sys/kernel.h> 33 #include <sys/lock.h> 34 #include <sys/module.h> 35 #include <sys/mutex.h> 36 #include <sys/systm.h> 37 38 #include <machine/bus.h> 39 #include <machine/resource.h> 40 #include <sys/rman.h> 41 42 #ifdef DEV_ISA 43 #include <isa/isavar.h> 44 #include <isa/isa_common.h> 45 #endif 46 #include <dev/pci/pcivar.h> 47 #include <dev/pci/pcireg.h> 48 49 #include <dev/iicbus/iiconf.h> 50 51 #include <dev/smbus/smbconf.h> 52 53 #include "iicbb_if.h" 54 #include "smbus_if.h" 55 56 #define VIAPM_DEBUG(x) if (viapm_debug) (x) 57 58 #ifdef DEBUG 59 static int viapm_debug = 1; 60 #else 61 static int viapm_debug = 0; 62 #endif 63 64 #define VIA_586B_PMU_ID 0x30401106 65 #define VIA_596A_PMU_ID 0x30501106 66 #define VIA_596B_PMU_ID 0x30511106 67 #define VIA_686A_PMU_ID 0x30571106 68 #define VIA_8233_PMU_ID 0x30741106 69 #define VIA_8233A_PMU_ID 0x31471106 70 #define VIA_8235_PMU_ID 0x31771106 71 #define VIA_8237_PMU_ID 0x32271106 72 #define VIA_CX700_PMU_ID 0x83241106 73 74 #define VIAPM_INB(port) \ 75 ((u_char)bus_read_1(viapm->iores, port)) 76 #define VIAPM_OUTB(port,val) \ 77 (bus_write_1(viapm->iores, port, (u_char)(val))) 78 79 #define VIAPM_TYP_UNKNOWN 0 80 #define VIAPM_TYP_586B_3040E 1 81 #define VIAPM_TYP_586B_3040F 2 82 #define VIAPM_TYP_596B 3 83 #define VIAPM_TYP_686A 4 84 #define VIAPM_TYP_8233 5 85 86 #define VIAPM_LOCK(sc) mtx_lock(&(sc)->lock) 87 #define VIAPM_UNLOCK(sc) mtx_unlock(&(sc)->lock) 88 #define VIAPM_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED) 89 90 struct viapm_softc { 91 int type; 92 u_int32_t base; 93 int iorid; 94 int irqrid; 95 struct resource *iores; 96 struct resource *irqres; 97 void *irqih; 98 device_t iicbb; 99 device_t smbus; 100 struct mtx lock; 101 }; 102 103 /* 104 * VT82C586B definitions 105 */ 106 107 #define VIAPM_586B_REVID 0x08 108 109 #define VIAPM_586B_3040E_BASE 0x20 110 #define VIAPM_586B_3040E_ACTIV 0x4 /* 16 bits */ 111 112 #define VIAPM_586B_3040F_BASE 0x48 113 #define VIAPM_586B_3040F_ACTIV 0x41 /* 8 bits */ 114 115 #define VIAPM_586B_OEM_REV_E 0x00 116 #define VIAPM_586B_OEM_REV_F 0x01 117 #define VIAPM_586B_PROD_REV_A 0x10 118 119 #define VIAPM_586B_BA_MASK 0x0000ff00 120 121 #define GPIO_DIR 0x40 122 #define GPIO_VAL 0x42 123 #define EXTSMI_VAL 0x44 124 125 #define VIAPM_SCL 0x02 /* GPIO1_VAL */ 126 #define VIAPM_SDA 0x04 /* GPIO2_VAL */ 127 128 /* 129 * VIAPRO common definitions 130 */ 131 132 #define VIAPM_PRO_BA_MASK 0x0000fff0 133 #define VIAPM_PRO_SMBCTRL 0xd2 134 #define VIAPM_PRO_REVID 0xd6 135 136 /* 137 * VT82C686A definitions 138 */ 139 140 #define VIAPM_PRO_BASE 0x90 141 142 #define SMBHST 0x0 143 #define SMBHSL 0x1 144 #define SMBHCTRL 0x2 145 #define SMBHCMD 0x3 146 #define SMBHADDR 0x4 147 #define SMBHDATA0 0x5 148 #define SMBHDATA1 0x6 149 #define SMBHBLOCK 0x7 150 151 #define SMBSST 0x1 152 #define SMBSCTRL 0x8 153 #define SMBSSDWCMD 0x9 154 #define SMBSEVENT 0xa 155 #define SMBSDATA 0xc 156 157 #define SMBHST_RESERVED 0xef /* reserved bits */ 158 #define SMBHST_FAILED 0x10 /* failed bus transaction */ 159 #define SMBHST_COLLID 0x08 /* bus collision */ 160 #define SMBHST_ERROR 0x04 /* device error */ 161 #define SMBHST_INTR 0x02 /* command completed */ 162 #define SMBHST_BUSY 0x01 /* host busy */ 163 164 #define SMBHCTRL_START 0x40 /* start command */ 165 #define SMBHCTRL_PROTO 0x1c /* command protocol mask */ 166 #define SMBHCTRL_QUICK 0x00 167 #define SMBHCTRL_SENDRECV 0x04 168 #define SMBHCTRL_BYTE 0x08 169 #define SMBHCTRL_WORD 0x0c 170 #define SMBHCTRL_BLOCK 0x14 171 #define SMBHCTRL_KILL 0x02 /* stop the current transaction */ 172 #define SMBHCTRL_ENABLE 0x01 /* enable interrupts */ 173 174 #define SMBSCTRL_ENABLE 0x01 /* enable slave */ 175 176 /* 177 * VIA8233 definitions 178 */ 179 180 #define VIAPM_8233_BASE 0xD0 181 182 static int 183 viapm_586b_probe(device_t dev) 184 { 185 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 186 u_int32_t l; 187 u_int16_t s; 188 u_int8_t c; 189 190 switch (pci_get_devid(dev)) { 191 case VIA_586B_PMU_ID: 192 193 bzero(viapm, sizeof(struct viapm_softc)); 194 195 l = pci_read_config(dev, VIAPM_586B_REVID, 1); 196 switch (l) { 197 case VIAPM_586B_OEM_REV_E: 198 viapm->type = VIAPM_TYP_586B_3040E; 199 viapm->iorid = VIAPM_586B_3040E_BASE; 200 201 /* Activate IO block access */ 202 s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2); 203 pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2); 204 break; 205 206 case VIAPM_586B_OEM_REV_F: 207 case VIAPM_586B_PROD_REV_A: 208 default: 209 viapm->type = VIAPM_TYP_586B_3040F; 210 viapm->iorid = VIAPM_586B_3040F_BASE; 211 212 /* Activate IO block access */ 213 c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1); 214 pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1); 215 break; 216 } 217 218 viapm->base = pci_read_config(dev, viapm->iorid, 4) & 219 VIAPM_586B_BA_MASK; 220 221 /* 222 * We have to set the I/O resources by hand because it is 223 * described outside the viapmope of the traditional maps 224 */ 225 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid, 226 viapm->base, 256)) { 227 device_printf(dev, "could not set bus resource\n"); 228 return ENXIO; 229 } 230 device_set_desc(dev, "VIA VT82C586B Power Management Unit"); 231 return (BUS_PROBE_DEFAULT); 232 233 default: 234 break; 235 } 236 237 return ENXIO; 238 } 239 240 static int 241 viapm_pro_probe(device_t dev) 242 { 243 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 244 #ifdef VIAPM_BASE_ADDR 245 u_int32_t l; 246 #endif 247 u_int32_t base_cfgreg; 248 char *desc; 249 250 switch (pci_get_devid(dev)) { 251 case VIA_596A_PMU_ID: 252 desc = "VIA VT82C596A Power Management Unit"; 253 viapm->type = VIAPM_TYP_596B; 254 base_cfgreg = VIAPM_PRO_BASE; 255 goto viapro; 256 257 case VIA_596B_PMU_ID: 258 desc = "VIA VT82C596B Power Management Unit"; 259 viapm->type = VIAPM_TYP_596B; 260 base_cfgreg = VIAPM_PRO_BASE; 261 goto viapro; 262 263 case VIA_686A_PMU_ID: 264 desc = "VIA VT82C686A Power Management Unit"; 265 viapm->type = VIAPM_TYP_686A; 266 base_cfgreg = VIAPM_PRO_BASE; 267 goto viapro; 268 269 case VIA_8233_PMU_ID: 270 case VIA_8233A_PMU_ID: 271 desc = "VIA VT8233 Power Management Unit"; 272 viapm->type = VIAPM_TYP_UNKNOWN; 273 base_cfgreg = VIAPM_8233_BASE; 274 goto viapro; 275 276 case VIA_8235_PMU_ID: 277 desc = "VIA VT8235 Power Management Unit"; 278 viapm->type = VIAPM_TYP_UNKNOWN; 279 base_cfgreg = VIAPM_8233_BASE; 280 goto viapro; 281 282 case VIA_8237_PMU_ID: 283 desc = "VIA VT8237 Power Management Unit"; 284 viapm->type = VIAPM_TYP_UNKNOWN; 285 base_cfgreg = VIAPM_8233_BASE; 286 goto viapro; 287 288 case VIA_CX700_PMU_ID: 289 desc = "VIA CX700 Power Management Unit"; 290 viapm->type = VIAPM_TYP_UNKNOWN; 291 base_cfgreg = VIAPM_8233_BASE; 292 goto viapro; 293 294 viapro: 295 296 #ifdef VIAPM_BASE_ADDR 297 /* force VIAPM I/O base address */ 298 299 /* enable the SMBus controller function */ 300 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); 301 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1); 302 303 /* write the base address */ 304 pci_write_config(dev, base_cfgreg, 305 VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4); 306 #endif 307 308 viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK; 309 310 /* 311 * We have to set the I/O resources by hand because it is 312 * described outside the viapmope of the traditional maps 313 */ 314 viapm->iorid = base_cfgreg; 315 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid, 316 viapm->base, 16)) { 317 device_printf(dev, "could not set bus resource 0x%x\n", 318 viapm->base); 319 return ENXIO; 320 } 321 322 if (bootverbose) { 323 device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base); 324 } 325 326 device_set_desc(dev, desc); 327 return (BUS_PROBE_DEFAULT); 328 329 default: 330 break; 331 } 332 333 return ENXIO; 334 } 335 336 static int 337 viapm_pro_attach(device_t dev) 338 { 339 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 340 u_int32_t l; 341 342 mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF); 343 if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 344 &viapm->iorid, RF_ACTIVE))) { 345 device_printf(dev, "could not allocate bus space\n"); 346 goto error; 347 } 348 349 #ifdef notyet 350 /* force irq 9 */ 351 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); 352 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1); 353 354 viapm->irqrid = 0; 355 if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, 356 &viapm->irqrid, 9, 9, 1, 357 RF_SHAREABLE | RF_ACTIVE))) { 358 device_printf(dev, "could not allocate irq\n"); 359 goto error; 360 } 361 362 if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC | INTR_MPSAFE, 363 (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) { 364 device_printf(dev, "could not setup irq\n"); 365 goto error; 366 } 367 #endif 368 369 if (bootverbose) { 370 l = pci_read_config(dev, VIAPM_PRO_REVID, 1); 371 device_printf(dev, "SMBus revision code 0x%x\n", l); 372 } 373 374 viapm->smbus = device_add_child(dev, "smbus", DEVICE_UNIT_ANY); 375 376 /* probe and attach the smbus */ 377 bus_attach_children(dev); 378 379 /* disable slave function */ 380 VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE); 381 382 /* enable the SMBus controller function */ 383 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); 384 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1); 385 386 #ifdef notyet 387 /* enable interrupts */ 388 VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE); 389 #endif 390 391 #ifdef DEV_ISA 392 /* If this device is a PCI-ISA bridge, then attach an ISA bus. */ 393 if ((pci_get_class(dev) == PCIC_BRIDGE) && 394 (pci_get_subclass(dev) == PCIS_BRIDGE_ISA)) 395 isab_attach(dev); 396 #endif 397 return 0; 398 399 error: 400 if (viapm->iores) 401 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores); 402 #ifdef notyet 403 if (viapm->irqres) 404 bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres); 405 #endif 406 mtx_destroy(&viapm->lock); 407 408 return ENXIO; 409 } 410 411 static int 412 viapm_586b_attach(device_t dev) 413 { 414 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 415 416 mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF); 417 if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 418 &viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) { 419 device_printf(dev, "could not allocate bus resource\n"); 420 goto error; 421 } 422 423 VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA); 424 425 /* add generic bit-banging code */ 426 if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1))) 427 goto error; 428 429 bus_attach_children(dev); 430 431 return 0; 432 433 error: 434 if (viapm->iores) 435 bus_release_resource(dev, SYS_RES_IOPORT, 436 viapm->iorid, viapm->iores); 437 mtx_destroy(&viapm->lock); 438 return ENXIO; 439 } 440 441 static int 442 viapm_586b_detach(device_t dev) 443 { 444 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 445 446 bus_generic_detach(dev); 447 448 if (viapm->iores) 449 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, 450 viapm->iores); 451 mtx_destroy(&viapm->lock); 452 453 return 0; 454 } 455 456 static int 457 viapm_pro_detach(device_t dev) 458 { 459 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 460 461 bus_generic_detach(dev); 462 463 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores); 464 465 #ifdef notyet 466 bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres); 467 #endif 468 mtx_destroy(&viapm->lock); 469 470 return 0; 471 } 472 473 static int 474 viabb_callback(device_t dev, int index, caddr_t data) 475 { 476 return 0; 477 } 478 479 static void 480 viabb_setscl(device_t dev, int ctrl) 481 { 482 struct viapm_softc *viapm = device_get_softc(dev); 483 u_char val; 484 485 VIAPM_LOCK(viapm); 486 val = VIAPM_INB(GPIO_VAL); 487 488 if (ctrl) 489 val |= VIAPM_SCL; 490 else 491 val &= ~VIAPM_SCL; 492 493 VIAPM_OUTB(GPIO_VAL, val); 494 VIAPM_UNLOCK(viapm); 495 496 return; 497 } 498 499 static void 500 viabb_setsda(device_t dev, int data) 501 { 502 struct viapm_softc *viapm = device_get_softc(dev); 503 u_char val; 504 505 VIAPM_LOCK(viapm); 506 val = VIAPM_INB(GPIO_VAL); 507 508 if (data) 509 val |= VIAPM_SDA; 510 else 511 val &= ~VIAPM_SDA; 512 513 VIAPM_OUTB(GPIO_VAL, val); 514 VIAPM_UNLOCK(viapm); 515 516 return; 517 } 518 519 static int 520 viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) 521 { 522 /* reset bus */ 523 viabb_setsda(dev, 1); 524 viabb_setscl(dev, 1); 525 526 return (IIC_ENOADDR); 527 } 528 529 static int 530 viabb_getscl(device_t dev) 531 { 532 struct viapm_softc *viapm = device_get_softc(dev); 533 u_char val; 534 535 VIAPM_LOCK(viapm); 536 val = VIAPM_INB(EXTSMI_VAL); 537 VIAPM_UNLOCK(viapm); 538 return ((val & VIAPM_SCL) != 0); 539 } 540 541 static int 542 viabb_getsda(device_t dev) 543 { 544 struct viapm_softc *viapm = device_get_softc(dev); 545 u_char val; 546 547 VIAPM_LOCK(viapm); 548 val = VIAPM_INB(EXTSMI_VAL); 549 VIAPM_UNLOCK(viapm); 550 return ((val & VIAPM_SDA) != 0); 551 } 552 553 static int 554 viapm_abort(struct viapm_softc *viapm) 555 { 556 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL); 557 DELAY(10); 558 559 return (0); 560 } 561 562 static int 563 viapm_clear(struct viapm_softc *viapm) 564 { 565 VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID | 566 SMBHST_ERROR | SMBHST_INTR); 567 DELAY(10); 568 569 return (0); 570 } 571 572 static int 573 viapm_busy(struct viapm_softc *viapm) 574 { 575 u_char sts; 576 577 sts = VIAPM_INB(SMBHST); 578 579 VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts)); 580 581 return (sts & SMBHST_BUSY); 582 } 583 584 /* 585 * Poll the SMBus controller 586 */ 587 static int 588 viapm_wait(struct viapm_softc *viapm) 589 { 590 int count = 10000; 591 u_char sts = 0; 592 int error; 593 594 VIAPM_LOCK_ASSERT(viapm); 595 596 /* wait for command to complete and SMBus controller is idle */ 597 while(count--) { 598 DELAY(10); 599 sts = VIAPM_INB(SMBHST); 600 601 /* check if the controller is processing a command */ 602 if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR)) 603 break; 604 } 605 606 VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts)); 607 608 error = SMB_ENOERR; 609 610 if (!count) 611 error |= SMB_ETIMEOUT; 612 613 if (sts & SMBHST_FAILED) 614 error |= SMB_EABORT; 615 616 if (sts & SMBHST_COLLID) 617 error |= SMB_ENOACK; 618 619 if (sts & SMBHST_ERROR) 620 error |= SMB_EBUSERR; 621 622 if (error != SMB_ENOERR) 623 viapm_abort(viapm); 624 625 viapm_clear(viapm); 626 627 return (error); 628 } 629 630 static int 631 viasmb_callback(device_t dev, int index, void *data) 632 { 633 int error = 0; 634 635 switch (index) { 636 case SMB_REQUEST_BUS: 637 case SMB_RELEASE_BUS: 638 /* ok, bus allocation accepted */ 639 break; 640 default: 641 error = EINVAL; 642 } 643 644 return (error); 645 } 646 647 static int 648 viasmb_quick(device_t dev, u_char slave, int how) 649 { 650 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 651 int error; 652 653 VIAPM_LOCK(viapm); 654 viapm_clear(viapm); 655 if (viapm_busy(viapm)) { 656 VIAPM_UNLOCK(viapm); 657 return (SMB_EBUSY); 658 } 659 660 switch (how) { 661 case SMB_QWRITE: 662 VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave)); 663 VIAPM_OUTB(SMBHADDR, slave & ~LSB); 664 break; 665 case SMB_QREAD: 666 VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave)); 667 VIAPM_OUTB(SMBHADDR, slave | LSB); 668 break; 669 default: 670 panic("%s: unknown QUICK command (%x)!", __func__, how); 671 } 672 673 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK); 674 675 error = viapm_wait(viapm); 676 VIAPM_UNLOCK(viapm); 677 678 return (error); 679 } 680 681 static int 682 viasmb_sendb(device_t dev, u_char slave, char byte) 683 { 684 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 685 int error; 686 687 VIAPM_LOCK(viapm); 688 viapm_clear(viapm); 689 if (viapm_busy(viapm)) { 690 VIAPM_UNLOCK(viapm); 691 return (SMB_EBUSY); 692 } 693 694 VIAPM_OUTB(SMBHADDR, slave & ~ LSB); 695 VIAPM_OUTB(SMBHCMD, byte); 696 697 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV); 698 699 error = viapm_wait(viapm); 700 701 VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); 702 VIAPM_UNLOCK(viapm); 703 704 return (error); 705 } 706 707 static int 708 viasmb_recvb(device_t dev, u_char slave, char *byte) 709 { 710 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 711 int error; 712 713 VIAPM_LOCK(viapm); 714 viapm_clear(viapm); 715 if (viapm_busy(viapm)) { 716 VIAPM_UNLOCK(viapm); 717 return (SMB_EBUSY); 718 } 719 720 VIAPM_OUTB(SMBHADDR, slave | LSB); 721 722 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV); 723 724 if ((error = viapm_wait(viapm)) == SMB_ENOERR) 725 *byte = VIAPM_INB(SMBHDATA0); 726 727 VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); 728 VIAPM_UNLOCK(viapm); 729 730 return (error); 731 } 732 733 static int 734 viasmb_writeb(device_t dev, u_char slave, char cmd, char byte) 735 { 736 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 737 int error; 738 739 VIAPM_LOCK(viapm); 740 viapm_clear(viapm); 741 if (viapm_busy(viapm)) { 742 VIAPM_UNLOCK(viapm); 743 return (SMB_EBUSY); 744 } 745 746 VIAPM_OUTB(SMBHADDR, slave & ~ LSB); 747 VIAPM_OUTB(SMBHCMD, cmd); 748 VIAPM_OUTB(SMBHDATA0, byte); 749 750 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE); 751 752 error = viapm_wait(viapm); 753 754 VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); 755 VIAPM_UNLOCK(viapm); 756 757 return (error); 758 } 759 760 static int 761 viasmb_readb(device_t dev, u_char slave, char cmd, char *byte) 762 { 763 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 764 int error; 765 766 VIAPM_LOCK(viapm); 767 viapm_clear(viapm); 768 if (viapm_busy(viapm)) { 769 VIAPM_UNLOCK(viapm); 770 return (SMB_EBUSY); 771 } 772 773 VIAPM_OUTB(SMBHADDR, slave | LSB); 774 VIAPM_OUTB(SMBHCMD, cmd); 775 776 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE); 777 778 if ((error = viapm_wait(viapm)) == SMB_ENOERR) 779 *byte = VIAPM_INB(SMBHDATA0); 780 781 VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); 782 VIAPM_UNLOCK(viapm); 783 784 return (error); 785 } 786 787 static int 788 viasmb_writew(device_t dev, u_char slave, char cmd, short word) 789 { 790 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 791 int error; 792 793 VIAPM_LOCK(viapm); 794 viapm_clear(viapm); 795 if (viapm_busy(viapm)) { 796 VIAPM_UNLOCK(viapm); 797 return (SMB_EBUSY); 798 } 799 800 VIAPM_OUTB(SMBHADDR, slave & ~ LSB); 801 VIAPM_OUTB(SMBHCMD, cmd); 802 VIAPM_OUTB(SMBHDATA0, word & 0x00ff); 803 VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8); 804 805 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD); 806 807 error = viapm_wait(viapm); 808 809 VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); 810 VIAPM_UNLOCK(viapm); 811 812 return (error); 813 } 814 815 static int 816 viasmb_readw(device_t dev, u_char slave, char cmd, short *word) 817 { 818 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 819 int error; 820 u_char high, low; 821 822 VIAPM_LOCK(viapm); 823 viapm_clear(viapm); 824 if (viapm_busy(viapm)) { 825 VIAPM_UNLOCK(viapm); 826 return (SMB_EBUSY); 827 } 828 829 VIAPM_OUTB(SMBHADDR, slave | LSB); 830 VIAPM_OUTB(SMBHCMD, cmd); 831 832 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD); 833 834 if ((error = viapm_wait(viapm)) == SMB_ENOERR) { 835 low = VIAPM_INB(SMBHDATA0); 836 high = VIAPM_INB(SMBHDATA1); 837 838 *word = ((high & 0xff) << 8) | (low & 0xff); 839 } 840 841 VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); 842 VIAPM_UNLOCK(viapm); 843 844 return (error); 845 } 846 847 static int 848 viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 849 { 850 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 851 u_char i; 852 int error; 853 854 if (count < 1 || count > 32) 855 return (SMB_EINVAL); 856 857 VIAPM_LOCK(viapm); 858 viapm_clear(viapm); 859 if (viapm_busy(viapm)) { 860 VIAPM_UNLOCK(viapm); 861 return (SMB_EBUSY); 862 } 863 864 VIAPM_OUTB(SMBHADDR, slave & ~LSB); 865 VIAPM_OUTB(SMBHCMD, cmd); 866 VIAPM_OUTB(SMBHDATA0, count); 867 i = VIAPM_INB(SMBHCTRL); 868 869 /* fill the 32-byte internal buffer */ 870 for (i = 0; i < count; i++) { 871 VIAPM_OUTB(SMBHBLOCK, buf[i]); 872 DELAY(2); 873 } 874 VIAPM_OUTB(SMBHCMD, cmd); 875 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK); 876 877 error = viapm_wait(viapm); 878 879 VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); 880 VIAPM_UNLOCK(viapm); 881 882 return (error); 883 884 } 885 886 static int 887 viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 888 { 889 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); 890 u_char data, len, i; 891 int error; 892 893 if (*count < 1 || *count > 32) 894 return (SMB_EINVAL); 895 896 VIAPM_LOCK(viapm); 897 viapm_clear(viapm); 898 if (viapm_busy(viapm)) { 899 VIAPM_UNLOCK(viapm); 900 return (SMB_EBUSY); 901 } 902 903 VIAPM_OUTB(SMBHADDR, slave | LSB); 904 VIAPM_OUTB(SMBHCMD, cmd); 905 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK); 906 907 if ((error = viapm_wait(viapm)) != SMB_ENOERR) 908 goto error; 909 910 len = VIAPM_INB(SMBHDATA0); 911 i = VIAPM_INB(SMBHCTRL); /* reset counter */ 912 913 /* read the 32-byte internal buffer */ 914 for (i = 0; i < len; i++) { 915 data = VIAPM_INB(SMBHBLOCK); 916 if (i < *count) 917 buf[i] = data; 918 DELAY(2); 919 } 920 *count = len; 921 922 error: 923 VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); 924 VIAPM_UNLOCK(viapm); 925 926 return (error); 927 } 928 929 static device_method_t viapm_methods[] = { 930 /* device interface */ 931 DEVMETHOD(device_probe, viapm_586b_probe), 932 DEVMETHOD(device_attach, viapm_586b_attach), 933 DEVMETHOD(device_detach, viapm_586b_detach), 934 935 /* iicbb interface */ 936 DEVMETHOD(iicbb_callback, viabb_callback), 937 DEVMETHOD(iicbb_setscl, viabb_setscl), 938 DEVMETHOD(iicbb_setsda, viabb_setsda), 939 DEVMETHOD(iicbb_getscl, viabb_getscl), 940 DEVMETHOD(iicbb_getsda, viabb_getsda), 941 DEVMETHOD(iicbb_reset, viabb_reset), 942 943 /* Bus interface */ 944 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 945 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 946 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 947 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 948 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 949 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 950 951 DEVMETHOD_END 952 }; 953 954 static driver_t viapm_driver = { 955 "viapm", 956 viapm_methods, 957 sizeof(struct viapm_softc), 958 }; 959 960 static device_method_t viapropm_methods[] = { 961 /* device interface */ 962 DEVMETHOD(device_probe, viapm_pro_probe), 963 DEVMETHOD(device_attach, viapm_pro_attach), 964 DEVMETHOD(device_detach, viapm_pro_detach), 965 966 /* smbus interface */ 967 DEVMETHOD(smbus_callback, viasmb_callback), 968 DEVMETHOD(smbus_quick, viasmb_quick), 969 DEVMETHOD(smbus_sendb, viasmb_sendb), 970 DEVMETHOD(smbus_recvb, viasmb_recvb), 971 DEVMETHOD(smbus_writeb, viasmb_writeb), 972 DEVMETHOD(smbus_readb, viasmb_readb), 973 DEVMETHOD(smbus_writew, viasmb_writew), 974 DEVMETHOD(smbus_readw, viasmb_readw), 975 DEVMETHOD(smbus_bwrite, viasmb_bwrite), 976 DEVMETHOD(smbus_bread, viasmb_bread), 977 978 /* Bus interface */ 979 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 980 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 981 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 982 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 983 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 984 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 985 986 DEVMETHOD_END 987 }; 988 989 static driver_t viapropm_driver = { 990 "viapropm", 991 viapropm_methods, 992 sizeof(struct viapm_softc), 993 }; 994 995 DRIVER_MODULE(viapm, pci, viapm_driver, 0, 0); 996 DRIVER_MODULE(viapropm, pci, viapropm_driver, 0, 0); 997 DRIVER_MODULE(iicbb, viapm, iicbb_driver, 0, 0); 998 DRIVER_MODULE(smbus, viapropm, smbus_driver, 0, 0); 999 1000 MODULE_DEPEND(viapm, pci, 1, 1, 1); 1001 MODULE_DEPEND(viapropm, pci, 1, 1, 1); 1002 MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); 1003 MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 1004 MODULE_VERSION(viapm, 1); 1005 1006 #ifdef DEV_ISA 1007 DRIVER_MODULE(isa, viapm, isa_driver, 0, 0); 1008 DRIVER_MODULE(isa, viapropm, isa_driver, 0, 0); 1009 MODULE_DEPEND(viapm, isa, 1, 1, 1); 1010 MODULE_DEPEND(viapropm, isa, 1, 1, 1); 1011 #endif 1012