From: "Chang, Abner via groups.io" <abner.chang=amd.com@groups.io>
To: "Chesley, Brit" <Brit.Chesley@amd.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Attar, AbdulLateef (Abdul Lateef)" <AbdulLateef.Attar@amd.com>
Subject: Re: [edk2-devel] [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus Drivers
Date: Thu, 2 May 2024 04:24:22 +0000 [thread overview]
Message-ID: <LV8PR12MB945232ECE230661EAA02F23FEA182@LV8PR12MB9452.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20240501190527.200937-3-brit.chesley@amd.com>
[AMD Official Use Only - General]
We had reviewed this patch internally before sending this to community.
Reviewed-by: Abner Chang <abner.chang@amd.com>
> -----Original Message-----
> From: Chesley, Brit <Brit.Chesley@amd.com>
> Sent: Thursday, May 2, 2024 3:05 AM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Attar, AbdulLateef (Abdul
> Lateef) <AbdulLateef.Attar@amd.com>
> Subject: [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus
> Drivers
>
> 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 | 41 ++
> MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf | 41 ++
> 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, 1052 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..3e2cc2daba1c
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
> @@ -0,0 +1,41 @@
> +## @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..9e3a5aae7d87
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
> @@ -0,0 +1,41 @@
> +## @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..b183ca182cab
> --- /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
> & SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH) !=
> SPI_PART_SUPPORTS_8_BIT_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 & SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH) !=
> SPI_PART_SUPPORTS_4_BIT_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 (#118493): https://edk2.groups.io/g/devel/message/118493
Mute This Topic: https://groups.io/mt/105849135/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-05-02 4:24 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-01 19:05 [edk2-devel] [PATCH v1 0/6] SPI Driver Stack Chesley, Brit via groups.io
2024-05-01 19:05 ` [edk2-devel] [PATCH v1 1/6] MdePkg/SpiConfiguration: Correct the definition spelling Chesley, Brit via groups.io
2024-05-02 4:20 ` Chang, Abner via groups.io
2024-05-01 19:05 ` [edk2-devel] [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus Drivers Chesley, Brit via groups.io
2024-05-02 4:24 ` Chang, Abner via groups.io [this message]
2024-05-01 19:05 ` [edk2-devel] [PATCH v1 3/6] MdeModulePkg: " Chesley, Brit via groups.io
2024-05-02 4:24 ` Chang, Abner via groups.io
2024-05-06 11:08 ` Chang, Abner via groups.io
2024-05-07 2:50 ` [edk2-devel] 回复: " gaoliming via groups.io
2024-05-01 19:05 ` [edk2-devel] [PATCH v1 4/6] MdeModulePkg:BaseSpiHcPlatformLib: Adding NULL lib instance Chesley, Brit via groups.io
2024-05-02 4:25 ` Chang, Abner via groups.io
2024-05-06 11:08 ` Chang, Abner via groups.io
2024-05-07 2:50 ` [edk2-devel] 回复: " gaoliming via groups.io
2024-05-01 19:05 ` [edk2-devel] [PATCH v1 5/6] MdeModulePkg: SpiHc: SpiHc Drivers Chesley, Brit via groups.io
2024-05-02 4:25 ` Chang, Abner via groups.io
2024-05-01 19:05 ` [edk2-devel] [PATCH v1 6/6] MdeModulePkg: Adding " Chesley, Brit via groups.io
2024-05-02 4:25 ` Chang, Abner via groups.io
2024-05-06 11:08 ` Chang, Abner via groups.io
2024-05-07 2:51 ` [edk2-devel] 回复: " gaoliming 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=LV8PR12MB945232ECE230661EAA02F23FEA182@LV8PR12MB9452.namprd12.prod.outlook.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