summaryrefslogtreecommitdiff
path: root/Chipset/SB/SmBus/SmBusPei.c
diff options
context:
space:
mode:
Diffstat (limited to 'Chipset/SB/SmBus/SmBusPei.c')
-rw-r--r--Chipset/SB/SmBus/SmBusPei.c527
1 files changed, 527 insertions, 0 deletions
diff --git a/Chipset/SB/SmBus/SmBusPei.c b/Chipset/SB/SmBus/SmBusPei.c
new file mode 100644
index 0000000..f9c5665
--- /dev/null
+++ b/Chipset/SB/SmBus/SmBusPei.c
@@ -0,0 +1,527 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SmBus/SmBusPei.c 3 3/27/13 10:29p Wesleychen $
+//
+// $Revision: 3 $
+//
+// $Date: 3/27/13 10:29p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SmBus/SmBusPei.c $
+//
+// 3 3/27/13 10:29p Wesleychen
+// Fix coding error.
+//
+// 2 11/25/12 10:40p Scottyang
+// [TAG] EIP107376
+// [Category] Improvement
+// [Description] Add token "PCH_SPD_WRITE_DISABLE" for SMBus reg 40h bit
+// 4.
+// [Files] SmBus.sdl
+// SmBusPei.c
+//
+// 1 6/06/12 8:00a Victortu
+// Implement EFI_PEI_SMBUS2_PPI Support.
+//
+// 10 7/21/11 7:31a Abelwu
+// [TAG] EIP63768
+// [Category] Improvement
+// [Description] Supported Core 4.6.5.x PI 1.2 / uEFI 2.3.1 compliance
+// [Files] SmBusPei.c
+//
+// 9 7/19/11 8:03a Abelwu
+// [TAG] EIP63768
+// [Category] Improvement
+// [Description] Supported Core 4.6.5.x PI 1.2 / uEFI 2.3.1 compliance
+// [Files] SmBusPei.c
+//
+// 8 6/27/11 2:26p Artems
+// Updated year in file header
+//
+// 7 6/17/11 5:53p Artems
+// EIP 53378: Replaced tabs with spaces, formatted to follow coding
+// standard
+//
+// 6 10/13/10 4:15p Artems
+// EIP 45184 - fixed pointer size to be same in IA32 and X64 mode
+//
+// 5 10/19/09 12:48p Artems
+// Updated copyright header
+//
+// 4 3/03/09 4:36p Artems
+// EIP 19949 Added support for multiple SM Bus controllers that
+// represented by different PCI devices
+//
+// 3 1/29/09 4:20p Artems
+// Change "Note" to "Notes" for HelpBuilder
+//
+// 2 1/28/09 6:51p Artems
+// Modified in accordance with coding standard
+//
+// 1 1/09/09 6:53p Artems
+// New implementation of SMBus EIP 16730
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: SmBusPei.c
+//
+// Description: SMBUS driver PEI functions implementation
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiLib.h>
+#include <AmiHobs.h>
+#include "SmBusPei.h"
+ // [EIP82310]>
+#include <Ppi\SmbusPolicy\SmbusPolicy.h>
+#include <PchAccess.h>
+
+static EFI_GUID gEfiPeiEndOfPeiPhasePpiGuid = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID;
+EFI_GUID mPeiSmbusPolicyPpiGuid = PEI_SMBUS_POLICY_PPI_GUID;
+
+extern EFI_GUID SmBusIdentifierGuid;
+extern UINT8 SmBusPlatformReservedAddress[];
+extern UINT8 SmBusPlatformReservedAddressSize;
+ // <[EIP82310]
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiEntryPoint
+//
+// Description: SMBUS driver PEI entry point
+//
+// Input: EFI_FFS_FILE_HEADER *FfsHeader - pointer to file header
+// EFI_PEI_SERVICES **PeiServices - pointer to PEI services table
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmBusPeiEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ EFI_STATUS Status;
+ SMBUS_PEI_PRIVATE *Private;
+
+ Status = (*PeiServices)->AllocatePool(
+ PeiServices,
+ sizeof(SMBUS_PEI_PRIVATE),
+ &Private);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Status = (*PeiServices)->AllocatePool(
+ PeiServices,
+ sizeof(EFI_SMBUS_DEVICE_MAP) * MAX_PEI_ARP_DEVICES,
+ &(Private->SmBusContext.ArpDeviceList));
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Private->SmBusPpi.Execute = SmBusPeiExecute;
+ Private->SmBusPpi.ArpDevice = SmBusPeiArpDevice;
+ Private->SmBusPpi.GetArpMap = SmBusPeiGetArpMap;
+ Private->SmBusPpi.Notify = SmBusPeiNotify;
+
+ Private->SmBusPpiDesc.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ Private->SmBusPpiDesc.Guid = &gEfiPeiSmbus2PpiGuid;
+ Private->SmBusPpiDesc.Ppi = &Private->SmBusPpi;
+
+ Private->NotifyDesc.Flags = EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ Private->NotifyDesc.Guid = &gEfiPeiEndOfPeiPhasePpiGuid;
+ Private->NotifyDesc.Notify = SmBusEndOfPeiCallback;
+
+ Private->SmBusContext.ArpDeviceCount = 0;
+ Private->SmBusContext.MaxDevices = MAX_PEI_ARP_DEVICES;
+ Private->SmBusContext.SmBusWait = SmBusPeiWait;
+
+ Private->SmBusPpi.Identifier = SmBusIdentifierGuid;
+
+ SmBusPeiInitialize(PeiServices, &Private->SmBusContext);
+
+ Status = (*PeiServices)->NotifyPpi(PeiServices, &Private->NotifyDesc);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ return (*PeiServices)->InstallPpi(PeiServices, &Private->SmBusPpiDesc);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiExecute
+//
+// Description: SMBUS driver PPI Execute function
+//
+// Input: PI 0.91
+// **PeiServices - Pointer to the PEI services table
+// *This - Pointer to the SMBus PPI structure
+//
+// PI 1.X
+// *This - Pointer to the SMBus2 PPI structure
+//
+// SlaveAddress - Address of the SMBus device to be used to
+// send this command
+// Command - Command to be sent to the device
+// Operation - SMBus operation to be performed
+// PecCheck - Flag indicating the usage of PEC
+// *Length - Length of the data in the Buffer (IN/OUT)
+// *Buffer - Pointer to the buffer with the data (IN/OUT)
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmBusPeiExecute (
+ IN CONST EFI_PEI_SMBUS2_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
+)
+{
+ SMBUS_PEI_PRIVATE *Private = (SMBUS_PEI_PRIVATE *)This;
+
+ return Execute(
+ &(Private->SmBusContext),
+ SlaveAddress,
+ Command,
+ Operation,
+ PecCheck,
+ Length,
+ Buffer);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiArpDevice
+//
+// Description: SMBUS driver PPI ArpDevice function
+//
+// Input: PI 0.91
+// **PeiServices - Pointer to the PEI services table
+// *This - Pointer to the SMBus PPI structure
+//
+// PI 1.X
+// *This - Pointer to the SMBus2 PPI structure
+//
+// ArpAll - Flag indicating ARP type - ALL or specific
+// *SmbusUdid - SMBus UDID for the device whose Address has
+// to be resolved
+// *SlaveAddress - Slave address to be assigned to the device
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmBusPeiArpDevice (
+ IN CONST EFI_PEI_SMBUS2_PPI *This,
+ IN BOOLEAN ArpAll,
+ IN EFI_SMBUS_UDID *SmbusUdid, OPTIONAL
+ IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL
+)
+{
+ SMBUS_PEI_PRIVATE *Private = (SMBUS_PEI_PRIVATE *)This;
+
+ return ArpDevice(
+ &(Private->SmBusContext),
+ ArpAll,
+ SmbusUdid,
+ SlaveAddress);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiGetArpMap
+//
+// Description: SMBUS driver PPI GetArpMap function
+//
+// Input: PI 0.91
+// **PeiServices - Pointer to the PEI services table
+// *This - Pointer to the SMBus PPI structure
+//
+// PI 1.X
+// *This - Pointer to the SMBus2 PPI structure
+//
+// *Length - Length of the Device map structure(IN & OUT)
+// *SmBusDeviceMap - Pointer to the buffer where the SMBus
+// device map will be filled in
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmBusPeiGetArpMap (
+ IN CONST EFI_PEI_SMBUS2_PPI *This,
+ IN OUT UINTN *Length,
+ IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap
+)
+{
+ SMBUS_PEI_PRIVATE *Private = (SMBUS_PEI_PRIVATE *)This;
+
+ return GetArpMap(
+ &(Private->SmBusContext),
+ Length,
+ SmbusDeviceMap);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiNotify
+//
+// Description: SMBUS driver PPI Notify function
+//
+// Input: EFI_PEI_SERVICES **PeiServices - pointer to PEI services table
+// EFI_PEI_SMBUS_PPI *This - pointer to PPI
+// EFI_SMBUS_DEVICE_ADDRESS SlaveAddress - address of notification device
+// UINTN Data - notification data
+// EFI_PEI_SMBUS_NOTIFY_FUNCTION NotifyFunction - pointer to callback function
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmBusPeiNotify (
+ IN CONST EFI_PEI_SMBUS2_PPI *This,
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN UINTN Data,
+ IN EFI_PEI_SMBUS_NOTIFY2_FUNCTION NotifyFunction
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusEndOfPeiCallback
+//
+// Description: This function creates map of devices connected to SMBUS at the end of PEI phase
+//
+// Input: EFI_PEI_SERVICES **PeiServices - pointer to PEI services table
+// EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor - pointer to notify descriptor
+// VOID *Ppi - pointer to notify PPI
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SmBusEndOfPeiCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+)
+{
+ SMBUS_PEI_PRIVATE *Private = OUTTER(NotifyDescriptor, NotifyDesc, SMBUS_PEI_PRIVATE);
+ UINTN HobSize;
+ AMI_SMBUS_HOB *Hob;
+ EFI_STATUS Status;
+
+ HobSize = sizeof(AMI_SMBUS_HOB) + Private->SmBusContext.ArpDeviceCount * sizeof(EFI_SMBUS_DEVICE_MAP);
+ Status = (*PeiServices)->CreateHob(PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, HobSize, &Hob);
+ if(!EFI_ERROR(Status))
+ {
+ Hob->Header.Name = Private->SmBusPpi.Identifier;
+ Hob->BoardReservedAddressCount = Private->SmBusContext.BoardReservedAddressCount;
+ Hob->BoardReservedAddressList = (UINT32) (Private->SmBusContext.BoardReservedAddressList);
+ Hob->ArpDeviceCount = Private->SmBusContext.ArpDeviceCount;
+ MemCpy(Hob->ArpDeviceList,
+ Private->SmBusContext.ArpDeviceList,
+ Private->SmBusContext.ArpDeviceCount * sizeof(EFI_SMBUS_DEVICE_MAP));
+ }
+ return Status;
+}
+
+//**********************************************************************
+// Porting functions
+//**********************************************************************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiWait
+//
+// Description: This function waits given number of microseconds
+//
+// Input: UINTN Microseconds - number of microseconds to wait
+//
+// Output: None
+//
+// Notes: Porting required
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SmBusPeiWait(
+ IN UINTN Microseconds
+)
+{
+ // The following code is to generate delay for specified amount of micro
+ // seconds using ACPI timer.
+ UINT16 AcpiTmrReg = PM_BASE_ADDRESS + ACPI_IOREG_PM1_TMR;
+ UINTN TicksNeeded;
+ UINT32 TimerValue;
+ UINT32 NewTimerValue;
+ UINTN OverFlow = 0;
+ UINTN TheRest;
+ UINTN EndValue;
+
+ // There are 3.58 ticks per us, so we have to convert the number of us
+ // passed in to the number of ticks that need to pass before the timer has
+ // expired convert us to Ticks, don't loose significant figures or as few
+ // as possible do integer math in ticks/tens of ns and then divide by 100
+ // to get ticks per us
+
+ TicksNeeded = Microseconds * 3; // (Microseconds * 3)
+ TicksNeeded += (Microseconds) / 2; // (Microseconds * 5)/10
+ TicksNeeded += (Microseconds * 2) / 25; // (Microseconds * 8)/100
+ TheRest = TicksNeeded;
+
+ // 32 bits corresponds to approz 71 mins no delay should be that long
+ // otherwise get the number of times the counter will have to overflow
+ // to delay as long as needed
+ if (NUM_BITS_IN_ACPI_TIMER < MAX_ACPI_TIMER_BITS) {
+ OverFlow = TicksNeeded / (1 << NUM_BITS_IN_ACPI_TIMER);
+ TheRest = TicksNeeded % (1 << NUM_BITS_IN_ACPI_TIMER);
+ }
+
+ // Read ACPI Timer
+ TimerValue = IoRead32( AcpiTmrReg );
+
+ // Need to adjust the values based off of the start time
+ EndValue = TheRest + TimerValue;
+
+ // Check for overflow on addition. possibly a problem
+ if (EndValue < TimerValue) {
+ OverFlow++;
+ } else {
+ if (NUM_BITS_IN_ACPI_TIMER < MAX_ACPI_TIMER_BITS) {
+ // Here make sure that EndValue is less than the max value
+ // of the counter
+ OverFlow += EndValue / (1 << NUM_BITS_IN_ACPI_TIMER);
+ EndValue = EndValue % (1 << NUM_BITS_IN_ACPI_TIMER);
+ }
+ }
+
+ // Let the timer wrap around as many times as calculated
+ while (OverFlow) {
+ // read timer amd look to see if the new value read is less than
+ // the current timer value. if this happens the timer overflowed
+ NewTimerValue = IoRead32( AcpiTmrReg );
+
+ if (NewTimerValue < TimerValue) OverFlow--;
+
+ TimerValue = NewTimerValue;
+ }
+
+ // Now wait for the correct number of ticks that need to occur after
+ // all the needed overflows
+ while (EndValue > TimerValue) {
+ NewTimerValue = IoRead32( AcpiTmrReg );
+
+ // check to see if the timer overflowed. if it did then
+ // the time has elapsed. Because EndValue should be greater than
+ // TimerValue
+ if (NewTimerValue < TimerValue) break;
+
+ TimerValue = NewTimerValue;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmBusPeiInitialize
+//
+// Description: This function initializes SMBUS PCI device and fills device context
+//
+// Input: **PeiServices - Pointer to the PEI Services table
+// *Context - Pointer to the SMBus private structure.
+//
+// Output: None
+//
+// Notes: Porting required
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SmBusPeiInitialize(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT SMBUS_PRIVATE *Context )
+{
+ // [EIP82310]>
+ EFI_STATUS Status;
+ PEI_SMBUS_POLICY_PPI *SmbusPolicy;
+ UINTN SmbusRegBase;
+
+ Context->BoardReservedAddressCount = SmBusPlatformReservedAddressSize;
+ Context->BoardReservedAddressList = SmBusPlatformReservedAddress;
+
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &mPeiSmbusPolicyPpiGuid,
+ 0,
+ NULL,
+ &SmbusPolicy
+ );
+ if (EFI_ERROR(Status)) return;
+
+ SmbusRegBase = SB_PCIE_CFG_ADDRESS (SMBUS_BUS, SMBUS_DEV, SMBUS_FUN, 0);
+
+ if (MEM_READ16(SmbusRegBase + R_PCH_SMBUS_VENDOR_ID) != 0xFFFF) {
+ Context->SmBusBase = MEM_READ16(SmbusRegBase + R_PCH_SMBUS_BASE) & (UINT16) B_PCH_SMBUS_BASE_BAR;
+ if (Context->SmBusBase == SmbusPolicy->BaseAddress) {
+ return;
+ } else if (Context->SmBusBase == 0) {
+ Context->SmBusBase = SmbusPolicy->BaseAddress;
+
+ // Set the BAR & I/O space enable ourselves
+ MEM_WRITE16(SmbusRegBase + SMBUS_REG_BASE_ADDR, Context->SmBusBase);
+ MEM_SET8(SmbusRegBase + R_PCH_SMBUS_PCICMD, B_PCH_SMBUS_PCICMD_IOSE);
+
+ // Reset the SMBus host controller
+ MEM_SET8(SmbusRegBase + R_PCH_SMBUS_HOSTC, (PCH_SPD_WRITE_DISABLE << 4) | B_PCH_SMBUS_HOSTC_SSRESET);
+
+ // Enable the SMBus host controller
+ MEM_RW8(SmbusRegBase + R_PCH_SMBUS_HOSTC, \
+ B_PCH_SMBUS_HOSTC_HST_EN, \
+ B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN);
+
+ // Clear Status Register before anyone uses the interfaces
+ IoWrite8 (Context->SmBusBase + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ }
+ }
+ // <[EIP82310]
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+