public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zhai, MingXin (Duke) via groups.io" <duke.zhai=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Eric Xing <eric.xing@amd.com>, Ken Yao <ken.yao@amd.com>,
	Igniculus Fu <igniculus.fu@amd.com>,
	Abner Chang <abner.chang@amd.com>
Subject: [edk2-devel] [PATCH V2 24/32] AMD/VanGoghBoard: Check in FchSpi module
Date: Fri, 26 Jan 2024 14:00:42 +0800	[thread overview]
Message-ID: <20240126060050.1725-25-duke.zhai@amd.com> (raw)
In-Reply-To: <20240126060050.1725-1-duke.zhai@amd.com>

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial FchSpi module. FCH SPI Common Driver implements
  the SPI Host Controller Compatibility Interface.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Universal/FchSpi/FchSpiProtect.c          |  67 ++
 .../Universal/FchSpi/FchSpiProtect.h          |  38 +
 .../Universal/FchSpi/FchSpiRuntimeDxe.c       | 163 ++++
 .../Universal/FchSpi/FchSpiRuntimeDxe.h       |  49 ++
 .../Universal/FchSpi/FchSpiRuntimeDxe.inf     |  84 ++
 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.c | 112 +++
 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.h |  32 +
 .../Universal/FchSpi/FchSpiSmm.inf            |  94 +++
 .../VanGoghBoard/Universal/FchSpi/SpiCommon.c | 790 ++++++++++++++++++
 .../VanGoghBoard/Universal/FchSpi/SpiInfo.h   |  24 +
 10 files changed, 1453 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h

diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
new file mode 100644
index 0000000000..658d9b063d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
@@ -0,0 +1,67 @@
+/** @file
+  Implements FchSpiProtect.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+
+#include "FchSpiProtect.h"
+
+/**
+
+   Fch Spi Protect Lock
+
+   @param SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_Lock (
+  IN UINTN  SpiMmioBase
+  )
+{
+  if (!(MmioRead8 (SpiMmioBase + 2) & 0xC0)) {
+    // Check BIT7+BIT6
+    return EFI_SUCCESS;
+  } else {
+    MmioWrite8 (SpiMmioBase + 9, 0x6);                                // PrefixOpCode WRITE_ENABLE
+    MmioWrite8 (SpiMmioBase + 2, MmioRead8 (SpiMmioBase + 2) & 0x3F); // Clear BIT7+BIT6
+    if (MmioRead8 (SpiMmioBase + 2) & 0xC0) {
+      return EFI_DEVICE_ERROR;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+   Fch Spi Protect UnLock
+
+   @param SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_UnLock (
+  IN UINTN  SpiMmioBase
+  )
+{
+  if ((MmioRead8 (SpiMmioBase + 2) & 0xC0) || (6 != MmioRead8 (SpiMmioBase + 9))) {
+    return EFI_SUCCESS;
+  } else {
+    MmioWrite8 (SpiMmioBase + 9, 0x0);
+    MmioWrite8 (SpiMmioBase + 2, MmioRead8 (SpiMmioBase + 2) | 0xC0); // Set BIT7+BIT6
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
new file mode 100644
index 0000000000..1dd57c6f52
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
@@ -0,0 +1,38 @@
+/** @file
+  Implements FchSpiProtect.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FCH_SPI_PROTECT_H__
+#define FCH_SPI_PROTECT_H__
+
+/**
+
+   Fch Spi Protect Lock
+
+   @param UINTN SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_Lock (
+  IN UINTN  SpiMmioBase
+  );
+
+/**
+
+   Fch Spi Protect UnLock
+
+   @param UINTN SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_UnLock (
+  IN UINTN  SpiMmioBase
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
new file mode 100644
index 0000000000..7bb402402c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
@@ -0,0 +1,163 @@
+/** @file
+PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FchSpiRuntimeDxe.h"
+
+extern EFI_GUID  gEfiEventVirtualAddressChangeGuid;
+CONST BOOLEAN    gInSmm = FALSE;
+
+//
+// Global variables
+//
+SPI_INSTANCE  *mSpiInstance;
+
+/**
+
+  Fixup internal data pointers so that the services can be called in virtual mode.
+
+  @param Event     The event registered.
+  @param Context   Event context. Not used in this event handler.
+
+  @retval   None
+
+**/
+VOID
+EFIAPI
+FchSpiVirtualddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiBar));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiProtocol.Init));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiProtocol.Lock));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiProtocol.Execute));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance));
+}
+
+/**
+
+  Entry point for the SPI host controller driver.
+
+  @param ImageHandle       Image handle of this driver.
+  @param SystemTable       Global system service table.
+
+  @retval EFI_SUCCESS           Initialization complete.
+  @retval EFI_UNSUPPORTED       The chipset is unsupported by this driver.
+  @retval EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.
+  @retval EFI_DEVICE_ERROR      Device error, driver exits abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallFchSpiRuntimeDxe (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                       Status;
+  UINT64                           BaseAddress;
+  UINT64                           Length;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  GcdMemorySpaceDescriptor;
+  UINT64                           Attributes;
+  EFI_EVENT                        Event;
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiRuntimeDxe() Start\n"));
+
+  //
+  // Allocate Runtime memory for the SPI protocol instance.
+  //
+  mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
+  if (mSpiInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the SPI protocol instance
+  //
+  Status = SpiProtocolConstructor (mSpiInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Install the EFI_SPI_PROTOCOL interface
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &(mSpiInstance->Handle),
+                  &gEfiSpiProtocolGuid,
+                  &(mSpiInstance->SpiProtocol),
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    FreePool (mSpiInstance);
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = mSpiInstance->SpiProtocol.Init (&(mSpiInstance->SpiProtocol));
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Set Spi space in GCD to be RUNTIME so that the range will be supported in
+  // virtual address mode in EFI aware OS runtime.
+  // It will assert if Spi Memory Space is not allocated
+  // The caller is responsible for the existence and allocation of the Spi Memory Spaces
+  //
+  BaseAddress = (EFI_PHYSICAL_ADDRESS)(mSpiInstance->SpiBar);
+  Length      = 0x1000;
+
+  Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
+  ASSERT_EFI_ERROR (Status);
+
+  Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  BaseAddress,
+                  Length,
+                  Attributes
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  FchSpiVirtualddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiRuntimeDxe() End\n"));
+
+  return EFI_SUCCESS;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
new file mode 100644
index 0000000000..929e821294
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
@@ -0,0 +1,49 @@
+/** @file
+Header file for the PCH SPI Runtime Driver.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FCH_SPI_RUNTIME_DXE_H_
+#define FCH_SPI_RUNTIME_DXE_H_
+
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SpiFlashDeviceLib.h>
+
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+
+#define EFI_INTERNAL_POINTER  0x00000004
+
+/**
+
+  Fixup internal data pointers so that the services can be called in virtual mode.
+
+  @param Event     The event registered.
+  @param Context   Event context. Not used in this event handler.
+
+  @retval   None
+
+**/
+VOID
+EFIAPI
+FchSpiVirtualddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
new file mode 100644
index 0000000000..c2af195d05
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
@@ -0,0 +1,84 @@
+## @file
+#    Component description file for the SPI Runtime driver.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FchSpiRuntimeDxe
+  FILE_GUID                      = B9B0740A-B4E9-46FF-AAC7-C632BAC15834
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InstallFchSpiRuntimeDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+[Sources]
+  FchSpiRuntimeDxe.c
+  FchSpiRuntimeDxe.h
+  FchSpiProtect.c
+  FchSpiProtect.h
+  SpiCommon.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+[Packages]
+  MdePkg/MdePkg.dec
+  ChachaniBoardPkg/Project.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+#                         this module.
+#
+################################################################################
+[LibraryClasses]
+  UefiRuntimeServicesTableLib
+  UefiRuntimeLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  TimerLib
+  DxeServicesTableLib
+  UefiLib
+  DebugLib
+  MemoryAllocationLib
+  PciExpressLib
+  SpiFlashDeviceLib
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+#                           that this module uses or produces.
+#
+################################################################################
+[Protocols]
+  gEfiSpiProtocolGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+
+[Depex]
+  TRUE
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
new file mode 100644
index 0000000000..1f842685a8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
@@ -0,0 +1,112 @@
+/** @file
+
+PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FchSpiSmm.h"
+
+CONST BOOLEAN  gInSmm = TRUE;
+
+//
+// Global variables
+//
+SPI_INSTANCE  *mSpiInstance;
+
+/**
+
+  Entry point for the SPI host controller driver.
+
+  @param ImageHandle       Image handle of this driver.
+  @param SystemTable       Global system service table.
+
+  @retval EFI_SUCCESS           Initialization complete.
+  @retval EFI_UNSUPPORTED       The chipset is unsupported by this driver.
+  @retval EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.
+  @retval EFI_DEVICE_ERROR      Device error, driver exits abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallFchSpiSmm (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  // VOID                            *SmmReadyToBootRegistration;
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiSmm() Start\n"));
+
+  Status = gSmst->SmmAllocatePool (
+                    EfiRuntimeServicesData,
+                    sizeof (SPI_INSTANCE),
+                    (VOID **)&mSpiInstance
+                    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ZeroMem (mSpiInstance, sizeof (SPI_INSTANCE));
+
+  if (mSpiInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the SPI protocol instance
+  //
+  Status = SpiProtocolConstructor (mSpiInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Install the EFI_SPI_PROTOCOL interface
+  //
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &(mSpiInstance->Handle),
+                    &gEfiSmmSpiProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &(mSpiInstance->SpiProtocol)
+                    );
+  if (EFI_ERROR (Status)) {
+    FreePool (mSpiInstance);
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = mSpiInstance->SpiProtocol.Init (&(mSpiInstance->SpiProtocol));
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiSmm() End\n"));
+
+  return EFI_SUCCESS;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
new file mode 100644
index 0000000000..47dbee9391
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
@@ -0,0 +1,32 @@
+/** @file
+Header file for the PCH SPI SMM Driver.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FCH_SPI_SMM_H__
+#define FCH_SPI_SMM_H__
+
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/SpiFlashDeviceLib.h>
+
+#include <Protocol/SmmReadyToBoot.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
new file mode 100644
index 0000000000..b30a17119d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
@@ -0,0 +1,94 @@
+## @file
+# Spi smm driver
+#
+# Component description file for the SPI SMM driver.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FchSpiSmm
+  FILE_GUID                      = 9D63F99F-609D-4EB3-A9D1-5ACE2E25792A
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.1
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  ENTRY_POINT                    = InstallFchSpiSmm
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+[Sources]
+  FchSpiSmm.c
+  FchSpiSmm.h
+  FchSpiProtect.c
+  FchSpiProtect.h
+  SpiCommon.c
+
+[sources.ia32]
+
+[sources.x64]
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+#                         this module.
+#
+################################################################################
+[LibraryClasses]
+  BaseLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  TimerLib
+  DxeServicesTableLib
+  UefiLib
+  DebugLib
+  MemoryAllocationLib
+  PciExpressLib
+  SmmServicesTableLib
+  SpiFlashDeviceLib
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+#                           that this module uses or produces.
+#
+################################################################################
+[Protocols]
+  gEfiSmmSpiProtocolGuid
+  gEfiSmmBase2ProtocolGuid
+  gEdkiiSmmReadyToBootProtocolGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+
+[Depex]
+   gEfiSmmBase2ProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
new file mode 100644
index 0000000000..4aab7294cb
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
@@ -0,0 +1,790 @@
+/** @file
+PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FchSpiProtect.h"
+#include "SpiInfo.h"
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/SpiFlashDeviceLib.h>
+#include <Protocol/SpiCommon.h>
+#include <Protocol/SmmBase2.h>
+
+#define SPI_WREN_INDEX  0                     // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX  1                     // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+
+#define FCH_SPI_MMIO_REG48_TXBYTECOUNT  0x48
+#define FCH_SPI_MMIO_REG4B_RXBYTECOUNT  0x4B
+#define FCH_SPI_MMIO_REG80_FIFO         0x80
+#define FCH_SPI_MMIO_REG50_ADDR32CTRL0  0x50
+#define FCH_SPI_MMIO_REG5C_ADDR32CTRL3  0x5C
+
+volatile UINTN        mFchSpiProtect_LOCKED_ReadyToBoot = FALSE;
+volatile UINTN        mSpiMmioBase;
+extern CONST BOOLEAN  gInSmm;
+volatile BOOLEAN      mSupport4ByteAddrFlag = FALSE;
+
+STATIC
+EFI_STATUS
+WaitForSpiDeviceWriteEnabled (
+  IN  EFI_SPI_PROTOCOL  *This
+  );
+
+/**
+
+  Initialize an SPI protocol instance.
+  The function will assert in debug if FCH SPI has not been initialized
+
+  @param SpiInstance   - Pointer to SpiInstance to initialize
+
+  @retval EFI_SUCCESS     The protocol instance was properly initialized
+  @retval EFI_UNSUPPORTED The FCH is not supported by this module
+
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+  SPI_INSTANCE  *SpiInstance
+  )
+{
+  DEBUG ((DEBUG_INFO, "SpiProtocolConstructor enter!\n"));
+
+  SpiInstance->InitDone = FALSE;  // Indicate NOT READY.
+  //
+  // Initialize the SPI protocol instance
+  //
+  SpiInstance->Signature           = FCH_SPI_PRIVATE_DATA_SIGNATURE;
+  SpiInstance->Handle              = NULL;
+  SpiInstance->SpiProtocol.Init    = SpiProtocolInit;
+  SpiInstance->SpiProtocol.Lock    = SpiProtocolLock;
+  SpiInstance->SpiProtocol.Execute = SpiProtocolExecute;
+
+  //
+  // Sanity check to ensure FCH SPI initialization has occurred previously.
+  //
+  SpiInstance->SpiBar = (EFI_PHYSICAL_ADDRESS)PciRead32 (
+                                                PCI_LIB_ADDRESS (
+                                                  0,
+                                                  20,
+                                                  3,
+                                                  0xA0
+                                                  )
+                                                )&0x00000000FFFFFFE0;
+  ASSERT (SpiInstance->SpiBar != 0);
+  mSpiMmioBase = SpiInstance->SpiBar;
+
+  DEBUG ((DEBUG_VERBOSE, "SpiInstance->SpiBar = 0x%x\n", SpiInstance->SpiBar));
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Initialize the host controller to execute SPI command.
+
+  @param This                    Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Initialization completed.
+  @retval EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
+  @retval EFI_INVALID_PARAMETER   Bad input parameters.
+  @retval EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+{
+  EFI_STATUS    Status;
+  SPI_INSTANCE  *SpiInstance;
+  UINT8         FlashPartId[3];
+  UINT8         FlashIndex;
+
+  DEBUG ((DEBUG_INFO, "SpiProtocolInit enter!\n"));
+
+  SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  CopyMem (&SpiInstance->SpiInitTable, &mSpiInitTable[0], sizeof (SPI_INIT_TABLE));
+
+  Status = SpiProtocolExecute (
+             This,
+             SPI_OPCODE_JEDEC_ID_INDEX,
+             0,
+             TRUE,
+             TRUE,
+             FALSE,
+             (UINTN)0,
+             3,
+             FlashPartId,
+             EnumSpiRegionDescriptor
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (FlashIndex = 0; FlashIndex < mNumSpiFlashMax; FlashIndex++) {
+    CopyMem (&SpiInstance->SpiInitTable, &mSpiInitTable[FlashIndex], sizeof (SPI_INIT_TABLE));
+
+    if ((FlashPartId[0] != SpiInstance->SpiInitTable.VendorId) ||
+        (FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0) ||
+        (FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1))
+    {
+      DEBUG ((
+        DEBUG_INFO,
+        "SpiProtocolInit()   Target SPI Flash Device [VendorID 0x%02x, DeviceID 0x%02x%02x]  ",
+        FlashPartId[0],
+        FlashPartId[1],
+        FlashPartId[2]
+        ));
+      DEBUG ((
+        DEBUG_INFO,
+        "but Current SPI Flash device [VendorId 0x%02x, DeviceID 0x%02x%02x]!\n",
+        SpiInstance->SpiInitTable.VendorId,
+        SpiInstance->SpiInitTable.DeviceId0,
+        SpiInstance->SpiInitTable.DeviceId1
+        )
+        );
+    } else {
+      DEBUG ((
+        DEBUG_INFO,
+        "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+        FlashPartId[0],
+        FlashPartId[1],
+        FlashPartId[2]
+        ));
+      break;
+    }
+  }
+
+  if (FlashIndex >= mNumSpiFlashMax) {
+    Status = EFI_UNSUPPORTED;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+      FlashPartId[0],
+      FlashPartId[1],
+      FlashPartId[2]
+      ));
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  SpiInstance->InitDone = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Lock the SPI Static Configuration Interface.
+  Once locked, the interface can not be changed and can only be clear by system reset.
+
+  @param This      Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Lock operation succeed.
+  @retval EFI_DEVICE_ERROR        Device error, operation failed.
+  @retval EFI_ACCESS_DENIED       The interface has already been locked.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolLock (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+{
+  if (gInSmm) {
+    // Trigger FCH SPI Protect/Lock
+    if (EFI_SUCCESS == FchSpiProtect_Lock (mSpiMmioBase)) {
+      mFchSpiProtect_LOCKED_ReadyToBoot = TRUE;
+      DEBUG ((DEBUG_INFO, "Set FchSpiProtect to LOCK SUCCESS! \n"));
+    } else {
+      DEBUG ((DEBUG_INFO, "Set FchSpiProtect to LOCK FAILED!!! \n"));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Execute SPI commands from the host controller.
+  This function would be called by runtime driver, please do not use any MMIO marco here
+
+  @param This              Pointer to the EFI_SPI_PROTOCOL instance.
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                    Region, this value specifies the offset from the Region Base; for BIOS Region,
+                    this value specifies the offset from the start of the BIOS Image. In Non
+                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                    the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                    data transfer into multiple operations. This function ensures each operation does
+                    not cross 256 byte flash address boundary.
+                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                    function to cut the data transfer at proper address boundaries, and it's the
+                    caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Pointer to caller-allocated buffer containing the dada received or sent during the
+                    SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                    to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_UNSUPPORTED         Command not supported.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       SpiStatus;
+
+  //
+  // Check if the parameters are valid.
+  //
+  if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (gInSmm) {
+    if (mFchSpiProtect_LOCKED_ReadyToBoot) {
+      FchSpiProtect_UnLock (mSpiMmioBase);
+      DEBUG ((DEBUG_INFO, "FchSpiProtect UnLock!\n"));
+    }
+  }
+
+  SendSpiCmd (
+    This,
+    SPI_OPCODE_READ_S_INDEX,
+    0,
+    TRUE,
+    FALSE,
+    FALSE,
+    0,
+    1,
+    &SpiStatus,
+    EnumSpiRegionAll
+    );
+  if ((SpiStatus & 1) != 0) {
+    if ((OpcodeIndex == SPI_OPCODE_ERASE_INDEX) && (ShiftOut == FALSE)) {
+      return EFI_ALREADY_STARTED;
+    }
+
+    DEBUG ((DEBUG_INFO, "SPI Busy, WaitForSpiCycleComplete\n"));
+    WaitForSpiCycleComplete (This);
+  }
+
+  //
+  // Enter 4 bytes address
+  //
+  if (MmioRead8 (mSpiMmioBase+FCH_SPI_MMIO_REG50_ADDR32CTRL0) & BIT0) {
+    DEBUG ((DEBUG_INFO, "Enter 4-Byte address mode\n"));
+    mSupport4ByteAddrFlag = TRUE;
+    Status                = SendSpiCmd (
+                              This,
+                              SPI_COMMAND_Enter_4Byte_Addr_INDEX,
+                              SPI_WREN_INDEX,
+                              FALSE,
+                              TRUE,
+                              FALSE,
+                              0,
+                              0,
+                              NULL,
+                              EnumSpiRegionDescriptor
+                              );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Enter 4-Byte address mode fail\n"));
+      goto Exit;
+    }
+  }
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             OpcodeIndex,
+             PrefixOpcodeIndex,
+             DataCycle,
+             Atomic,
+             ShiftOut,
+             Address,
+             DataByteCount,
+             Buffer,
+             SpiRegionType
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Operate SPI Flash fail\n"));
+    goto Exit;
+  }
+
+  //
+  // Exit 32-bit address
+  //
+  if (mSupport4ByteAddrFlag) {
+    mSupport4ByteAddrFlag = FALSE;
+    Status                = SendSpiCmd (
+                              This,
+                              SPI_COMMAND_Exit_4Byte_Addr_INDEX,
+                              SPI_WREN_INDEX,
+                              FALSE,
+                              TRUE,
+                              FALSE,
+                              0,
+                              0,
+                              NULL,
+                              EnumSpiRegionDescriptor
+                              );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Exit 4-Byte address mode fail\n"));
+      goto Exit;
+    }
+  }
+
+Exit:
+  if (gInSmm) {
+    if (mFchSpiProtect_LOCKED_ReadyToBoot) {
+      FchSpiProtect_Lock (mSpiMmioBase);
+      DEBUG ((DEBUG_INFO, "FchSpiProtect Lock again!\n"));
+    }
+  }
+
+  return Status;
+}
+
+/**
+
+  Waits for SPI device not busy
+
+  @param SpiBar           The SPI Bar Address
+
+  @retval EFI_SUCCESS     Function successfully returned
+  @retval EFI_TIMEOUT     timeout, SPI device busy more than 6s.
+
+**/
+EFI_STATUS
+FchSpiControllerNotBusy (
+  UINTN  SpiBar
+  )
+{
+  volatile  UINT32  SpiStatus;
+  UINT64            WaitTicks;
+  UINT64            WaitCount;
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = WAIT_TIME / WAIT_PERIOD;
+  //
+  // Wait until SPI Conroller Not Busy
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    SpiStatus = MmioRead32 (SpiBar + FCH_SPI_MMIO_REG4C);
+    if (SpiStatus & FCH_SPI_BUSY) {
+      MicroSecondDelay (WAIT_PERIOD);
+    } else {
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_TIMEOUT;
+}
+
+STATIC
+EFI_STATUS
+ResetFifoIndex (
+  SPI_INSTANCE  *SpiInstance
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+
+  This function sends the programmed SPI command to the slave device.
+
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                           Region, this value specifies the offset from the Region Base; for BIOS Region,
+                           this value specifies the offset from the start of the BIOS Image. In Non
+                           Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                           Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                           Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                           supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                           the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                           data transfer into multiple operations. This function ensures each operation does
+                           not cross 256 byte flash address boundary.
+                           *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                           (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                           function to cut the data transfer at proper address boundaries, and it's the
+                           caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Data received or sent during the SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                           EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                           Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                           and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                           to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             SPI command completes successfully.
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+
+**/
+EFI_STATUS
+SendSpiCmd (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+{
+  SPI_INSTANCE           *SpiInstance;
+  UINTN                  SpiBiosSize;
+  UINT32                 SpiDataCount;
+  UINT32                 TxByteCount;
+  UINT32                 RxByteCount;
+  UINTN                  Addr, Retry;
+  INTN                   Index, CountIndex;
+  UINTN                  SpiBar;
+  BOOLEAN                WriteFlag;
+  BOOLEAN                AddressFlag;
+  UINT8                  PrefixOpcode;
+  SPI_OPCODE_MENU_ENTRY  OPCodeMenu;
+  UINT8                  Dummy;
+  UINT8                  AddressByteNum;
+
+  SpiInstance    = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  SpiBiosSize    = SpiInstance->SpiInitTable.BiosSize;
+  OPCodeMenu     = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex];
+  PrefixOpcode   = SpiInstance->SpiInitTable.PrefixOpcode[PrefixOpcodeIndex];
+  SpiBar         = SpiInstance->SpiBar;
+  Dummy          = 0;
+  AddressByteNum = 3;
+
+  AddressFlag  = (OPCodeMenu.Type == EnumSpiOpcodeWrite);
+  WriteFlag    = AddressFlag;
+  AddressFlag |= (OPCodeMenu.Type == EnumSpiOpcodeRead);
+  WriteFlag   |= (OPCodeMenu.Type == EnumSpiOpcodeWriteNoAddr);
+
+  //
+  // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
+  //
+  if (SpiBiosSize == 0) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((DataCycle == FALSE) && (DataByteCount > 0)) {
+    DataByteCount = 0;
+  }
+
+  do {
+    SpiDataCount = DataByteCount;
+    TxByteCount  = 0;
+    RxByteCount  = 0;
+
+    //
+    // Calculate the number of bytes to shift in/out during the SPI data cycle.
+    // Valid settings for the number of bytes duing each data portion of the
+    // FCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+    //
+    if ((Address & 0xFF) == 0) {
+      SpiDataCount = (DataByteCount > 0x100) ? 0x100 : DataByteCount;
+    } else {
+      SpiDataCount = (DataByteCount > ((~Address + 1) & 0xFF)) ? ((~Address + 1) & 0xFF) : DataByteCount;
+    }
+
+    SpiDataCount = (SpiDataCount > 64) ? 64 : SpiDataCount;
+
+    if (Atomic) {
+      Retry = 0;
+      do {
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG45, PrefixOpcode);
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG48_TXBYTECOUNT, 0);
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG4B_RXBYTECOUNT, 0);
+        MmioOr8 (SpiBar + FCH_SPI_MMIO_REG47, FCH_SPI_EXEC_OPCODE);
+        if (EFI_ERROR (FchSpiControllerNotBusy (SpiBar))) {
+          return EFI_DEVICE_ERROR;
+        }
+
+        if (PrefixOpcodeIndex == SPI_WREN_INDEX) {
+          if (WaitForSpiDeviceWriteEnabled (This) == EFI_SUCCESS) {
+            Retry = 0;
+          } else {
+            Retry++;
+            if (Retry >= 3) {
+              return EFI_DEVICE_ERROR;
+            }
+          }
+        }
+      } while (Retry);
+    }
+
+    Index = 0;
+    //
+    // Check Address Mode
+    //
+    if (AddressFlag) {
+      ResetFifoIndex (SpiInstance);
+      Addr = (UINTN)Address;
+      // if not SPI_COMMAND_READ_SFDP and 32bit address
+      if ((OPCodeMenu.Code != SPI_COMMAND_READ_SFDP) && mSupport4ByteAddrFlag) {
+        AddressByteNum = 4;
+        Addr           = Addr | (UINT32)((MmioRead8 (SpiBar+FCH_SPI_MMIO_REG5C_ADDR32CTRL3) & BIT0) << 24);
+      }
+
+      for (CountIndex = 0; CountIndex < AddressByteNum; CountIndex++) {
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, (UINT8)((Addr >> (AddressByteNum - CountIndex - 1) * 8) & 0xff));
+        Index++;
+      }
+
+      TxByteCount += AddressByteNum;
+    }
+
+    if ((OPCodeMenu.Code == SPI_COMMAND_READ_SFDP) || (OPCodeMenu.Code == SPI_COMMAND_RPMC_OP2)) {
+      MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, Dummy);
+      Index++;
+      TxByteCount += 1;
+    }
+
+    if (DataCycle) {
+      //
+      // Check Read/Write Mode
+      //
+      if (WriteFlag) {
+        TxByteCount += SpiDataCount;
+        for (CountIndex = 0; CountIndex < (INTN)(SpiDataCount); CountIndex++) {
+          MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, Buffer[CountIndex]);
+          Index++;
+        }
+      } else {
+        RxByteCount = SpiDataCount;
+      }
+    }
+
+    // Set SPI Command
+    MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG45, OPCodeMenu.Code);
+    MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG48_TXBYTECOUNT, (UINT8)TxByteCount);
+    MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG4B_RXBYTECOUNT, (UINT8)RxByteCount);
+    MmioOr8 (SpiBar + FCH_SPI_MMIO_REG47, FCH_SPI_EXEC_OPCODE);
+    if (EFI_ERROR (FchSpiControllerNotBusy (SpiBar))) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    if (ShiftOut) {
+      Retry = 0;
+      do {
+        if (WaitForSpiCycleComplete (This)) {
+          Retry = 0;
+        } else {
+          Retry++;
+          if (Retry >= FCH_SPI_RETRY_TIMES) {
+            return EFI_DEVICE_ERROR;
+          }
+        }
+      } while (Retry);
+    }
+
+    if (DataCycle && RxByteCount) {
+      //
+      // Reset Fifo Ptr
+      //
+      ResetFifoIndex (SpiInstance);
+
+      for (CountIndex = 0; CountIndex < (INTN)(SpiDataCount); CountIndex++) {
+        Buffer[CountIndex] = MmioRead8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index);
+        Index++;
+      }
+    }
+
+    //
+    // If shifts data in, get data from the SPI data buffer.
+    //
+    Address       += SpiDataCount;
+    Buffer        += SpiDataCount;
+    DataByteCount -= SpiDataCount;
+  } while (DataByteCount > 0);
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Wait execution cycle to complete on the SPI interface. Check both Hardware
+  and Software Sequencing status registers
+
+  @param This   The SPI protocol instance
+
+  @retval TRUE  SPI cycle completed on the interface.
+  @retval FALSE Time out while waiting the SPI cycle to complete.
+             It's not safe to program the next command on the SPI interface.
+
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+  IN     EFI_SPI_PROTOCOL  *This
+  )
+{
+  UINT8   SpiStatus;
+  UINT64  WaitTicks;
+  UINT64  WaitCount;
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = WAIT_TIME / WAIT_PERIOD;
+
+  //
+  // Wait for the SPI cycle to complete.
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    //
+    // Execute Read Status Command
+    //
+    SendSpiCmd (
+      This,
+      SPI_OPCODE_READ_S_INDEX,
+      0,
+      TRUE,
+      FALSE,
+      FALSE,
+      0,
+      1,
+      &SpiStatus,
+      EnumSpiRegionAll
+      );
+
+    if ((SpiStatus & 1) != 0) {
+      MicroSecondDelay (WAIT_PERIOD);
+    } else {
+      return TRUE;
+    }
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "WaitForSpiCycleComplete() Timeout\n"));
+  return FALSE;
+}
+
+/**
+
+  Wait execution cycle to complete on the SPI interface. Check both Hardware
+  and Software Sequencing status registers
+
+  @param This   The SPI protocol instance
+
+  @retval EFI_SUCCESS  SPI cycle completed on the interface.
+  @retval EFI_TIMEOUT  Time out while waiting the SPI cycle to complete.
+             It's not safe to program the next command on the SPI interface.
+
+**/
+STATIC
+EFI_STATUS
+WaitForSpiDeviceWriteEnabled (
+  IN  EFI_SPI_PROTOCOL  *This
+  )
+{
+  UINT8   SpiStatus;
+  UINT64  WaitTicks;
+  UINT64  WaitCount;
+
+  DEBUG ((DEBUG_VERBOSE, "WaitForSpiDeviceWriteEnabled() Enter!\n"));
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = WAIT_TIME / WAIT_PERIOD;
+
+  //
+  // Wait for the SPI cycle to complete.
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    //
+    // Execute Read Status Command
+    //
+    SendSpiCmd (
+      This,
+      SPI_OPCODE_READ_S_INDEX,
+      0,
+      TRUE,
+      FALSE,
+      FALSE,
+      0,
+      1,
+      &SpiStatus,
+      EnumSpiRegionAll
+      );
+
+    if ((SpiStatus & 2) == 0) {
+      MicroSecondDelay (WAIT_PERIOD);
+    } else {
+      DEBUG ((DEBUG_VERBOSE, "WaitForSpiCycleComplete() Exit\n"));
+      return EFI_SUCCESS;
+    }
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "WaitForSpiDeviceWriteEnabled() Exit Timeout !\n"));
+  return EFI_TIMEOUT;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h
new file mode 100644
index 0000000000..b3b23842a3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h
@@ -0,0 +1,24 @@
+/** @file
+  Implements SpiInfo.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_INFO_H__
+#define SPI_INFO_H__
+
+#include <Uefi/UefiBaseType.h>
+#include <Protocol/Spi.h>
+
+#ifdef FCH_SPI_EXEC_OPCODE
+  #undef FCH_SPI_EXEC_OPCODE
+#define FCH_SPI_EXEC_OPCODE  BIT7
+#endif
+
+#define FCH_SPI_MMIO_REG45  0x45             // OpCode Access
+#define FCH_SPI_MMIO_REG47  0x47             // Execute Access
+#define FCH_SPI_MMIO_REG4C  0x4C             // SPI Status
+
+#endif
--
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114517): https://edk2.groups.io/g/devel/message/114517
Mute This Topic: https://groups.io/mt/103971415/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-01-26  6:03 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-26  6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
2024-01-26  9:19   ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 04/32] AMD/VanGoghBoard: Check in AgesaPublic pkg Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 05/32]AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
2024-01-26  9:28   ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` Zhai, MingXin (Duke) via groups.io [this message]
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
2024-01-26  9:34   ` Chang, Abner via groups.io
2024-01-26  9:36     ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
2024-01-26  9:37   ` Chang, Abner via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
2024-01-26  6:00 ` [edk2-devel] [PATCH V2 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
2024-01-26  9:48 ` [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240126060050.1725-25-duke.zhai@amd.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox