diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c')
-rw-r--r-- | ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c b/ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c new file mode 100644 index 0000000..3e4a6a0 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c @@ -0,0 +1,241 @@ +/** @file + PCH Smbus PEIM. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchSmbus.h" + +/// +/// Global variables +/// +EFI_GUID mPeiSmbusPolicyPpiGuid = PEI_SMBUS_POLICY_PPI_GUID; + +// +// Functions +// + +/** + This function provides a standard way to execute an SMBUS command + PPI as defined in the SMBus Specification. The data can either be of + the length byte, word, or a block of data (1 to 32 bytes long). + The resulting transaction will be either the SMBus Slave Device accepts + this transaction or this function returns with an error + + @param[in] PeiServices PEI services table pointer + @param[in] This PEI_SMBUS_PPI instance + @param[in] SlaveAddress Smbus Slave device address + @param[in] Command Command to be sent + @param[in] Operation Which SMBus PPI will be used + @param[in] PecCheck Defines if Packet Error Code Checking is to be used + @param[in, out] Length How many bytes to read/write. Must be 1 <= Length <= 32 depending on the Operation + @param[in, out] Buffer Data buffer + + @retval EFI_SUCCESS Operation success. + Length will contain the actual number of bytes read. + Buffer will contain the data read. + @retval Otherwise Operation failed. +**/ +EFI_STATUS +EFIAPI +SmbusExecute ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + SMBUS_INSTANCE *Private; + DEBUG ((EFI_D_EVENT, "PEI SmbusExecute() Start, SmbusDeviceAddress=%x, Command=%x, Operation=%x\n", (SlaveAddress.SmbusDeviceAddress << 1), Command, Operation)); + Private = SMBUS_PRIVATE_DATA_FROM_PPI_THIS (This); + + Status = SmbusExec ( + SlaveAddress, + Command, + Operation, + PecCheck, + Length, + Buffer + ); + /// + /// Last step, check notification + /// + CheckNotification (Private); + DEBUG ((EFI_D_EVENT, "PEI SmbusExecute() End\n")); + return Status; +} + +/** + Initialize the Smbus PPI and program the Smbus BAR + + @param[in] FfsHeader Not used. + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completes successfully + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database +**/ +EFI_STATUS +InitializePchSmbusPeim ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + SMBUS_INSTANCE *Private; + UINTN SmbusRegBase; + + DEBUG ((EFI_D_INFO, "InitializePchSmbusPeim() Start\n")); + + Private = (SMBUS_INSTANCE *) AllocatePool (sizeof (SMBUS_INSTANCE)); + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "Failed to allocate memory for Private! \n")); + return EFI_OUT_OF_RESOURCES; + } + + InitializePeiPrivate (PeiServices, Private); + + SmbusRegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS, + 0 + ); + /// + /// Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves + /// + MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, Private->SmbusIoBase); + + MmioOr8 (SmbusRegBase + R_PCH_SMBUS_PCICMD, B_PCH_SMBUS_PCICMD_IOSE); + + /// + /// Reset the SMBus host controller + /// + MmioOr8 (SmbusRegBase + R_PCH_SMBUS_HOSTC, B_PCH_SMBUS_HOSTC_SSRESET); + + /// + /// Enable the SMBus host controller + /// + MmioAndThenOr8 ( + SmbusRegBase + R_PCH_SMBUS_HOSTC, + (UINT8) (~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)), + B_PCH_SMBUS_HOSTC_HST_EN + ); + + /// + /// Clear Status Register before anyone uses the interfaces + /// + SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + + Status = PeiServicesInstallPpi (&Private->PpiDescriptor); + ASSERT_EFI_ERROR (Status); + + /// + /// Install a call-back for the permanent-memory so that we can fix up internal pointers + /// + Status = (**PeiServices).NotifyPpi (PeiServices, &Private->NotifyDescriptor); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InitializePchSmbusPeim() End\n")); + + return EFI_SUCCESS; +} + +/** + This function initializes the SmBus driver in PEI. + + @param[in] PeiServices Standard PEI services + @param[in] Private SMBUS private data structure + + @retval None. +**/ +VOID +InitializePeiPrivate ( + IN EFI_PEI_SERVICES **PeiServices, + IN SMBUS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + + Private->Signature = PCH_SMBUS_PRIVATE_DATA_SIGNATURE; + Private->PeiServices = PeiServices; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &mPeiSmbusPolicyPpiGuid, + 0, + NULL, + (VOID **) &(Private->SmbusPolicy) + ); + ASSERT_EFI_ERROR (Status); + + Private->SmbusIoBase = Private->SmbusPolicy->BaseAddress; + + Private->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + Private->PpiDescriptor.Guid = &gEfiPeiSmbusPpiGuid; + + Private->PpiDescriptor.Ppi = &Private->SmbusPpi; + + Private->SmbusPpi.Execute = SmbusExecute; + Private->SmbusPpi.ArpDevice = SmbusArpDevice; + Private->SmbusPpi.GetArpMap = SmbusGetArpMap; + Private->SmbusPpi.Notify = SmbusNotify; + + Private->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + Private->NotifyDescriptor.Guid = &gEfiPeiMemoryDiscoveredPpiGuid; + Private->NotifyDescriptor.Notify = MemoryDiscoveredPpiNotifyCallback; + + Private->DeviceMapEntries = 0; + Private->PlatformNumRsvd = Private->SmbusPolicy->NumRsvdAddress; + Private->PlatformRsvdAddr = Private->SmbusPolicy->RsvdAddress; + + Private->NotifyFunctionNum = 0; + + return; +} + +/** + Fix up pointers since they are located in real memory now. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + SMBUS_INSTANCE *Private; + + Private = SMBUS_PRIVATE_DATA_FROM_NOTIFY_THIS (NotifyDescriptor); + + InitializePeiPrivate (PeiServices, Private); + + return EFI_SUCCESS; +} |