* [PATCH 2/2] NXP/SpiBusDxe: Add SPI Bus driver.
2018-02-09 11:53 [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack Pankaj Bansal
@ 2018-02-09 11:53 ` Pankaj Bansal
2018-02-20 4:51 ` [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack Pankaj Bansal
1 sibling, 0 replies; 3+ messages in thread
From: Pankaj Bansal @ 2018-02-09 11:53 UTC (permalink / raw)
To: edk2-devel; +Cc: Pankaj Bansal, Ard Biesheuvel, Leif Lindholm, Michael D Kinney
This Driver is based on revised PI 1.6 SPI specs.
This driver is DXE_RUNTIME_DRIVER, so that the SPI peripherals that
are needed to support runtime services can be used with this driver.
This driver follows UEFI driver model and its a Bus Driver that creates
all of its child handles on the first call to Start.
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
---
Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.c | 1548 +++++++++++++++++
Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.h | 510 ++++++
Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.inf | 53 +
3 files changed, 2111 insertions(+)
diff --git a/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.c b/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.c
new file mode 100644
index 0000000..70c0aba
--- /dev/null
+++ b/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.c
@@ -0,0 +1,1548 @@
+/** @file
+ This file implements SPI IO Protocol which enables the user to manipulate a single
+ SPI device independent of the host controller and SPI design.
+
+ Based on MdeModulePkg/Bus/I2c/I2cDxe/I2cBus.c
+
+ Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright 2018 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Specification Reference:
+ - UEFI 2.7 errata A, Chapter 8, Runtime Services
+ - UEFI 2.7 errata A, Chapter 10, Device Path Protocol
+ - UEFI 2.7 errata A, Chapter 11, UEFI Driver Model
+ - PI 1.6, Volume 5, Chapter 18 SPI Protocol Stack
+**/
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Protocol/DriverBinding.h>
+
+#include "SpiBusDxe.h"
+
+//
+// Global Variables
+//
+extern EFI_COMPONENT_NAME_PROTOCOL gSpiBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSpiBusComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL gSpiBusDriverBinding;
+
+//
+// EFI_DRIVER_BINDING_PROTOCOL instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gSpiBusDriverBinding = {
+ .Supported = SpiBusDriverSupported,
+ .Start = SpiBusDriverStart,
+ .Stop = SpiBusDriverStop,
+ .Version = 0x10,
+ .ImageHandle = NULL,
+ .DriverBindingHandle = NULL
+};
+
+//
+// Template for SPI Bus Context
+//
+SPI_BUS_CONTEXT gEfiSpiBusContextTemplate = {
+ .Signature = SPI_BUS_SIGNATURE,
+ .SpiHost = NULL,
+ .SpiBus = NULL,
+ .Link = {
+ .ForwardLink = NULL,
+ .BackLink = NULL
+ }
+};
+
+//
+// Template for SPI Device Context
+//
+SPI_DEVICE_CONTEXT gEfiSpiDeviceContextTemplate = {
+ .Signature = SPI_DEVICE_SIGNATURE,
+ .Handle = NULL,
+ .SpiIo = {
+ .SpiPeripheral = NULL,
+ .OriginalSpiPeripheral = NULL,
+ .FrameSizeSupportMask = 0,
+ .MaximumTransferBytes = 1,
+ .Attributes = 0,
+ .LegacySpiProtocol = NULL,
+ .Transaction = SpiBusTransaction,
+ .UpdateSpiPeripheral = SpiBusUpdateSpiPeripheral
+ },
+ .SpiBusContext = NULL,
+ .Link = {
+ .ForwardLink = NULL,
+ .BackLink = NULL
+ }
+};
+
+STATIC EFI_EVENT mSpiBusVirtualAddrChangeEvent;
+
+// Link list of SPI Buses that are runtime
+STATIC LIST_ENTRY mSpiBusList = INITIALIZE_LIST_HEAD_VARIABLE (mSpiBusList);
+
+// Link list of SPI Devices that are runtime
+STATIC LIST_ENTRY mSpiDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mSpiDeviceList);
+
+//
+// Driver name table
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSpiBusDriverNameTable[] = {
+ { "eng;en", (CHAR16 *) L"SPI Bus Driver" },
+ { NULL , NULL }
+};
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSpiBusComponentName = {
+ (EFI_COMPONENT_NAME_GET_DRIVER_NAME) SpiBusComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) SpiBusComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSpiBusComponentName2 = {
+ SpiBusComponentNameGetDriverName,
+ SpiBusComponentNameGetControllerName,
+ "en"
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSpiBusDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This != &gSpiBusComponentName2)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Check if the Spi Host controller's device path exists in Spi Bus configuration
+
+ @param[in] SpiBusConfig A pointer to the EFI_SPI_CONFIGURATION_PROTOCOL instance.
+ @param[in] ParentDevicePath A pointer to the Spi Host controller device path.
+ @param[Out] SpiBusIndex Index of Spi Bus corresponding to Spi Host controller which controls that SPI bus.
+ @param[Out] SpiBusRuntime Indicates weather Spi Bus is to be configured for runtime access.
+
+ @retval EFI_SUCCESS Spi Bus Found.
+ @retval EFI_NOT_FOUND No Spi Bus Found.
+ @retval EFI_INVALID_PARAMETER Input Pointers are NULL.
+
+**/
+STATIC
+EFI_STATUS
+SearchSpiHostController (
+ IN EFI_SPI_CONFIGURATION_PROTOCOL *SpiBusConfig,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ OUT UINT32 *SpiBusIndex,
+ OUT BOOLEAN *SpiBusRuntime
+ )
+{
+ CONST EFI_SPI_BUS *SpiBus;
+ UINT32 Index;
+ EFI_STATUS Status;
+
+ if (SpiBusConfig == NULL || ParentDevicePath == NULL || SpiBusIndex == NULL || SpiBusRuntime == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SpiBusConfig->Buslist == NULL || SpiBusConfig->BusCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0, Status = EFI_NOT_FOUND; Index < SpiBusConfig->BusCount; Index++) {
+ SpiBus = SpiBusConfig->Buslist[Index];
+ if (SpiBus == NULL || SpiBus->ControllerPath == NULL) {
+ continue;
+ }
+ if (CompareMem (ParentDevicePath, SpiBus->ControllerPath, GetDevicePathSize (SpiBus->ControllerPath)) == 0) {
+ *SpiBusIndex = Index;
+ Status = EFI_SUCCESS;
+ if (SpiBus->RuntimePeripherallist != NULL) {
+ *SpiBusRuntime = TRUE;
+ }
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+SpiBusDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_SPI_HC_PROTOCOL *SpiHostController;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_HANDLE *Handle;
+ UINTN HandleCount;
+
+ //
+ // Determine if the SPI Host controller Protocol is available
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ (VOID **) &SpiHostController,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ //
+ // Determine if the Device Path protocol is available
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // Check if the first node of RemainingDevicePath is a hardware vendor device path
+ //
+ if ((DevicePathType (RemainingDevicePath) != HARDWARE_DEVICE_PATH) ||
+ (DevicePathSubType (RemainingDevicePath) != HW_VENDOR_DP)) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check if the second node of RemainingDevicePath is a controller node
+ //
+ DevPathNode = NextDevicePathNode (RemainingDevicePath);
+ if (!IsDevicePathEnd (DevPathNode)) {
+ if ((DevicePathType (DevPathNode) != HARDWARE_DEVICE_PATH) ||
+ (DevicePathSubType (DevPathNode) != HW_CONTROLLER_DP)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ // Determine if the SPI Configuration Protocol is available
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSpiConfigurationProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ FreePool (Handle);
+ // Only one SpiConfiguration protocol is allowed
+ if (HandleCount != 1) {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ SPI_BUS_CONTEXT *SpiBusContext;
+ EFI_STATUS Status;
+ EFI_SPI_HC_PROTOCOL *SpiHostController;
+ EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *LegacySpiHostController;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_HANDLE *Handle;
+ UINTN HandleCount;
+ EFI_SPI_CONFIGURATION_PROTOCOL *SpiBusConfig;
+ UINT32 SpiBusIndex;
+ BOOLEAN SpiBusRuntime;
+
+ SpiBusContext = NULL;
+ ParentDevicePath = NULL;
+ SpiHostController = NULL;
+ SpiBusConfig = NULL;
+ SpiBusIndex = 0;
+ SpiBusRuntime = FALSE;
+ LegacySpiHostController = NULL;
+
+ //
+ // Determine if the SPI controller is available
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ (VOID**)&SpiHostController,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: open SPI host Controller error, Status = %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Get the Device Path protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: open device path error, Status = %r\n", Status));
+ goto ErrorExit;
+ }
+
+ if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // don't create any child device and return EFI_SUCESS
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get the Spi Bus Configuration protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSpiConfigurationProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handle
+ );
+ if (EFI_ERROR (Status) || (HandleCount != 1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "SpiBus: SPI Configuration Protocol error, Status = %r, HandleCount =%lu\n",
+ Status,
+ HandleCount
+ ));
+ goto ErrorExit;
+ }
+
+ //
+ // Open Spi Configuration Protocol
+ //
+ Status = gBS->HandleProtocol (
+ Handle[0],
+ &gEfiSpiConfigurationProtocolGuid,
+ (VOID **)&SpiBusConfig
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: SPI Configuration Protocol error, Status = %r\n", Status));
+ goto ErrorExit;
+ }
+
+ Status = SearchSpiHostController (SpiBusConfig, ParentDevicePath, &SpiBusIndex, &SpiBusRuntime);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: Could not find Spi Host Controller Status = %r\n", Status));
+ goto ErrorExit;
+ }
+
+ //
+ // Allocate the buffer for SPI_BUS_CONTEXT.
+ //
+ if (SpiBusRuntime == FALSE) {
+ SpiBusContext = AllocateCopyPool (sizeof (SPI_BUS_CONTEXT), &gEfiSpiBusContextTemplate);
+ } else {
+ SpiBusContext = AllocateRuntimeCopyPool (sizeof (SPI_BUS_CONTEXT), &gEfiSpiBusContextTemplate);
+ }
+ if (SpiBusContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: there is no enough memory to allocate.\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ /*
+ +----------------+
+ .->| SPI_BUS_CONTEXT|
+ | +----------------+
+ |
+ | +----------------------------+
+ | | SPI_DEVICE_CONTEXT |
+ `--| |
+ | |
+ | SPI IO Protocol Structure | <----- SPI IO Protocol
+ | |
+ +----------------------------+
+
+ */
+ SpiBusContext->SpiHost = SpiHostController;
+ SpiBusContext->SpiBus = SpiBusConfig->Buslist[SpiBusIndex];
+ SpiBusContext->DriverBindingHandle = This->DriverBindingHandle;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid, SpiBusContext,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: install private protocol error, Status = %r.\n", Status));
+ goto ErrorExit;
+ }
+
+ if (SpiBusRuntime == TRUE) {
+ InsertTailList (&mSpiBusList, &SpiBusContext->Link);
+ }
+
+ //
+ // Determine if the SPI controller has installed Legacy Spi controller protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiLegacySpiControllerProtocolGuid,
+ (VOID**)&LegacySpiHostController,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: open SPI host Controller error, Status = %r\n", Status));
+ goto ErrorExit;
+ }
+
+ //
+ // Start the driver
+ //
+ Status = RegisterSpiDevice (SpiBusContext, Controller, LegacySpiHostController, FALSE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: Failed to register SPI peripherals on SPI bus Status = %r\n", Status));
+ goto ErrorExit;
+ }
+
+ if (SpiBusRuntime == TRUE) {
+ Status = RegisterSpiDevice (SpiBusContext, Controller, LegacySpiHostController, TRUE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: Failed to register Runtime SPI peripherals on SPI bus Status = %r\n", Status));
+ goto ErrorExit;
+ }
+ }
+
+ErrorExit:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SpiBus: Start() function failed, Status = %r\n", Status));
+ if (ParentDevicePath != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if (SpiHostController != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if (Handle != NULL) {
+ FreePool (Handle);
+ }
+
+ if (SpiBusContext != NULL) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ &Controller,
+ gEfiCallerIdGuid, SpiBusContext,
+ NULL
+ );
+ if (SpiBusRuntime == TRUE) {
+ RemoveEntryList (&SpiBusContext->Link);
+ }
+ FreePool (SpiBusContext);
+ }
+
+ if (LegacySpiHostController != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiLegacySpiControllerProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ }
+
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ SPI_BUS_CONTEXT *SpiBusContext;
+ BOOLEAN SpiBusRuntime;
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+
+ if (NumberOfChildren == 0) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiLegacySpiControllerProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ //
+ // Get our context back
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &SpiBusContext,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ SpiBusRuntime = SpiBusContext->SpiBus->RuntimePeripherallist ? TRUE : FALSE;
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid, SpiBusContext,
+ NULL
+ );
+ //
+ // No more child now, free bus context data.
+ //
+ if (SpiBusRuntime) {
+ RemoveEntryList (&SpiBusContext->Link);
+ }
+ FreePool (SpiBusContext);
+ }
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = UnRegisterSpiDevice (This, Controller, ChildHandleBuffer[Index]);
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Enumerate the SPI bus
+
+ This routine walks the platform specific data describing the
+ SPI bus to create the SPI devices where driver GUIDs were
+ specified.
+
+ @param[in] SpiBusContext Address of an SPI_BUS_CONTEXT structure
+ @param[in] Controller Handle to the controller
+ @param[in] LegacySpiHostController A pointer to the LEGACY_SPI_CONTROLLER_PROTOCOL
+ interface installed on controller.
+ @param[in] RegisterRuntime Weather to register runtime SPI devices or non runtime
+ Spi devices.
+
+ @retval EFI_SUCCESS The bus is successfully configured
+
+**/
+EFI_STATUS
+RegisterSpiDevice (
+ IN SPI_BUS_CONTEXT *SpiBusContext,
+ IN EFI_HANDLE Controller,
+ IN EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *LegacySpiHostController,
+ IN BOOLEAN RegisterRuntime
+ )
+{
+ CONST EFI_SPI_PERIPHERAL *SpiPeripheral;
+ SPI_DEVICE_CONTEXT *SpiDeviceContext;
+ UINT32 SpiAttributes;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ SpiDeviceContext = NULL;
+ if (RegisterRuntime == FALSE) {
+ SpiPeripheral = SpiBusContext->SpiBus->Peripherallist;
+ } else {
+ SpiPeripheral = SpiBusContext->SpiBus->RuntimePeripherallist;
+ }
+
+ //
+ // Walk the list of SPI devices on this bus
+ //
+ for ( ; SpiPeripheral != NULL; SpiPeripheral = SpiPeripheral->NextSpiPeripheral) {
+ //
+ // Determine if the device info is valid
+ //
+ if ((SpiPeripheral->SpiPeripheralDriverGuid == NULL)
+ || (SpiPeripheral->SpiPart == NULL)
+ || (SpiPeripheral->SpiBus != SpiBusContext->SpiBus)
+ || (SpiPeripheral->ChipSelectParameter == NULL))
+ {
+ DEBUG ((DEBUG_ERROR, "Invalid EFI_SPI_PERIPHERAL reported by Spi Configuration protocol.\n"));
+ continue;
+ }
+
+ //
+ // Build the device context for current SPI device.
+ //
+ if (RegisterRuntime == FALSE) {
+ SpiDeviceContext = AllocateCopyPool (sizeof (SPI_DEVICE_CONTEXT), &gEfiSpiDeviceContextTemplate);
+ } else {
+ SpiDeviceContext = AllocateRuntimeCopyPool (sizeof (SPI_DEVICE_CONTEXT), &gEfiSpiDeviceContextTemplate);
+ }
+
+ if (SpiDeviceContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "Failed to allocate memory for SPI device context.\n"));
+ continue;
+ }
+
+ //
+ // Initialize the specific device context
+ //
+ SpiDeviceContext->SpiBusContext = SpiBusContext;
+ SpiDeviceContext->SpiIo.SpiPeripheral = SpiPeripheral;
+ SpiDeviceContext->SpiIo.OriginalSpiPeripheral = SpiPeripheral;
+ SpiDeviceContext->SpiIo.FrameSizeSupportMask = SpiBusContext->SpiHost->FrameSizeSupportMask;
+ SpiDeviceContext->SpiIo.MaximumTransferBytes = SpiBusContext->SpiHost->MaximumTransferBytes;
+ SpiAttributes = SpiBusContext->SpiHost->Attributes;
+ // SPI Io attributes are least attributes supported by both SPI peripheral and SPI Host controller
+ SpiAttributes = BitFieldOr32 (
+ SpiAttributes,
+ __builtin_ctz (SPI_HALF_DUPLEX),
+ __builtin_ctz (SPI_SUPPORTS_READ_ONLY_OPERATIONS),
+ SpiPeripheral->Attributes
+ );
+
+ SpiAttributes = BitFieldAnd32 (
+ SpiAttributes,
+ __builtin_ctz (SPI_SUPPORTS_DTR_OPERATIONS),
+ __builtin_ctz (SPI_SUPPORTS_8_BIT_DATA_BUS_WIDTH),
+ SpiPeripheral->Attributes
+ );
+
+ SpiDeviceContext->SpiIo.Attributes = SpiAttributes;
+ SpiDeviceContext->SpiIo.LegacySpiProtocol = LegacySpiHostController;
+
+ //
+ // Install the protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &SpiDeviceContext->Handle,
+ SpiPeripheral->SpiPeripheralDriverGuid, &SpiDeviceContext->SpiIo,
+ &gEfiCallerIdGuid, SpiDeviceContext,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Free resources for this SPI device
+ //
+ ReleaseSpiDeviceContext (SpiDeviceContext);
+ continue;
+ }
+
+ //
+ // Create the child handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ (VOID **) &SpiBusContext->SpiHost,
+ SpiBusContext->DriverBindingHandle,
+ SpiDeviceContext->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ SpiDeviceContext->Handle,
+ SpiPeripheral->SpiPeripheralDriverGuid, &SpiDeviceContext->SpiIo,
+ &gEfiCallerIdGuid, SpiDeviceContext,
+ NULL
+ );
+ //
+ // Free resources for this SPI device
+ //
+ ReleaseSpiDeviceContext (SpiDeviceContext);
+ continue;
+ }
+
+ //
+ // Child has been created successfully
+ //
+ if (RegisterRuntime == TRUE) {
+ InsertTailList (&mSpiDeviceList, &SpiDeviceContext->Link);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ 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 transactions to the
+ SPI controller for execution on the SPI bus.
+
+ @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
+ @param[in] RequestPacket Pointer to an EFI_SPI_REQUEST_PACKET
+ structure describing the SPI transactions.
+
+ @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.
+
+ @retval EFI_SUCCESS The transaction completed successfully.
+ @retval EFI_ALREADY_STARTED The controller is busy with another transaction.
+ @retval EFI_BAD_BUFFER_SIZE The Length value in SPI Transaction is wrong.
+ @retval EFI_DEVICE_ERROR There was an SPI error during the transaction.
+ @retval EFI_INVALID_PARAMETER The parameters specified in RequestPacket are not
+ Valid. or the RequestPacket is NULL.
+ @retval EFI_NOT_READY Support for the chip select is not properly
+ initialized
+ @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents are
+ invalid
+ @retval EFI_NO_RESPONSE The SPI device is not responding to the slave
+ address. EFI_DEVICE_ERROR will be returned if
+ the controller cannot distinguish when the NACK
+ occurred.
+ @retval EFI_UNSUPPORTED The controller does not support the requested
+ transaction. or The SPI controller was not able to support
+ the frequency requested by ClockHz
+**/
+EFI_STATUS
+SpiBusTransaction (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN EFI_SPI_REQUEST_PACKET *RequestPacket,
+ IN UINT32 ClockHz OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ SPI_DEVICE_CONTEXT *SpiDeviceContext;
+ SPI_BUS_CONTEXT *SpiBusContext;
+ CONST EFI_SPI_HC_PROTOCOL *SpiHostController;
+ CONST EFI_SPI_BUS *SpiBus;
+ CONST EFI_SPI_PERIPHERAL *SpiPeripheral;
+ UINT32 RequestedClockHz;
+ BOOLEAN ChipSelectPolarity;
+
+ if (This == NULL || RequestPacket == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Backup requested clock frequency
+ RequestedClockHz = ClockHz;
+
+ SpiPeripheral = This->SpiPeripheral;
+ ASSERT (SpiPeripheral != NULL || SpiPeripheral->SpiPart != NULL);
+
+ SpiDeviceContext = SPI_DEVICE_CONTEXT_FROM_PROTOCOL (This);
+ SpiBusContext = SpiDeviceContext->SpiBusContext;
+ ASSERT (SpiBusContext != NULL);
+
+ SpiHostController = SpiBusContext->SpiHost;
+ SpiBus = SpiBusContext->SpiBus;
+ ASSERT (SpiHostController != NULL || SpiBus != NULL);
+
+ // The SPI transaction consists of:
+ // 1. Adjusting the clock speed, polarity and phase for a SPI peripheral
+ if (RequestedClockHz == 0) {
+ if (SpiPeripheral->MaxClockHz != 0) {
+ ClockHz = MIN (SpiPeripheral->MaxClockHz, SpiPeripheral->SpiPart->MaxClockHz);
+ } else {
+ ClockHz = SpiPeripheral->SpiPart->MaxClockHz;
+ }
+ RequestedClockHz = ClockHz;
+ } else {
+ if (SpiPeripheral->MaxClockHz != 0) {
+ if (RequestedClockHz > MIN (SpiPeripheral->MaxClockHz, SpiPeripheral->SpiPart->MaxClockHz)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ if (RequestedClockHz > SpiPeripheral->SpiPart->MaxClockHz) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ if (SpiBus->Clock != NULL) {
+ Status = SpiBus->Clock (SpiPeripheral, &ClockHz);
+ } else {
+ Status = SpiHostController->Clock (SpiHostController, SpiPeripheral, &ClockHz);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ } else if (ClockHz > RequestedClockHz) {
+ return EFI_UNSUPPORTED;
+ }
+
+ // 2. Use the chip select to enable the SPI peripheral, signaling the transaction start to the chip
+ ChipSelectPolarity = SpiPeripheral->SpiPart->ChipSelectPolarity;
+
+ if (SpiPeripheral->ChipSelect != NULL) {
+ Status = SpiPeripheral->ChipSelect (SpiPeripheral, ChipSelectPolarity);
+ } else {
+ Status = SpiHostController->ChipSelect (SpiHostController, SpiPeripheral, ChipSelectPolarity);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // 3. Transfer the data in one or both directions simultaneously
+ Status = SpiHostController->Transaction (SpiHostController, RequestPacket);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // 4. Remove the chip select from the SPI peripheral signaling the transaction end to the chip
+ if (SpiPeripheral->ChipSelect != NULL) {
+ Status = SpiPeripheral->ChipSelect (SpiPeripheral, !ChipSelectPolarity);
+ } else {
+ Status = SpiHostController->ChipSelect (SpiHostController, SpiPeripheral, !ChipSelectPolarity);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // 5. Optionally, shutdown the SPI controller's internal clock to reduce power
+ ClockHz = 0;
+ if (SpiBus->Clock != NULL) {
+ Status = SpiBus->Clock (SpiPeripheral, &ClockHz);
+ } else {
+ Status = SpiHostController->Clock (SpiHostController, SpiPeripheral, &ClockHz);
+ }
+
+ // Since its optional for a controller to turn off the clock of spi peripherals
+ // its not an error if any controller doesn't support this.
+ if (Status != EFI_UNSUPPORTED) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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
+SpiBusUpdateSpiPeripheral (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral
+ )
+{
+ SPI_DEVICE_CONTEXT *SpiDeviceContext;
+ BOOLEAN ReinstallProtocol;
+ CONST EFI_SPI_PERIPHERAL *ExistingSpiPeripheral;
+ EFI_STATUS Status;
+
+ if ( (This == NULL)
+ || (SpiPeripheral == NULL)
+ || (SpiPeripheral->SpiBus == NULL)
+ || (SpiPeripheral->SpiPart == NULL)
+ || (SpiPeripheral->ChipSelectParameter == NULL)
+ || (SpiPeripheral->SpiPeripheralDriverGuid == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ExistingSpiPeripheral = This->SpiPeripheral;
+ ASSERT (ExistingSpiPeripheral != NULL || ExistingSpiPeripheral->SpiBus != NULL);
+
+ if ( (SpiPeripheral->SpiBus != ExistingSpiPeripheral->SpiBus)
+ || (SpiPeripheral->ChipSelectParameter != ExistingSpiPeripheral->ChipSelectParameter))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SpiDeviceContext = SPI_DEVICE_CONTEXT_FROM_PROTOCOL (This);
+
+ ReinstallProtocol = FALSE;
+ if (!(CompareGuid (SpiPeripheral->SpiPeripheralDriverGuid, ExistingSpiPeripheral->SpiPeripheralDriverGuid))) {
+ ReinstallProtocol = TRUE;
+ }
+
+ if (ReinstallProtocol) {
+ Status = gBS->UninstallProtocolInterface (
+ SpiDeviceContext->Handle,
+ (EFI_GUID *)ExistingSpiPeripheral->SpiPeripheralDriverGuid,
+ &SpiDeviceContext->SpiIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ SpiDeviceContext->SpiIo.SpiPeripheral = SpiPeripheral;
+
+ if (SpiDeviceContext->SpiIo.OriginalSpiPeripheral == NULL) {
+ SpiDeviceContext->SpiIo.OriginalSpiPeripheral = ExistingSpiPeripheral;
+ } else if (SpiDeviceContext->SpiIo.OriginalSpiPeripheral != ExistingSpiPeripheral) {
+ if (SpiPeripheral->SpiPart != ExistingSpiPeripheral->SpiPart) {
+ FreePool ((VOID *)(ExistingSpiPeripheral->SpiPart));
+ }
+ if (SpiPeripheral->ConfigurationData != ExistingSpiPeripheral->ConfigurationData) {
+ FreePool ((VOID *)(ExistingSpiPeripheral->ConfigurationData));
+ }
+ FreePool ((VOID *)ExistingSpiPeripheral);
+ }
+
+ if (ReinstallProtocol) {
+ Status = gBS->InstallProtocolInterface (
+ &SpiDeviceContext->Handle,
+ (EFI_GUID *)SpiPeripheral->SpiPeripheralDriverGuid,
+ EFI_NATIVE_INTERFACE,
+ &SpiDeviceContext->SpiIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Release all the resources allocated for the SPI device.
+
+ This function releases all the resources allocated for the SPI device.
+
+ @param SpiDeviceContext The SPI child device involved for the operation.
+
+**/
+VOID
+ReleaseSpiDeviceContext (
+ IN SPI_DEVICE_CONTEXT *SpiDeviceContext
+ )
+{
+ if (SpiDeviceContext == NULL) {
+ return;
+ }
+
+ FreePool (SpiDeviceContext);
+}
+
+/**
+ Unregister an SPI device.
+
+ This function removes the protocols installed on the controller handle and
+ frees the resources allocated for the SPI device.
+
+ @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The controller handle of the SPI device.
+ @param Handle The child handle.
+
+ @retval EFI_SUCCESS The SPI device is successfully unregistered.
+ @return Others Some error occurs when unregistering the SPI device.
+
+**/
+EFI_STATUS
+UnRegisterSpiDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ SPI_DEVICE_CONTEXT *SpiDeviceContext;
+ CONST EFI_SPI_PERIPHERAL *SpiPeripheral;
+ EFI_SPI_HC_PROTOCOL *SpiHost;
+
+ SpiDeviceContext = NULL;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiCallerIdGuid,
+ (VOID **) &SpiDeviceContext,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SpiPeripheral = SpiDeviceContext->SpiIo.SpiPeripheral;
+
+ //
+ // Close the child handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ //
+ // The SPI Bus driver installs the SPI Io and Local Protocol in the DriverBindingStart().
+ // Here should uninstall them.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ SpiPeripheral->SpiPeripheralDriverGuid, &SpiDeviceContext->SpiIo,
+ &gEfiCallerIdGuid, SpiDeviceContext,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Keep parent and child relationship
+ //
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiSpiHcProtocolGuid,
+ (VOID **) &SpiHost,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // Free resources for this SPI device
+ //
+ if (SpiDeviceContext->Link.ForwardLink != NULL || SpiDeviceContext->Link.BackLink != NULL) {
+ RemoveEntryList (&SpiDeviceContext->Link);
+ }
+ ReleaseSpiDeviceContext (SpiDeviceContext);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+SpiBusVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ LIST_ENTRY *Link;
+ SPI_DEVICE_CONTEXT *SpiDeviceContext;
+ SPI_BUS_CONTEXT *SpiBusContext;
+
+ for (Link = mSpiBusList.ForwardLink; Link != &mSpiBusList; Link = Link->ForwardLink) {
+ SpiBusContext = CR (Link, SPI_BUS_CONTEXT, Link, SPI_BUS_SIGNATURE);
+
+ EfiConvertPointer (0x0, (VOID **)&SpiBusContext->SpiHost);
+ EfiConvertPointer (0x0, (VOID **)&SpiBusContext->SpiBus);
+ }
+
+ for (Link = mSpiDeviceList.ForwardLink; Link != &mSpiDeviceList; Link = Link->ForwardLink) {
+ SpiDeviceContext = CR (Link, SPI_DEVICE_CONTEXT, Link, SPI_DEVICE_SIGNATURE);
+
+ EfiConvertPointer (0x0, (VOID **)&SpiDeviceContext->SpiBusContext);
+
+ EfiConvertPointer (0x0, (VOID **)&SpiDeviceContext->SpiIo.SpiPeripheral);
+ EfiConvertPointer (0x0, (VOID **)&SpiDeviceContext->SpiIo.OriginalSpiPeripheral);
+ EfiConvertPointer (0x0, (VOID **)&SpiDeviceContext->SpiIo.LegacySpiProtocol);
+ EfiConvertPointer (0x0, (VOID **)&SpiDeviceContext->SpiIo.Transaction);
+ EfiConvertPointer (0x0, (VOID **)&SpiDeviceContext->SpiIo.UpdateSpiPeripheral);
+ }
+
+ return;
+}
+
+/**
+ The user entry point for the SPI bus module. The user code starts with
+ this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSpiBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSpiBusDriverBinding,
+ NULL,
+ &gSpiBusComponentName,
+ &gSpiBusComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ SpiBusVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mSpiBusVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ This is the unload handle for SPI bus module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *DeviceHandleBuffer;
+ UINTN DeviceHandleCount;
+ UINTN Index;
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
+ EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
+
+ //
+ // Get the list of all SPI Controller handles in the handle database.
+ // If there is an error getting the list, then the unload
+ // operation fails.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSpiHcProtocolGuid,
+ NULL,
+ &DeviceHandleCount,
+ &DeviceHandleBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Disconnect the driver specified by Driver BindingHandle from all
+ // the devices in the handle database.
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->DisconnectController (
+ DeviceHandleBuffer[Index],
+ gSpiBusDriverBinding.DriverBindingHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Uninstall all the protocols installed in the driver entry point
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ gSpiBusDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gSpiBusDriverBinding,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Note we have to one by one uninstall the following protocols.
+ // It's because some of them are optionally installed based on
+ // the following PCD settings.
+ // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
+ // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
+ // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
+ // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
+ //
+ Status = gBS->HandleProtocol (
+ gSpiBusDriverBinding.DriverBindingHandle,
+ &gEfiComponentNameProtocolGuid,
+ (VOID **) &ComponentName
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ gSpiBusDriverBinding.DriverBindingHandle,
+ &gEfiComponentNameProtocolGuid,
+ ComponentName
+ );
+ }
+
+ Status = gBS->HandleProtocol (
+ gSpiBusDriverBinding.DriverBindingHandle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **) &ComponentName2
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ gSpiBusDriverBinding.DriverBindingHandle,
+ &gEfiComponentName2ProtocolGuid,
+ ComponentName2
+ );
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ //
+ // Free the buffer containing the list of handles from the handle database
+ //
+ if (DeviceHandleBuffer != NULL) {
+ gBS->FreePool (DeviceHandleBuffer);
+ }
+
+ return Status;
+}
diff --git a/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.h b/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.h
new file mode 100644
index 0000000..3d4074e
--- /dev/null
+++ b/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.h
@@ -0,0 +1,510 @@
+/** @file
+ Private data structures for the SPI DXE driver.
+
+ This file defines common data structures, macro definitions and some module
+ internal function header files.
+
+ Based on MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.h
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ Copyright 2018 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SPI_BUS_DXE_H__
+#define __SPI_BUS_DXE_H__
+
+#include <Pi/PiSpi.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiIo.h>
+#include <Protocol/SpiConfiguration.h>
+
+#define SPI_BUS_SIGNATURE SIGNATURE_32 ('S', 'P', 'I', 'B')
+#define SPI_DEVICE_SIGNATURE SIGNATURE_32 ('S', 'P', 'I', 'D')
+
+///
+/// SPI bus context. This data structure provides connection point
+/// between SPI IO protocol (which tells the SPI bus) and SPI host
+/// controller protocol.
+///
+typedef struct {
+ ///
+ /// Structure identification
+ ///
+ UINT32 Signature;
+
+ ///
+ /// Spi Host controller protocol
+ ///
+ CONST EFI_SPI_HC_PROTOCOL *SpiHost;
+
+ ///
+ /// Spi BUS data structure
+ ///
+ CONST EFI_SPI_BUS *SpiBus;
+
+ EFI_HANDLE DriverBindingHandle;
+
+ ///
+ /// Link List of SPI Buses
+ ///
+ LIST_ENTRY Link;
+} SPI_BUS_CONTEXT;
+
+///
+/// SPI device context
+///
+typedef struct {
+ ///
+ /// Structure identification
+ ///
+ UINT32 Signature;
+
+ ///
+ /// Spi device handle
+ ///
+ EFI_HANDLE Handle;
+
+ ///
+ /// Upper level API to support the SPI device I/O
+ ///
+ EFI_SPI_IO_PROTOCOL SpiIo;
+
+ ///
+ /// Context for the common I/O support including the
+ /// lower level API to the host controller.
+ ///
+ SPI_BUS_CONTEXT *SpiBusContext;
+
+ ///
+ /// Link List of SPI Devices
+ ///
+ LIST_ENTRY Link;
+} SPI_DEVICE_CONTEXT;
+
+#define SPI_DEVICE_CONTEXT_FROM_PROTOCOL(a) CR (a, SPI_DEVICE_CONTEXT, SpiIo, SPI_DEVICE_SIGNATURE)
+
+/**
+ Enumerate the SPI bus
+
+ This routine walks the platform specific data describing the
+ SPI bus to create the SPI devices where driver GUIDs were
+ specified.
+
+ @param[in] SpiBusContext Address of an SPI_BUS_CONTEXT structure
+ @param[in] Controller Handle to the controller
+ @param[in] LegacySpiHostController A pointer to the LEGACY_SPI_CONTROLLER_PROTOCOL
+ interface installed on controller.
+ @param[in] RegisterRuntime Weather to register runtime SPI devices or non runtime
+ Spi devices.
+
+ @retval EFI_SUCCESS The bus is successfully configured
+
+**/
+EFI_STATUS
+RegisterSpiDevice (
+ IN SPI_BUS_CONTEXT *SpiBusContext,
+ IN EFI_HANDLE Controller,
+ IN EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *LegacySpiHostController,
+ IN BOOLEAN RegisterRuntime
+ );
+
+/**
+ Unregister an SPI device.
+
+ This function removes the protocols installed on the controller handle and
+ frees the resources allocated for the SPI device.
+
+ @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The controller handle of the SPI device.
+ @param Handle The child handle.
+
+ @retval EFI_SUCCESS The SPI device is successfully unregistered.
+ @return Others Some error occurs when unregistering the SPI device.
+
+**/
+EFI_STATUS
+UnRegisterSpiDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+SpiBusDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ The user entry point for the SPI bus module. The user code starts with
+ this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSpiBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This is the unload handle for SPI bus module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiBusUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Release all the resources allocated for the SPI device.
+
+ This function releases all the resources allocated for the SPI device.
+
+ @param SpiDeviceContext The SPI child device involved for the operation.
+
+**/
+VOID
+ReleaseSpiDeviceContext (
+ IN SPI_DEVICE_CONTEXT *SpiDeviceContext
+ );
+
+/**
+ 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 transactions to the
+ SPI controller for execution on the SPI bus.
+
+ @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
+ @param[in] RequestPacket Pointer to an EFI_SPI_REQUEST_PACKET
+ structure describing the SPI transactions.
+
+ @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.
+
+ @retval EFI_SUCCESS The transaction completed successfully.
+ @retval EFI_ALREADY_STARTED The controller is busy with another transaction.
+ @retval EFI_BAD_BUFFER_SIZE The Length value in SPI Transaction is wrong.
+ @retval EFI_DEVICE_ERROR There was an SPI error during the transaction.
+ @retval EFI_INVALID_PARAMETER The parameters specified in RequestPacket are not
+ Valid. or the RequestPacket is NULL.
+ @retval EFI_NOT_READY Support for the chip select is not properly
+ initialized
+ @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents are
+ invalid
+ @retval EFI_NO_RESPONSE The SPI device is not responding to the slave
+ address. EFI_DEVICE_ERROR will be returned if
+ the controller cannot distinguish when the NACK
+ occurred.
+ @retval EFI_UNSUPPORTED The controller does not support the requested
+ transaction. or The SPI controller was not able to support
+ the frequency requested by ClockHz
+**/
+EFI_STATUS
+SpiBusTransaction (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN EFI_SPI_REQUEST_PACKET *RequestPacket,
+ IN UINT32 ClockHz OPTIONAL
+ );
+
+/**
+ 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 SpiP eripheral - >SpiBus pointing at
+ wrong bus,
+ or the SpiP eripheral - >SpiPart is NULL
+
+**/
+EFI_STATUS
+SpiBusUpdateSpiPeripheral (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral
+ );
+
+#endif // __SPI_BUS_DXE_H__
diff --git a/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.inf b/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.inf
new file mode 100644
index 0000000..37adf6d
--- /dev/null
+++ b/Silicon/NXP/Drivers/SpiBusDxe/SpiBusDxe.inf
@@ -0,0 +1,53 @@
+## @file
+# This driver enumerates SPI devices on SPI bus and produce SPI IO Protocol on SPI devices.
+#
+# Based on MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
+#
+# Copyright 2018 NXP
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000A
+ BASE_NAME = SpiBusDxe
+ FILE_GUID = 5145643e-b84f-4033-86e4-15e9dab163fb
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSpiBus
+ UNLOAD_IMAGE = SpiBusUnload
+
+[Sources.common]
+ SpiBusDxe.h
+ SpiBusDxe.c
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeLib
+
+[Packages]
+ Platform/NXP/NxpQoriqLs.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEfiSpiHcProtocolGuid ## TO_START
+ gEfiSpiConfigurationProtocolGuid ## TO_START
+ gEfiLegacySpiControllerProtocolGuid ## TO_START
+
+[Depex]
+ TRUE
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack
2018-02-09 11:53 [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack Pankaj Bansal
2018-02-09 11:53 ` [PATCH 2/2] NXP/SpiBusDxe: Add SPI Bus driver Pankaj Bansal
@ 2018-02-20 4:51 ` Pankaj Bansal
1 sibling, 0 replies; 3+ messages in thread
From: Pankaj Bansal @ 2018-02-20 4:51 UTC (permalink / raw)
To: edk2-devel@lists.01.org; +Cc: Ard Biesheuvel, Leif Lindholm, Michael D Kinney
Hi everybody,
Any review comments on this patch set ?
> -----Original Message-----
> From: Pankaj Bansal
> Sent: Friday, February 09, 2018 5:24 PM
> To: edk2-devel@lists.01.org
> Cc: Pankaj Bansal <pankaj.bansal@nxp.com>; Ard Biesheuvel
> <ard.biesheuvel@linaro.org>; Leif Lindholm <leif.lindholm@linaro.org>;
> Michael D Kinney <michael.d.kinney@intel.com>
> Subject: [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack
>
> The PI 1.6 SPI specs are not adequate to handle all type of SPI
> communication, specially the QUAD mode read/write comminications with
> the periphrals that support it.
>
> Therefore we are modifying the SPI protocol defined in PI 1.6 spec.
>
> Untill these changes are incorporated in PI specs, we are calling it revised PI
> 1.6 spec.
>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
> ---
> Silicon/NXP/Include/Pi/PiSpi.h | 233 ++++++++++++
> .../NXP/Include/Protocol/SpiConfiguration.h | 313 +++++++++++++++++
> Silicon/NXP/Include/Protocol/SpiHc.h | 208 +++++++++++
> Silicon/NXP/Include/Protocol/SpiIo.h | 168 +++++++++
> Silicon/NXP/Include/Protocol/SpiNorFlash.h | 269 ++++++++++++++
> 5 files changed, 1191 insertions(+)
>
> diff --git a/Silicon/NXP/Include/Pi/PiSpi.h b/Silicon/NXP/Include/Pi/PiSpi.h
> new file mode 100644 index 0000000..8c35d86
> --- /dev/null
> +++ b/Silicon/NXP/Include/Pi/PiSpi.h
> @@ -0,0 +1,233 @@
> +/** @file
> + Include file matches things in PI.
> +
> + Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> + Copyright 2017-2018 NXP
> +
> + This program and the accompanying materials are licensed and made
> + available under the terms and conditions of the BSD License which
> + accompanies this distribution. The full text of the license may be
> + found at http://opensource.org/licenses/bsd-license.php
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> + @par Revision Reference:
> + This Protocol was introduced in revised UEFI PI Specification 1.6.
> +
> +**/
> +
> +#ifndef __PI_SPI_H__
> +#define __PI_SPI_H__
> +
> +///
> +/// Define the SPI flags
> +///
> +
> +/// The SPI peripheral/controller supports only half duplex transactions
> +#define SPI_HALF_DUPLEX BIT0
> +/// The SPI peripheral/controller supports write only transactions.
> +#define SPI_SUPPORTS_WRITE_ONLY_OPERATIONS BIT1
> +/// The SPI peripheral/controller supports Read only transactions.
> +#define SPI_SUPPORTS_READ_ONLY_OPERATIONS BIT2
> +/// The SPI peripheral/controller supports Double Transfer Rate (DTR).
> +/// DTR : Transfer may be input or output on both the /// rising and
> +falling edges of the clock.
> +#define SPI_SUPPORTS_DTR_OPERATIONS BIT3
> +/// The SPI peripheral/controller supports a 2-bit data bus
> +#define SPI_SUPPORTS_2_BIT_DATA_BUS_WIDTH BIT4
> +/// The SPI peripheral/controller supports a 4-bit data bus
> +#define SPI_SUPPORTS_4_BIT_DATA_BUS_WIDTH BIT5
> +/// The SPI peripheral/controller supports a 8-bit data bus
> +#define SPI_SUPPORTS_8_BIT_DATA_BUS_WIDTH BIT6
> +/// Transfer size includes the opcode byte
> +#define SPI_TRANSFER_SIZE_INCLUDES_OPCODE BIT7
> +/// Transfer size includes the 4 address bytes
> +#define SPI_TRANSFER_SIZE_INCLUDES_ADDRESS BIT8
> +
> +///
> +/// SPI Frame Size supported Mask
> +///
> +#define SPI_FRAME_MASK(FrameSize) (1U << FrameSize)
> +
> +///
> +/// Calculate the Clock cycles from number of bytes and BusWidth ///
> +#define SPI_BYTES_TO_CYCLES(Bytes, BusWidth) ( ( (Bytes << sizeof
> (UINT8)) + BusWidth - 1) / BusWidth)
> +///
> +/// Calculate the number of bytes from Clock cycles and BusWidth ///
> +#define SPI_CYCLES_TO_BYTES(Cycles, BusWidth) ( (Cycles * BusWidth) >>
> sizeof (UINT8))
> +
> +///
> +/// SPI Device Path can be used to describe the device path of both SPI
> +controller /// and SPI Peripheral.
> +///
> +typedef struct {
> + ///
> + /// Vendor device path specifying Vendor GUID for SPI Host controller or
> SPI Peripheral.
> + ///
> + VENDOR_DEVICE_PATH Vendor;
> + ///
> + /// Controller device path to distinguish between two instances of SPI
> controller or SPI Peripheral.
> + ///
> + CONTROLLER_DEVICE_PATH Controller;
> + ///
> + /// Signify the end of Device Path.
> + ///
> + EFI_DEVICE_PATH_PROTOCOL End;
> +} EFI_SPI_DEVICE_PATH;
> +
> +///
> +/// Note: The revised UEFI PI 1.6 specification does not specify values for
> the
> +/// members below. The order matches the specification.
> +///
> +typedef enum {
> + ///
> + /// Data flowing from the host to the SPI peripheral
> + /// or Data flowing from the SPI peripheral to the host
> + ///
> + SPI_TRANSACTION_DATA = 0,
> +
> + ///
> + /// Command to send to SPI Peripheral ///
> SPI_TRANSACTION_COMMAND,
> +
> + ///
> + /// Offset in SPI Peripheral from/to which data is to be read/written
> + /// SPI_TRANSACTION_ADDRESS,
> +
> + ///
> + /// Optional control bits that follow the address bits.
> + /// These bits are driven by the controller if they are specified.
> + ///
> + /// NOTE This field should be counted in clocks not number of bits
> + received by the /// serial flash. The SPI master drives the bus
> + during "mode bits" cycles; /// Example: If 8 mode bits are needed
> + with a quad input address phase command, then /// length for this type of
> transaction would be 2.
> + ///
> + SPI_TRANSACTION_MODE,
> +
> + ///
> + /// Clock cycles during which no data is transferred to or from a memory.
> + /// the master tri-states the bus during "dummy" cycles.
> + /// No data (WriteBuffer = NULL and ReadBuffer = NULL) can be
> + specified /// in SPI Transaction. if these buffer are specified, then
> + SPI HOST controller must ignore /// these buffers.
> + ///
> + SPI_TRANSACTION_DUMMY,
> +
> + ///
> + /// Maximum element that should be present in any enum.
> + ///
> + SPI_TRANSACTION_MAX
> +
> +} EFI_SPI_TRANSACTION_TYPE;
> +
> +///
> +/// SPI Peripheral transaction bus width /// /// The SPI_TRANSFER_LINE
> +describes the number of data lines to use for /// a transaction.
> +///
> +typedef enum {
> + /// One line transfer
> + SPI_TRANSACTION_BUS_WIDTH_1 = 1,
> +
> + /// Two line transfer
> + SPI_TRANSACTION_BUS_WIDTH_2 = 2,
> +
> + /// Four line transfer
> + SPI_TRANSACTION_BUS_WIDTH_4 = 4,
> +
> + /// Eight line transfer
> + SPI_TRANSACTION_BUS_WIDTH_8 = 8,
> +
> + /// Maximum element that should be present in any enum.
> + SPI_TRANSACTION_BUS_WIDTH
> +} EFI_SPI_TRANSACTION_BUS_WIDTH;
> +
> +///
> +/// The EFI_SPI_BUS_TRANSACTION data structure contains the description
> +of the /// SPI transaction to perform on the host controller.
> +///
> +typedef struct _EFI_SPI_BUS_TRANSACTION {
> + ///
> + /// Type of transaction specified by one of the
> +EFI_SPI_TRANSACTION_TYPE
> + /// values.
> + ///
> + EFI_SPI_TRANSACTION_TYPE TransactionType;
> +
> + ///
> + /// TRUE if the transaction is being debugged. 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.
> + ///
> + BOOLEAN DebugTransaction;
> +
> + ///
> + /// SPI bus width in bits: 1, 2, 4, 8 ///
> + UINT32 BusWidth;
> +
> + ///
> + /// Transfer may be input or output on both the /// rising and
> + falling edges of the clock.
> + ///
> + BOOLEAN DoubleTransferRate;
> +
> + ///
> + /// Frame size in bits, range: 1 - 32 ///
> + UINT32 FrameSize;
> +
> + /// For TransactionType command/address/data, number of bytes needed
> + to complete the /// transaction. (Read or write or both).
> + /// e.g. for 3 byte address the Length is 3.
> + ///
> + /// For TransactionType dummy/mode, the clock cycles needed to
> + complete the /// transaction.
> + /// e.g. if 1 byte (8 bits) of mode is to be transferred on 2 data bus.
> + /// then clock cycles needed are 8/2 = 4. so Length is 4.
> + ///
> + UINT32 Length;
> +
> + ///
> + /// Buffer containing data to send to the SPI peripheral /// Frame
> + sizes 1 - 8 bits: UINT8 (one byte) per frame /// Frame sizes 7 - 16
> + bits : UINT16 (two bytes) per frame /// Can be NULL if the SPI
> + TransactionType is SPI_TRANSACTION_DUMMY.
> + ///
> + UINT8 *WriteBuffer;
> +
> + ///
> + /// Buffer to receive the data from the SPI peripheral
> + /// * 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
> + /// Can be NULL if the SPI TransactionType is SPI_TRANSACTION_DUMMY
> + ///
> + UINT8 *ReadBuffer;
> +} EFI_SPI_BUS_TRANSACTION;
> +
> +///
> +/// SPI device request
> +///
> +/// The EFI_SPI_REQUEST_PACKET describes a single SPI transaction.
> +///
> +typedef struct {
> + ///
> + /// Number of elements in the Transaction array
> + ///
> + UINTN TransactionCount;
> +
> + ///
> + /// Description of the SPI TransactionTransaction
> + ///
> + EFI_SPI_BUS_TRANSACTION Transaction [1];
> +} EFI_SPI_REQUEST_PACKET;
> +
> +#endif // __PI_SPI_H__
> diff --git a/Silicon/NXP/Include/Protocol/SpiConfiguration.h
> b/Silicon/NXP/Include/Protocol/SpiConfiguration.h
> new file mode 100644
> index 0000000..6383151
> --- /dev/null
> +++ b/Silicon/NXP/Include/Protocol/SpiConfiguration.h
> @@ -0,0 +1,313 @@
> +/** @file
> + This file defines the SPI Configuration Protocol.
> +
> + Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> + Copyright 2017-2018 NXP
> +
> + This program and the accompanying materials are licensed and made
> + available under the terms and conditions of the BSD License which
> + accompanies this distribution. The full text of the license may be
> + found at http://opensource.org/licenses/bsd-license.php
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> + @par Revision Reference:
> + This Protocol was introduced in UEFI PI Specification 1.6.
> +
> +**/
> +
> +#ifndef __SPI_CONFIGURATION_PROTOCOL_H__ #define
> +__SPI_CONFIGURATION_PROTOCOL_H__
> +
> +///
> +/// Global ID for the SPI Configuration Protocol /// #define
> +EFI_SPI_CONFIGURATION_GUID \
> + { 0x85a6d3e6, 0xb65b, 0x4afc, \
> + { 0xb3, 0x8f, 0xc6, 0xd5, 0x4a, 0xf6, 0xdd, 0xc8 }}
> +
> +///
> +/// Macros to easily specify frequencies in hertz, kilohertz and megahertz.
> +///
> +#define Hz(Frequency) (Frequency)
> +#define KHz(Frequency) (1000 * Hz (Frequency)) #define MHz(Frequency)
> +(1000 * KHz (Frequency))
> +
> +typedef struct _EFI_SPI_PERIPHERAL EFI_SPI_PERIPHERAL;
> +
> +/**
> + Manipulate the chip select for a SPI device.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + Update the value of the chip select line for a SPI peripheral.
> + The SPI bus layer calls this routine either in the board layer or in
> + the SPI controller to manipulate the chip select pin at the start and
> + end of a SPI transaction.
> +
> + @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data
> structure
> + describing the SPI peripheral whose chip select pin
> + is to be manipulated. The routine may access the
> + ChipSelectParameter field to gain sufficient
> + context to complete the operation.
> + @param[in] PinValue The value to be applied to the chip select line of
> + the SPI peripheral.
> +
> + @retval EFI_SUCCESS The chip select was set successfully
> + @retval EFI_NOT_READY Support for the chip select is not properly
> + initialized @retval
> + EFI_INVALID_PARAMETER The SpiPeripheral->ChipSelectParameter value
> + is invalid
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_CHIP_SELECT) (
> + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
> + IN BOOLEAN PinValue
> + );
> +
> +/**
> + Set up the clock generator to produce the correct clock frequency,
> +phase and
> + polarity for a SPI chip.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + This routine updates the clock generator to generate the correct
> + frequency and polarity for the SPI clock.
> +
> + @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure
> from
> + which the routine can access the ClockParameter,
> + ClockPhase and ClockPolarity fields. The routine
> + also has access to the names for the SPI bus and
> + chip which can be used during debugging.
> + @param[in] ClockHz Pointer to the requested clock frequency. The
> clock
> + generator will choose a supported clock frequency
> + which is less then or equal to this value.
> + Specify zero to turn the clock generator off.
> + The actual clock frequency supported by the clock
> + generator will be returned.
> +
> + @retval EFI_SUCCESS The clock was set up successfully
> + @retval EFI_UNSUPPORTED The SPI controller was not able to support the
> + frequency requested by CLockHz
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *EFI_SPI_CLOCK) (
> + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
> + IN UINT32 *ClockHz
> + );
> +
> +///
> +/// The EFI_SPI_PART data structure provides a description of a SPI
> +part which /// is independent of the use on the board. This data is
> +available directly /// from the part's datasheet and may be provided by the
> vendor.
> +///
> +typedef struct _EFI_SPI_PART {
> + ///
> + /// A Unicode string specifying the SPI chip vendor.
> + ///
> + CONST CHAR16 *Vendor;
> +
> + ///
> + /// A Unicode string specifying the SPI chip part number.
> + ///
> + CONST CHAR16 *PartNumber;
> +
> + ///
> + /// The minimum SPI bus clock frequency used to access this chip.
> + This value /// may be specified in the chip's datasheet. If not, use the value
> of zero.
> + ///
> + UINT32 MinClockHz;
> +
> + ///
> + /// The maximum SPI bus clock frequency used to access this chip.
> + This value /// is found in the chip's datasheet.
> + ///
> + UINT32 MaxClockHz;
> +
> + ///
> + /// Specify the polarity of the chip select pin. This value can be
> +found in
> + /// the SPI chip's datasheet. Specify TRUE when a one asserts the
> +chip select
> + ///and FALSE when a zero asserts the chip select.
> + ///
> + BOOLEAN ChipSelectPolarity;
> +} EFI_SPI_PART;
> +
> +///
> +/// The EFI_SPI_BUS data structure provides the connection details
> +between the /// physical SPI bus and the EFI_SPI_HC_PROTOCOL instance
> +which controls that /// SPI bus. This data structure also describes the
> +details of how the clock is /// generated for that SPI bus. Finally
> +this data structure provides the list /// of physical SPI devices which are
> attached to the SPI bus.
> +///
> +typedef struct _EFI_SPI_BUS {
> + ///
> + /// A Unicode string describing the SPI bus
> + ///
> + CONST CHAR16 *FriendlyName;
> +
> + ///
> + /// Address of the first EFI_SPI_PERIPHERAL data structure connected
> + to this /// bus. Specify NULL if there are no SPI peripherals connected to
> this bus.
> + ///
> + CONST EFI_SPI_PERIPHERAL *Peripherallist;
> +
> + ///
> + /// Address of the first Runtime EFI_SPI_PERIPHERAL data structure
> + connected to this /// bus. Specify NULL if there are no Runtime SPI
> peripherals connected to this bus.
> + ///
> + CONST EFI_SPI_PERIPHERAL *RuntimePeripherallist;
> +
> + ///
> + /// Address of an EFI_DEVICE_PATH_PROTOCOL data structure which
> + uniquely /// describes the SPI controller.
> + ///
> + CONST EFI_DEVICE_PATH_PROTOCOL *ControllerPath;
> +
> + ///
> + /// Address of the routine which controls the clock used by the SPI
> + bus for /// this SPI peripheral. The SPI host controller's clock
> + routine is called /// when this value is set to NULL.
> + ///
> + EFI_SPI_CLOCK Clock;
> +
> + ///
> + /// Address of a data structure containing the additional values
> +which
> + /// describe the necessary control for the clock. When Clock is NULL,
> + /// the declaration for this data structure is provided by the vendor
> +of the
> + /// host's SPI controller driver. When Clock is not NULL, the
> +declaration for
> + /// this data structure is provided by the board layer.
> + ///
> + VOID *ClockParameter;
> +} EFI_SPI_BUS;
> +
> +///
> +/// The EFI_SPI_PERIPHERAL data structure describes how a specific
> +block of /// logic which is connected to the SPI bus. This data
> +structure also selects /// which upper level driver is used to manipulate this
> SPI device.
> +/// The SpiPeripheraLDriverGuid is available from the vendor of the SPI
> +/// peripheral driver.
> +///
> +struct _EFI_SPI_PERIPHERAL {
> + ///
> + /// Address of the next EFI_SPI_PERIPHERAL data structure. Specify
> +NULL if
> + /// the current data structure is the last one on the SPI bus.
> + ///
> + CONST EFI_SPI_PERIPHERAL *NextSpiPeripheral;
> +
> + ///
> + /// A unicode string describing the function of the SPI part.
> + ///
> + CONST CHAR16 *FriendlyName;
> +
> + ///
> + /// Address of a GUID provided by the vendor of the SPI peripheral driver.
> + /// Instead of using a " EFI_SPI_IO_PROTOCOL" GUID, the SPI bus
> + driver uses /// this GUID to identify an EFI_SPI_IO_PROTOCOL data
> + structure and to /// provide the connection points for the SPI peripheral
> drivers.
> + /// This reduces the comparison logic in the SPI peripheral driver's
> + /// Supported routine.
> + ///
> + CONST GUID *SpiPeripheralDriverGuid;
> +
> + ///
> + /// The address of an EFI_SPI_PART data structure which describes this
> chip.
> + ///
> + CONST EFI_SPI_PART *SpiPart;
> +
> + ///
> + /// The maximum clock frequency is specified in the EFI_SPI_P ART.
> + When this /// this value is non-zero and less than the value in the
> + EFI_SPI_PART then /// this value is used for the maximum clock frequency
> for the SPI part.
> + ///
> + UINT32 MaxClockHz;
> +
> + ///
> + /// Specify the idle value of the clock as found in the datasheet.
> + /// Use zero (0) if the clock'S idle value is low or one (1) if the
> + the /// clock's idle value is high.
> + ///
> + BOOLEAN ClockPolarity;
> +
> + ///
> + /// Specify the clock delay after chip select. Specify zero (0) to
> + delay an /// entire clock cycle or one (1) to delay only half a clock cycle.
> + ///
> + BOOLEAN ClockPhase;
> +
> + ///
> + /// SPI peripheral attributes, select zero or more of:
> + /// * SPI_HALF_DUPLEX - The SPI peripheral supports only half duplex
> + /// transactions
> + /// * SPI_SUPPORTS_WRITE_ONLY_OPERATIONS - The SPI peripheral
> supports
> + /// write only transactions.
> + /// * SPI_SUPPORTS_READ_ONLY_OPERATIONS - The SPI peripheral
> supports
> + /// read only transactions.
> + /// * SPI_SUPPORTS_DTR_OPERATIONS - The SPI peripheral supports
> + /// Double Transfer Rate (DTR).
> + /// DTR : Transfer may be input or output on both the
> + /// rising and falling edges of the clock.
> + /// * SPI_SUPPORTS_2_B1T_DATA_BUS_W1DTH - The SPI peripheral is
> wired to
> + /// support a 2-bit data bus
> + /// * SPI_SUPPORTS_4_B1T_DATA_BUS_W1DTH - The SPI peripheral is
> wired to
> + /// support a 4-bit data bus
> + /// * SPI_SUPPORTS_8_B1T_DATA_BUS_W1DTH - The SPI peripheral is
> wired to
> + /// support a 8-bit data bus
> + ///
> + UINT32 Attributes;
> +
> + ///
> + /// Address of a vendor specific data structure containing additional
> + board /// configuration details related to the SPI chip. The SPI
> + peripheral layer /// uses this data structure when configuring the chip.
> + ///
> + CONST VOID *ConfigurationData;
> +
> + ///
> + /// The address of an EFI_SPI_BUS data structure which describes the
> + SPI bus /// to which this chip is connected.
> + ///
> + CONST EFI_SPI_BUS *SpiBus;
> +
> + ///
> + /// Address of the routine which controls the chip select pin for
> + this SPI /// peripheral. Call the SPI host controller's chip select
> + routine when this /// value is set to NULL.
> + ///
> + EFI_SPI_CHIP_SELECT ChipSelect;
> +
> + ///
> + /// Address of a data structure containing the additional values
> +which
> + /// describe the necessary control for the chip select. When
> +ChipSelect is
> + /// NULL, the declaration for this data structure is provided by the
> +vendor
> + /// of the host's SPI controller driver. The vendor's documentation
> +specifies
> + /// the necessary values to use for the chip select pin selection and
> + /// control. When Chipselect is not NULL, the declaration for this
> +data
> + /// structure is provided by the board layer.
> + ///
> + VOID *ChipSelectParameter;
> +};
> +
> +///
> +/// Describe the details of the board's SPI busses to the SPI driver stack.
> +/// The board layer uses the EFI_SPI_CONFIGURATION_PROTOCOL to
> expose
> +the data /// tables which describe the board's SPI busses, The SPI bus
> +layer uses these /// tables to configure the clock, chip select and
> +manage the SPI transactions /// on the SPI controllers.
> +///
> +typedef struct _EFI_SPI_CONFIGURATION_PROTOCOL {
> + ///
> + /// The number of SPI busses on the board.
> + ///
> + UINT32 BusCount;
> +
> + ///
> + /// The address of an array of EFI_SPI_BUS data structure addresses.
> + ///
> + CONST EFI_SPI_BUS *CONST *CONST Buslist; }
> +EFI_SPI_CONFIGURATION_PROTOCOL;
> +
> +extern EFI_GUID gEfiSpiConfigurationProtocolGuid;
> +
> +#endif // __SPI_CONFIGURATION_PROTOCOL_H__
> diff --git a/Silicon/NXP/Include/Protocol/SpiHc.h
> b/Silicon/NXP/Include/Protocol/SpiHc.h
> new file mode 100644
> index 0000000..86d27b3
> --- /dev/null
> +++ b/Silicon/NXP/Include/Protocol/SpiHc.h
> @@ -0,0 +1,208 @@
> +/** @file
> + This file defines the SPI Host Controller Protocol.
> +
> + Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> + Copyright 2017-2018 NXP
> +
> + This program and the accompanying materials are licensed and made
> + available under the terms and conditions of the BSD License which
> + accompanies this distribution. The full text of the license may be
> + found at http://opensource.org/licenses/bsd-license.php
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> + @par Revision Reference:
> + This Protocol was introduced in revised UEFI PI Specification 1.6.
> +
> +**/
> +
> +#ifndef __SPI_HC_PROTOCOL_H__
> +#define __SPI_HC_PROTOCOL_H__
> +
> +#include <Pi/PiSpi.h>
> +#include <Protocol/SpiConfiguration.h>
> +
> +///
> +/// Global ID for the SPI Host Controller Protocol /// #define
> +EFI_SPI_HOST_GUID \
> + { 0xc74e5db2, 0xfa96, 0x4ae2, \
> + { 0xb3, 0x99, 0x15, 0x97, 0x7f, 0xe3, 0x0, 0x2d }}
> +
> +///
> +/// EDK2-style name
> +///
> +#define EFI_SPI_HC_PROTOCOL_GUID EFI_SPI_HOST_GUID
> +
> +typedef struct _EFI_SPI_HC_PROTOCOL EFI_SPI_HC_PROTOCOL;
> +
> +/**
> + Assert or deassert the SPI chip select.
> +
> + This routine is called at TPL_NOTIFY.
> + Update the value of the chip select line for a SPI peripheral. The
> + SPI bus layer calls this routine either in the board layer or in the
> + SPI controller to manipulate the chip select pin at the start and end of a SPI
> transaction.
> +
> + @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
> + @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data
> structure
> + describing the SPI peripheral whose chip select pin
> + is to be manipulated. The routine may access the
> + ChipSelectParameter field to gain sufficient
> + context to complete the operation.
> + @param[in] PinValue The value to be applied to the chip select line of
> + the SPI peripheral.
> +
> + @retval EFI_SUCCESS The chip select was set as requested
> + @retval EFI_NOT_READY Support for the chip select is not properly
> + initialized @retval
> + EFI_INVALID_PARAMETER The ChipSeLect value or its contents are
> + invalid
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *EFI_SPI_HC_PROTOCOL_CHIP_SELECT) (
> + IN CONST EFI_SPI_HC_PROTOCOL *This,
> + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
> + IN BOOLEAN PinValue
> + );
> +
> +/**
> + Set up the clock generator to produce the correct clock frequency,
> +phase and
> + polarity for a SPI chip.
> +
> + This routine is called at TPL_NOTIFY.
> + This routine updates the clock generator to generate the correct
> + frequency and polarity for the SPI clock.
> +
> + @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
> + @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure
> from
> + which the routine can access the ClockParameter,
> + ClockPhase and ClockPolarity fields. The routine
> + also has access to the names for the SPI bus and
> + chip which can be used during debugging.
> + @param[in] ClockHz Pointer to the requested clock frequency. The SPI
> + host controller will choose a supported clock
> + frequency which is less then or equal to this
> + value. Specify zero to turn the clock generator
> + off. The actual clock frequency supported by the
> + SPI host controller will be returned.
> +
> + @retval EFI_SUCCESS The clock was set up successfully
> + @retval EFI_UNSUPPORTED The SPI controller was not able to support the
> + frequency requested by ClockHz
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *EFI_SPI_HC_PROTOCOL_CLOCK) (
> + IN CONST EFI_SPI_HC_PROTOCOL *This,
> + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
> + IN UINT32 *ClockHz
> + );
> +
> +/**
> + Perform the SPI transaction on the SPI peripheral using the SPI host
> + controller.
> +
> + This routine is called at TPL_NOTIFY.
> + This routine synchronously returns EFI_SUCCESS indicating that the
> + asynchronous SPI transaction was started. The routine then waits for
> + completion of the SPI transaction prior to returning the final
> + transaction status.
> +
> + @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
> + @param[in] RequestPacket Pointer to a EFI_SPI_REQUEST_PACKET
> containing
> + the description of the SPI transactions to perform.
> +
> + @retval EFI_SUCCESS The transaction completed successfully.
> + @retval EFI_ALREADY_STARTED The controller is busy with another
> transaction.
> + @retval EFI_BAD_BUFFER_SIZE The Length value in SPI Transaction is
> wrong.
> + @retval EFI_DEVICE_ERROR There was an SPI error during the
> transaction.
> + @retval EFI_INVALID_PARAMETER The parameters specified in
> RequestPacket are not
> + Valid. or the RequestPacket is NULL.
> + @retval EFI_NO_RESPONSE The SPI device is not responding to the
> slave
> + address. EFI_DEVICE_ERROR will be returned if
> + the controller cannot distinguish when the NACK
> + occurred.
> + @retval EFI_UNSUPPORTED The controller does not support the
> requested
> + transaction.
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *EFI_SPI_HC_PROTOCOL_TRANSACTION) (
> + IN CONST EFI_SPI_HC_PROTOCOL *This,
> + IN EFI_SPI_REQUEST_PACKET *RequestPacket
> + );
> +
> +///
> +/// Support a SPI data transaction between the SPI controller and a SPI chip.
> +///
> +struct _EFI_SPI_HC_PROTOCOL {
> + ///
> + /// Host control attributes, may have zero or more of the following set:
> + /// * SPI_HALF_DUPLEX - The SPI Host Controller supports only half duplex
> + /// transactions
> + /// * SPI_SUPPORTS_WRITE_ONLY_OPERATIONS - The SPI Host Controller
> supports
> + /// write only transactions.
> + /// * SPI_SUPPORTS_READ_ONLY_OPERATIONS - The SPI Host Controller
> supports
> + /// read only transactions.
> + /// * SPI_SUPPORTS_DTR_OPERATIONS - The SPI Host Controller supports
> + /// Double Transfer Rate (DTR).
> + /// DTR : Transfer may be input or output on both the
> + /// rising and falling edges of the clock.
> + /// * SPI_SUPPORTS_2_B1T_DATA_BUS_W1DTH - The SPI Host Controller is
> wired to
> + /// support a 2-bit data bus
> + /// * SPI_SUPPORTS_4_B1T_DATA_BUS_W1DTH - The SPI Host Controller is
> wired to
> + /// support a 4-bit data bus
> + /// * SPI_SUPPORTS_8_B1T_DATA_BUS_W1DTH - The SPI Host Controller is
> wired to
> + /// support a 8-bit data bus
> + /// The SPI host controller must support a 1 - bit bus
> + /// width.
> + /// * HC_TX_FRAME_IN_MOST_SIGNIFICANT_BITS
> + /// - The SPI host controller requires the transmit frame to be in most
> + /// significant bits instead of least significant bits.The host driver
> + /// will adjust the frames if necessary.
> + /// * HC_RX_FRAME_IN_MOST_SIGNIFICANT_BITS
> + /// - The SPI host controller places the receive frame to be in most
> + /// significant bits instead of least significant bits.The host driver
> + /// will adjust the frames to be in the least significant bits if
> + /// necessary.
> + /// * SPI_TRANSFER_SIZE_INCLUDES_OPCODE
> + /// - Transfer size includes the opcode byte
> + /// * SPI_TRANSFER_SIZE_INCLUDES_ADDRESS
> + /// - Transfer size includes the 4 address bytes
> + UINT32 Attributes;
> +
> + ///
> + /// Mask of frame sizes which the SPI host controller supports. Frame
> + size of /// N-bits is supported when bit N-1 is set. The host
> + controller must support /// a frame size of 8-bits.
> + ///
> + UINT32 FrameSizeSupportMask;
> +
> + ///
> + /// Maximum transfer size in bytes: 1 - Oxffffffff ///
> + UINT32 MaximumTransferBytes;
> +
> + ///
> + /// Assert or deassert the SPI chip select.
> + ///
> + EFI_SPI_HC_PROTOCOL_CHIP_SELECT ChipSelect;
> +
> + ///
> + /// Set up the clock generator to produce the correct clock
> + frequency, phase /// and polarity for a SPI chip.
> + ///
> + EFI_SPI_HC_PROTOCOL_CLOCK Clock;
> +
> + ///
> + /// Perform the SPI transaction on the SPI peripheral using the SPI
> +host
> + /// controller.
> + ///
> + EFI_SPI_HC_PROTOCOL_TRANSACTION Transaction;
> +};
> +
> +extern EFI_GUID gEfiSpiHcProtocolGuid;
> +
> +#endif // __SPI_HC_PROTOCOL_H__
> diff --git a/Silicon/NXP/Include/Protocol/SpiIo.h
> b/Silicon/NXP/Include/Protocol/SpiIo.h
> new file mode 100644
> index 0000000..c08c3bd
> --- /dev/null
> +++ b/Silicon/NXP/Include/Protocol/SpiIo.h
> @@ -0,0 +1,168 @@
> +/** @file
> + This file defines the SPI I/O Protocol.
> +
> + Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> + Copyright 2017-2018 NXP
> +
> + This program and the accompanying materials are licensed and made
> + available under the terms and conditions of the BSD License which
> + accompanies this distribution. The full text of the license may be
> + found at http://opensource.org/licenses/bsd-license.php
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> + @par Revision Reference:
> + This Protocol was introduced in revised UEFI PI Specification 1.6.
> +
> +**/
> +
> +#ifndef __SPI_IO_PROTOCOL_H__
> +#define __SPI_IO_PROTOCOL_H__
> +
> +#include <Pi/PiSpi.h>
> +#include <Protocol/LegacySpiController.h> #include
> +<Protocol/SpiConfiguration.h>
> +
> +typedef struct _EFI_SPI_IO_PROTOCOL EFI_SPI_IO_PROTOCOL;
> +
> +/**
> + 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
> + transactions to the SPI controller for execution on the SPI bus.
> +
> + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
> + @param[in] RequestPacket Pointer to an EFI_SPI_REQUEST_PACKET
> + structure describing the SPI transactions.
> +
> + @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.
> +
> + @retval EFI_SUCCESS The transaction completed successfully.
> + @retval EFI_ALREADY_STARTED The controller is busy with another
> transaction.
> + @retval EFI_BAD_BUFFER_SIZE The Length value in SPI Transaction is
> wrong.
> + @retval EFI_DEVICE_ERROR There was an SPI error during the
> transaction.
> + @retval EFI_INVALID_PARAMETER The parameters specified in
> RequestPacket are not
> + Valid. or the RequestPacket is NULL.
> + @retval EFI_NOT_READY Support for the chip select is not properly
> + initialized
> + @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents
> are
> + invalid
> + @retval EFI_NO_RESPONSE The SPI device is not responding to the
> slave
> + address. EFI_DEVICE_ERROR will be returned if
> + the controller cannot distinguish when the NACK
> + occurred.
> + @retval EFI_UNSUPPORTED The controller does not support the
> requested
> + transaction. or The SPI controller was not able to support
> + the frequency requested by ClockHz
> +**/ typedef EFI_STATUS (EFIAPI *EFI_SPI_IO_PROTOCOL_TRANSACTION) (
> + IN CONST EFI_SPI_IO_PROTOCOL *This,
> + IN EFI_SPI_REQUEST_PACKET *RequestPacket,
> + IN UINT32 ClockHz OPTIONAL
> + );
> +
> +/**
> + 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 SpiP eripheral - >SpiBus pointing at
> + wrong bus,
> + or the SpiP eripheral - >SpiPart is
> + NULL
> +
> +**/
> +typedef EFI_STATUS
> +(EFIAPI *EFI_SPI_IO_PROTOCOL_UPDATE_SPI_PERIPHERAL) (
> + IN CONST EFI_SPI_IO_PROTOCOL *This,
> + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral
> + );
> +
> +///
> +/// Support managed SPI data transactions between the SPI controller
> +and a SPI /// chip.
> +///
> +struct _EFI_SPI_IO_PROTOCOL {
> + ///
> + /// Address of an EFI_SPI_PERIPHERAL data structure associated with
> +this
> + /// protocol instance.
> + ///
> + CONST EFI_SPI_PERIPHERAL *SpiPeripheral;
> +
> + ///
> + /// Address of the original EFI_SPI_PERIPHERAL data structure
> + associated with /// this protocol instance.
> + ///
> + CONST EFI_SPI_PERIPHERAL *OriginalSpiPeripheral;
> +
> + ///
> + /// Mask of frame sizes which the SPI 10 layer supports. Frame size
> + of N-bits /// is supported when bit N-1 is set. The host controller
> + must support a /// frame size of 8-bits. Frame sizes of 16, 24 and
> + 32-bits are converted to /// 8-bit frame sizes by the SPI bus layer
> + if the frame size is not supported /// by the SPI host controller.
> + ///
> + UINT32 FrameSizeSupportMask;
> +
> + ///
> + /// Maximum transfer size in bytes: 1 - Oxffffffff ///
> + UINT32 MaximumTransferBytes;
> +
> + ///
> + /// Transaction attributes: One or more from:
> + /// * SPI_HALF_DUPLEX
> + /// - The SPI host or peripheral supports only half duplex transactions
> + /// * SPI_SUPPORTS_WRITE_ONLY_OPERATIONS
> + /// - The SPI host or peripheral supports write only transactions.
> + /// * SPI_SUPPORTS_READ_ONLY_OPERATIONS
> + /// - The SPI host or peripheral support read only transactions.
> + /// * SPI_SUPPORTS_DTR_OPERATIONS
> + /// - The SPI SPI host and peripheral supports Double Transfer Rate (DTR).
> + /// DTR : Transfer may be input or output on both the
> + /// rising and falling edges of the clock.
> + /// * SPI_SUPPORTS_2_B1T_DATA_BUS_W1DTH
> + /// - The SPI host and peripheral supports a 2-bit data bus
> + /// * SPI_SUPPORTS_4_BIT_DATA_BUS_W1DTH
> + /// - The SPI host and peripheral supports a 4-bit data bus
> + /// * SPI_SUPPORTS_8_BIT_DATA_BUS_W1DTH
> + /// - The SPI host and peripheral supports a 8-bit data bus
> + /// * SPI_TRANSFER_SIZE_INCLUDES_OPCODE
> + /// - Transfer size includes the opcode byte
> + /// * SPI_TRANSFER_SIZE_INCLUDES_ADDRESS
> + /// - Transfer size includes the 4 address bytes
> + UINT32 Attributes;
> +
> + ///
> + /// Pointer to legacy SPI controller protocol /// CONST
> + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *LegacySpiProtocol;
> +
> + ///
> + /// Initiate a SPI transaction between the host and a SPI peripheral.
> + ///
> + EFI_SPI_IO_PROTOCOL_TRANSACTION Transaction;
> +
> + ///
> + /// Update the SPI peripheral associated with this SPI 10 instance.
> + ///
> + EFI_SPI_IO_PROTOCOL_UPDATE_SPI_PERIPHERAL UpdateSpiPeripheral; };
> +
> +#endif // __SPI_IO_PROTOCOL_H__
> diff --git a/Silicon/NXP/Include/Protocol/SpiNorFlash.h
> b/Silicon/NXP/Include/Protocol/SpiNorFlash.h
> new file mode 100644
> index 0000000..2e57107
> --- /dev/null
> +++ b/Silicon/NXP/Include/Protocol/SpiNorFlash.h
> @@ -0,0 +1,269 @@
> +/** @file
> + This file defines the SPI NOR Flash Protocol.
> +
> + Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> + Copyright 2018 NXP
> +
> + This program and the accompanying materials are licensed and made
> + available under the terms and conditions of the BSD License which
> + accompanies this distribution. The full text of the license may be
> + found at http://opensource.org/licenses/bsd-license.php
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> + @par Revision Reference:
> + This Protocol was introduced in revised UEFI PI Specification 1.6.
> +
> +**/
> +
> +#ifndef __SPI_NOR_FLASH_PROTOCOL_H__
> +#define __SPI_NOR_FLASH_PROTOCOL_H__
> +
> +#include <Protocol/SpiConfiguration.h>
> +
> +///
> +/// Global ID for the SPI NOR Flash Protocol /// #define
> +EFI_SPI_NOR_FLASH_PROTOCOL_GUID \
> + { 0xb57ec3fe, 0xf833, 0x4ba6, \
> + { 0x85, 0x78, 0x2a, 0x7d, 0x6a, 0x87, 0x44, 0x4b }}
> +
> +typedef struct _EFI_SPI_NOR_FLASH_PROTOCOL
> EFI_SPI_NOR_FLASH_PROTOCOL;
> +
> +/**
> + Read the 3 byte manufacture and device ID from the SPI flash.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + This routine reads the 3 byte manufacture and device ID from the
> + flash part filling the buffer provided.
> +
> + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
> structure.
> + @param[out] Buffer Pointer to a 3 byte buffer to receive the manufacture
> and
> + device ID.
> +
> +
> +
> + @retval EFI_SUCCESS The manufacture and device ID was read
> + successfully.
> + @retval EFI_INVALID_PARAMETER Buffer is NULL
> + @retval EFI_DEVICE_ERROR Invalid data received from SPI flash part.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_GET_FLASH_ID) (
> + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
> + OUT UINT8 *Buffer
> + );
> +
> +/**
> + Read data from the SPI flash.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + This routine reads data from the SPI part in the buffer provided.
> +
> + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
> + structure.
> + @param[in] FlashAddress Address in the flash to start reading
> + @param[in] LengthInBytes Read length in bytes
> + @param[out] Buffer Address of a buffer to receive the data
> +
> + @retval EFI_SUCCESS The data was read successfully.
> + @retval EFI_INVALID_PARAMETER Buffer is NULL, or
> + FlashAddress >= This->FlashSize, or
> + LengthInBytes > This->FlashSize -
> + FlashAddress
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_READ_DATA) (
> + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
> + IN UINT32 FlashAddress,
> + IN UINT32 LengthInBytes,
> + OUT UINT8 *Buffer
> + );
> +
> +/**
> + Read the flash status register.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + This routine reads the flash part status register.
> +
> + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
> + structure.
> + @param[in] LengthInBytes Number of status bytes to read.
> + @param[out] FlashStatus Pointer to a buffer to receive the flash status.
> +
> + @retval EFI_SUCCESS The status register was read successfully.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_READ_STATUS) (
> + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
> + IN UINT32 LengthInBytes,
> + OUT UINT8 *FlashStatus
> + );
> +
> +/**
> + Write the flash status register.
> +
> + This routine must be called at or below TPL_N OTIFY.
> + This routine writes the flash part status register.
> +
> + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
> + structure.
> + @param[in] LengthInBytes Number of status bytes to write.
> + @param[in] FlashStatus Pointer to a buffer containing the new status.
> +
> + @retval EFI_SUCCESS The status write was successful.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate the write buffer.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_STATUS) (
> + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
> + IN UINT32 LengthInBytes,
> + IN UINT8 *FlashStatus
> + );
> +
> +/**
> + Write data to the SPI flash.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + This routine breaks up the write operation as necessary to write the
> + data to the SPI part.
> +
> + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
> + structure.
> + @param[in] FlashAddress Address in the flash to start writing
> + @param[in] LengthInBytes Write length in bytes
> + @param[in] Buffer Address of a buffer containing the data
> +
> + @retval EFI_SUCCESS The data was written successfully.
> + @retval EFI_INVALID_PARAMETER Buffer is NULL, or
> + FlashAddress >= This->FlashSize, or
> + LengthInBytes > This->FlashSize - FlashAddress
> + @retval EFI_OUT_OF_RESOURCES Insufficient memory to copy buffer.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_DATA) (
> + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
> + IN UINT32 FlashAddress,
> + IN UINT32 LengthInBytes,
> + IN UINT8 *Buffer
> + );
> +
> +/**
> + Efficiently erases one or more 4KiB regions in the SPI flash.
> +
> + This routine must be called at or below TPL_NOTIFY.
> + This routine uses a combination of 4 KiB and larger blocks to erase
> + the specified area.
> +
> + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
> + structure.
> + @param[in] FlashAddress Address within a 4 KiB block to start erasing
> + @param[in] BlockCount Number of 4 KiB blocks to erase
> +
> + @retval EFI_SUCCESS The erase was completed successfully.
> + @retval EFI_INVALID_PARAMETER FlashAddress >= This->FlashSize, or
> + BlockCount * 4 KiB
> + > This->FlashSize - FlashAddress
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_ERASE) (
> + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
> + IN UINT32 FlashAddress,
> + IN UINT32 BlockCount
> + );
> +
> +///
> +/// The EFI_SPI_NOR_FLASH_PROTOCOL exists in the SPI peripheral layer.
> +/// This protocol manipulates the SPI NOR flash parts using a common
> +set of /// commands. The board layer provides the interconnection and
> +configuration /// details for the SPI NOR flash part. The SPI NOR flash
> +driver uses this /// configuration data to expose a generic interface
> +which provides the /// following APls:
> +/// * Read manufacture and device ID
> +/// * Read data
> +/// * Read data using low frequency
> +/// * Read status
> +/// * Write data
> +/// * Erase 4 KiB blocks
> +/// * Erase 32 or 64 KiB blocks
> +/// * Write status
> +/// The EFI_SPI_NOR_FLASH_PROTOCOL also exposes some APls to set the
> +security /// features on the legacy SPI flash controller.
> +///
> +struct _EFI_SPI_NOR_FLASH_PROTOCOL {
> + ///
> + /// Pointer to an EFI_SPI_PERIPHERAL data structure
> + ///
> + CONST EFI_SPI_PERIPHERAL *SpiPeripheral;
> +
> + ///
> + /// Flash size in bytes
> + ///
> + UINT32 FlashSize;
> +
> + ///
> + /// Manufacture and Device ID
> + ///
> + UINT8 Deviceid[3];
> +
> + ///
> + /// Erase block size in bytes
> + ///
> + UINT32 EraseBlockBytes;
> +
> + ///
> + /// Page Write size in bytes
> + ///
> + UINT32 PageWriteSize;
> +
> + ///
> + /// Read the 3 byte manufacture and device ID from the SPI flash.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_GET_FLASH_ID GetFlashid;
> +
> + ///
> + /// Read data from the SPI flash.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_READ_DATA ReadData;
> +
> + ///
> + /// Low frequency read data from the SPI flash.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_READ_DATA LfReadData;
> +
> + ///
> + /// Read the flash status register.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_READ_STATUS ReadStatus;
> +
> + ///
> + /// Write the flash status register.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_STATUS WriteStatus;
> +
> + ///
> + /// Write data to the SPI flash.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_DATA WriteData;
> +
> + ///
> + /// Efficiently erases one or more 4KiB regions in the SPI flash.
> + ///
> + EFI_SPI_NOR_FLASH_PROTOCOL_ERASE Erase;
> +};
> +
> +extern EFI_GUID gEfiSpiNorFlashProtocolGuid;
> +
> +#endif // __SPI_NOR_FLASH_PROTOCOL_H__
> --
> 2.7.4
^ permalink raw reply [flat|nested] 3+ messages in thread