public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "duke.zhai 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 24/33] AMD/VanGoghBoard: Check in FchSpi module.
Date: Thu, 18 Jan 2024 14:50:37 +0800	[thread overview]
Message-ID: <20240118065046.961-25-duke.zhai@amd.com> (raw)
In-Reply-To: <20240118065046.961-1-duke.zhai@amd.com>

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


BZ #:4640

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       | 172 ++++

 .../Universal/FchSpi/FchSpiRuntimeDxe.h       |  58 ++

 .../Universal/FchSpi/FchSpiRuntimeDxe.inf     |  91 ++

 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.c | 121 +++

 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.h |  41 +

 .../Universal/FchSpi/FchSpiSmm.inf            | 101 +++

 .../VanGoghBoard/Universal/FchSpi/SpiCommon.c | 799 ++++++++++++++++++

 .../VanGoghBoard/Universal/FchSpi/SpiInfo.h   |  26 +

 10 files changed, 1514 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..e12246d5a3

--- /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..f7817838f2

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c

@@ -0,0 +1,172 @@

+/** @file

+  Implements FchSpiRuntimeDxe.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.

+

+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..c63a4b3e31

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h

@@ -0,0 +1,58 @@

+/** @file

+  Implements FchSpiRuntimeDxe.h

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+Header file for the PCH SPI Runtime Driver.

+

+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..00480ff75e

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf

@@ -0,0 +1,91 @@

+## @file

+# Fch Spi Runtime

+#

+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+# This file includes code originally published under the following license.

+## @file

+#    Component description file for the SPI Runtime driver.

+#

+# 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..683d2251df

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c

@@ -0,0 +1,121 @@

+/** @file

+  Implements FchSpiSmm.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+

+PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.

+

+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..5ed9f62914

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h

@@ -0,0 +1,41 @@

+/** @file

+  Implements FchSpiSmm.h

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+Header file for the PCH SPI SMM Driver.

+

+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..2288d35b84

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf

@@ -0,0 +1,101 @@

+## @file

+# Spi smm driver

+#

+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+# This file includes code originally published under the following license.

+## @file

+# Spi smm driver

+#

+# Component description file for the SPI SMM driver.

+#

+# 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..5be5026655

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c

@@ -0,0 +1,799 @@

+/** @file

+  Implements SpiCommon.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.

+

+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..fd51b71c83

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h

@@ -0,0 +1,26 @@

+/** @file

+  Implements SpiInfo.h

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+#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 (#114073): https://edk2.groups.io/g/devel/message/114073
Mute This Topic: https://groups.io/mt/103831196/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-19 14:57 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-18  6:50 [edk2-devel] [PATCH 00/33] Introduce AMD Vangogh platform reference code duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 01/33] AMD/AmdPlatformPkg: Check in AMD S3 logo duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 02/33] AMD/VanGoghBoard: Check in ACPI tables duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update duke.zhai via groups.io
2024-01-23  4:42   ` Chang, Abner via groups.io
2024-01-25  8:25     ` Zhai, MingXin (Duke) via groups.io
2024-01-25 11:45       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 04/33] AMD/VanGoghBoard: Check in AgesaPublic pkg duke.zhai via groups.io
2024-01-23  4:44   ` Chang, Abner via groups.io
2024-01-25  8:17     ` Xing, Eric via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 05/33] AMD/VanGoghBoard: Check in PlatformSecLib duke.zhai via groups.io
2024-01-23  4:46   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 06/33] AMD/VanGoghBoard: Check in AmdIdsExtLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 07/33] AMD/VanGoghBoard: Check in PciPlatform duke.zhai via groups.io
2024-01-23  4:50   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 08/33] AMD/VanGoghBoard: Check in UDKFlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 09/33] AMD/VanGoghBoard: Check in Flash_AB duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 10/33] AMD/VanGoghBoard: Check in FlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 11/33] AMD/VanGoghBoard: Check in FvbServices duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 12/33] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 13/33] AMD/VanGoghBoard: Check in PlatformFlashAccessLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 14/33] AMD/VanGoghBoard: Check in SmbiosLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 15/33] AMD/VanGoghBoard: Check in SpiFlashDeviceLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 16/33] AMD/VanGoghBoard: Check in BaseTscTimerLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 17/33] AMD/VanGoghBoard: Check in Smm access module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 18/33] AMD/VanGoghBoard: Check in PciHostBridge module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 19/33] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 20/33] AMD/VanGoghBoard: Check in FTPM module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 22/33] AMD/VanGoghBoard: Check in Vtf0 duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 23/33] AMD/VanGoghBoard: Check in AcpiPlatform duke.zhai via groups.io
2024-01-18  6:50 ` duke.zhai via groups.io [this message]
2024-01-18  6:50 ` [edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module duke.zhai via groups.io
2024-01-23  6:35   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 26/33] AMD/VanGoghBoard: Check in Smbios platform dxe drivers duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 27/33] AMD/VanGoghBoard: Check in Fsp2WrapperPkg duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 28/33] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module duke.zhai via groups.io
2024-01-23  5:14   ` Chang, Abner via groups.io
2024-01-23 10:20     ` Xing, Eric via groups.io
2024-01-23 10:44       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 29/33] AMD/VanGoghBoard: Check in SmramSaveState module duke.zhai via groups.io
2024-01-20 14:37   ` Abdul Lateef Attar via groups.io
2024-01-23  5:15     ` Chang, Abner via groups.io
2024-01-23 10:27       ` Xing, Eric via groups.io
2024-01-23 10:44         ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 30/33] AMD/VanGoghBoard: Check in EDK2 override files duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 31/33] AMD/VanGoghBoard: Check in AMD SmmControlPei module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 32/33] AMD/VanGoghBoard: Check in Chachani board project files and build script duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 33/33] AMD/VanGoghBoard: Improvement coding style duke.zhai 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=20240118065046.961-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