/** OR a 32-bit MMIO register. OR the 32-bit MMIO register specified by Address with the value specified by Value and returns Value. This function must guarantee that all MMIO read and write operations are serialized. If 32-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 32-bit boundary, then ASSERT(). @param Address The MMIO register to write OR. @param Value The value to OR to the MMIO register. @return Value. **/ UINT32 EFIAPI I2CLibPeiMmioOr32 ( IN UINTN Address, IN UINT32 OrData ) { return I2CLibPeiMmioWrite32 (Address, I2CLibPeiMmioRead32(Address) | OrData); }
/** Initializes the host controller to execute I2C commands. @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device. @return EFI_SUCCESS Opcode initialization on the I2C host controller completed. @return EFI_DEVICE_ERROR Device error, operation failed. **/ EFI_STATUS I2CInit ( UINT8 I2cControllerIndex, UINT16 SlaveAddress ) { EFI_STATUS Status; UINT32 NumTries = 0; UINTN I2CBaseAddress; UINT16 I2cMode; UINTN PciMmBase=0; PciMmBase = MmPciAddress ( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, (I2cControllerIndex + 1), 0 ); I2CBaseAddress = I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR); // // Verify the parameters // if (1023 < SlaveAddress ) { Status = EFI_INVALID_PARAMETER; DEBUG((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n", Status)); return Status; } if(I2CBaseAddress == (PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE)) { return EFI_SUCCESS; } ProgramPciLpssI2C(); I2CBaseAddress = (UINT32) (PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE); DEBUG ((EFI_D_ERROR, "I2CBaseAddress = 0x%x \n",I2CBaseAddress)); NumTries = 10000; // 1 seconds while ((1 == ( I2CLibPeiMmioRead32 ( I2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) { MicroSecondDelay(10); NumTries --; if(0 == NumTries) return EFI_DEVICE_ERROR; } Status = I2cDisable (I2cControllerIndex); DEBUG((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status)); I2cBusFrequencySet(I2CBaseAddress, 400 * 1000, &I2cMode);//Set I2cMode I2CLibPeiMmioWrite16(I2CBaseAddress + R_IC_INTR_MASK, 0x0); if (0x7F < SlaveAddress) { SlaveAddress = (SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER; } I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TAR, (UINT16) SlaveAddress ); I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_RX_TL, 0); I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TX_TL, 0 ); I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_CON, I2cMode); Status = I2cEnable(I2cControllerIndex); DEBUG((EFI_D_INFO, "I2cEnable Status = %r\r\n", Status)); I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_CLR_TX_ABRT ); return EFI_SUCCESS; }
/** Programe all I2C controllers on LPSS. I2C0 is function 1 of LPSS. I2C1 is function 2 of LPSS, etc.. @param VOID @return EFI_SUCCESS **/ EFI_STATUS ProgramPciLpssI2C ( VOID ) { UINT32 PmcBase; UINT32 DevID; UINTN PciMmBase=0; UINTN Index; UINTN Bar0; UINTN Bar1; DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() Start\n")); // // Set the VLV Function Disable Register to ZERO // PmcBase = I2CLibPeiMmioRead32(PciD31F0RegBase + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR; if(I2CLibPeiMmioRead32(PmcBase + R_PCH_PMC_FUNC_DIS)& (B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7)) { I2CLibPeiMmioWrite32( PmcBase+R_PCH_PMC_FUNC_DIS, I2CLibPeiMmioRead32(PmcBase + R_PCH_PMC_FUNC_DIS)& \ ~(B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 \ | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 \ | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6|B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7) ); DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() enable all I2C controllers\n")); } for(Index = 0; Index < LPSS_PCI_DEVICE_NUMBER; Index ++) { PciMmBase = MmPciAddress ( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, Index, 0 ); DevID = I2CLibPeiMmioRead32(PciMmBase); Bar0 = PEI_TEPM_LPSS_DMA_BAR + (Index * PCI_CONFIG_SPACE_SIZE); Bar1 = Bar0 + 0x8000; DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device Function=%x DevID=%08x\n", Index, DevID)); // // Check if device present // if (DevID != 0xFFFFFFFF) { if(!(I2CLibPeiMmioRead32 (PciMmBase + R_PCH_LPSS_I2C_STSCMD) & B_PCH_LPSS_I2C_STSCMD_MSE)) { // // Program BAR 0 // I2CLibPeiMmioWrite32((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32)(Bar0 & B_PCH_LPSS_I2C_BAR_BA)); DEBUG ((EFI_D_ERROR, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR))); // // Program BAR 1 // I2CLibPeiMmioWrite32 ((UINTN)(PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32)(Bar1 & B_PCH_LPSS_I2C_BAR1_BA)); DEBUG ((EFI_D_ERROR, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32(PciMmBase+R_PCH_LPSS_I2C_BAR1))); // // Bus Master Enable & Memory Space Enable // I2CLibPeiMmioWrite32((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32)(B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE)); } // // Release Resets // I2CLibPeiMmioWrite32 (Bar0 + R_PCH_LPIO_I2C_MEM_RESETS, (B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB)); // // Activate Clocks // I2CLibPeiMmioWrite32 (Bar0 + R_PCH_LPSS_I2C_MEM_PCP, 0x80020003);//No use for A0 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Programmed()\n")); } } DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() End\n")); return EFI_SUCCESS; }