summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Smbus/Pei/PchSmbusEntry.c241
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;
+}