public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chesley, Brit via groups.io" <brit.chesley=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Abner Chang <abner.chang@amd.com>,
	Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
Subject: [edk2-devel] [PATCH 1/5] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus Drivers
Date: Tue, 30 Apr 2024 09:05:32 -0500	[thread overview]
Message-ID: <20240430140536.4252-2-brit.chesley@amd.com> (raw)
In-Reply-To: <20240430140536.4252-1-brit.chesley@amd.com>

From: Brit Chesley <brit.chesley@amd.com>

Added SpiBus DXE and SMM drivers. This code translates SPI requests from
the application layer into SPI Bus transactions on the SPI host
controller. The code is responsible for checking if the transaction is
valid, then setting up the SPI clock and chip select properly before
passing the bus transaction to the host controller.

Platform Initialization Spec 1.7 volume 5 section 18.1.6

Bugzilla #4753

Cc: Abner Chang <abner.chang@amd.com>
Cc: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
Signed-off-by: Brit Chesley <brit.chesley@amd.com>
---
 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf |  42 +++
 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf |  42 +++
 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h      | 167 +++++++++
 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c      | 433 ++++++++++++++++++++++
 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c   | 198 ++++++++++
 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c   | 162 ++++++++
 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni    |  10 +
 7 files changed, 1054 insertions(+)
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c
 create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni

diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
new file mode 100644
index 000000000000..992135a76ee6
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
@@ -0,0 +1,42 @@
+#/** @file
+#
+#  Component description for the SPI BUS DXE module
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+[Defines]
+  INF_VERSION               = 1.27
+  BASE_NAME                 = SpiBusDxe
+  FILE_GUID                 = 25CE038C-5C3A-4A9B-A111-90DF5897E058
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 0.1
+  PI_SPECIFICATION_VERSION  = 0x0001000A
+  ENTRY_POINT               = SpiBusEntry
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Sources]
+  SpiBusDxe.c
+  SpiBus.c
+  SpiBus.h
+
+[Protocols]
+  gEfiSpiConfigurationProtocolGuid              ## CONSUMES
+  gEfiSpiHcProtocolGuid                         ## CONSUMES
+
+[Depex]
+  gEfiSpiConfigurationProtocolGuid AND
+  gEfiSpiHcProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SpiBus.uni
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
new file mode 100644
index 000000000000..56ce87e9296a
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
@@ -0,0 +1,42 @@
+#/** @file
+#
+#  Component description for the SPI BUS SMM module
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+[Defines]
+  INF_VERSION               = 1.27
+  BASE_NAME                 = SpiBusSmm
+  FILE_GUID                 = 5DBB52E1-3D78-4C9C-A9D7-A43E79E93AC0
+  MODULE_TYPE               = DXE_SMM_DRIVER
+  VERSION_STRING            = 0.1
+  PI_SPECIFICATION_VERSION  = 0x0001000A
+  ENTRY_POINT               = SpiBusEntry
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  MmServicesTableLib
+  UefiDriverEntryPoint
+
+[Sources]
+  SpiBus.h
+  SpiBus.c
+  SpiBusSmm.c
+
+[Protocols]
+  gEfiSpiSmmConfigurationProtocolGuid                           ## CONSUMES
+  gEfiSpiSmmHcProtocolGuid                                      ## CONSUMES
+
+[Depex]
+  gEfiSpiSmmConfigurationProtocolGuid AND
+  gEfiSpiSmmHcProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SpiBus.uni
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h
new file mode 100644
index 000000000000..7a43f66ac750
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h
@@ -0,0 +1,167 @@
+/** @file
+
+  SPI bus driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_BUS_H_
+#define SPI_BUS_H_
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Protocol/DevicePath.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/SpiIo.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiConfiguration.h>
+
+#define SPI_IO_SIGNATURE  SIGNATURE_32 ('s', 'i', 'o', 'c')
+
+typedef struct {
+  UINTN                             Signature;
+  EFI_HANDLE                        Handle;
+  EFI_SPI_IO_PROTOCOL               Protocol;
+  EFI_SPI_BUS_TRANSACTION           BusTransaction;
+  EFI_SPI_CONFIGURATION_PROTOCOL    *SpiConfig;
+  EFI_SPI_HC_PROTOCOL               *SpiHc;
+  EFI_SPI_BUS                       *SpiBus;
+} SPI_IO_CHIP;
+
+#define SPI_IO_CHIP_FROM_THIS(a) \
+  CR (a, SPI_IO_CHIP, Protocol, \
+      SPI_IO_SIGNATURE)
+
+/**
+  Checks if two device paths are the same
+
+  @param[in] DevicePath1        First device path to compare
+  @param[in] DevicePath2        Second device path to compare
+
+  @retval TRUE              The device paths share the same nodes and values
+  @retval FALSE             The device paths differ
+**/
+BOOLEAN
+EFIAPI
+DevicePathsAreEqual (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath1,
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath2
+  );
+
+/**
+  Initiate a SPI transaction between the host and a SPI peripheral.
+
+  This routine must be called at or below TPL_NOTIFY.
+  This routine works with the SPI bus layer to pass the SPI transaction to the
+  SPI controller for execution on the SPI bus. There are four types of
+  supported transactions supported by this routine:
+  * Full Duplex: WriteBuffer and ReadBuffer are the same size.
+  * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0
+  * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0
+  * Write Then Read: WriteBuffer contains control data to write to SPI
+                     peripheral before data is placed into the ReadBuffer.
+                     Both WriteBytes and ReadBytes must be non-zero.
+
+  @param[in]  This              Pointer to an EFI_SPI_IO_PROTOCOL structure.
+  @param[in]  TransactionType   Type of SPI transaction.
+  @param[in]  DebugTransaction  Set TRUE only when debugging is desired.
+                                Debugging may be turned on for a single SPI
+                                transaction. Only this transaction will display
+                                debugging messages. All other transactions with
+                                this value set to FALSE will not display any
+                                debugging messages.
+  @param[in]  ClockHz           Specify the ClockHz value as zero (0) to use
+                                the maximum clock frequency supported by the
+                                SPI controller and part. Specify a non-zero
+                                value only when a specific SPI transaction
+                                requires a reduced clock rate.
+  @param[in]  BusWidth          Width of the SPI bus in bits: 1, 2, 4
+  @param[in]  FrameSize         Frame size in bits, range: 1 - 32
+  @param[in]  WriteBytes        The length of the WriteBuffer in bytes.
+                                Specify zero for read-only operations.
+  @param[in]  WriteBuffer       The buffer containing data to be sent from the
+                                host to the SPI chip. Specify NULL for read
+                                only operations.
+                                * Frame sizes 1-8 bits: UINT8 (one byte) per
+                                  frame
+                                * Frame sizes 7-16 bits: UINT16 (two bytes) per
+                                  frame
+                                * Frame sizes 17-32 bits: UINT32 (four bytes)
+                                  per frame The transmit frame is in the least
+                                  significant N bits.
+  @param[in]  ReadBytes         The length of the ReadBuffer in bytes.
+                                Specify zero for write-only operations.
+  @param[out] ReadBuffer        The buffer to receeive data from the SPI chip
+                                during the transaction. Specify NULL for write
+                                only operations.
+                                * Frame sizes 1-8 bits: UINT8 (one byte) per
+                                  frame
+                                * Frame sizes 7-16 bits: UINT16 (two bytes) per
+                                  frame
+                                * Frame sizes 17-32 bits: UINT32 (four bytes)
+                                  per frame The received frame is in the least
+                                  significant N bits.
+
+  @retval EFI_SUCCESS            The SPI transaction completed successfully
+  @retval EFI_BAD_BUFFER_SIZE    The writeBytes value was invalid
+  @retval EFI_BAD_BUFFER_SIZE    The ReadBytes value was invalid
+  @retval EFI_INVALID_PARAMETER  TransactionType is not valid,
+                                 or BusWidth not supported by SPI peripheral or
+                                 SPI host controller,
+                                 or WriteBytes non-zero and WriteBuffer is
+                                 NULL,
+                                 or ReadBytes non-zero and ReadBuffer is NULL,
+                                 or ReadBuffer != WriteBuffer for full-duplex
+                                 type,
+                                 or WriteBuffer was NULL,
+                                 or TPL is too high
+  @retval EFI_OUT_OF_RESOURCES   Insufficient memory for SPI transaction
+  @retval EFI_UNSUPPORTED        The FrameSize is not supported by the SPI bus
+                                 layer or the SPI host controller
+  @retval EFI_UNSUPPORTED        The SPI controller was not able to support
+
+**/
+EFI_STATUS
+EFIAPI
+Transaction (
+  IN  CONST EFI_SPI_IO_PROTOCOL  *This,
+  IN  EFI_SPI_TRANSACTION_TYPE   TransactionType,
+  IN  BOOLEAN                    DebugTransaction,
+  IN  UINT32                     ClockHz OPTIONAL,
+  IN  UINT32                     BusWidth,
+  IN  UINT32                     FrameSize,
+  IN  UINT32                     WriteBytes,
+  IN  UINT8                      *WriteBuffer,
+  IN  UINT32                     ReadBytes,
+  OUT UINT8                      *ReadBuffer
+  );
+
+/**
+  Update the SPI peripheral associated with this SPI 10 instance.
+
+  Support socketed SPI parts by allowing the SPI peripheral driver to replace
+  the SPI peripheral after the connection is made. An example use is socketed
+  SPI NOR flash parts, where the size and parameters change depending upon
+  device is in the socket.
+
+  @param[in] This           Pointer to an EFI_SPI_IO_PROTOCOL structure.
+  @param[in] SpiPeripheral  Pointer to an EFI_SPI_PERIPHERAL structure.
+
+  @retval EFI_SUCCESS            The SPI peripheral was updated successfully
+  @retval EFI_INVALID_PARAMETER  The SpiPeripheral value is NULL,
+                                 or the SpiPeripheral->SpiBus is NULL,
+                                 or the SpiPeripheral->SpiBus pointing at
+                                 wrong bus, or the SpiPeripheral->SpiPart is NULL
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateSpiPeripheral (
+  IN CONST EFI_SPI_IO_PROTOCOL  *This,
+  IN CONST EFI_SPI_PERIPHERAL   *SpiPeripheral
+  );
+
+#endif //SPI_BUS_H_
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
new file mode 100644
index 000000000000..63a762dff1a1
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
@@ -0,0 +1,433 @@
+/** @file
+
+  SpiBus driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/SpiConfiguration.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiIo.h>
+#include "SpiBus.h"
+
+/**
+  Checks if two device paths are the same
+
+  @param[in] DevicePath1        First device path to compare
+  @param[in] DevicePath2        Second device path to compare
+
+  @retval TRUE              The device paths share the same nodes and values
+  @retval FALSE             The device paths differ
+**/
+BOOLEAN
+EFIAPI
+DevicePathsAreEqual (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath1,
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath2
+  )
+{
+  UINTN  Size1;
+  UINTN  Size2;
+
+  Size1 = GetDevicePathSize (DevicePath1);
+  Size2 = GetDevicePathSize (DevicePath2);
+
+  if (Size1 != Size2) {
+    return FALSE;
+  }
+
+  if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Calls the SpiPeripherals ChipSelect if it is not null, otherwise
+  calls the Host Controllers ChipSelect function
+
+  @param[in] SpiChip        The SpiChip to place on the bus via asserting its chip select
+  @param[in] PinValue       Value to place on the chip select pin
+
+  @retval EFI_SUCCESS                 Chip select pin was placed at requested level
+  @retval EFI_INVALID_PARAMETER       Invalid parameters passed into ChipSelect function
+**/
+EFI_STATUS
+EFIAPI
+SpiChipSelect (
+  IN CONST SPI_IO_CHIP  *SpiChip,
+  IN BOOLEAN            PinValue
+  )
+{
+  EFI_STATUS  Status;
+
+  // Check which chip select function to use
+  if (SpiChip->Protocol.SpiPeripheral->ChipSelect != NULL) {
+    Status = SpiChip->Protocol.SpiPeripheral->ChipSelect (
+                                                SpiChip->BusTransaction.SpiPeripheral,
+                                                PinValue
+                                                );
+  } else {
+    Status = SpiChip->SpiHc->ChipSelect (
+                               SpiChip->SpiHc,
+                               SpiChip->BusTransaction.SpiPeripheral,
+                               PinValue
+                               );
+  }
+
+  return Status;
+}
+
+/**
+  Checks the SpiChip's BusTransaction attributes to ensure its a valid SPI transaction
+
+  @param[in] SpiChip        The SpiChip where a bus transaction is requested
+
+  @retval EFI_SUCCESS            This is a valid SPI bus transaction
+  @retval EFI_BAD_BUFFER_SIZE    The WriteBytes value was invalid
+  @retval EFI_BAD_BUFFER_SIZE    The ReadBytes value was invalid
+  @retval EFI_INVALID_PARAMETER  TransactionType is not valid,
+                                 or BusWidth not supported by SPI peripheral or
+                                 SPI host controller,
+                                 or WriteBytes non-zero and WriteBuffer is
+                                 NULL,
+                                 or ReadBytes non-zero and ReadBuffer is NULL,
+                                 or ReadBuffer != WriteBuffer for full-duplex
+                                 type,
+                                 or WriteBuffer was NULL,
+                                 or TPL is too high
+  @retval EFI_OUT_OF_RESOURCES   Insufficient memory for SPI transaction
+  @retval EFI_UNSUPPORTED        The FrameSize is not supported by the SPI bus
+                                 layer or the SPI host controller
+  @retval EFI_UNSUPPORTED        The SPI controller was not able to support
+**/
+EFI_STATUS
+EFIAPI
+IsValidSpiTransaction (
+  IN SPI_IO_CHIP  *SpiChip
+  )
+{
+  // Error checking
+  if (SpiChip->BusTransaction.TransactionType > SPI_TRANSACTION_WRITE_THEN_READ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((SpiChip->BusTransaction.BusWidth != 1) && (SpiChip->BusTransaction.BusWidth != 2) && (SpiChip->BusTransaction.BusWidth != 4) &&
+       (SpiChip->BusTransaction.BusWidth != 8)) || (SpiChip->BusTransaction.FrameSize == 0))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((SpiChip->BusTransaction.BusWidth == 8) && (((SpiChip->Protocol.Attributes & SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) ||
+                                                  ((SpiChip->BusTransaction.SpiPeripheral->Attributes & SPl_PART_SUPPORTS_8_B1T_DATA_BUS_WIDTH) != SPl_PART_SUPPORTS_8_B1T_DATA_BUS_WIDTH)))
+  {
+    return EFI_INVALID_PARAMETER;
+  } else if ((SpiChip->BusTransaction.BusWidth == 4) && (((SpiChip->Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) ||
+                                                         ((SpiChip->BusTransaction.SpiPeripheral->Attributes & SPl_PART_SUPPORTS_4_B1T_DATA_BUS_WIDTH) != SPl_PART_SUPPORTS_4_B1T_DATA_BUS_WIDTH)))
+  {
+    return EFI_INVALID_PARAMETER;
+  } else if ((SpiChip->BusTransaction.BusWidth == 2) && (((SpiChip->Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) ||
+                                                         ((SpiChip->BusTransaction.SpiPeripheral->Attributes & SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH)))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((SpiChip->BusTransaction.WriteBytes > 0) && (SpiChip->BusTransaction.WriteBuffer == NULL)) || ((SpiChip->BusTransaction.ReadBytes > 0) && (SpiChip->BusTransaction.ReadBuffer == NULL))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((SpiChip->BusTransaction.TransactionType == SPI_TRANSACTION_FULL_DUPLEX) &&  (SpiChip->BusTransaction.ReadBytes != SpiChip->BusTransaction.WriteBytes)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check frame size, passed parameter is in bits
+  if ((SpiChip->Protocol.FrameSizeSupportMask & (1<<(SpiChip->BusTransaction.FrameSize-1))) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initiate a SPI transaction between the host and a SPI peripheral.
+
+  This routine must be called at or below TPL_NOTIFY.
+  This routine works with the SPI bus layer to pass the SPI transaction to the
+  SPI controller for execution on the SPI bus. There are four types of
+  supported transactions supported by this routine:
+  * Full Duplex: WriteBuffer and ReadBuffer are the same size.
+  * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0
+  * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0
+  * Write Then Read: WriteBuffer contains control data to write to SPI
+                     peripheral before data is placed into the ReadBuffer.
+                     Both WriteBytes and ReadBytes must be non-zero.
+
+  @param[in]  This              Pointer to an EFI_SPI_IO_PROTOCOL structure.
+  @param[in]  TransactionType   Type of SPI transaction.
+  @param[in]  DebugTransaction  Set TRUE only when debugging is desired.
+                                Debugging may be turned on for a single SPI
+                                transaction. Only this transaction will display
+                                debugging messages. All other transactions with
+                                this value set to FALSE will not display any
+                                debugging messages.
+  @param[in]  ClockHz           Specify the ClockHz value as zero (0) to use
+                                the maximum clock frequency supported by the
+                                SPI controller and part. Specify a non-zero
+                                value only when a specific SPI transaction
+                                requires a reduced clock rate.
+  @param[in]  BusWidth          Width of the SPI bus in bits: 1, 2, 4
+  @param[in]  FrameSize         Frame size in bits, range: 1 - 32
+  @param[in]  WriteBytes        The length of the WriteBuffer in bytes.
+                                Specify zero for read-only operations.
+  @param[in]  WriteBuffer       The buffer containing data to be sent from the
+                                host to the SPI chip. Specify NULL for read
+                                only operations.
+                                * Frame sizes 1-8 bits: UINT8 (one byte) per
+                                  frame
+                                * Frame sizes 7-16 bits: UINT16 (two bytes) per
+                                  frame
+                                * Frame sizes 17-32 bits: UINT32 (four bytes)
+                                  per frame The transmit frame is in the least
+                                  significant N bits.
+  @param[in]  ReadBytes         The length of the ReadBuffer in bytes.
+                                Specify zero for write-only operations.
+  @param[out] ReadBuffer        The buffer to receeive data from the SPI chip
+                                during the transaction. Specify NULL for write
+                                only operations.
+                                * Frame sizes 1-8 bits: UINT8 (one byte) per
+                                  frame
+                                * Frame sizes 7-16 bits: UINT16 (two bytes) per
+                                  frame
+                                * Frame sizes 17-32 bits: UINT32 (four bytes)
+                                  per frame The received frame is in the least
+                                  significant N bits.
+
+  @retval EFI_SUCCESS            The SPI transaction completed successfully
+  @retval EFI_BAD_BUFFER_SIZE    The WriteBytes value was invalid
+  @retval EFI_BAD_BUFFER_SIZE    The ReadBytes value was invalid
+  @retval EFI_INVALID_PARAMETER  TransactionType is not valid,
+                                 or BusWidth not supported by SPI peripheral or
+                                 SPI host controller,
+                                 or WriteBytes non-zero and WriteBuffer is
+                                 NULL,
+                                 or ReadBytes non-zero and ReadBuffer is NULL,
+                                 or ReadBuffer != WriteBuffer for full-duplex
+                                 type,
+                                 or WriteBuffer was NULL,
+                                 or TPL is too high
+  @retval EFI_OUT_OF_RESOURCES   Insufficient memory for SPI transaction
+  @retval EFI_UNSUPPORTED        The FrameSize is not supported by the SPI bus
+                                 layer or the SPI host controller
+  @retval EFI_UNSUPPORTED        The SPI controller was not able to support
+
+**/
+EFI_STATUS
+EFIAPI
+Transaction (
+  IN  CONST EFI_SPI_IO_PROTOCOL  *This,
+  IN  EFI_SPI_TRANSACTION_TYPE   TransactionType,
+  IN  BOOLEAN                    DebugTransaction,
+  IN  UINT32                     ClockHz OPTIONAL,
+  IN  UINT32                     BusWidth,
+  IN  UINT32                     FrameSize,
+  IN  UINT32                     WriteBytes,
+  IN  UINT8                      *WriteBuffer,
+  IN  UINT32                     ReadBytes,
+  OUT UINT8                      *ReadBuffer
+  )
+{
+  EFI_STATUS   Status;
+  SPI_IO_CHIP  *SpiChip;
+  UINT32       MaxClockHz;
+  UINT8        *DummyReadBuffer;
+  UINT8        *DummyWriteBuffer;
+
+  SpiChip                               = SPI_IO_CHIP_FROM_THIS (This);
+  SpiChip->BusTransaction.SpiPeripheral =
+    (EFI_SPI_PERIPHERAL *)SpiChip->Protocol.SpiPeripheral;
+  SpiChip->BusTransaction.TransactionType  = TransactionType;
+  SpiChip->BusTransaction.DebugTransaction = DebugTransaction;
+  SpiChip->BusTransaction.BusWidth         = BusWidth;
+  SpiChip->BusTransaction.FrameSize        = FrameSize;
+  SpiChip->BusTransaction.WriteBytes       = WriteBytes;
+  SpiChip->BusTransaction.WriteBuffer      = WriteBuffer;
+  SpiChip->BusTransaction.ReadBytes        = ReadBytes;
+  SpiChip->BusTransaction.ReadBuffer       = ReadBuffer;
+
+  // Ensure valid spi transaction parameters
+  Status = IsValidSpiTransaction (SpiChip);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Setup the proper clock frequency
+  if (SpiChip->BusTransaction.SpiPeripheral->MaxClockHz != 0) {
+    MaxClockHz = SpiChip->BusTransaction.SpiPeripheral->MaxClockHz;
+  } else {
+    MaxClockHz = SpiChip->BusTransaction.SpiPeripheral->SpiPart->MaxClockHz;
+  }
+
+  // Call proper clock function
+  if (SpiChip->Protocol.SpiPeripheral->SpiBus->Clock != NULL) {
+    Status = SpiChip->Protocol.SpiPeripheral->SpiBus->Clock (
+                                                        SpiChip->BusTransaction.SpiPeripheral,
+                                                        &MaxClockHz
+                                                        );
+  } else {
+    Status = SpiChip->SpiHc->Clock (
+                               SpiChip->SpiHc,
+                               SpiChip->BusTransaction.SpiPeripheral,
+                               &MaxClockHz
+                               );
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = SpiChipSelect (SpiChip, SpiChip->BusTransaction.SpiPeripheral->SpiPart->ChipSelectPolarity);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Check transaction types and match to HC capabilities
+  if ((TransactionType == SPI_TRANSACTION_WRITE_ONLY) &&
+      ((SpiChip->SpiHc->Attributes & HC_SUPPORTS_WRITE_ONLY_OPERATIONS) != HC_SUPPORTS_WRITE_ONLY_OPERATIONS))
+  {
+    // Convert to full duplex transaction
+    SpiChip->BusTransaction.ReadBytes  = SpiChip->BusTransaction.WriteBytes;
+    SpiChip->BusTransaction.ReadBuffer = AllocateZeroPool (SpiChip->BusTransaction.ReadBytes);
+
+    Status = SpiChip->SpiHc->Transaction (
+                               SpiChip->SpiHc,
+                               &SpiChip->BusTransaction
+                               );
+
+    SpiChip->BusTransaction.ReadBytes = ReadBytes; // assign to passed parameter
+    FreePool (SpiChip->BusTransaction.ReadBuffer); // Free temporary buffer
+  } else if ((TransactionType == SPI_TRANSACTION_READ_ONLY) &&
+             ((SpiChip->SpiHc->Attributes & HC_SUPPORTS_READ_ONLY_OPERATIONS) != HC_SUPPORTS_READ_ONLY_OPERATIONS))
+  {
+    // Convert to full duplex transaction
+    SpiChip->BusTransaction.WriteBytes  = SpiChip->BusTransaction.WriteBytes;
+    SpiChip->BusTransaction.WriteBuffer = AllocateZeroPool (SpiChip->BusTransaction.WriteBytes);
+
+    Status = SpiChip->SpiHc->Transaction (
+                               SpiChip->SpiHc,
+                               &SpiChip->BusTransaction
+                               );
+
+    SpiChip->BusTransaction.WriteBytes = WriteBytes;
+    FreePool (SpiChip->BusTransaction.WriteBuffer);
+  } else if ((TransactionType == SPI_TRANSACTION_WRITE_THEN_READ) &&
+             ((SpiChip->SpiHc->Attributes & HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS) != HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS))
+  {
+    // Convert to full duplex transaction
+    DummyReadBuffer                    = AllocateZeroPool (WriteBytes);
+    DummyWriteBuffer                   = AllocateZeroPool (ReadBytes);
+    SpiChip->BusTransaction.ReadBuffer = DummyReadBuffer;
+    SpiChip->BusTransaction.ReadBytes  = WriteBytes;
+
+    Status = SpiChip->SpiHc->Transaction (
+                               SpiChip->SpiHc,
+                               &SpiChip->BusTransaction
+                               );
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    // Write is done, now need to read, restore passed in read buffer info
+    SpiChip->BusTransaction.ReadBuffer = ReadBuffer;
+    SpiChip->BusTransaction.ReadBytes  = ReadBytes;
+
+    SpiChip->BusTransaction.WriteBuffer = DummyWriteBuffer;
+    SpiChip->BusTransaction.WriteBytes  = ReadBytes;
+
+    Status = SpiChip->SpiHc->Transaction (
+                               SpiChip->SpiHc,
+                               &SpiChip->BusTransaction
+                               );
+    // Restore write data
+    SpiChip->BusTransaction.WriteBuffer = WriteBuffer;
+    SpiChip->BusTransaction.WriteBytes  = WriteBytes;
+
+    FreePool (DummyReadBuffer);
+    FreePool (DummyWriteBuffer);
+  } else {
+    // Supported transaction type, just pass info the SPI HC Protocol Transaction
+    Status = SpiChip->SpiHc->Transaction (
+                               SpiChip->SpiHc,
+                               &SpiChip->BusTransaction
+                               );
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = SpiChipSelect (SpiChip, !SpiChip->BusTransaction.SpiPeripheral->SpiPart->ChipSelectPolarity);
+
+  return Status;
+}
+
+/**
+  Update the SPI peripheral associated with this SPI 10 SpiChip.
+
+  Support socketed SPI parts by allowing the SPI peripheral driver to replace
+  the SPI peripheral after the connection is made. An example use is socketed
+  SPI NOR flash parts, where the size and parameters change depending upon
+  device is in the socket.
+
+  @param[in] This           Pointer to an EFI_SPI_IO_PROTOCOL structure.
+  @param[in] SpiPeripheral  Pointer to an EFI_SPI_PERIPHERAL structure.
+
+  @retval EFI_SUCCESS            The SPI peripheral was updated successfully
+  @retval EFI_INVALID_PARAMETER  The SpiPeripheral value is NULL,
+                                 or the SpiPeripheral->SpiBus is NULL,
+                                 or the SpiPeripheral->SpiBus pointing at
+                                 wrong bus, or the SpiPeripheral->SpiPart is NULL
+**/
+EFI_STATUS
+EFIAPI
+UpdateSpiPeripheral (
+  IN CONST EFI_SPI_IO_PROTOCOL  *This,
+  IN CONST EFI_SPI_PERIPHERAL   *SpiPeripheral
+  )
+{
+  EFI_STATUS   Status;
+  SPI_IO_CHIP  *SpiChip;
+
+  DEBUG ((DEBUG_VERBOSE, "%a: SPI Bus - Entry\n", __func__));
+
+  SpiChip = SPI_IO_CHIP_FROM_THIS (This);
+
+  if ((SpiPeripheral == NULL) || (SpiPeripheral->SpiBus == NULL) ||
+      (SpiPeripheral->SpiPart == NULL))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // EFI_INVALID_PARAMETER if SpiPeripheral->SpiBus is pointing at wrong bus
+  if (!DevicePathsAreEqual (SpiPeripheral->SpiBus->ControllerPath, SpiChip->SpiBus->ControllerPath)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SpiChip->Protocol.OriginalSpiPeripheral = SpiChip->Protocol.SpiPeripheral;
+  SpiChip->Protocol.SpiPeripheral         = SpiPeripheral;
+
+  Status = EFI_SUCCESS;
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "%a: SPI Bus - Exit Status=%r\n",
+    __func__,
+    Status
+    ));
+  return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
new file mode 100644
index 000000000000..cd0a2c99a27b
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
@@ -0,0 +1,198 @@
+/** @file
+
+  SPI bus DXE driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/SpiConfiguration.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiIo.h>
+#include "SpiBus.h"
+
+/**
+  Entry point of the Spi Bus layer
+
+  @param[in] ImageHandle  Image handle of this driver.
+  @param[in] SystemTable  Pointer to standard EFI system table.
+
+  @retval EFI_SUCCESS           Succeed.
+  @retval EFI_DEVICE_ERROR      SpiPeripheral is NULL.
+  @retval EFI_NOT_FOUND         Fail to locate SpiHcProtocol or SpiIoConfigurationProtocol
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate SpiIoChip
+**/
+EFI_STATUS
+EFIAPI
+SpiBusEntry (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                      Status;
+  SPI_IO_CHIP                     *SpiChip;
+  EFI_SPI_HC_PROTOCOL             *SpiHc;
+  EFI_SPI_CONFIGURATION_PROTOCOL  *SpiConfiguration;
+  EFI_SPI_PERIPHERAL              *SpiPeripheral;
+  EFI_SPI_BUS                     *Bus;
+  UINTN                           BusIndex;
+  UINTN                           HcIndex;
+  EFI_HANDLE                      *SpiHcHandles;
+  UINTN                           HandleCount;
+  EFI_DEVICE_PATH_PROTOCOL        *SpiHcDevicePath;
+
+  DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__));
+
+  // Get all SPI HC protocols, could be multiple SPI HC's on a single platform
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiSpiHcProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &SpiHcHandles
+                  );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n"));
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  // Locate the SPI Configuration Protocol
+  Status = gBS->LocateProtocol (
+                  &gEfiSpiConfigurationProtocolGuid,
+                  NULL,
+                  (VOID **)&SpiConfiguration
+                  );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n"));
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  // Parse through Hc protocols, find correct device path
+  for (HcIndex = 0; HcIndex < HandleCount; HcIndex++) {
+    Status = gBS->HandleProtocol (
+                    SpiHcHandles[HcIndex],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **)&SpiHcDevicePath
+                    );
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_VERBOSE, "Error locating EFI device path for this SPI controller, status=%r \n", Status));
+      continue; // Continue searching
+    }
+
+    // Parse through SpiConfiguration's SpiBuses, find matching devicepath for SpiHc
+    for (BusIndex = 0; BusIndex < SpiConfiguration->BusCount; BusIndex++) {
+      Bus = (EFI_SPI_BUS *)SpiConfiguration->Buslist[BusIndex];
+      if (!DevicePathsAreEqual (SpiHcDevicePath, Bus->ControllerPath)) {
+        DEBUG ((DEBUG_VERBOSE, "SpiHc and SpiConfig device paths dont match, continue parsing\n"));
+        continue;
+      }
+
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "%a: Found matching device paths, Enumerating SPI BUS: %s with DevicePath: %s\n",
+        __func__,
+        Bus->FriendlyName,
+        ConvertDevicePathToText (SpiHcDevicePath, FALSE, FALSE)
+        ));
+
+      // Get SpiHc from the SpiHcHandles
+      Status = gBS->HandleProtocol (
+                      SpiHcHandles[HcIndex],
+                      &gEfiDevicePathProtocolGuid,
+                      (VOID **)&SpiHc
+                      );
+
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", __func__));
+        goto Exit;
+      }
+
+      SpiPeripheral = (EFI_SPI_PERIPHERAL *)Bus->Peripherallist;
+      if (SpiPeripheral != NULL) {
+        do {
+          DEBUG ((
+            DEBUG_VERBOSE,
+            "%a: Installing SPI IO protocol for %s, by %s, PN=%s\n",
+            __func__,
+            SpiPeripheral->FriendlyName,
+            SpiPeripheral->SpiPart->Vendor,
+            SpiPeripheral->SpiPart->PartNumber
+            ));
+          // Allocate the SPI IO Device
+          SpiChip = AllocateZeroPool (sizeof (SPI_IO_CHIP));
+          ASSERT (SpiChip != NULL);
+          if (SpiChip != NULL) {
+            // Fill in the SpiChip
+            SpiChip->Signature                      = SPI_IO_SIGNATURE;
+            SpiChip->SpiConfig                      = SpiConfiguration;
+            SpiChip->SpiHc                          = SpiHc;
+            SpiChip->SpiBus                         = Bus;
+            SpiChip->Protocol.SpiPeripheral         = SpiPeripheral;
+            SpiChip->Protocol.OriginalSpiPeripheral = SpiPeripheral;
+            SpiChip->Protocol.FrameSizeSupportMask  = SpiHc->FrameSizeSupportMask;
+            SpiChip->Protocol.MaximumTransferBytes  = SpiHc->MaximumTransferBytes;
+            if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) != 0) {
+              SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS;
+            }
+
+            if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != 0) {
+              SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE;
+            }
+
+            if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != 0) {
+              SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH;
+            }
+
+            if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != 0) {
+              SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH;
+            }
+
+            if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != 0) {
+              SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH;
+            }
+
+            SpiChip->Protocol.Transaction         = Transaction;
+            SpiChip->Protocol.UpdateSpiPeripheral = UpdateSpiPeripheral;
+            // Install the SPI IO Protocol
+            Status = gBS->InstallProtocolInterface (
+                            &SpiChip->Handle,
+                            (GUID *)SpiPeripheral->SpiPeripheralDriverGuid,
+                            EFI_NATIVE_INTERFACE,
+                            &SpiChip->Protocol
+                            );
+            if (EFI_ERROR (Status)) {
+              DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n", __func__));
+              continue;
+            }
+          } else {
+            Status = EFI_OUT_OF_RESOURCES;
+            DEBUG ((
+              DEBUG_ERROR,
+              "%a: Out of Memory resources\n",
+              __func__
+              ));
+            break;
+          }
+
+          SpiPeripheral = (EFI_SPI_PERIPHERAL *)SpiPeripheral->NextSpiPeripheral;
+        } while (SpiPeripheral != NULL);
+      } else {
+        Status = EFI_DEVICE_ERROR;
+      }
+    }
+  }
+
+Exit:
+  DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status));
+  return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c
new file mode 100644
index 000000000000..d9189b984835
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c
@@ -0,0 +1,162 @@
+/** @file
+
+  SPI bus SMM driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Protocol/SpiSmmConfiguration.h>
+#include <Protocol/SpiSmmHc.h>
+#include <Protocol/SpiIo.h>
+#include "SpiBus.h"
+
+/**
+  Entry point of the Spi Bus layer
+
+  @param[in] ImageHandle  Image handle of this driver.
+  @param[in] SystemTable  Pointer to standard EFI system table.
+
+  @retval EFI_SUCCESS       Succeed.
+  @retval EFI_DEVICE_ERROR  Fail to install EFI_SPI_HC_PROTOCOL protocol.
+  @retval EFI_NOT_FOUND     fail to locate SpiHcProtocol or SpiIoConfigurationProtocol
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate SpiIoChip
+**/
+EFI_STATUS
+EFIAPI
+SpiBusEntry (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                      Status;
+  SPI_IO_CHIP                     *SpiChip;
+  EFI_SPI_HC_PROTOCOL             *SpiHc;
+  EFI_SPI_CONFIGURATION_PROTOCOL  *SpiConfiguration;
+  EFI_SPI_PERIPHERAL              *SpiPeripheral;
+  EFI_SPI_BUS                     *Bus;
+
+  DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__));
+
+  // Only a single Spi HC protocol in SMM
+  Status = gMmst->MmLocateProtocol (
+                    &gEfiSpiSmmHcProtocolGuid,
+                    NULL,
+                    (VOID **)&SpiHc
+                    );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n"));
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  // Locate the SPI Configuration Protocol
+  Status = gMmst->MmLocateProtocol (
+                    &gEfiSpiSmmConfigurationProtocolGuid,
+                    NULL,
+                    (VOID **)&SpiConfiguration
+                    );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n"));
+    Status = EFI_NOT_FOUND;
+    goto Exit;
+  }
+
+  // Only one SpiBus supported in SMM
+  if (SpiConfiguration->BusCount != 1) {
+    DEBUG ((DEBUG_VERBOSE, "Only one SPI Bus supported in SMM\n"));
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  Bus = (EFI_SPI_BUS *)SpiConfiguration->Buslist[0];
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", __func__));
+    goto Exit;
+  }
+
+  SpiPeripheral = (EFI_SPI_PERIPHERAL *)Bus->Peripherallist;
+  if (SpiPeripheral != NULL) {
+    do {
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "%a: Installing SPI IO protocol for %s, by %s, PN=%s\n",
+        __func__,
+        SpiPeripheral->FriendlyName,
+        SpiPeripheral->SpiPart->Vendor,
+        SpiPeripheral->SpiPart->PartNumber
+        ));
+      // Allocate the SPI IO Device
+      SpiChip = AllocateZeroPool (sizeof (SPI_IO_CHIP));
+      ASSERT (SpiChip != NULL);
+      if (SpiChip != NULL) {
+        // Fill in the SpiChip
+        SpiChip->Signature                      = SPI_IO_SIGNATURE;
+        SpiChip->SpiConfig                      = SpiConfiguration;
+        SpiChip->SpiHc                          = SpiHc;
+        SpiChip->SpiBus                         = Bus;
+        SpiChip->Protocol.SpiPeripheral         = SpiPeripheral;
+        SpiChip->Protocol.OriginalSpiPeripheral = SpiPeripheral;
+        SpiChip->Protocol.FrameSizeSupportMask  = SpiHc->FrameSizeSupportMask;
+        SpiChip->Protocol.MaximumTransferBytes  = SpiHc->MaximumTransferBytes;
+        if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) != 0) {
+          SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS;
+        }
+
+        if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != 0) {
+          SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE;
+        }
+
+        if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != 0) {
+          SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH;
+        }
+
+        if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != 0) {
+          SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH;
+        }
+
+        if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != 0) {
+          SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH;
+        }
+
+        SpiChip->Protocol.Transaction         = Transaction;
+        SpiChip->Protocol.UpdateSpiPeripheral = UpdateSpiPeripheral;
+        // Install the SPI IO Protocol
+        Status = gMmst->MmInstallProtocolInterface (
+                          &SpiChip->Handle,
+                          (GUID *)SpiPeripheral->SpiPeripheralDriverGuid,
+                          EFI_NATIVE_INTERFACE,
+                          &SpiChip->Protocol
+                          );
+        if (EFI_ERROR (Status)) {
+          DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n", __func__));
+          continue;
+        }
+      } else {
+        Status = EFI_OUT_OF_RESOURCES;
+        DEBUG ((
+          DEBUG_ERROR,
+          "%a: Out of Memory resources\n",
+          __func__
+          ));
+        break;
+      }
+
+      SpiPeripheral = (EFI_SPI_PERIPHERAL *)SpiPeripheral->NextSpiPeripheral;
+    } while (SpiPeripheral != NULL);
+  } else {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+Exit:
+  DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status));
+  return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni
new file mode 100644
index 000000000000..0d913bdbae39
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni
@@ -0,0 +1,10 @@
+// /** @file
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US   "SPI Bus driver"
-- 
2.42.1



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



  reply	other threads:[~2024-04-30 14:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-30 14:05 [edk2-devel] [PATCH 0/5] SPI Driver Stack Chesley, Brit via groups.io
2024-04-30 14:05 ` Chesley, Brit via groups.io [this message]
2024-04-30 14:05 ` [edk2-devel] [PATCH 2/5] MdeModulePkg: Adding SpiBus Drivers Chesley, Brit via groups.io
2024-04-30 14:05 ` [edk2-devel] [PATCH 3/5] MdeModulePkg:BaseSpiHcPlatformLib: Adding NULL lib instance Chesley, Brit via groups.io
2024-04-30 14:05 ` [edk2-devel] [PATCH 4/5] MdeModulePkg: SpiHc: SpiHc Drivers Chesley, Brit via groups.io
2024-04-30 14:05 ` [edk2-devel] [PATCH 5/5] MdeModulePkg: Adding " Chesley, Brit via groups.io
2024-05-01  9:46 ` [edk2-devel] [PATCH 0/5] SPI Driver Stack 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=20240430140536.4252-2-brit.chesley@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