1 /** @file 2 I2C PEI Lib Instance. 3 4 Copyright (c) 1999- 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "I2CDelayPei.h" 16 #include "I2CIoLibPei.h" 17 #include "I2CAccess.h" 18 #include "I2CLibPei.h" 19 #include <PlatformBaseAddresses.h> 20 #include <Library/DebugLib.h> 21 #include <Library/BaseMemoryLib.h> 22 #include <Library/PeiServicesTablePointerLib.h> 23 #include <Library/HobLib.h> 24 #include <PchRegs/PchRegsPcu.h> 25 #include <PchRegs/PchRegsLpss.h> 26 27 #define LPSS_PCI_DEVICE_NUMBER 8 28 29 #define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset 30 #define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset 31 #define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset 32 #define R_PCH_LPSS_I2C_MEM_PCP 0x800 // Private Clock Parameters 33 34 #define PEI_TEPM_LPSS_DMA_BAR 0xFE900000 35 #define PEI_TEPM_LPSS_I2C0_BAR 0xFE910000 36 #define PCI_CONFIG_SPACE_SIZE 0x10000 37 38 EFI_GUID mI2CPeiInitGuid = { 39 0x96DED71A, 0xB9E7, 0x4EAD, 0x96, 0x2C, 0x01, 0x69, 0x3C, 0xED, 0x2A, 0x64 40 }; 41 42 43 UINT16 I2CGPIO[]= { 44 // 45 // 19.1.6 I2C0 46 // I2C0_SDA-OD-O - write 0x2003CC81 to IOBASE + 0x0210 47 // I2C0_SCL-OD-O - write 0x2003CC81 to IOBASE + 0x0200 48 // 49 0x0210, 50 0x0200, 51 52 // 53 // 19.1.7 I2C1 54 // I2C1_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01F0 55 // I2C1_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01E0 56 // 57 0x01F0, 58 0x01E0, 59 60 // 61 // 19.1.8 I2C2 62 // I2C2_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01D0 63 // I2C2_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01B0 64 // 65 0x01D0, 66 0x01B0, 67 68 // 69 // 19.1.9 I2C3 70 // I2C3_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0190 71 // I2C3_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01C0 72 // 73 0x0190, 74 0x01C0, 75 76 // 77 // 19.1.10 I2C4 78 // I2C4_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01A0 79 // I2C4_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0170 80 // 81 0x01A0, 82 0x0170, 83 84 // 85 // 19.1.11 I2C5 86 // I2C5_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0150 87 // I2C5_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0140 88 // 89 0x0150, 90 0x0140, 91 92 // 93 // 19.1.12 I2C6 94 // I2C6_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0180 95 // I2C6_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0160 96 // 97 0x0180, 98 0x0160 99 }; 100 101 /** 102 Constructor of this library. 103 104 @param VOID 105 106 @return EFI_SUCCESS 107 **/ 108 EFI_STATUS 109 EFIAPI 110 IntelI2CPeiLibConstructor ( 111 IN EFI_PEI_FILE_HANDLE FileHandle, 112 IN CONST EFI_PEI_SERVICES **PeiServices 113 ) 114 { 115 UINTN Index; 116 117 for (Index = 0; Index < sizeof(I2CGPIO)/sizeof(UINT16); Index ++) { 118 I2CLibPeiMmioWrite32(IO_BASE_ADDRESS+I2CGPIO[Index], 0x2003CC81); 119 } 120 121 return EFI_SUCCESS; 122 } 123 124 /** 125 Programe all I2C controllers on LPSS. 126 127 I2C0 is function 1 of LPSS. I2C1 is function 2 of LPSS, etc.. 128 129 @param VOID 130 131 @return EFI_SUCCESS 132 **/ 133 EFI_STATUS 134 ProgramPciLpssI2C ( 135 VOID 136 ) 137 { 138 UINT32 PmcBase; 139 UINT32 DevID; 140 UINTN PciMmBase=0; 141 UINTN Index; 142 UINTN Bar0; 143 UINTN Bar1; 144 DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() Start\n")); 145 146 // 147 // Set the VLV Function Disable Register to ZERO 148 // 149 PmcBase = I2CLibPeiMmioRead32(PciD31F0RegBase + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR; 150 151 if(I2CLibPeiMmioRead32(PmcBase + R_PCH_PMC_FUNC_DIS)& 152 (B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 153 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5 154 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7)) { 155 I2CLibPeiMmioWrite32( 156 PmcBase+R_PCH_PMC_FUNC_DIS, 157 I2CLibPeiMmioRead32(PmcBase + R_PCH_PMC_FUNC_DIS)& \ 158 ~(B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 \ 159 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 \ 160 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6|B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7) 161 ); 162 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() enable all I2C controllers\n")); 163 } 164 165 for(Index = 0; Index < LPSS_PCI_DEVICE_NUMBER; Index ++) { 166 167 PciMmBase = MmPciAddress ( 168 0, 169 DEFAULT_PCI_BUS_NUMBER_PCH, 170 PCI_DEVICE_NUMBER_PCH_LPSS_I2C, 171 Index, 172 0 173 ); 174 DevID = I2CLibPeiMmioRead32(PciMmBase); 175 176 Bar0 = PEI_TEPM_LPSS_DMA_BAR + (Index * PCI_CONFIG_SPACE_SIZE); 177 Bar1 = Bar0 + 0x8000; 178 179 DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device Function=%x DevID=%08x\n", Index, DevID)); 180 181 // 182 // Check if device present 183 // 184 if (DevID != 0xFFFFFFFF) { 185 if(!(I2CLibPeiMmioRead32 (PciMmBase + R_PCH_LPSS_I2C_STSCMD) & B_PCH_LPSS_I2C_STSCMD_MSE)) { 186 // 187 // Program BAR 0 188 // 189 I2CLibPeiMmioWrite32((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32)(Bar0 & B_PCH_LPSS_I2C_BAR_BA)); 190 191 DEBUG ((EFI_D_ERROR, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR))); 192 193 // 194 // Program BAR 1 195 // 196 I2CLibPeiMmioWrite32 ((UINTN)(PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32)(Bar1 & B_PCH_LPSS_I2C_BAR1_BA)); 197 DEBUG ((EFI_D_ERROR, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32(PciMmBase+R_PCH_LPSS_I2C_BAR1))); 198 199 // 200 // Bus Master Enable & Memory Space Enable 201 // 202 I2CLibPeiMmioWrite32((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32)(B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE)); 203 } 204 205 // 206 // Release Resets 207 // 208 I2CLibPeiMmioWrite32 (Bar0 + R_PCH_LPIO_I2C_MEM_RESETS, (B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB)); 209 210 // 211 // Activate Clocks 212 // 213 I2CLibPeiMmioWrite32 (Bar0 + R_PCH_LPSS_I2C_MEM_PCP, 0x80020003);//No use for A0 214 215 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Programmed()\n")); 216 } 217 218 } 219 220 DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() End\n")); 221 222 return EFI_SUCCESS; 223 } 224 225 /** 226 Disable I2C Bus. 227 228 @param I2cControllerIndex Index of I2C controller. 229 230 @return EFI_SUCCESS 231 **/ 232 EFI_STATUS 233 I2cDisable ( 234 IN UINT8 I2cControllerIndex 235 ) 236 { 237 UINTN I2CBaseAddress; 238 UINT32 NumTries = 10000; // 0.1 seconds 239 240 I2CBaseAddress = (UINT32) PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE; 241 242 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 0); 243 while (0 != ( I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_ENABLE_STATUS ) & 1)) { 244 MicroSecondDelay (10); 245 NumTries --; 246 if(0 == NumTries) return EFI_NOT_READY; 247 } 248 249 return EFI_SUCCESS; 250 } 251 252 /** 253 Enable I2C Bus. 254 255 @param I2cControllerIndex Index of I2C controller. 256 257 @return EFI_SUCCESS 258 **/ 259 EFI_STATUS 260 I2cEnable ( 261 IN UINT8 I2cControllerIndex 262 ) 263 { 264 UINTN I2CBaseAddress; 265 UINT32 NumTries = 10000; // 0.1 seconds 266 267 I2CBaseAddress = (UINT32) PEI_TEPM_LPSS_I2C0_BAR+ I2cControllerIndex * PCI_CONFIG_SPACE_SIZE; 268 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 1); 269 while (0 == ( I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_ENABLE_STATUS ) & 1)) { 270 MicroSecondDelay (10); 271 NumTries --; 272 if(0 == NumTries) return EFI_NOT_READY; 273 } 274 275 return EFI_SUCCESS; 276 } 277 278 279 /** 280 Set the I2C controller bus clock frequency. 281 282 @param[in] This Address of the library's I2C context structure 283 @param[in] PlatformData Address of the platform configuration data 284 @param[in] BusClockHertz New I2C bus clock frequency in Hertz 285 286 @retval RETURN_SUCCESS The bus frequency was set successfully. 287 @retval RETURN_UNSUPPORTED The controller does not support this frequency. 288 289 **/ 290 EFI_STATUS 291 I2cBusFrequencySet ( 292 IN UINTN I2CBaseAddress, 293 IN UINTN BusClockHertz, 294 IN UINT16 *I2cMode 295 ) 296 { 297 DEBUG((EFI_D_INFO,"InputFreq BusClockHertz: %d\r\n",BusClockHertz)); 298 299 *I2cMode = B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE; 300 301 // 302 // Set the 100 KHz clock divider 303 // 304 // From Table 10 of the I2C specification 305 // 306 // High: 4.00 uS 307 // Low: 4.70 uS 308 // 309 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x214 ); 310 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x272 ); 311 312 // 313 // Set the 400 KHz clock divider 314 // 315 // From Table 10 of the I2C specification 316 // 317 // High: 0.60 uS 318 // Low: 1.30 uS 319 // 320 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x50 ); 321 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xAD ); 322 323 switch ( BusClockHertz ) { 324 case 100 * 1000: 325 I2CLibPeiMmioWrite32 ( I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x40);//100K 326 *I2cMode |= V_SPEED_STANDARD; 327 break; 328 case 400 * 1000: 329 I2CLibPeiMmioWrite32 ( I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);//400K 330 *I2cMode |= V_SPEED_FAST; 331 break; 332 default: 333 I2CLibPeiMmioWrite32 ( I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);//3.4M 334 *I2cMode |= V_SPEED_HIGH; 335 } 336 337 return EFI_SUCCESS; 338 } 339 340 /** 341 Initializes the host controller to execute I2C commands. 342 343 @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device. 344 345 @return EFI_SUCCESS Opcode initialization on the I2C host controller completed. 346 @return EFI_DEVICE_ERROR Device error, operation failed. 347 **/ 348 EFI_STATUS 349 I2CInit ( 350 UINT8 I2cControllerIndex, 351 UINT16 SlaveAddress 352 ) 353 { 354 EFI_STATUS Status; 355 UINT32 NumTries = 0; 356 UINTN I2CBaseAddress; 357 UINT16 I2cMode; 358 UINTN PciMmBase=0; 359 360 361 PciMmBase = MmPciAddress ( 362 0, 363 DEFAULT_PCI_BUS_NUMBER_PCH, 364 PCI_DEVICE_NUMBER_PCH_LPSS_I2C, 365 (I2cControllerIndex + 1), 366 0 367 ); 368 369 I2CBaseAddress = I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR); 370 371 // 372 // Verify the parameters 373 // 374 if (1023 < SlaveAddress ) { 375 Status = EFI_INVALID_PARAMETER; 376 DEBUG((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n", Status)); 377 return Status; 378 } 379 380 if(I2CBaseAddress == (PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE)) { 381 return EFI_SUCCESS; 382 } 383 ProgramPciLpssI2C(); 384 385 I2CBaseAddress = (UINT32) (PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE); 386 DEBUG ((EFI_D_ERROR, "I2CBaseAddress = 0x%x \n",I2CBaseAddress)); 387 NumTries = 10000; // 1 seconds 388 while ((1 == ( I2CLibPeiMmioRead32 ( I2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) { 389 MicroSecondDelay(10); 390 NumTries --; 391 if(0 == NumTries) 392 return EFI_DEVICE_ERROR; 393 } 394 395 Status = I2cDisable (I2cControllerIndex); 396 DEBUG((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status)); 397 398 I2cBusFrequencySet(I2CBaseAddress, 400 * 1000, &I2cMode);//Set I2cMode 399 400 I2CLibPeiMmioWrite16(I2CBaseAddress + R_IC_INTR_MASK, 0x0); 401 if (0x7F < SlaveAddress) { 402 SlaveAddress = (SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER; 403 } 404 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TAR, (UINT16) SlaveAddress ); 405 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_RX_TL, 0); 406 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TX_TL, 0 ); 407 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_CON, I2cMode); 408 409 Status = I2cEnable(I2cControllerIndex); 410 DEBUG((EFI_D_INFO, "I2cEnable Status = %r\r\n", Status)); 411 I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_CLR_TX_ABRT ); 412 413 return EFI_SUCCESS; 414 } 415 416 /** 417 Reads a Byte from I2C Device. 418 419 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected 420 @param SlaveAddress Device Address from which the byte value has to be read 421 @param Offset Offset from which the data has to be read 422 @param *Byte Address to which the value read has to be stored 423 424 @return EFI_SUCCESS If the byte value has been successfully read 425 @return EFI_DEVICE_ERROR Operation Failed, Device Error 426 **/ 427 EFI_STATUS ByteReadI2CBasic( 428 IN UINT8 I2cControllerIndex, 429 IN UINT8 SlaveAddress, 430 IN UINTN ReadBytes, 431 OUT UINT8 *ReadBuffer, 432 IN UINT8 Start, 433 IN UINT8 End 434 ) 435 { 436 437 EFI_STATUS Status; 438 UINT32 I2cStatus; 439 UINT16 ReceiveData; 440 UINT8 *ReceiveDataEnd; 441 UINT8 *ReceiveRequest; 442 UINT16 RawIntrStat; 443 UINTN I2CBaseAddress; 444 445 I2CBaseAddress = (UINT32)(PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE); 446 447 Status = EFI_SUCCESS; 448 449 I2CInit(I2cControllerIndex, SlaveAddress); 450 451 ReceiveDataEnd = &ReadBuffer [ReadBytes]; 452 if(ReadBytes) { 453 ReceiveRequest = ReadBuffer; 454 DEBUG((EFI_D_INFO,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd - ReceiveRequest)); 455 456 while ((ReceiveDataEnd > ReceiveRequest) || (ReceiveDataEnd > ReadBuffer)) { 457 // 458 // Check for NACK 459 // 460 RawIntrStat = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RawIntrStat ); 461 if ( 0 != (RawIntrStat & I2C_INTR_TX_ABRT )) { 462 I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_CLR_TX_ABRT ); 463 Status = RETURN_DEVICE_ERROR; 464 DEBUG((EFI_D_INFO,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd - ReceiveRequest)); 465 break; 466 } 467 468 // 469 // Determine if another byte was received 470 // 471 I2cStatus = I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_STATUS ); 472 if ( 0 != ( I2cStatus & STAT_RFNE )) { 473 ReceiveData = I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_DATA_CMD ); 474 *ReadBuffer++ = (UINT8)ReceiveData; 475 DEBUG((EFI_D_INFO,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData)); 476 } 477 478 if(ReceiveDataEnd==ReceiveRequest) { 479 // 480 // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE. 481 // 482 continue; 483 } 484 485 // 486 // Wait until a read request will fit 487 // 488 if ( 0 == ( I2cStatus & STAT_TFNF )) { 489 MicroSecondDelay ( 10 ); 490 continue; 491 } 492 493 // 494 // Issue the next read request 495 // 496 if(End && Start ) { 497 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART|B_CMD_STOP); 498 } else if (!End && Start ) { 499 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART); 500 } else if (End && !Start ) { 501 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_STOP); 502 } else if (!End && !Start ) { 503 I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD); 504 } 505 ReceiveRequest += 1; 506 } 507 508 } 509 return Status; 510 511 } 512 513 /** 514 Writes a Byte to I2C Device. 515 516 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected 517 @param SlaveAddress Device Address from which the byte value has to be written 518 @param Offset Offset from which the data has to be read 519 @param *Byte Address to which the value written is stored 520 521 @return EFI_SUCCESS IF the byte value has been successfully written 522 @return EFI_DEVICE_ERROR Operation Failed, Device Error 523 **/ 524 EFI_STATUS 525 ByteWriteI2CBasic( 526 IN UINT8 I2cControllerIndex, 527 IN UINT8 SlaveAddress, 528 IN UINTN WriteBytes, 529 IN UINT8 *WriteBuffer, 530 IN UINT8 Start, 531 IN UINT8 End 532 ) 533 { 534 535 EFI_STATUS Status; 536 UINT32 I2cStatus; 537 UINT8 *TransmitEnd; 538 UINT16 RawIntrStat; 539 UINTN I2CBaseAddress; 540 541 I2CBaseAddress = (UINT32)PEI_TEPM_LPSS_I2C0_BAR+ I2cControllerIndex * PCI_CONFIG_SPACE_SIZE; 542 543 Status = EFI_SUCCESS; 544 545 I2CInit(I2cControllerIndex, SlaveAddress); 546 547 TransmitEnd = &WriteBuffer [WriteBytes]; 548 if( WriteBytes ) { 549 550 DEBUG((EFI_D_INFO,"Write: --------------%d bytes to TX\r\n", TransmitEnd - WriteBuffer)); 551 552 while ( TransmitEnd > WriteBuffer) { 553 I2cStatus = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_STATUS); 554 RawIntrStat = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RawIntrStat); 555 if ( 0 != (RawIntrStat & I2C_INTR_TX_ABRT)) { 556 I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT); 557 Status = RETURN_DEVICE_ERROR; 558 DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer)); 559 break; 560 } 561 if (0 == ( I2cStatus & STAT_TFNF)) { 562 continue; 563 } 564 if(End && Start) { 565 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++) | B_CMD_RESTART | B_CMD_STOP); 566 } else if (!End && Start ) { 567 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++) | B_CMD_RESTART); 568 } else if (End && !Start ) { 569 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++) | B_CMD_STOP); 570 } else if (!End && !Start ) { 571 I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)); 572 } 573 574 // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped. 575 MicroSecondDelay ( FIFO_WRITE_DELAY ); 576 } 577 578 } 579 580 if(EFI_ERROR(Status)) { 581 DEBUG((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n",Status)); 582 } 583 584 return Status; 585 } 586 587 /** 588 Reads a Byte from I2C Device. 589 590 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected 591 @param SlaveAddress Device Address from which the byte value has to be read 592 @param Offset Offset from which the data has to be read 593 @param ReadBytes Number of bytes to be read 594 @param *ReadBuffer Address to which the value read has to be stored 595 596 @return EFI_SUCCESS IF the byte value has been successfully read 597 @return EFI_DEVICE_ERROR Operation Failed, Device Error 598 **/ 599 EFI_STATUS 600 ByteReadI2C( 601 IN UINT8 I2cControllerIndex, 602 IN UINT8 SlaveAddress, 603 IN UINT8 Offset, 604 IN UINTN ReadBytes, 605 OUT UINT8 *ReadBuffer 606 ) 607 { 608 EFI_STATUS Status; 609 610 DEBUG ((EFI_D_ERROR, "ByteReadI2C:---offset:0x%x\n",Offset)); 611 Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress, 1, &Offset,TRUE,FALSE); 612 Status = ByteReadI2CBasic(I2cControllerIndex, SlaveAddress, ReadBytes, ReadBuffer, TRUE, TRUE); 613 614 return Status; 615 } 616 617 /** 618 Writes a Byte to I2C Device. 619 620 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected 621 @param SlaveAddress Device Address from which the byte value has to be written 622 @param Offset Offset from which the data has to be written 623 @param WriteBytes Number of bytes to be written 624 @param *Byte Address to which the value written is stored 625 626 @return EFI_SUCCESS IF the byte value has been successfully read 627 @return EFI_DEVICE_ERROR Operation Failed, Device Error 628 **/ 629 EFI_STATUS ByteWriteI2C( 630 IN UINT8 I2cControllerIndex, 631 IN UINT8 SlaveAddress, 632 IN UINT8 Offset, 633 IN UINTN WriteBytes, 634 IN UINT8 *WriteBuffer 635 ) 636 { 637 EFI_STATUS Status; 638 639 DEBUG ((EFI_D_ERROR, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset,WriteBytes,WriteBuffer,*WriteBuffer)); 640 Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress, 1, &Offset, TRUE, FALSE); 641 Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress, WriteBytes, WriteBuffer, FALSE, TRUE); 642 643 return Status; 644 } 645