1 /** @file 2 Intel ICH9 SMBUS library implementation built upon I/O library. 3 4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> 5 6 7 This program and the accompanying materials are licensed and made available under 8 9 the terms and conditions of the BSD License that accompanies this distribution. 10 11 The full text of the license may be found at 12 13 http://opensource.org/licenses/bsd-license.php. 14 15 16 17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 18 19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 20 21 22 23 24 **/ 25 26 #include "CommonHeader.h" 27 28 /** 29 Gets Io port base address of Smbus Host Controller. 30 InternalGetSmbusIoPortBaseAddress(VOID)31 This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress 32 to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base 33 address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always 34 read Pci configuration space to get that value in each Smbus bus transaction. 35 36 @return The Io port base address of Smbus host controller. 37 38 **/ 39 UINTN 40 InternalGetSmbusIoPortBaseAddress ( 41 VOID 42 ) 43 { 44 UINTN IoPortBaseAddress; 45 46 IoPortBaseAddress = (UINTN) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SMBUS, PCI_FUNCTION_NUMBER_PCH_SMBUS, R_PCH_SMBUS_BASE)) & B_PCH_SMBUS_BASE_BAR; 47 48 // 49 // Make sure that the IO port base address has been properly set. 50 // 51 ASSERT (IoPortBaseAddress != 0); 52 53 return IoPortBaseAddress; 54 } 55 56 /** 57 Acquires the ownership of SMBUS. 58 59 This internal function reads the host state register. 60 If the SMBUS is not available, RETURN_TIMEOUT is returned; 61 Otherwise, it performs some basic initializations and returns InternalSmBusAcquire(UINTN IoPortBaseAddress)62 RETURN_SUCCESS. 63 64 @param IoPortBaseAddress The Io port base address of Smbus Host controller. 65 66 @retval RETURN_SUCCESS The SMBUS command was executed successfully. 67 @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. 68 69 **/ 70 RETURN_STATUS 71 InternalSmBusAcquire ( 72 UINTN IoPortBaseAddress 73 ) 74 { 75 UINT8 HostStatus; 76 77 HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS); 78 if ((HostStatus & B_PCH_SMBUS_IUS) != 0) { 79 return RETURN_TIMEOUT; 80 } else if ((HostStatus & B_PCH_SMBUS_HBSY) != 0) { 81 // 82 // Clear host status register and exit. 83 // 84 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); 85 return RETURN_TIMEOUT; 86 } 87 // 88 // Clear out any odd status information (Will Not Clear In Use). 89 // 90 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, HostStatus); 91 92 return RETURN_SUCCESS; 93 } 94 95 /** 96 Starts the SMBUS transaction and waits until the end. 97 98 This internal function start the SMBUS transaction and waits until the transaction 99 of SMBUS is over by polling the INTR bit of Host status register. 100 If the SMBUS is not available, RETURN_TIMEOUT is returned; 101 Otherwise, it performs some basic initializations and returns 102 RETURN_SUCCESS. 103 104 @param IoPortBaseAddress The Io port base address of Smbus Host controller. 105 @param HostControl The Host control command to start SMBUS transaction. 106 InternalSmBusStart(IN UINTN IoPortBaseAddress,IN UINT8 HostControl)107 @retval RETURN_SUCCESS The SMBUS command was executed successfully. 108 @retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect). 109 @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected 110 in the Host Status Register bit. Device errors are 111 a result of a transaction collision, illegal command field, 112 unclaimed cycle (host initiated), or bus errors (collisions). 113 114 **/ 115 RETURN_STATUS 116 InternalSmBusStart ( 117 IN UINTN IoPortBaseAddress, 118 IN UINT8 HostControl 119 ) 120 { 121 UINT8 HostStatus; 122 UINT8 AuxiliaryStatus; 123 124 // 125 // Set Host Control Register (Initiate Operation, Interrupt disabled). 126 // 127 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL, (UINT8)(HostControl + B_PCH_SMBUS_START)); 128 129 do { 130 // 131 // Poll INTR bit of Host Status Register. 132 // 133 HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS); 134 } while ((HostStatus & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_ERRORS | B_PCH_SMBUS_BYTE_DONE_STS)) == 0); 135 136 if ((HostStatus & B_PCH_SMBUS_ERRORS) == 0) { 137 return RETURN_SUCCESS; 138 } 139 140 // 141 // Clear error bits of Host Status Register. 142 // 143 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_ERRORS); 144 145 // 146 // Read Auxiliary Status Register to judge CRC error. 147 // 148 AuxiliaryStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS); 149 if ((AuxiliaryStatus & B_PCH_SMBUS_CRCE) != 0) { 150 return RETURN_CRC_ERROR; 151 } 152 153 return RETURN_DEVICE_ERROR; 154 } 155 156 /** 157 Executes an SMBUS quick, byte or word command. 158 159 This internal function executes an SMBUS quick, byte or word commond. 160 If Status is not NULL, then the status of the executed command is returned in Status. 161 162 @param HostControl The value of Host Control Register to set. 163 @param SmBusAddress Address that encodes the SMBUS Slave Address, InternalSmBusNonBlock(IN UINT8 HostControl,IN UINTN SmBusAddress,IN UINT16 Value,OUT RETURN_STATUS * Status)164 SMBUS Command, SMBUS Data Length, and PEC. 165 @param Value The byte/word write to the SMBUS. 166 @param Status Return status for the executed command. 167 This is an optional parameter and may be NULL. 168 169 @return The byte/word read from the SMBUS. 170 171 **/ 172 UINT16 173 InternalSmBusNonBlock ( 174 IN UINT8 HostControl, 175 IN UINTN SmBusAddress, 176 IN UINT16 Value, 177 OUT RETURN_STATUS *Status 178 ) 179 { 180 RETURN_STATUS ReturnStatus; 181 UINTN IoPortBaseAddress; 182 UINT8 AuxiliaryControl; 183 184 IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress (); 185 186 // 187 // Try to acquire the ownership of ICH SMBUS. 188 // 189 ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress); 190 if (RETURN_ERROR (ReturnStatus)) { 191 goto Done; 192 } 193 194 // 195 // Set the appropriate Host Control Register and auxiliary Control Register. 196 // 197 AuxiliaryControl = 0; 198 if (SMBUS_LIB_PEC (SmBusAddress)) { 199 AuxiliaryControl |= B_PCH_SMBUS_AAC; 200 HostControl |= B_PCH_SMBUS_PEC_EN; 201 } 202 203 // 204 // Set Host Command Register. 205 // 206 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress)); 207 208 // 209 // Write value to Host Data 0 and Host Data 1 Registers. 210 // 211 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) Value); 212 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD1, (UINT8) (Value >> 8)); 213 214 // 215 // Set Auxiliary Control Register. 216 // 217 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl); 218 219 // 220 // Set SMBUS slave address for the device to send/receive from. 221 // 222 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress); 223 224 // 225 // Start the SMBUS transaction and wait for the end. 226 // 227 ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl); 228 229 // 230 // Read value from Host Data 0 and Host Data 1 Registers. 231 // 232 Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD1) << 8); 233 Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0)); 234 235 // 236 // Clear Host Status Register and Auxiliary Status Register. 237 // 238 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); 239 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); 240 241 Done: 242 if (Status != NULL) { 243 *Status = ReturnStatus; 244 } 245 246 return Value; 247 } 248 249 /** 250 Executes an SMBUS quick read command. 251 252 Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. 253 Only the SMBUS slave address field of SmBusAddress is required. 254 If Status is not NULL, then the status of the executed command is returned in Status. 255 If PEC is set in SmBusAddress, then ASSERT(). 256 If Command in SmBusAddress is not zero, then ASSERT(). 257 If Length in SmBusAddress is not zero, then ASSERT(). 258 If any reserved bits of SmBusAddress are set, then ASSERT(). SmBusQuickRead(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)259 260 @param SmBusAddress Address that encodes the SMBUS Slave Address, 261 SMBUS Command, SMBUS Data Length, and PEC. 262 @param Status Return status for the executed command. 263 This is an optional parameter and may be NULL. 264 265 **/ 266 VOID 267 EFIAPI 268 SmBusQuickRead ( 269 IN UINTN SmBusAddress, 270 OUT RETURN_STATUS *Status OPTIONAL 271 ) 272 { 273 ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); 274 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); 275 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 276 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 277 278 InternalSmBusNonBlock ( 279 V_PCH_SMBUS_SMB_CMD_QUICK, 280 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, 281 0, 282 Status 283 ); 284 } 285 286 /** 287 Executes an SMBUS quick write command. 288 289 Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. 290 Only the SMBUS slave address field of SmBusAddress is required. 291 If Status is not NULL, then the status of the executed command is returned in Status. 292 If PEC is set in SmBusAddress, then ASSERT(). 293 If Command in SmBusAddress is not zero, then ASSERT(). 294 If Length in SmBusAddress is not zero, then ASSERT(). 295 If any reserved bits of SmBusAddress are set, then ASSERT(). SmBusQuickWrite(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)296 297 @param SmBusAddress Address that encodes the SMBUS Slave Address, 298 SMBUS Command, SMBUS Data Length, and PEC. 299 @param Status Return status for the executed command. 300 This is an optional parameter and may be NULL. 301 302 **/ 303 VOID 304 EFIAPI 305 SmBusQuickWrite ( 306 IN UINTN SmBusAddress, 307 OUT RETURN_STATUS *Status OPTIONAL 308 ) 309 { 310 ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); 311 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); 312 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 313 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 314 315 InternalSmBusNonBlock ( 316 V_PCH_SMBUS_SMB_CMD_QUICK, 317 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 318 0, 319 Status 320 ); 321 } 322 323 /** 324 Executes an SMBUS receive byte command. 325 326 Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. 327 Only the SMBUS slave address field of SmBusAddress is required. 328 The byte received from the SMBUS is returned. 329 If Status is not NULL, then the status of the executed command is returned in Status. 330 If Command in SmBusAddress is not zero, then ASSERT(). 331 If Length in SmBusAddress is not zero, then ASSERT(). 332 If any reserved bits of SmBusAddress are set, then ASSERT(). 333 334 @param SmBusAddress Address that encodes the SMBUS Slave Address, SmBusReceiveByte(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)335 SMBUS Command, SMBUS Data Length, and PEC. 336 @param Status Return status for the executed command. 337 This is an optional parameter and may be NULL. 338 339 @return The byte received from the SMBUS. 340 341 **/ 342 UINT8 343 EFIAPI 344 SmBusReceiveByte ( 345 IN UINTN SmBusAddress, 346 OUT RETURN_STATUS *Status OPTIONAL 347 ) 348 { 349 UINT8 ValueReturn = 0; 350 351 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); 352 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 353 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 354 355 ValueReturn = (UINT8) InternalSmBusNonBlock ( 356 V_PCH_SMBUS_SMB_CMD_BYTE, 357 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, 358 0, 359 Status 360 ); 361 return ValueReturn; 362 363 } 364 365 /** 366 Executes an SMBUS send byte command. 367 368 Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. 369 The byte specified by Value is sent. 370 Only the SMBUS slave address field of SmBusAddress is required. Value is returned. 371 If Status is not NULL, then the status of the executed command is returned in Status. 372 If Command in SmBusAddress is not zero, then ASSERT(). 373 If Length in SmBusAddress is not zero, then ASSERT(). 374 If any reserved bits of SmBusAddress are set, then ASSERT(). 375 376 @param SmBusAddress Address that encodes the SMBUS Slave Address, 377 SMBUS Command, SMBUS Data Length, and PEC. SmBusSendByte(IN UINTN SmBusAddress,IN UINT8 Value,OUT RETURN_STATUS * Status OPTIONAL)378 @param Value The 8-bit value to send. 379 @param Status Return status for the executed command. 380 This is an optional parameter and may be NULL. 381 382 @return The parameter of Value. 383 384 **/ 385 UINT8 386 EFIAPI 387 SmBusSendByte ( 388 IN UINTN SmBusAddress, 389 IN UINT8 Value, 390 OUT RETURN_STATUS *Status OPTIONAL 391 ) 392 { 393 UINT8 ValueReturn = 0; 394 395 ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); 396 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 397 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 398 399 ValueReturn = (UINT8) InternalSmBusNonBlock ( 400 V_PCH_SMBUS_SMB_CMD_BYTE, 401 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 402 Value, 403 Status 404 ); 405 return ValueReturn; 406 407 } 408 409 /** 410 Executes an SMBUS read data byte command. 411 412 Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. 413 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. 414 The 8-bit value read from the SMBUS is returned. 415 If Status is not NULL, then the status of the executed command is returned in Status. 416 If Length in SmBusAddress is not zero, then ASSERT(). 417 If any reserved bits of SmBusAddress are set, then ASSERT(). 418 419 @param SmBusAddress Address that encodes the SMBUS Slave Address, SmBusReadDataByte(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)420 SMBUS Command, SMBUS Data Length, and PEC. 421 @param Status Return status for the executed command. 422 This is an optional parameter and may be NULL. 423 424 @return The byte read from the SMBUS. 425 426 **/ 427 UINT8 428 EFIAPI 429 SmBusReadDataByte ( 430 IN UINTN SmBusAddress, 431 OUT RETURN_STATUS *Status OPTIONAL 432 ) 433 { 434 UINT8 ValueReturn = 0; 435 436 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 437 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 438 ValueReturn = (UINT8) InternalSmBusNonBlock ( 439 V_PCH_SMBUS_SMB_CMD_BYTE_DATA, 440 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, 441 0, 442 Status 443 ); 444 return ValueReturn; 445 } 446 447 /** 448 Executes an SMBUS write data byte command. 449 450 Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. 451 The 8-bit value specified by Value is written. 452 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. 453 Value is returned. 454 If Status is not NULL, then the status of the executed command is returned in Status. 455 If Length in SmBusAddress is not zero, then ASSERT(). 456 If any reserved bits of SmBusAddress are set, then ASSERT(). 457 458 @param SmBusAddress Address that encodes the SMBUS Slave Address, 459 SMBUS Command, SMBUS Data Length, and PEC. SmBusWriteDataByte(IN UINTN SmBusAddress,IN UINT8 Value,OUT RETURN_STATUS * Status OPTIONAL)460 @param Value The 8-bit value to write. 461 @param Status Return status for the executed command. 462 This is an optional parameter and may be NULL. 463 464 @return The parameter of Value. 465 466 **/ 467 UINT8 468 EFIAPI 469 SmBusWriteDataByte ( 470 IN UINTN SmBusAddress, 471 IN UINT8 Value, 472 OUT RETURN_STATUS *Status OPTIONAL 473 ) 474 { 475 UINT8 ValueReturn = 0; 476 477 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 478 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 479 480 ValueReturn = (UINT8) InternalSmBusNonBlock ( 481 V_PCH_SMBUS_SMB_CMD_BYTE_DATA, 482 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 483 Value, 484 Status 485 ); 486 return ValueReturn; 487 488 } 489 490 /** 491 Executes an SMBUS read data word command. 492 493 Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. 494 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. 495 The 16-bit value read from the SMBUS is returned. 496 If Status is not NULL, then the status of the executed command is returned in Status. 497 If Length in SmBusAddress is not zero, then ASSERT(). 498 If any reserved bits of SmBusAddress are set, then ASSERT(). 499 500 @param SmBusAddress Address that encodes the SMBUS Slave Address, SmBusReadDataWord(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)501 SMBUS Command, SMBUS Data Length, and PEC. 502 @param Status Return status for the executed command. 503 This is an optional parameter and may be NULL. 504 505 @return The byte read from the SMBUS. 506 507 **/ 508 UINT16 509 EFIAPI 510 SmBusReadDataWord ( 511 IN UINTN SmBusAddress, 512 OUT RETURN_STATUS *Status OPTIONAL 513 ) 514 { 515 UINT16 ValueReturn = 0; 516 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 517 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 518 519 ValueReturn = InternalSmBusNonBlock ( 520 V_PCH_SMBUS_SMB_CMD_WORD_DATA, 521 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, 522 0, 523 Status 524 ); 525 return ValueReturn; 526 527 } 528 529 /** 530 Executes an SMBUS write data word command. 531 532 Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. 533 The 16-bit value specified by Value is written. 534 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. 535 Value is returned. 536 If Status is not NULL, then the status of the executed command is returned in Status. 537 If Length in SmBusAddress is not zero, then ASSERT(). 538 If any reserved bits of SmBusAddress are set, then ASSERT(). 539 540 @param SmBusAddress Address that encodes the SMBUS Slave Address, 541 SMBUS Command, SMBUS Data Length, and PEC. SmBusWriteDataWord(IN UINTN SmBusAddress,IN UINT16 Value,OUT RETURN_STATUS * Status OPTIONAL)542 @param Value The 16-bit value to write. 543 @param Status Return status for the executed command. 544 This is an optional parameter and may be NULL. 545 546 @return The parameter of Value. 547 548 **/ 549 UINT16 550 EFIAPI 551 SmBusWriteDataWord ( 552 IN UINTN SmBusAddress, 553 IN UINT16 Value, 554 OUT RETURN_STATUS *Status OPTIONAL 555 ) 556 { 557 UINT16 ValueReturn = 0; 558 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 559 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 560 561 ValueReturn = InternalSmBusNonBlock ( 562 V_PCH_SMBUS_SMB_CMD_WORD_DATA, 563 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 564 Value, 565 Status 566 ); 567 return ValueReturn; 568 } 569 570 /** 571 Executes an SMBUS process call command. 572 573 Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. 574 The 16-bit value specified by Value is written. 575 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. 576 The 16-bit value returned by the process call command is returned. 577 If Status is not NULL, then the status of the executed command is returned in Status. 578 If Length in SmBusAddress is not zero, then ASSERT(). 579 If any reserved bits of SmBusAddress are set, then ASSERT(). 580 581 @param SmBusAddress Address that encodes the SMBUS Slave Address, 582 SMBUS Command, SMBUS Data Length, and PEC. SmBusProcessCall(IN UINTN SmBusAddress,IN UINT16 Value,OUT RETURN_STATUS * Status OPTIONAL)583 @param Value The 16-bit value to write. 584 @param Status Return status for the executed command. 585 This is an optional parameter and may be NULL. 586 587 @return The 16-bit value returned by the process call command. 588 589 **/ 590 UINT16 591 EFIAPI 592 SmBusProcessCall ( 593 IN UINTN SmBusAddress, 594 IN UINT16 Value, 595 OUT RETURN_STATUS *Status OPTIONAL 596 ) 597 { 598 UINT16 ValueReturn = 0; 599 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 600 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 601 602 ValueReturn = InternalSmBusNonBlock ( 603 V_PCH_SMBUS_SMB_CMD_PROCESS_CALL, 604 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 605 Value, 606 Status 607 ); 608 return ValueReturn; 609 } 610 611 /** 612 Executes an SMBUS block command. 613 614 Executes an SMBUS block read, block write and block write-block read command 615 on the SMBUS device specified by SmBusAddress. 616 Bytes are read from the SMBUS and stored in Buffer. 617 The number of bytes read is returned, and will never return a value larger than 32-bytes. 618 If Status is not NULL, then the status of the executed command is returned in Status. 619 It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. 620 SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. 621 622 @param HostControl The value of Host Control Register to set. 623 @param SmBusAddress Address that encodes the SMBUS Slave Address, 624 SMBUS Command, SMBUS Data Length, and PEC. InternalSmBusBlock(IN UINT8 HostControl,IN UINTN SmBusAddress,IN UINT8 * WriteBuffer,OUT UINT8 * ReadBuffer,OUT RETURN_STATUS * Status)625 @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS. 626 @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS. 627 @param Status Return status for the executed command. 628 This is an optional parameter and may be NULL. 629 630 @return The number of bytes read from the SMBUS. 631 632 **/ 633 UINTN 634 InternalSmBusBlock ( 635 IN UINT8 HostControl, 636 IN UINTN SmBusAddress, 637 IN UINT8 *WriteBuffer, 638 OUT UINT8 *ReadBuffer, 639 OUT RETURN_STATUS *Status 640 ) 641 { 642 RETURN_STATUS ReturnStatus; 643 UINTN Index; 644 UINTN BytesCount; 645 UINTN IoPortBaseAddress; 646 UINT8 AuxiliaryControl; 647 648 IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress (); 649 650 BytesCount = SMBUS_LIB_LENGTH (SmBusAddress); 651 652 // 653 // Try to acquire the ownership of ICH SMBUS. 654 // 655 ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress); 656 if (RETURN_ERROR (ReturnStatus)) { 657 goto Done; 658 } 659 660 // 661 // Set the appropriate Host Control Register and auxiliary Control Register. 662 // 663 AuxiliaryControl = B_PCH_SMBUS_E32B; 664 if (SMBUS_LIB_PEC (SmBusAddress)) { 665 AuxiliaryControl |= B_PCH_SMBUS_AAC; 666 HostControl |= B_PCH_SMBUS_PEC_EN; 667 } 668 669 // 670 // Set Host Command Register. 671 // 672 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress)); 673 674 // 675 // Set Auxiliary Control Regiester. 676 // 677 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl); 678 679 // 680 // Clear byte pointer of 32-byte buffer. 681 // 682 IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL); 683 684 if (WriteBuffer != NULL) { 685 // 686 // Write the number of block to Host Block Data Byte Register. 687 // 688 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) BytesCount); 689 690 // 691 // Write data block to Host Block Data Register. 692 // 693 for (Index = 0; Index < BytesCount; Index++) { 694 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HBD, WriteBuffer[Index]); 695 } 696 } 697 698 // 699 // Set SMBUS slave address for the device to send/receive from. 700 // 701 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress); 702 703 // 704 // Start the SMBUS transaction and wait for the end. 705 // 706 ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl); 707 if (RETURN_ERROR (ReturnStatus)) { 708 goto Done; 709 } 710 711 if (ReadBuffer != NULL) { 712 // 713 // Read the number of block from host block data byte register. 714 // 715 BytesCount = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0); 716 717 // 718 // Write data block from Host Block Data Register. 719 // 720 for (Index = 0; Index < BytesCount; Index++) { 721 ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HBD); 722 } 723 } 724 725 Done: 726 // 727 // Clear Host Status Register and Auxiliary Status Register. 728 // 729 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); 730 IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); 731 732 if (Status != NULL) { 733 *Status = ReturnStatus; 734 } 735 736 return BytesCount; 737 } 738 739 /** 740 Executes an SMBUS read block command. 741 742 Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. 743 Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. 744 Bytes are read from the SMBUS and stored in Buffer. 745 The number of bytes read is returned, and will never return a value larger than 32-bytes. 746 If Status is not NULL, then the status of the executed command is returned in Status. 747 It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. 748 SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. 749 If Length in SmBusAddress is not zero, then ASSERT(). 750 If Buffer is NULL, then ASSERT(). 751 If any reserved bits of SmBusAddress are set, then ASSERT(). 752 753 @param SmBusAddress Address that encodes the SMBUS Slave Address, 754 SMBUS Command, SMBUS Data Length, and PEC. SmBusReadBlock(IN UINTN SmBusAddress,OUT VOID * Buffer,OUT RETURN_STATUS * Status OPTIONAL)755 @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. 756 @param Status Return status for the executed command. 757 This is an optional parameter and may be NULL. 758 759 @return The number of bytes read. 760 761 **/ 762 UINTN 763 EFIAPI 764 SmBusReadBlock ( 765 IN UINTN SmBusAddress, 766 OUT VOID *Buffer, 767 OUT RETURN_STATUS *Status OPTIONAL 768 ) 769 { 770 UINTN BytesCount = 0; 771 772 ASSERT (Buffer != NULL); 773 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); 774 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 775 776 777 BytesCount = InternalSmBusBlock ( 778 V_PCH_SMBUS_SMB_CMD_BLOCK, 779 SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, 780 NULL, 781 Buffer, 782 Status 783 ); 784 return BytesCount; 785 786 } 787 788 /** 789 Executes an SMBUS write block command. 790 791 Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. 792 The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. 793 Bytes are written to the SMBUS from Buffer. 794 The number of bytes written is returned, and will never return a value larger than 32-bytes. 795 If Status is not NULL, then the status of the executed command is returned in Status. 796 If Length in SmBusAddress is zero or greater than 32, then ASSERT(). 797 If Buffer is NULL, then ASSERT(). 798 If any reserved bits of SmBusAddress are set, then ASSERT(). 799 800 @param SmBusAddress Address that encodes the SMBUS Slave Address, 801 SMBUS Command, SMBUS Data Length, and PEC. SmBusWriteBlock(IN UINTN SmBusAddress,OUT VOID * Buffer,OUT RETURN_STATUS * Status OPTIONAL)802 @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. 803 @param Status Return status for the executed command. 804 This is an optional parameter and may be NULL. 805 806 @return The number of bytes written. 807 808 **/ 809 UINTN 810 EFIAPI 811 SmBusWriteBlock ( 812 IN UINTN SmBusAddress, 813 OUT VOID *Buffer, 814 OUT RETURN_STATUS *Status OPTIONAL 815 ) 816 { 817 UINTN BytesCount = 0; 818 819 ASSERT (Buffer != NULL); 820 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); 821 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); 822 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 823 824 825 BytesCount = InternalSmBusBlock ( 826 827 V_PCH_SMBUS_SMB_CMD_BLOCK, 828 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 829 Buffer, 830 NULL, 831 Status 832 ); 833 834 return BytesCount; 835 } 836 837 /** 838 Executes an SMBUS block process call command. 839 840 Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. 841 The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. 842 Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. 843 If Status is not NULL, then the status of the executed command is returned in Status. 844 It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read. 845 SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. 846 If Length in SmBusAddress is zero or greater than 32, then ASSERT(). 847 If WriteBuffer is NULL, then ASSERT(). 848 If ReadBuffer is NULL, then ASSERT(). 849 If any reserved bits of SmBusAddress are set, then ASSERT(). 850 851 @param SmBusAddress Address that encodes the SMBUS Slave Address, 852 SMBUS Command, SMBUS Data Length, and PEC. 853 @param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS. SmBusBlockProcessCall(IN UINTN SmBusAddress,IN VOID * WriteBuffer,OUT VOID * ReadBuffer,OUT RETURN_STATUS * Status OPTIONAL)854 @param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS. 855 @param Status Return status for the executed command. 856 This is an optional parameter and may be NULL. 857 858 @return The number of bytes written. 859 860 **/ 861 UINTN 862 EFIAPI 863 SmBusBlockProcessCall ( 864 IN UINTN SmBusAddress, 865 IN VOID *WriteBuffer, 866 OUT VOID *ReadBuffer, 867 OUT RETURN_STATUS *Status OPTIONAL 868 ) 869 { 870 UINTN BytesCount = 0; 871 872 ASSERT (WriteBuffer != NULL); 873 ASSERT (ReadBuffer != NULL); 874 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); 875 ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); 876 ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); 877 878 BytesCount = InternalSmBusBlock ( 879 V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS, 880 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, 881 WriteBuffer, 882 ReadBuffer, 883 Status 884 ); 885 return BytesCount; 886 887 } 888