/** Writes single byte data to TPM specified by I2C register address. @param[in] TpmAddress The register to write. @param[in] Data The data to write to the register. **/ VOID TpmWriteByte ( IN UINTN TpmAddress, IN UINT8 Data ) { EFI_STATUS Status; UINTN WriteLength; UINT8 WriteData[2]; EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr; // // Setup I2C Slave device address and address mode (7-bit). // I2CDeviceAddr.I2CDeviceAddress = TPM_I2C_SLAVE_DEVICE_ADDRESS; // // 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 to TPM register. // WriteLength = 2; WriteData[0] = (UINT8)TpmAddress; WriteData[1] = Data; Status = I2cWriteMultipleByte ( I2CDeviceAddr, EfiI2CSevenBitAddrMode, &WriteLength, &WriteData ); if (EFI_ERROR(Status)) { DEBUG ((EFI_D_ERROR, "TpmWriteByte(): I2C Write to TPM address %0x failed (%r)\n", TpmAddress, Status)); ASSERT (FALSE); // Writes to TPM should always succeed. } mI2CPrevReadTransfer = FALSE; }
/** Send command to Atmel I2c TPM breaking request up into multiple I2C transfers if required. @param[in] Buffer Pointer to TPM command data. @param[in] Length Number of bytes of TPM command data. @retval EFI_SUCCESS TPM command sent. @retval EFI_NOT_FOUND TPM chip doesn't exit. @retval EFI_TIMEOUT Can't get the TPM control in time. **/ EFI_STATUS WriteTpmBufferMultiple ( IN UINT8 *Buffer, IN UINTN Length ) { EFI_STATUS Status; EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr; UINTN Index; UINTN PartialLength; Status = EFI_SUCCESS; I2CDeviceAddr.I2CDeviceAddress = ATMEL_I2C_TPM_SLAVE_ADDRESS; DEBUG ((EFI_D_VERBOSE, "WriteTpmBufferMultiple: Addr=%02x Length=%02x\n", I2CDeviceAddr.I2CDeviceAddress, Length)); for (PartialLength = 0; Length > 0; Length -= PartialLength, Buffer += PartialLength) { // // Write data to TPM. // PartialLength = MIN (Length, ATMEL_I2C_TPM_MAX_TRANSFER_SIZE); Status = I2cWriteMultipleByte ( I2CDeviceAddr, EfiI2CSevenBitAddrMode, &PartialLength, Buffer ); DEBUG ((EFI_D_VERBOSE, " ")); for (Index = 0; Index < PartialLength; Index++) { DEBUG ((EFI_D_VERBOSE, "%02x ", Buffer[Index])); } DEBUG ((EFI_D_VERBOSE, "\n")); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_VERBOSE, " Status = %r\n", Status)); return Status; } } DEBUG ((EFI_D_VERBOSE, " Status = %r\n", Status)); return Status; }
/** Initialize state of I2C GPIO expanders. **/ EFI_STATUS EarlyPlatformConfigGpioExpanders ( VOID ) { EFI_STATUS Status; EFI_I2C_DEVICE_ADDRESS I2CSlaveAddress; UINTN Length; UINTN ReadLength; UINT8 Buffer[2]; // // Configure GPIO expanders for Galileo // Set all GPIO expander pins connected to the Reset Button as inputs // Route I2C pins to Arduino header // // // Detect the I2C Slave Address of the GPIO Expander // if (PlatformLegacyGpioGetLevel(R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) { I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR; } else { I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR; } DEBUG((EFI_D_INFO, "Galileo GPIO Expender Slave Address = %02x\n", I2CSlaveAddress.I2CDeviceAddress)); // // Set I2C_MUX (GPORT1_BIT5) low to route I2C to Arduino Shield connector // // // Select GPIO Expander GPORT1 // Length = 2; Buffer[0] = 0x18; //sub-address Buffer[1] = 0x01; //data Status = I2cWriteMultipleByte( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); if (EFI_ERROR(Status)) { DEBUG((EFI_D_WARN, "Fail to select GPIO Expander\n")); return EFI_SUCCESS; } // // Read "Pin Direction" of GPIO Expander GPORT1 // Length = 1; ReadLength = 1; Buffer[1] = 0x1C; Status = I2cReadMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &ReadLength, &Buffer[1] ); ASSERT_EFI_ERROR (Status); // // Configure GPIO Expander GPORT1_BIT5 as an output // Length = 2; Buffer[0] = 0x1C; //sub-address Buffer[1] = (UINT8)(Buffer[1] & (~BIT5)); //data Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); // // Set GPIO Expander GPORT1_BIT5 low // Length = 2; Buffer[0] = 0x09; //sub-address Buffer[1] = (UINT8)(~BIT5); //data Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); // // Configure RESET_N_SHLD (GPORT5_BIT0) and SW_RESET_N_SHLD (GPORT5_BIT1) as inputs // // // Select GPIO Expander GPORT5 // Length = 2; Buffer[0] = 0x18; Buffer[1] = 0x05; Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); // // Read "Pin Direction" of GPIO Expander GPORT5 // Length = 1; ReadLength = 1; Buffer[1] = 0x1C; Status = I2cReadMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &ReadLength, &Buffer[1] ); ASSERT_EFI_ERROR (Status); // // Configure GPIO Expander GPORT5_BIT0 and GPORT5_BIT1 as inputs // Length = 2; Buffer[0] = 0x1C; Buffer[1] = Buffer[1] | BIT0 | BIT1; Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
VOID EFIAPI PlatformInitializeUart0MuxGalileo ( VOID ) /*++ Routine Description: This is the routine to initialize UART0 for DBG2 support. The hardware used in this process is a Legacy Bridge (Legacy GPIO), I2C controller, a bi-directional MUX and a Cypress CY8C9540A chip. Arguments: None. Returns: None. --*/ { EFI_STATUS Status; EFI_I2C_DEVICE_ADDRESS I2CSlaveAddress; UINTN Length; UINT8 Buffer[2]; if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) { I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR; } else { I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR; } // // Set GPIO_SUS<2> as an output, raise voltage to Vdd. // PlatformLegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, 2, TRUE); // // Select Port 3 // Length = 2; Buffer[0] = 0x18; //sub-address Buffer[1] = 0x03; //data Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); // // Set "Pin Direction" bit4 and bit5 as outputs // Length = 2; Buffer[0] = 0x1C; //sub-address Buffer[1] = 0xCF; //data Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); // // Lower GPORT3 bit4 and bit5 to Vss // Length = 2; Buffer[0] = 0x0B; //sub-address Buffer[1] = 0xCF; //data Status = I2cWriteMultipleByte ( I2CSlaveAddress, EfiI2CSevenBitAddrMode, &Length, &Buffer ); ASSERT_EFI_ERROR (Status); }