public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack
@ 2018-02-09 11:53 Pankaj Bansal
  2018-02-09 11:53 ` [PATCH 2/2] NXP/SpiBusDxe: Add SPI Bus driver Pankaj Bansal
  2018-02-20  4:51 ` [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack Pankaj Bansal
  0 siblings, 2 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

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 related	[flat|nested] 3+ messages in thread

* [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

end of thread, other threads:[~2018-02-20  4:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 1/2] Silicon/NXP: Add Modified SPI protocol stack Pankaj Bansal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox