This adds the implementation of SMBUS PPI and Protocol to produce SMBUS
interface in both PEI and DXE phases for use by IPMI SSIF.

Signed-off-by: Nhi Pham <n...@os.amperecomputing.com>
---
 Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.inf  |  43 +++
 Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.inf  |  43 +++
 Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.h |  95 +++++++
 Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.c | 262 
++++++++++++++++++
 Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.c    | 277 
++++++++++++++++++++
 Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.c    | 263 
+++++++++++++++++++
 6 files changed, 983 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.inf 
b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.inf
new file mode 100644
index 000000000000..7e8c8176658e
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.inf
@@ -0,0 +1,43 @@
+## @file
+#
+# Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = SmbusHcDxe
+  FILE_GUID                      = A92C6874-B59E-49A7-957D-8511C9D8520E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeSmbus
+
+[Sources]
+  SmbusHcCommon.c
+  SmbusHcDxe.c
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  GpioLib
+  I2cLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiSmbusHcProtocolGuid        # PRODUCES
+
+[Pcd]
+  gAmpereTokenSpaceGuid.PcdSmbusI2cBusNumber
+  gAmpereTokenSpaceGuid.PcdSmbusI2cBusSpeed
+
+[Depex]
+  TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.inf 
b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.inf
new file mode 100644
index 000000000000..810a583feab3
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.inf
@@ -0,0 +1,43 @@
+## @file
+#
+# Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = SmbusHcPeim
+  FILE_GUID                      = 1D770ACE-36E9-4B74-B548-4F423B60A26C
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeSmbusPeim
+
+[Sources]
+  SmbusHcCommon.c
+  SmbusHcPei.c
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  GpioLib
+  I2cLib
+  PeimEntryPoint
+  PeiServicesLib
+
+[Ppis]
+  gEfiPeiSmbus2PpiGuid        # PRODUCES
+
+[Pcd]
+  gAmpereTokenSpaceGuid.PcdSmbusI2cBusNumber
+  gAmpereTokenSpaceGuid.PcdSmbusI2cBusSpeed
+
+[Depex]
+  TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.h 
b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.h
new file mode 100644
index 000000000000..db19d50b0f2a
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.h
@@ -0,0 +1,95 @@
+/** @file
+
+  Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SMBUS_HC_COMMON_LIB_H_
+#define SMBUS_HC_COMMON_LIB_H_
+
+#include <Library/PcdLib.h>
+#include <IndustryStandard/SmBus.h>
+#include <Uefi/UefiBaseType.h>
+
+//
+// I2C Based SMBus info
+//
+#define I2C_BUS_NUMBER  (FixedPcdGet8 (PcdSmbusI2cBusNumber))
+#define I2C_BUS_SPEED   (FixedPcdGet32 (PcdSmbusI2cBusSpeed))
+#define I2C_WRITE_ADDRESS(Addr)  ((Addr) << 1 | 0)
+#define I2C_READ_ADDRESS(Addr)   ((Addr) << 1 | 1)
+
+//
+// SMBus 2.0
+//
+#define SMBUS_MAX_BLOCK_LENGTH   0x20
+#define SMBUS_READ_TEMP_LENGTH   (SMBUS_MAX_BLOCK_LENGTH + 2)  // Length + 32 
Bytes + PEC
+#define SMBUS_WRITE_TEMP_LENGTH  (SMBUS_MAX_BLOCK_LENGTH + 3)  // CMD + Length 
+ 32 Bytes + PEC
+
+//
+// SMBus PEC
+//
+#define CRC8_POLYNOMINAL_KEY  0x107     // X^8 + X^2 + X + 1
+
+/**
+  Executes an SMBus operation to an SMBus controller. Returns when either the 
command has been
+  executed or an error is encountered in doing the operation.
+
+  The Execute() function provides a standard way to execute an operation as 
defined in the System
+  Management Bus (SMBus) Specification. The resulting transaction will be 
either that the SMBus
+  slave devices accept this transaction or that this function returns with 
error.
+
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL 
instance.
+  @param  SlaveAddress            The SMBus slave address of the device with 
which to communicate.
+  @param  Command                 This command is transmitted by the SMBus 
host controller to the
+                                  SMBus slave device and the interpretation is 
SMBus slave device
+                                  specific. It can mean the offset to a list 
of functions inside an
+                                  SMBus slave device. Not all operations or 
slave devices support
+                                  this command's registers.
+  @param  Operation               Signifies which particular SMBus hardware 
protocol instance that
+                                  it will use to execute the SMBus 
transactions. This SMBus
+                                  hardware protocol is defined by the SMBus 
Specification and is
+                                  not related to EFI.
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking 
is required for this
+                                  operation.
+  @param  Length                  Signifies the number of bytes that this 
operation will do. The
+                                  maximum number of bytes can be revision 
specific and operation
+                                  specific. This field will contain the actual 
number of bytes that
+                                  are executed for this operation. Not all 
operations require this
+                                  argument.
+  @param  Buffer                  Contains the value of data to execute to the 
SMBus slave device.
+                                  Not all operations require this argument. 
The length of this
+                                  buffer is identified by Length.
+
+  @retval EFI_SUCCESS             The last data that was returned from the 
access matched the poll
+                                  exit criteria.
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
+  @retval EFI_TIMEOUT             Timeout expired before the operation was 
completed. Timeout is
+                                  determined by the SMBus host controller 
device.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a 
lack of resources.
+  @retval EFI_DEVICE_ERROR        The request was not completed because a 
failure that was
+                                  reflected in the Host Status Register bit. 
Device errors are a
+                                  result of a transaction collision, illegal 
command field,
+                                  unclaimed cycle (host initiated), or bus 
errors (collisions).
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in 
EFI_SMBUS_OPERATION.
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except 
for EfiSmbusQuickRead
+                                  and EfiSmbusQuickWrite. Length is outside 
the range of valid
+                                  values.
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcCommonExecute (
+  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
+  );
+
+#endif /* SMBUS_HC_COMMON_LIB_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.c 
b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.c
new file mode 100644
index 000000000000..6219c99cda18
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcCommon.c
@@ -0,0 +1,262 @@
+/** @file
+  SmbusHcCommon implement common api for SmbusHc
+
+  Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/GpioLib.h>
+#include <Library/I2cLib.h>
+#include <Library/PcdLib.h>
+
+#include "SmbusHcCommon.h"
+
+/**
+  Incremental calculate Pec base on previous Pec value and CRC8 of data array
+  pointed to by Buffer
+
+  @param  Pec        Previous Pec
+  @param  Buffer     Pointer to data array
+  @param  Length     Array count
+
+  @retval Pec
+
+**/
+UINT8
+CalculatePec (
+  UINT8   Pec,
+  UINT8   *Buffer,
+  UINT32  Length
+  )
+{
+  UINT8  Offset, Index;
+
+  for (Offset = 0; Offset < Length; Offset++) {
+    Pec ^= Buffer[Offset];
+    for (Index = 0; Index < 8; Index++) {
+      if ((Pec & 0x80) != 0) {
+        Pec = (UINT8)((Pec << 1) ^ CRC8_POLYNOMINAL_KEY);
+      } else {
+        Pec <<= 1;
+      }
+    }
+  }
+
+  return Pec & 0xFF;
+}
+
+/**
+  Executes an SMBus operation to an SMBus controller. Returns when either the 
command has been
+  executed or an error is encountered in doing the operation.
+
+  The Execute() function provides a standard way to execute an operation as 
defined in the System
+  Management Bus (SMBus) Specification. The resulting transaction will be 
either that the SMBus
+  slave devices accept this transaction or that this function returns with 
error.
+
+  @param  SlaveAddress            The SMBus slave address of the device with 
which to communicate.
+  @param  Command                 This command is transmitted by the SMBus 
host controller to the
+                                  SMBus slave device and the interpretation is 
SMBus slave device
+                                  specific. It can mean the offset to a list 
of functions inside an
+                                  SMBus slave device. Not all operations or 
slave devices support
+                                  this command's registers.
+  @param  Operation               Signifies which particular SMBus hardware 
protocol instance that
+                                  it will use to execute the SMBus 
transactions. This SMBus
+                                  hardware protocol is defined by the SMBus 
Specification and is
+                                  not related to EFI.
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking 
is required for this
+                                  operation.
+  @param  Length                  Signifies the number of bytes that this 
operation will do. The
+                                  maximum number of bytes can be revision 
specific and operation
+                                  specific. This field will contain the actual 
number of bytes that
+                                  are executed for this operation. Not all 
operations require this
+                                  argument.
+  @param  Buffer                  Contains the value of data to execute to the 
SMBus slave device.
+                                  Not all operations require this argument. 
The length of this
+                                  buffer is identified by Length.
+
+  @retval EFI_SUCCESS             The last data that was returned from the 
access matched the poll
+                                  exit criteria.
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
+  @retval EFI_TIMEOUT             Timeout expired before the operation was 
completed. Timeout is
+                                  determined by the SMBus host controller 
device.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a 
lack of resources.
+  @retval EFI_DEVICE_ERROR        The request was not completed because a 
failure that was
+                                  reflected in the Host Status Register bit. 
Device errors are a
+                                  result of a transaction collision, illegal 
command field,
+                                  unclaimed cycle (host initiated), or bus 
errors (collisions).
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in 
EFI_SMBUS_OPERATION.
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except 
for EfiSmbusQuickRead
+                                  and EfiSmbusQuickWrite. Length is outside 
the range of valid
+                                  values.
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcCommonExecute (
+  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;
+  UINTN       DataLen, Idx;
+  UINT8       ReadTemp[SMBUS_READ_TEMP_LENGTH];
+  UINT8       WriteTemp[SMBUS_WRITE_TEMP_LENGTH];
+  UINT8       CrcTemp[10];
+  UINT8       Pec;
+
+  if (  ((Operation != EfiSmbusQuickRead) && (Operation != EfiSmbusQuickWrite))
+     && ((Length == NULL) || (Buffer == NULL)))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Switch to correct I2C bus and speed
+  //
+  Status = I2cProbe (I2C_BUS_NUMBER, I2C_BUS_SPEED);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Process Operation
+  //
+  switch (Operation) {
+    case EfiSmbusWriteBlock:
+      if (*Length > SMBUS_MAX_BLOCK_LENGTH) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      WriteTemp[0] = Command;
+      WriteTemp[1] = *Length;
+      CopyMem (&WriteTemp[2], Buffer, *Length);
+      DataLen = *Length + 2;
+
+      //
+      // PEC handling
+      //
+      if (PecCheck) {
+        CrcTemp[0] = I2C_WRITE_ADDRESS (SlaveAddress.SmbusDeviceAddress);
+        Pec        = CalculatePec (0, &CrcTemp[0], 1);
+        Pec        = CalculatePec (Pec, WriteTemp, DataLen);
+        DEBUG ((DEBUG_VERBOSE, "\nWriteBlock PEC = 0x%x \n", Pec));
+        WriteTemp[DataLen] = Pec;
+        DataLen           += 1;
+      }
+
+      DEBUG ((DEBUG_VERBOSE, "W %d: ", DataLen));
+      for (Idx = 0; Idx < DataLen; Idx++) {
+        DEBUG ((DEBUG_VERBOSE, "0x%x ", WriteTemp[Idx]));
+      }
+
+      DEBUG ((DEBUG_VERBOSE, "\n"));
+
+      Status = I2cWrite (
+                 I2C_BUS_NUMBER,
+                 SlaveAddress.SmbusDeviceAddress,
+                 WriteTemp,
+                 (UINT32 *)&DataLen
+                 );
+      if (EFI_ERROR (Status)) {
+        if (Status != EFI_TIMEOUT) {
+          Status = EFI_DEVICE_ERROR;
+        }
+      }
+
+      break;
+
+    case EfiSmbusReadBlock:
+      WriteTemp[0] = Command;
+      DataLen      = *Length + 2; // +1 byte for Data Length +1 byte for PEC
+      Status       = SmbusRead (
+                       I2C_BUS_NUMBER,
+                       SlaveAddress.SmbusDeviceAddress,
+                       WriteTemp,
+                       1,
+                       ReadTemp,
+                       (UINT32 *)&DataLen,
+                       PecCheck
+                       );
+      if (EFI_ERROR (Status)) {
+        if (Status != EFI_TIMEOUT) {
+          Status = EFI_DEVICE_ERROR;
+        }
+
+        *Length = 0;
+        break;
+      }
+
+      DEBUG ((DEBUG_VERBOSE, "R %d: ", DataLen));
+      for (Idx = 0; Idx < DataLen; Idx++) {
+        DEBUG ((DEBUG_VERBOSE, "0x%x ", ReadTemp[Idx]));
+      }
+
+      DEBUG ((DEBUG_VERBOSE, "\n"));
+
+      DataLen = ReadTemp[0];
+
+      //
+      // PEC handling
+      //
+      if (PecCheck) {
+        CrcTemp[0] = I2C_WRITE_ADDRESS (SlaveAddress.SmbusDeviceAddress);
+        CrcTemp[1] = Command;
+        CrcTemp[2] = I2C_READ_ADDRESS (SlaveAddress.SmbusDeviceAddress);
+
+        Pec = CalculatePec (0, &CrcTemp[0], 3);
+        Pec = CalculatePec (Pec, ReadTemp, DataLen + 1);
+
+        if (Pec != ReadTemp[DataLen + 1]) {
+          DEBUG ((DEBUG_ERROR, "ReadBlock PEC cal = 0x%x != 0x%x\n", Pec, 
ReadTemp[DataLen + 1]));
+          return EFI_CRC_ERROR;
+        } else {
+          DEBUG ((DEBUG_VERBOSE, "ReadBlock PEC 0x%x\n", ReadTemp[DataLen + 
1]));
+        }
+      }
+
+      if ((DataLen == 0) || (DataLen > SMBUS_MAX_BLOCK_LENGTH)) {
+        DEBUG ((DEBUG_ERROR, "%a: Invalid length = %d\n", __func__, DataLen));
+        *Length = 0;
+        Status  = EFI_INVALID_PARAMETER;
+      } else if (DataLen > *Length) {
+        DEBUG ((DEBUG_ERROR, "%a: Buffer too small\n", __func__));
+        *Length = 0;
+        Status  = EFI_BUFFER_TOO_SMALL;
+      } else {
+        *Length = DataLen;
+        CopyMem (Buffer, &ReadTemp[1], DataLen);
+      }
+
+      break;
+
+    case EfiSmbusQuickRead:
+    case EfiSmbusQuickWrite:
+    case EfiSmbusReceiveByte:
+    case EfiSmbusSendByte:
+    case EfiSmbusReadByte:
+    case EfiSmbusWriteByte:
+    case EfiSmbusReadWord:
+    case EfiSmbusWriteWord:
+    case EfiSmbusProcessCall:
+    case EfiSmbusBWBRProcessCall:
+      DEBUG ((DEBUG_ERROR, "%a: Unsupported command\n", __func__));
+      Status = EFI_UNSUPPORTED;
+      break;
+
+    default:
+      Status = EFI_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.c 
b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.c
new file mode 100644
index 000000000000..49a16a2c3d7e
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcDxe.c
@@ -0,0 +1,277 @@
+/** SmbusHc protocol implementation follows SMBus 2.0 specification.
+
+  Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/GpioLib.h>
+#include <Library/I2cLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/SmbusHc.h>
+
+#include "SmbusHcCommon.h"
+
+//
+// Handle to install SMBus Host Controller protocol.
+//
+EFI_HANDLE  mSmbusHcHandle = NULL;
+
+/**
+  Executes an SMBus operation to an SMBus controller. Returns when either the 
command has been
+  executed or an error is encountered in doing the operation.
+
+  The Execute() function provides a standard way to execute an operation as 
defined in the System
+  Management Bus (SMBus) Specification. The resulting transaction will be 
either that the SMBus
+  slave devices accept this transaction or that this function returns with 
error.
+
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL 
instance.
+  @param  SlaveAddress            The SMBus slave address of the device with 
which to communicate.
+  @param  Command                 This command is transmitted by the SMBus 
host controller to the
+                                  SMBus slave device and the interpretation is 
SMBus slave device
+                                  specific. It can mean the offset to a list 
of functions inside an
+                                  SMBus slave device. Not all operations or 
slave devices support
+                                  this command's registers.
+  @param  Operation               Signifies which particular SMBus hardware 
protocol instance that
+                                  it will use to execute the SMBus 
transactions. This SMBus
+                                  hardware protocol is defined by the SMBus 
Specification and is
+                                  not related to EFI.
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking 
is required for this
+                                  operation.
+  @param  Length                  Signifies the number of bytes that this 
operation will do. The
+                                  maximum number of bytes can be revision 
specific and operation
+                                  specific. This field will contain the actual 
number of bytes that
+                                  are executed for this operation. Not all 
operations require this
+                                  argument.
+  @param  Buffer                  Contains the value of data to execute to the 
SMBus slave device.
+                                  Not all operations require this argument. 
The length of this
+                                  buffer is identified by Length.
+
+  @retval EFI_SUCCESS             The last data that was returned from the 
access matched the poll
+                                  exit criteria.
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
+  @retval EFI_TIMEOUT             Timeout expired before the operation was 
completed. Timeout is
+                                  determined by the SMBus host controller 
device.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a 
lack of resources.
+  @retval EFI_DEVICE_ERROR        The request was not completed because a 
failure that was
+                                  reflected in the Host Status Register bit. 
Device errors are a
+                                  result of a transaction collision, illegal 
command field,
+                                  unclaimed cycle (host initiated), or bus 
errors (collisions).
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in 
EFI_SMBUS_OPERATION.
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except 
for EfiSmbusQuickRead
+                                  and EfiSmbusQuickWrite. Length is outside 
the range of valid
+                                  values.
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcExecute (
+  IN CONST EFI_SMBUS_HC_PROTOCOL     *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;
+  EFI_TPL     OldTpl;
+
+  ASSERT (This != NULL);
+
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  Status = SmbusHcCommonExecute (SlaveAddress, Command, Operation, PecCheck, 
Length, Buffer);
+
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
+
+  The SmbusHcArpDevice() function provides a standard way for a device driver 
to
+  enumerate the entire SMBus or specific devices on the bus.
+
+  @param This           A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+
+  @param ArpAll         A Boolean expression that indicates if the
+                        host drivers need to enumerate all the devices
+                        or enumerate only the device that is
+                        identified by SmbusUdid. If ArpAll is TRUE,
+                        SmbusUdid and SlaveAddress are optional. If
+                        ArpAll is FALSE, ArpDevice will enumerate
+                        SmbusUdid and the address will be at
+                        SlaveAddress.
+
+  @param SmbusUdid      The Unique Device Identifier (UDID) that is
+                        associated with this device. Type
+                        EFI_SMBUS_UDID is defined in
+                        EFI_PEI_SMBUS_PPI.ArpDevice() in the
+                        Platform Initialization SMBus PPI
+                        Specification.
+
+  @param SlaveAddress   The SMBus slave address that is
+                        associated with an SMBus UDID.
+
+  @retval EFI_SUCCESS           The last data that was returned from the
+                                access matched the poll exit criteria.
+
+  @retval EFI_CRC_ERROR         Checksum is not correct (PEC is
+                                incorrect).
+
+  @retval EFI_TIMEOUT           Timeout expired before the operation was
+                                completed. Timeout is determined by the
+                                SMBus host controller device.
+
+  @retval EFI_OUT_OF_RESOURCES  The request could not be
+                                completed due to a lack of
+                                resources.
+
+  @retval EFI_DEVICE_ERROR      The request was not completed
+                                because a failure was reflected in
+                                the Host Status Register bit. Device
+                                Errors are a result of a transaction
+                                collision, illegal command field,
+                                unclaimed cycle (host initiated), or
+                                bus errors (collisions).
+
+  @retval EFI_UNSUPPORTED       ArpDevice, GetArpMap, and Notify are
+                                not implemented by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcArpDevice (
+  IN CONST EFI_SMBUS_HC_PROTOCOL *This,
+  IN       BOOLEAN ArpAll,
+  IN       EFI_SMBUS_UDID *SmbusUdid, OPTIONAL
+  IN OUT   EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL
+  )
+{
+  //
+  // Not supported
+  //
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  The SmbusHcGetArpMap() function returns the mapping of all the SMBus devices
+  that were enumerated by the SMBus host driver.
+
+  @param This           A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+
+  @param Length         Size of the buffer that contains the SMBus
+                        device map.
+
+  @param SmbusDeviceMap The pointer to the device map as
+                        enumerated by the SMBus controller
+                        driver.
+
+  @retval EFI_SUCCESS       The SMBus returned the current device map.
+
+  @retval EFI_UNSUPPORTED   ArpDevice, GetArpMap, and Notify are
+                            not implemented by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcGetArpMap (
+  IN CONST EFI_SMBUS_HC_PROTOCOL  *This,
+  IN OUT   UINTN                  *Length,
+  IN OUT   EFI_SMBUS_DEVICE_MAP   **SmbusDeviceMap
+  )
+{
+  //
+  // Not supported
+  //
+  return EFI_UNSUPPORTED;
+}
+
+/**
+
+  The SmbusHcNotify() function registers all the callback functions to
+  allow the bus driver to call these functions when the
+  SlaveAddress/Data pair happens.
+
+  @param  This            A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
+
+  @param  SlaveAddress    Address that the host controller detects
+                          as sending a message and calls all the registered 
function.
+
+  @param  Data            Data that the host controller detects as sending
+                          message and calls all the registered function.
+
+
+  @param  NotifyFunction  The function to call when the bus
+                          driver detects the SlaveAddress and
+                          Data pair.
+
+  @retval EFI_SUCCESS       NotifyFunction was registered.
+
+  @retval EFI_UNSUPPORTED   ArpDevice, GetArpMap, and Notify are
+                            not implemented by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcNotify (
+  IN CONST EFI_SMBUS_HC_PROTOCOL      *This,
+  IN       EFI_SMBUS_DEVICE_ADDRESS   SlaveAddress,
+  IN       UINTN                      Data,
+  IN       EFI_SMBUS_NOTIFY_FUNCTION  NotifyFunction
+  )
+{
+  //
+  // Not supported
+  //
+  return EFI_UNSUPPORTED;
+}
+
+//
+// Interface defintion of SMBUS Host Controller Protocol.
+//
+EFI_SMBUS_HC_PROTOCOL  mSmbusHcProtocol = {
+  SmbusHcExecute,
+  SmbusHcArpDevice,
+  SmbusHcGetArpMap,
+  SmbusHcNotify
+};
+
+/**
+  SmbusHc driver entry point
+
+  @param[in] ImageHandle          ImageHandle of this module
+  @param[in] SystemTable          EFI System Table
+
+  @retval EFI_SUCCESS             Driver initializes successfully
+  @retval Other values            Some error occurred
+**/
+EFI_STATUS
+InitializeSmbus (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Install Smbus protocol
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mSmbusHcHandle,
+                  &gEfiSmbusHcProtocolGuid,
+                  &mSmbusHcProtocol,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.c 
b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.c
new file mode 100644
index 000000000000..39483a2a602a
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/SmbusHc/SmbusHcPei.c
@@ -0,0 +1,263 @@
+/** @file
+  SmbusHc protocol implementation follows SMBus 2.0 specification.
+
+  Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/Smbus2.h>
+
+#include "SmbusHcCommon.h"
+
+/**
+  Executes an SMBus operation to an SMBus controller. Returns when either the 
command has been
+  executed or an error is encountered in doing the operation.
+
+  The Execute() function provides a standard way to execute an operation as 
defined in the System
+  Management Bus (SMBus) Specification. The resulting transaction will be 
either that the SMBus
+  slave devices accept this transaction or that this function returns with 
error.
+
+  @param  This                    A pointer to the EFI_PEI_SMBUS2_PPI instance.
+  @param  SlaveAddress            The SMBus slave address of the device with 
which to communicate.
+  @param  Command                 This command is transmitted by the SMBus 
host controller to the
+                                  SMBus slave device and the interpretation is 
SMBus slave device
+                                  specific. It can mean the offset to a list 
of functions inside an
+                                  SMBus slave device. Not all operations or 
slave devices support
+                                  this command's registers.
+  @param  Operation               Signifies which particular SMBus hardware 
protocol instance that
+                                  it will use to execute the SMBus 
transactions. This SMBus
+                                  hardware protocol is defined by the SMBus 
Specification and is
+                                  not related to EFI.
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking 
is required for this
+                                  operation.
+  @param  Length                  Signifies the number of bytes that this 
operation will do. The
+                                  maximum number of bytes can be revision 
specific and operation
+                                  specific. This field will contain the actual 
number of bytes that
+                                  are executed for this operation. Not all 
operations require this
+                                  argument.
+  @param  Buffer                  Contains the value of data to execute to the 
SMBus slave device.
+                                  Not all operations require this argument. 
The length of this
+                                  buffer is identified by Length.
+
+  @retval EFI_SUCCESS             The last data that was returned from the 
access matched the poll
+                                  exit criteria.
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
+  @retval EFI_TIMEOUT             Timeout expired before the operation was 
completed. Timeout is
+                                  determined by the SMBus host controller 
device.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a 
lack of resources.
+  @retval EFI_DEVICE_ERROR        The request was not completed because a 
failure that was
+                                  reflected in the Host Status Register bit. 
Device errors are a
+                                  result of a transaction collision, illegal 
command field,
+                                  unclaimed cycle (host initiated), or bus 
errors (collisions).
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in 
EFI_SMBUS_OPERATION.
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except 
for EfiSmbusQuickRead
+                                  and EfiSmbusQuickWrite. Length is outside 
the range of valid
+                                  values.
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcExecute (
+  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
+  )
+{
+  ASSERT (This != NULL);
+  return SmbusHcCommonExecute (SlaveAddress, Command, Operation, PecCheck, 
Length, Buffer);
+}
+
+/**
+
+  The SmbusHcArpDevice() function provides a standard way for a device driver 
to
+  enumerate the entire SMBus or specific devices on the bus.
+
+  @param This           A pointer to the EFI_PEI_SMBUS2_PPI instance.
+
+  @param ArpAll         A Boolean expression that indicates if the
+                        host drivers need to enumerate all the devices
+                        or enumerate only the device that is
+                        identified by SmbusUdid. If ArpAll is TRUE,
+                        SmbusUdid and SlaveAddress are optional. If
+                        ArpAll is FALSE, ArpDevice will enumerate
+                        SmbusUdid and the address will be at
+                        SlaveAddress.
+
+  @param SmbusUdid      The Unique Device Identifier (UDID) that is
+                        associated with this device. Type
+                        EFI_SMBUS_UDID is defined in
+                        EFI_PEI_SMBUS_PPI.ArpDevice() in the
+                        Platform Initialization SMBus PPI
+                        Specification.
+
+  @param SlaveAddress   The SMBus slave address that is
+                        associated with an SMBus UDID.
+
+  @retval EFI_SUCCESS           The last data that was returned from the
+                                access matched the poll exit criteria.
+
+  @retval EFI_CRC_ERROR         Checksum is not correct (PEC is
+                                incorrect).
+
+  @retval EFI_TIMEOUT           Timeout expired before the operation was
+                                completed. Timeout is determined by the
+                                SMBus host controller device.
+
+  @retval EFI_OUT_OF_RESOURCES  The request could not be
+                                completed due to a lack of
+                                resources.
+
+  @retval EFI_DEVICE_ERROR      The request was not completed
+                                because a failure was reflected in
+                                the Host Status Register bit. Device
+                                Errors are a result of a transaction
+                                collision, illegal command field,
+                                unclaimed cycle (host initiated), or
+                                bus errors (collisions).
+
+  @retval EFI_UNSUPPORTED       ArpDevice, GetArpMap, and Notify are
+                                not implemented by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcArpDevice (
+  IN CONST EFI_PEI_SMBUS2_PPI *This,
+  IN       BOOLEAN ArpAll,
+  IN       EFI_SMBUS_UDID *SmbusUdid, OPTIONAL
+  IN OUT   EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL
+  )
+{
+  //
+  // Not supported
+  //
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  The SmbusHcGetArpMap() function returns the mapping of all the SMBus devices
+  that were enumerated by the SMBus host driver.
+
+  @param This           A pointer to the EFI_PEI_SMBUS2_PPI instance.
+
+  @param Length         Size of the buffer that contains the SMBus
+                        device map.
+
+  @param SmbusDeviceMap The pointer to the device map as
+                        enumerated by the SMBus controller
+                        driver.
+
+  @retval EFI_SUCCESS       The SMBus returned the current device map.
+
+  @retval EFI_UNSUPPORTED   ArpDevice, GetArpMap, and Notify are
+                            not implemented by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcGetArpMap (
+  IN CONST EFI_PEI_SMBUS2_PPI    *This,
+  IN OUT   UINTN                 *Length,
+  IN OUT   EFI_SMBUS_DEVICE_MAP  **SmbusDeviceMap
+  )
+{
+  //
+  // Not supported
+  //
+  return EFI_UNSUPPORTED;
+}
+
+/**
+
+  The SmbusHcNotify() function registers all the callback functions to
+  allow the bus driver to call these functions when the
+  SlaveAddress/Data pair happens.
+
+  @param  This            A pointer to the EFI_PEI_SMBUS2_PPI instance.
+
+  @param  SlaveAddress    Address that the host controller detects
+                          as sending a message and calls all the registered 
function.
+
+  @param  Data            Data that the host controller detects as sending
+                          message and calls all the registered function.
+
+
+  @param  NotifyFunction  The function to call when the bus
+                          driver detects the SlaveAddress and
+                          Data pair.
+
+  @retval EFI_SUCCESS       NotifyFunction was registered.
+
+  @retval EFI_UNSUPPORTED   ArpDevice, GetArpMap, and Notify are
+                            not implemented by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusHcNotify (
+  IN CONST EFI_PEI_SMBUS2_PPI              *This,
+  IN       EFI_SMBUS_DEVICE_ADDRESS        SlaveAddress,
+  IN       UINTN                           Data,
+  IN       EFI_PEI_SMBUS_NOTIFY2_FUNCTION  NotifyFunction
+  )
+{
+  //
+  // Not supported
+  //
+  return EFI_UNSUPPORTED;
+}
+
+//
+// Interface defintion of SMBUS Host Controller Protocol.
+//
+EFI_PEI_SMBUS2_PPI  mSmbusHcPpi = {
+  SmbusHcExecute,
+  SmbusHcArpDevice,
+  SmbusHcGetArpMap,
+  SmbusHcNotify
+};
+
+EFI_PEI_PPI_DESCRIPTOR  gPpiSmbusHcPpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPeiSmbus2PpiGuid,
+  &mSmbusHcPpi
+};
+
+/**
+  SmbusHc driver entry point
+
+  @param[in] ImageHandle          ImageHandle of this module
+  @param[in]  PeiServices         An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+
+  @retval EFI_SUCCESS             Driver initializes successfully
+  @retval Other values            Some error occurred
+**/
+EFI_STATUS
+EFIAPI
+InitializeSmbusPeim (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Install Smbus Ppi
+  //
+  Status = PeiServicesInstallPpi (&gPpiSmbusHcPpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
-- 
2.25.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#120165): https://edk2.groups.io/g/devel/message/120165
Mute This Topic: https://groups.io/mt/107662237/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to