/** Read EDID information from I2C Bus on CirrusLogic. @param Private Pointer to VBOX_VGA_PRIVATE_DATA. @param EdidDataBlock Pointer to EDID data block. @param EdidSize Returned EDID block size. @retval EFI_UNSUPPORTED @retval EFI_SUCCESS **/ EFI_STATUS ReadEdidData ( VBOX_VGA_PRIVATE_DATA *Private, UINT8 **EdidDataBlock, UINTN *EdidSize ) { UINTN Index; UINT8 EdidData[EDID_BLOCK_SIZE * 2]; UINT8 *ValidEdid; UINT64 Signature; for (Index = 0; Index < EDID_BLOCK_SIZE * 2; Index ++) { I2cReadByte (Private->PciIo, 0xa0, (UINT8)Index, &EdidData[Index]); } // // Search for the EDID signature // ValidEdid = &EdidData[0]; Signature = 0x00ffffffffffff00ull; for (Index = 0; Index < EDID_BLOCK_SIZE * 2; Index ++, ValidEdid ++) { if (CompareMem (ValidEdid, &Signature, 8) == 0) { break; } } if (Index == 256) { // // No EDID signature found // return EFI_UNSUPPORTED; } *EdidDataBlock = AllocateCopyPool ( sizeof (EDID_BLOCK_SIZE), ValidEdid ); if (*EdidDataBlock == NULL) { return EFI_OUT_OF_RESOURCES; } // // Currently only support EDID 1.x // *EdidSize = EDID_BLOCK_SIZE; return EFI_SUCCESS; }
/** * @brief This function receive multiple bytes to I2C slave. * @param Buf: Buffer pointer to hold the received data. * @param Len: Data Length to be received * @return None */ void I2cReadBytes(void* I2cMasterHandle, uint8_t* Buf, uint8_t Len) { while(Len--) { *(Buf++) = I2cReadByte(I2cMasterHandle); if(Len == 0) { I2cSendNoAck(I2cMasterHandle); } else { I2cSendAck(I2cMasterHandle); } } }
/** Reads single byte data from TPM specified by I2C register address. Due to stability issues when using I2C combined write/read transfers (with RESTART) to TPM (specifically read from status register), a single write is performed followed by single read (with STOP condition in between). @param[in] TpmAddress Address of register to read. @return The value register read. **/ UINT8 TpmReadByte ( IN UINTN TpmAddress ) { UINT8 Data[1]; UINT8 ReadData; UINT8 ReadCount; EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr; EFI_I2C_ADDR_MODE I2CAddrMode; EFI_STATUS Status; Status = EFI_SUCCESS; ReadData = 0xFF; ReadCount = 0; // // Locate I2C protocol for TPM I2C access. // I2CDeviceAddr.I2CDeviceAddress = TPM_I2C_SLAVE_DEVICE_ADDRESS; I2CAddrMode = EfiI2CSevenBitAddrMode; // // As recommended by Infineon (SLB9645 I2C Communication protocol application // note revision 1.0) retry up to 3 times if TPM status, access or burst count // registers return 0xFF. // while ((ReadData == 0xFF) && (ReadCount < READ_RETRY)) { // // As recommended by Infineon (SLB9645 I2C Communication protocol application // note revision 1.0) wait 250 microseconds between a read and a write transfer. // if (mI2CPrevReadTransfer) { MicroSecondDelay (GUARD_TIME); } // // Write address to TPM. // Data[0] = (UINT8)TpmAddress; Status = I2cWriteByte ( I2CDeviceAddr, I2CAddrMode, &Data ); if (EFI_ERROR(Status)) { DEBUG ((EFI_D_INFO, "TpmReadByte(): write to TPM address %0x failed (%r)\n", TpmAddress, Status)); } mI2CPrevReadTransfer = FALSE; // // Read data from TPM. // Data[0] = (UINT8)TpmAddress; Status = I2cReadByte ( I2CDeviceAddr, I2CAddrMode, &Data ); if (EFI_ERROR(Status)) { DEBUG ((EFI_D_INFO, "TpmReadByte(): read from TPM address %0x failed (%r)\n", TpmAddress, Status)); ReadData = 0xFF; } else { ReadData = Data[0]; } // // Only need to retry 3 times for TPM status, access, and burst count registers. // If read transfer is to TPM Data FIFO, do not retry, exit loop. // if (TpmAddress == INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT) { ReadCount = READ_RETRY; } else { ReadCount++; } mI2CPrevReadTransfer = TRUE; } if (EFI_ERROR(Status)) { // // Only reads to access register allowed to fail. // if (TpmAddress != INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT) { DEBUG ((EFI_D_ERROR, "TpmReadByte(): read from TPM address %0x failed\n", TpmAddress)); ASSERT_EFI_ERROR (Status); } } return ReadData; }
SDWORD I2cReadTest(BYTE byIicPort, BYTE bySlave, DWORD dwAddr) { BYTE byData = 0; volatile BYTE i2c_bw_ctrl; /* I2C write control */ volatile BYTE i2c_br_ctrl; /* I2C read control */ volatile BYTE i2c_addr_00; /* I2C address (0) */ STATUS semStatus; /*i2c同步信号量*/ semStatus = semTake(semI2cLock, WAIT_FOREVER); /*获得信号量*/ if(ERROR == semStatus) { logMsg("i2c semTake ERROR\n", 0, 0, 0, 0, 0, 0); return; } if(0 == byIicPort) { sCurI2cPort.byClkPin = IICCLK0; sCurI2cPort.byDataPin = IICDATA0; } else if(1 == byIicPort) { sCurI2cPort.byClkPin = IICCLK1; sCurI2cPort.byDataPin = IICDATA1; } #ifdef I2C_DEBUG printf("\n i2cRead() slave address is 0x%08x, addr: 0x%08x", bySlave, dwAddr); #endif /* I2C_DEBUG */ i2c_ack_stat=0x0; i2c_bw_ctrl = bySlave | I2C_WRITE; i2c_br_ctrl = bySlave | I2C_READ; /*i2c_addr_01 = I2C_W1_ADDR(addr);*/ i2c_addr_00 = I2C_W0_ADDR(dwAddr); if(1) { i2cStart(); I2cWriteByte(i2c_bw_ctrl); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x1; I2C_DELAY(CLOCK_LOW_TIME*3); /*I2cWriteByte(i2c_addr_01);*/ /*ack1=I2cReadBit();*/ /*read ack from slave*/ /*if(ack1!=0) i2c_ack_stat |= 0x2; */ I2cWriteByte(i2c_addr_00); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x2; i2cStart(); I2C_DELAY(CLOCK_LOW_TIME*3); I2cWriteByte(i2c_br_ctrl); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x3; I2C_DELAY(CLOCK_LOW_TIME*3); byData = I2cReadByte(); I2cStop(); } #ifdef I2C_DEBUG if(i2c_ack_stat!=0) printf("\nError in read, ack not recd, i2c_ack_stat=0x%x\n",i2c_ack_stat); #endif printf("byData: %x \n", byData); semGive(semI2cLock); /*释放信号量*/ if(0 != i2c_ack_stat) { return SYS_ERROR; } return SYS_OK; }
SDWORD TestCpld(void) { BYTE byData[5] = {0}; BYTE bySlave = 0xca; BYTE i2c_br_ctrl = 0; /* I2C read control */ BYTE byIicPort = 0; STATUS semStatus; /*i2c同步信号量*/ if (0==I2Cisinit) { dev_I2cInit( ); } semStatus = semTake(semI2cLock, WAIT_FOREVER); /*获得信号量*/ if(ERROR == semStatus) { logMsg("i2c semTake ERROR\n", 0, 0, 0, 0, 0, 0); return; } if(0 == byIicPort) { sCurI2cPort.byClkPin = IICCLK0; sCurI2cPort.byDataPin = IICDATA0; } else if(1 == byIicPort) { sCurI2cPort.byClkPin = IICCLK1; sCurI2cPort.byDataPin = IICDATA1; } #ifdef I2C_DEBUG /* printf("\n i2cRead() slave address is 0x%08x, addr: 0x%08x", bySlave, dwAddr);*/ #endif /* I2C_DEBUG */ i2c_ack_stat=0x0; i2c_br_ctrl = bySlave | I2C_READ; if(1)/*0 == I2cDeviceBusy(bySlave))*/ { i2cStart(); I2cWriteByte(i2c_br_ctrl); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x3; I2C_DELAY(CLOCK_LOW_TIME*3); byData[0] = I2cReadByte(); I2cWriteBit(0x0); /*send ack*/ I2cData(HIGH); byData[1] = I2cReadByte(); I2cWriteBit(0x0); /*send ack*/ I2cData(HIGH); byData[2] = I2cReadByte(); I2cWriteBit(0x00); /*send ack*/ I2cData(HIGH); byData[3] = I2cReadByte(); I2cWriteBit(0x00); /*send ack*/ I2cData(HIGH); byData[4] = I2cReadByte(); I2cWriteBit(0x80); /*send ack*/ I2cData(HIGH); I2cStop(); } #ifdef I2C_DEBUG if(i2c_ack_stat!=0) printf("\nError in read, ack not recd, i2c_ack_stat=0x%x\n",i2c_ack_stat); #endif printf("\Data[0] = 0x%2x, Data[1] = 0x%2x, Data[2] = 0x%2d, Data[3] = 0x%2d, Data[4] = 0x%2d\n", byData[0], byData[1], byData[2], byData[3], byData[4]); semGive(semI2cLock); /*释放信号量*/ if(0 != i2c_ack_stat) { return SYS_ERROR; } return SYS_OK; }
SDWORD I2cReadCpld(BYTE *pbyData, BYTE byDataNum) { BYTE bySlave = I2C_CPLDID; BYTE i2c_br_ctrl = 0; /* I2C read control */ BYTE byIicPort = I2C_CPLDPORT; static BYTE *pCpldData = (BYTE *)0x20000020; STATUS semStatus; /*i2c同步信号量*/ if (0==I2Cisinit) { dev_I2cInit( ); } semStatus = semTake(semI2cLock, WAIT_FOREVER); /*获得信号量*/ if(ERROR == semStatus) { logMsg("i2c semTake ERROR\n", 0, 0, 0, 0, 0, 0); return; } if(0 == byIicPort) { sCurI2cPort.byClkPin = IICCLK0; sCurI2cPort.byDataPin = IICDATA0; } else if(1 == byIicPort) { sCurI2cPort.byClkPin = IICCLK1; sCurI2cPort.byDataPin = IICDATA1; } #ifdef I2C_DEBUG /* printf("\n i2cRead() slave address is 0x%08x, addr: 0x%08x", bySlave, dwAddr);*/ #endif /* I2C_DEBUG */ i2c_ack_stat=0x0; i2c_br_ctrl = bySlave | I2C_READ; if(1) { i2cStart(); I2cWriteByte(i2c_br_ctrl); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x3; I2C_DELAY(CLOCK_LOW_TIME*3); pbyData[0] = I2cReadByte(); I2cWriteBit(0x0); /*send ack*/ I2cData(HIGH); pbyData[1] = I2cReadByte(); I2cWriteBit(0x0); /*send ack*/ I2cData(HIGH); pbyData[2] = I2cReadByte(); I2cWriteBit(0x80); /*send ack*/ I2cData(HIGH); I2cStop(); } #ifdef I2C_DEBUG if(i2c_ack_stat!=0) printf("\nError in read, ack not recd, i2c_ack_stat=0x%x\n",i2c_ack_stat); #endif /* printf("\nbyData[0] =%d, byData[1] =%d,byData[2] =%d\n",pbyData[0], pbyData[1], pbyData[2]);*/ if (0x20000030 > pCpldData) { *pCpldData++ = pbyData[0]; *pCpldData++ = pbyData[1]; *pCpldData++ = pbyData[2]; } semGive(semI2cLock); /*释放信号量*/ if(0 != i2c_ack_stat) { return SYS_ERROR; } return SYS_OK; }
/*I2C读字符串 功能暂时不提供 //input : byIicPort I2C端口号为 0 ~ 1 // bySlave 设备号 // dwAddr 命令地址 // dwCount 命令长度 //output: pbyData 命令值 return: SYS_OK SYS_ERR */ SDWORD I2cReadSeq(BYTE byIicPort, BYTE bySlave, DWORD dwAddr, BYTE *pbyData, DWORD dwCount) { volatile BYTE i2c_bw_ctrl; /* I2C write control */ volatile BYTE i2c_br_ctrl; /* I2C read control */ volatile BYTE i2c_addr_00; /* I2C address (0) */ int i; STATUS semStatus; /*i2c同步信号量*/ if (0 == dwCount) { return SYS_ERROR; } semStatus = semTake(semI2cLock, WAIT_FOREVER); /*获得信号量*/ if(ERROR == semStatus) { logMsg("i2c semTake ERROR\n", 0, 0, 0, 0, 0, 0); return; } if(0 == byIicPort) { sCurI2cPort.byClkPin = IICCLK0; sCurI2cPort.byDataPin = IICDATA0; } else if(1 == byIicPort) { sCurI2cPort.byClkPin = IICCLK1; sCurI2cPort.byDataPin = IICDATA1; } #ifdef I2C_DEBUG printf("\n i2cReadSeq() slave address is 0x%x", bySlave); #endif /* I2C_DEBUG */ i2c_ack_stat=0x0; i2c_bw_ctrl = bySlave | I2C_WRITE; i2c_br_ctrl = bySlave | I2C_READ; /*i2c_addr_01 = I2C_W1_ADDR(dwAddr);*/ i2c_addr_00 = I2C_W0_ADDR(dwAddr); if(1) { i2cStart(); I2cWriteByte(i2c_bw_ctrl); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x1; I2cWriteByte(i2c_addr_00); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x2; i2cStart(); I2cWriteByte(i2c_br_ctrl); ack1=I2cReadBit(); /*read ack from slave*/ if(ack1!=0) i2c_ack_stat |= 0x3; for(i=0;i<dwCount;i++) { pbyData[i] = I2cReadByte(); if(i != (dwCount-1)) I2cWriteBit(0x0); /*send ack*/ else I2cWriteBit(0x80); /*send nack after reading the last byte*/ I2cData(HIGH); } I2cStop(); } if(i2c_ack_stat!=0) printf("\nError in read, ack not recd, i2c_ack_stat=0x%x\n",i2c_ack_stat); semGive(semI2cLock); /*释放信号量*/ if(0 != i2c_ack_stat) { return SYS_ERROR; } return SYS_OK; }