/** * @brief This function send device address and register address to I2C slave. * @param DeviceAddr: I2C slave address * @param RegAddr: slave device's register address, usually before read/write slave device's register, * i2c master should first send it. * @return * @arg TRUE: success * @arg FALSE:fail */ bool I2cSendAddr(void* I2cMasterHandle, uint8_t SlaveAddr, uint8_t RegAddr, uint8_t RwFlag) { I2cStart(I2cMasterHandle); if(!I2cWriteByte(I2cMasterHandle, SlaveAddr)) { /* Retry */ I2cStart(I2cMasterHandle); if(!I2cWriteByte(I2cMasterHandle, SlaveAddr)) { I2cStop(I2cMasterHandle); return FALSE; } } if(!I2cWriteByte(I2cMasterHandle, RegAddr)) { I2cStop(I2cMasterHandle); return FALSE; } if(RwFlag == IIC_READ) { I2cStart(I2cMasterHandle); if(!I2cWriteByte(I2cMasterHandle, SlaveAddr | IIC_READ)) { I2cStop(I2cMasterHandle); return FALSE; } } return TRUE; }
/** * @brief This function send multiple bytes to I2C slave. * @param Buf: Buffer pointer to the data to be send * @param Len: Data Length to be send in byte uint * @return * @arg TRUE: success * @arg FALSE: fail */ bool I2cWriteBytes(void* I2cMasterHandle, uint8_t* Buf, uint8_t Len) { while(Len--) { if(!I2cWriteByte(I2cMasterHandle, *(Buf++))) { DBG("write data err\n"); return FALSE; } } return TRUE; }
/*检测I2C设备是否忙*/ BYTE I2cDeviceBusy(BYTE bySlave) { BYTE byBusy = 1; int i = 0; while((byBusy != 0) && (i < 100)) { i2cStart(); I2cWriteByte(bySlave); byBusy=I2cReadBit(); if(byBusy) I2cStop(); i++; } #ifdef I2C_DEBUG if(byBusy == 1) printf("\nThe device is busy\n"); else printf("\nThe device is free\n"); #endif /* I2C_DEBUG */ return byBusy; }
/** 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; }
/*return: SYS_OK SYS_ERR */ SDWORD I2cWritePage(BYTE byIicPort, BYTE bySlave, DWORD dwAddr, BYTE *pbyData, DWORD dwCount) { int i; volatile BYTE i2c_bw_ctrl; /* I2C write 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; } i2c_ack_stat=0x0; i2c_bw_ctrl = bySlave | I2C_WRITE; /*i2c_addr_01 = I2C_W1_ADDR(dwAddr);*/ i2c_addr_00 = I2C_W0_ADDR(dwAddr); for(i=0;i<dwCount;i++) if(dwCount>16) dwCount=16; if(0 == I2cDeviceBusy(bySlave)) { i2cStart(); I2cWriteByte(i2c_bw_ctrl); ack1=I2cReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2; /*I2cWriteByte(i2c_addr_01); ack1=I2cReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2;*/ I2cWriteByte(i2c_addr_00); ack1=I2cReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2; for(i=0;i<dwCount;i++) { I2cWriteByte(pbyData[i]); ack2=I2cReadBit(); if(ack2!=0) i2c_ack_stat |= 0x8; } I2cStop(); } semGive(semI2cLock); /*释放信号量*/ if(0 != i2c_ack_stat) { return SYS_ERROR; } return SYS_OK; }
SDWORD I2cWrite(BYTE byIicPort, BYTE bySlave, DWORD dwAddr, BYTE byData) { volatile BYTE i2c_bw_ctrl; /* I2C write 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; } i2c_ack_stat=0x0; i2c_bw_ctrl = bySlave | I2C_WRITE; /*i2c_addr_01 = I2C_W1_ADDR(dwAddr);*/ i2c_addr_00 = I2C_W0_ADDR(dwAddr); if(1)/*0 == I2cDeviceBusy(bySlave))*/ { i2cStart(); I2cWriteByte(i2c_bw_ctrl); ack1=I2cReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2; I2C_DELAY(CLOCK_LOW_TIME*3); /*I2cWriteByte(i2c_addr_01); ack1=I2cReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2;*/ I2cWriteByte(i2c_addr_00); ack1=I2cReadBit(); if(ack1!=0) i2c_ack_stat |= 0x2; I2C_DELAY(CLOCK_LOW_TIME*3); I2cWriteByte(byData); ack2=I2cReadBit(); if(ack2!=0) i2c_ack_stat |= 0x8; I2C_DELAY(CLOCK_LOW_TIME*3); I2cStop(); } semGive(semI2cLock); /*释放信号量*/ if(0 != i2c_ack_stat) { printf("\nError in write, ack not recd, i2c_ack_stat=0x%x\n",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; }