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