public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sami Mujawar" <sami.mujawar@arm.com>
To: Sahil Kaushal <Sahil.Kaushal@arm.com>, devel@edk2.groups.io
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Leif Lindholm <quic_llindhol@quicinc.com>, sahil <sahil@arm.com>,
	"nd@arm.com" <nd@arm.com>
Subject: Re: [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 12/14] Platform/ARM: Add CadenceQspiNorFlashDeviceLib for NorFlashDxe
Date: Thu, 16 May 2024 16:24:11 +0100	[thread overview]
Message-ID: <1674c97a-a13e-4ae6-ab79-e174b010140d@arm.com> (raw)
In-Reply-To: <20240423055638.1271531-13-Sahil.Kaushal@arm.com>

[-- Attachment #1: Type: text/plain, Size: 39005 bytes --]

Hi Sahil,

Thank you for this patch.

Please find my response inline marked [SAMI].

With that fixed,

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar

On 23/04/2024 06:56 am, Sahil Kaushal wrote:
> From: sahil<sahil@arm.com>
>
> In N1Sdp platform, the SoC is connected to IOFPGA which has a
> Cadence Quad SPI (QSPI) controller. This QSPI controller manages
> the flash chip device via QSPI bus.
>
> This patch adds CadenceQspiNorFlashDeviceLib which is used to
> manage and access the above configuration.
>
> Signed-off-by: sahil<sahil@arm.com>
> ---
>   Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.inf |   32 +
>   Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.h   |   44 +
>   Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.c   | 1011 ++++++++++++++++++++
>   3 files changed, 1087 insertions(+)
>
> diff --git a/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.inf b/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.inf
> new file mode 100644
> index 000000000000..506876b62285
> --- /dev/null
> +++ b/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.inf
> @@ -0,0 +1,32 @@
> +#/** @file
>
> +#
>
> +#  Component description file for CadenceQspiNorFlashDeviceLib Library
>
> +#
>
> +#  Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
>
> +#
>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +#**/
>
> +
>
> +[Defines]
>
> +  INF_VERSION                = 0x00010005
>
> +  BASE_NAME                  = CadenceQspiNorFlashDeviceLib
>
> +  FILE_GUID                  = ed172366-066b-4998-9b5e-ca7f385a170b
>
> +  MODULE_TYPE                = DXE_RUNTIME_DRIVER
>
> +  VERSION_STRING             = 1.0
>
> +  LIBRARY_CLASS              = NorFlashDeviceLib
>
> +
>
> +[Sources.common]
>
> +  CadenceQspiNorFlashDeviceLib.c
>
> +  CadenceQspiNorFlashDeviceLib.h
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  Platform/ARM/ARM.dec
>
> +
>
> +[LibraryClasses]
>
> +  BaseLib
>
> +  BaseMemoryLib
>
> +  DebugLib
>
> +  IoLib
>
> +  TimerLib
>
> diff --git a/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.h b/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.h
> new file mode 100644
> index 000000000000..d43d27fe5eb4
> --- /dev/null
> +++ b/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.h
> @@ -0,0 +1,44 @@
> +/** @file
>
> +
>
> +  Copyright (c) 2024, ARM Limited. All rights reserved.<BR>
>
> +
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef CADENCE_QSPI_NOR_FLASH_DEVICE_LIB_H_
>
> +#define CADENCE_QSPI_NOR_FLASH_DEVICE_LIB_H_
>
> +
>
> +#define NOR_FLASH_ERASE_RETRY  10
>
> +
>
> +// QSPI Controller defines
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET             0x90
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE            0x01
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE        0x01
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS       19
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS  16
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT         0x02
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS     24
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE        0x01
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_BYTE_3B       0x02
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS     23
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS   20
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C           0x8
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS      7
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(x)  ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS)
>
> +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(x)  ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS)
>
> +
>
> +#define CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET  0xA0
>
> +
>
> +#define CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET  0x94
>
> +
>
> +#define SPINOR_SR_WIP  BIT0                 // Write in progress
>
> +
>
> +#define SPINOR_OP_WREN   0x06               // Write enable
>
> +#define SPINOR_OP_BE_4K  0x20               // Erase 4KiB block
>
> +#define SPINOR_OP_RDID   0x9f               // Read JEDEC ID
>
> +#define SPINOR_OP_RDSR   0x05               // Read status register
>
> +
>
> +#define SPINOR_SR_WIP_POLL_TIMEOUT_MS  1000u // Status Register read timeout
>
> +
>
> +#endif /* CADENCE_QSPI_NOR_FLASH_DEVICE_LIB_H_ */
>
> diff --git a/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.c b/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.c
> new file mode 100644
> index 000000000000..8a416e07f15e
> --- /dev/null
> +++ b/Platform/ARM/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.c
> @@ -0,0 +1,1011 @@
> +/** @file
>
> +
>
> +  Copyright (c) 2024 ARM Limited. All rights reserved.<BR>
>
> +
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/IoLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/NorFlashDeviceLib.h>
>
> +#include <Library/TimerLib.h>
>
> +#include <Library/UefiLib.h>
>
> +
>
> +#include "CadenceQspiNorFlashDeviceLib.h"
>
> +
>
> +/**
>
> +  Execute Flash cmd ctrl and Read Status.
>
> +
>
> +  @param[in]      Instance         NOR flash Instance.
>
> +  @param[in]      Val              Value to be written to Flash cmd ctrl Register.
>
> +
>
> +  @retval         EFI_SUCCESS      Request is executed successfully.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +CdnsQspiExecuteCommand (
>
> +  IN  NOR_FLASH_INSTANCE  *Instance,
>
> +  IN  UINT32              Val
>
> +  )
>
> +{
>
> +  // Set the command
>
> +  MmioWrite32 (
>
> +    Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET,
>
> +    Val
>
> +    );
>
> +  // Execute the command
>
> +  MmioWrite32 (
>
> +    Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET,
>
> +    Val | CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE
>
> +    );
>
> +
>
> +  // Wait until command has been executed
>
> +  while (
>
> +         (MmioRead32 (
>
> +            Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET
>
> +            ) & CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT) ==
>
> +         CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT
>
> +         )
>
> +  {
>
> +    continue;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Converts milliseconds into number of ticks of the performance counter.
>
> +
>
> +  @param[in] Milliseconds  Milliseconds to convert into ticks.
>
> +
>
> +  @retval Milliseconds expressed as number of ticks.
>
> +
>
> +**/
>
> +STATIC
>
> +UINT64
>
> +MilliSecondsToTicks (
>
> +  IN UINTN  Milliseconds
>
> +  )
>
> +{
>
> +  CONST UINT64  NanoSecondsPerTick = GetTimeInNanoSecond (1);
>
> +
>
> +  return (Milliseconds * 1000000) / NanoSecondsPerTick;
>
> +}
>
> +
>
> +/**
>
> +  Poll Status register for NOR flash erase/write completion.
>
> +
>
> +  @param[in]      Instance           NOR flash Instance.
>
> +
>
> +  @retval         EFI_SUCCESS        Request is executed successfully.
>
> +  @retval         EFI_TIMEOUT        Operation timed out.
>
> +  @retval         EFI_DEVICE_ERROR   Controller operartion failed.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +NorFlashPollStatusRegister (
>
> +  IN NOR_FLASH_INSTANCE  *Instance
>
> +  )
>
> +{
>
> +  BOOLEAN  SRegDone;
>
> +  UINT32   val;
>
> +
>
> +  val = (SPINOR_OP_RDSR << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS) |
>
> +        (CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE <<
>
> +         CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS) |
>
> +        CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES (1) |
>
> +        (CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C <<
>
> +         CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS);
>
> +
>
> +  CONST UINT64  TickOut =
>
> +    GetPerformanceCounter () +
>
> +    MilliSecondsToTicks (SPINOR_SR_WIP_POLL_TIMEOUT_MS);
>
> +
>
> +  do {
>
> +    if (GetPerformanceCounter () > TickOut) {
>
> +      DEBUG ((
>
> +        DEBUG_ERROR,
>
> +        "NorFlashPollStatusRegister: Timeout waiting for erase/write.\n"
>
> +        ));
>
> +      return EFI_TIMEOUT;
>
> +    }
>
> +
>
> +    if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
>
> +      return EFI_DEVICE_ERROR;
[SAMI] CdnsQspiExecuteCommand() always wiats in a loop until the 
CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT bit is set and returns success. 
Should CdnsQspiExecuteCommand() implement a timeout? Can you check, 
please? Otherwise these checks do not really make sense.
>
> +    }
>
> +
>
> +    SRegDone =
>
> +      (MmioRead8 (
>
> +         Instance->HostRegisterBaseAddress +
>
> +         CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET
>
> +         )
>
> +       & SPINOR_SR_WIP
>
> +      ) == 0;
>
> +  } while (!SRegDone);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Check whether NOR flash opertions are Locked.
>
> +
>
> +  @param[in]     Instance         NOR flash Instance.
>
> +  @param[in]     BlockAddress     BlockAddress in NOR flash device.
>
> +
>
> +  @retval        FALSE            If NOR flash is not locked.
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +NorFlashBlockIsLocked (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN UINTN               BlockAddress
>
> +  )
>
> +{
>
> +  return FALSE;
>
> +}
>
> +
>
> +/**
>
> +  Unlock NOR flash operations on given block.
>
> +
>
> +  @param[in]      Instance         NOR flash instance.
>
> +  @param[in]      BlockAddress     BlockAddress in NOR flash device.
>
> +
>
> +  @retval         EFI_SUCCESS      NOR flash operations is unlocked.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashUnlockSingleBlock (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN UINTN               BlockAddress
>
> +  )
>
> +{
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Unlock NOR flash operations if it is necessary.
>
> +
>
> +  @param[in]      Instance         NOR flash instance.
>
> +  @param[in]      BlockAddress     BlockAddress in NOR flash device.
>
> +
>
> +  @retval         EFI_SUCCESS      Request is executed successfully.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashUnlockSingleBlockIfNecessary (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN UINTN               BlockAddress
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +
>
> +  if (!NorFlashBlockIsLocked (Instance, BlockAddress)) {
>
> +    Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Enable write to NOR flash device.
>
> +
>
> +  @param[in]      Instance         NOR flash instance.
>
> +
>
> +  @retval         EFI_SUCCESS      Request is executed successfully.
>
> +  @retval       EFI_DEVICE_ERROR  The device reported an error.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +NorFlashEnableWrite (
>
> +  IN  NOR_FLASH_INSTANCE  *Instance
>
> +  )
>
> +{
>
> +  UINT32  val;
>
> +
>
> +  DEBUG ((DEBUG_INFO, "NorFlashEnableWrite()\n"));
>
> +  val = (SPINOR_OP_WREN << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS);
>
> +  if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  The following function presumes that the block has already been unlocked.
>
> +
>
> +  @param[in]      Instance          NOR flash instance.
>
> +  @param[in]      BlockAddress      Block address within the variable region.
>
> +
>
> +  @retval         EFI_SUCCESS       Request is executed successfully.
>
> +  @retval         EFI_DEVICE_ERROR  The device reported an error.
>
> + **/
>
> +EFI_STATUS
>
> +NorFlashEraseSingleBlock (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN UINTN               BlockAddress
>
> +  )
>
> +{
>
> +  UINT32  DevConfigVal;
>
> +  UINT32  EraseOffset;
>
> +
>
> +  EraseOffset = 0x0;
>
> +
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashEraseSingleBlock(BlockAddress=0x%08x)\n",
>
> +    BlockAddress
>
> +    ));
>
> +
>
> +  if (EFI_ERROR (NorFlashEnableWrite (Instance))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  EraseOffset = BlockAddress - Instance->DeviceBaseAddress;
>
> +
>
> +  MmioWrite32 (
>
> +    Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET,
>
> +    EraseOffset
>
> +    );
>
> +
>
> +  DevConfigVal = (SPINOR_OP_BE_4K << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS) |
>
> +                 (CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE <<
>
> +                  CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS) |
>
> +                 CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES (3);
>
> +
>
> +  if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, DevConfigVal))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  This function unlock and erase an entire NOR Flash block.
>
> +
>
> +  @param[in]     Instance       NOR flash Instance of variable store region.
>
> +  @param[in]     BlockAddress   Block address within the variable store region.
>
> +
>
> +  @retval        EFI_SUCCESS    The erase and unlock successfully completed.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashUnlockAndEraseSingleBlock (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN UINTN               BlockAddress
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +  UINTN       Index;
>
> +  EFI_TPL     OriginalTPL;
>
> +
>
> +  NorFlashLock (&OriginalTPL);
>
> +
>
> +  Index = 0;
>
> +  do {
>
> +    // Unlock the block if we have to
>
> +    Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
>
> +    if (EFI_ERROR (Status)) {
>
> +      break;
>
> +    }
>
> +
>
> +    Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
>
> +    if (EFI_ERROR (Status)) {
>
> +      break;
>
> +    }
>
> +
>
> +    Index++;
>
> +  } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
>
> +
>
> +  if (Index == NOR_FLASH_ERASE_RETRY) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error "
>
> +      "(try to erase %d times)\n",
>
> +      BlockAddress,
>
> +      Index
>
> +      ));
>
> +  }
>
> +
>
> +  NorFlashUnlock (OriginalTPL);
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Write a single word to given location.
>
> +
>
> +  @param[in]    Instance          NOR flash Instance of variable store region.
>
> +  @param[in]    WordAddress       The address in NOR flash to write given word.
>
> +  @param[in]    WriteData         The data to write into NOR flash location.
>
> +
>
> +  @retval       EFI_SUCCESS       The write is completed.
>
> +  @retval       EFI_DEVICE_ERROR  The device reported an error.
[SAMI] any other error code?
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashWriteSingleWord (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN UINTN               WordAddress,
>
> +  IN UINT32              WriteData
>
> +  )
>
> +{
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashWriteSingleWord(WordAddress=0x%08x, WriteData=0x%08x)\n",
>
> +    WordAddress,
>
> +    WriteData
>
> +    ));
>
> +
>
> +  if (EFI_ERROR (NorFlashEnableWrite (Instance))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  MmioWrite32 (WordAddress, WriteData);
>
> +  if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Write a full block to given location.
>
> +
>
> +  @param[in]    Instance           NOR flash Instance of variable store region.
>
> +  @param[in]    Lba                The logical block address in NOR flash.
>
> +  @param[in]    DataBuffer         The data to write into NOR flash location.
>
> +  @param[in]    BlockSizeInWords   The number of bytes to write.
>
> +
>
> +  @retval       EFI_SUCCESS        The write is completed.
[SAMI] any other error code? I tihink EFI_DEVICE_ERROR can be returned. 
Can you check the other functions in the file as well, please?
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashWriteFullBlock (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN EFI_LBA             Lba,
>
> +  IN UINT32              *DataBuffer,
>
> +  IN UINT32              BlockSizeInWords
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +  UINTN       WordAddress;
>
> +  UINT32      WordIndex;
>
> +  UINTN       BlockAddress;
>
> +  EFI_TPL     OriginalTPL;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +
>
> +  // Get the physical address of the block
>
> +  BlockAddress = GET_NOR_BLOCK_ADDRESS (
>
> +                   Instance->RegionBaseAddress,
>
> +                   Lba,
>
> +                   BlockSizeInWords * 4
>
> +                   );
>
> +
>
> +  // Start writing from the first address at the start of the block
>
> +  WordAddress = BlockAddress;
>
> +
>
> +  NorFlashLock (&OriginalTPL);
>
> +
>
> +  Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single "
>
> +      "block at 0x%X\n",
>
> +      BlockAddress
>
> +      ));
>
> +    goto EXIT;

[SAMI] According to the edk2 coding guidelines words with all capital 
letters are intended for macros. Change EXIT => exit_handler.

  I know the P30 device lib has this issue as well. But atleast we 
should not repeat this again here.

[/SAMI]

>
> +  }
>
> +
>
> +  for (WordIndex = 0;
>
> +       WordIndex < BlockSizeInWords;
>
> +       WordIndex++, DataBuffer++, WordAddress += 4)
>
> +  {
>
> +    Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
>
> +    if (EFI_ERROR (Status)) {
>
> +      goto EXIT;
>
> +    }
>
> +  }
>
> +
>
> +EXIT:
>
> +  NorFlashUnlock (OriginalTPL);
>
> +
>
> +  if (EFI_ERROR (Status)) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. "
>
> +      "Exit Status = %r.\n",
>
> +      WordAddress,
>
> +      Status
>
> +      ));
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Write a full  block.
>
> +
>
> +  @param[in]    Instance               NOR flash Instance of variable store region.
>
> +  @param[in]    Lba                    The starting logical block index.
>
> +  @param[in]    BufferSizeInBytes      The number of bytes to read.
>
> +  @param[in]    Buffer                 The pointer to a caller-allocated buffer that
>
> +                                       contains the source for the write.
>
> +
>
> +  @retval       EFI_SUCCESS            The write is completed.
>
> +  @retval       EFI_INVALID_PARAMETER  Invalid parameters passed.
>
> +  @retval       EFI_BAD_BUFFER_SIZE    Invalid buffer size passed.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashWriteBlocks (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN EFI_LBA             Lba,
>
> +  IN UINTN               BufferSizeInBytes,
>
> +  IN VOID                *Buffer
>
> +  )
>
> +{
>
> +  UINT32      *pWriteBuffer;
[SAMI] The 'p' prefix does not comply with the edk2 coding standard. Can 
you check, please?
>
> +  EFI_STATUS  Status;
>
> +  EFI_LBA     CurrentBlock;
>
> +  UINT32      BlockSizeInWords;
>
> +  UINT32      NumBlocks;
>
> +  UINT32      BlockCount;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +  // The buffer must be valid
>
> +  if (Buffer == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // We must have some bytes to read
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n",
>
> +    BufferSizeInBytes
>
> +    ));
>
> +  if (BufferSizeInBytes == 0) {
>
> +    return EFI_BAD_BUFFER_SIZE;
>
> +  }
>
> +
>
> +  // The size of the buffer must be a multiple of the block size
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n",
>
> +    Instance->Media.BlockSize
>
> +    ));
>
> +  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
>
> +    return EFI_BAD_BUFFER_SIZE;
>
> +  }
>
> +
>
> +  // All blocks must be within the device
>
> +  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
>
> +
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n",
>
> +    NumBlocks,
>
> +    Instance->Media.LastBlock,
>
> +    Lba
>
> +    ));
>
> +
>
> +  if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"
>
> +      ));
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  ASSERT (((UINTN)Buffer % sizeof (UINT32)) == 0);
[SAMI] Is this an alignment requirement for the Buffer? what happens in 
release build?
>
> +
>
> +  BlockSizeInWords = Instance->Media.BlockSize / 4;
>
> +
>
> +  // Because the target *Buffer is a pointer to VOID, we must put
>
> +  // all the data into a pointer to a proper data type, so use *ReadBuffer
[SAMI] *ReadBuffer => *WriteBuffer ?
>
> +  pWriteBuffer = (UINT32 *)Buffer;
>
> +
>
> +  CurrentBlock = Lba;
>
> +  for (BlockCount = 0;
>
> +       BlockCount < NumBlocks;
>
> +       BlockCount++, CurrentBlock++, pWriteBuffer += BlockSizeInWords)
>
> +  {
>
> +    DEBUG ((
>
> +      DEBUG_INFO,
>
> +      "NorFlashWriteBlocks: Writing block #%d\n",
>
> +      (UINTN)CurrentBlock
>
> +      ));
>
> +
>
> +    Status = NorFlashWriteFullBlock (
>
> +               Instance,
>
> +               CurrentBlock,
>
> +               pWriteBuffer,
>
> +               BlockSizeInWords
>
> +               );
>
> +
>
> +    if (EFI_ERROR (Status)) {
>
> +      break;
>
> +    }
>
> +  }
>
> +
>
> +  DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: Exit Status = %r.\n", Status));
>
> +  return Status;
>
> +}
>
> +
>
> +/**
>
> +  Read a full  block.
>
> +
>
> +  @param[in]     Instance               NOR flash Instance of variable store region.
>
> +  @param[in]     Lba                    The starting logical block index to read from.
>
> +  @param[in]     BufferSizeInBytes      The number of bytes to read.
>
> +  @param[out]    Buffer                 The pointer to a caller-allocated buffer that
>
> +                                        should be copied with read data.
>
> +
>
> +  @retval        EFI_SUCCESS            The read is completed.
>
> +  @retval        EFI_INVALID_PARAMETER  Invalid parameters passed.
>
> +  @retval        EFI_BAD_BUFFER_SIZE    Invalid buffer size passed.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashReadBlocks (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN EFI_LBA             Lba,
>
> +  IN UINTN               BufferSizeInBytes,
>
> +  OUT VOID               *Buffer
>
> +  )
>
> +{
>
> +  UINT32  NumBlocks;
>
> +  UINTN   StartAddress;
>
> +
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, "
>
> +    "Lba=%ld.\n",
>
> +    BufferSizeInBytes,
>
> +    Instance->Media.BlockSize,
>
> +    Instance->Media.LastBlock,
>
> +    Lba
>
> +    ));
>
> +
>
> +  // The buffer must be valid
>
> +  if (Buffer == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Return if we do not have any byte to read
>
> +  if (BufferSizeInBytes == 0) {
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  // The size of the buffer must be a multiple of the block size
>
> +  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
>
> +    return EFI_BAD_BUFFER_SIZE;
>
> +  }
>
> +
>
> +  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
>
> +
>
> +  if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NorFlashReadBlocks: ERROR - Read will exceed last block\n"
>
> +      ));
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Get the address to start reading from
>
> +  StartAddress = GET_NOR_BLOCK_ADDRESS (
>
> +                   Instance->RegionBaseAddress,
>
> +                   Lba,
>
> +                   Instance->Media.BlockSize
>
> +                   );
>
> +
>
> +  // Readout the data
>
> +  CopyMem (Buffer, (UINTN *)StartAddress, BufferSizeInBytes);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Read from nor flash.
>
> +
>
> +  @param[in]     Instance               NOR flash Instance of variable store region.
>
> +  @param[in]     Lba                    The starting logical block index to read from.
>
> +  @param[in]     Offset                 Offset into the block at which to begin reading.
>
> +  @param[in]     BufferSizeInBytes      The number of bytes to read.
>
> +  @param[out]    Buffer                 The pointer to a caller-allocated buffer that
>
> +                                        should copied with read data.
>
> +
>
> +  @retval        EFI_SUCCESS            The read is completed.
>
> +  @retval        EFI_INVALID_PARAMETER  Invalid parameters passed.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashRead (
>
> +  IN NOR_FLASH_INSTANCE  *Instance,
>
> +  IN EFI_LBA             Lba,
>
> +  IN UINTN               Offset,
>
> +  IN UINTN               BufferSizeInBytes,
>
> +  OUT VOID               *Buffer
>
> +  )
>
> +{
>
> +  UINTN  StartAddress;
>
> +
>
> +  // The buffer must be valid
>
> +  if (Buffer == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Return if we do not have any byte to read
>
> +  if (BufferSizeInBytes == 0) {
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) >
>
> +      Instance->Size)
>
> +  {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NorFlashRead: ERROR - Read will exceed device size.\n"
>
> +      ));
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Get the address to start reading from
>
> +  StartAddress = GET_NOR_BLOCK_ADDRESS (
>
> +                   Instance->RegionBaseAddress,
>
> +                   Lba,
>
> +                   Instance->Media.BlockSize
>
> +                   );
>
> +
>
> +  // Readout the data
>
> +  CopyMem (Buffer, (UINTN *)(StartAddress + Offset), BufferSizeInBytes);
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Write a full or portion of a block.
>
> +
>
> +  @param[in]       Instance              NOR flash Instance of variable store region.
>
> +  @param[in]       Lba                   The starting logical block index to write to.
>
> +  @param[in]       Offset                Offset into the block at which to begin writing.
>
> +  @param[in, out]  NumBytes              The total size of the buffer.
>
> +  @param[in]       Buffer                The pointer to a caller-allocated buffer that
>
> +                                         contains the source for the write.
>
> +
>
> +  @retval          EFI_SUCCESS           The write is completed.
>
> +  @retval          EFI_OUT_OF_RESOURCES  Invalid Buffer passed.
>
> +  @retval          EFI_BAD_BUFFER_SIZE   Buffer size not enough.
>
> +  @retval          EFI_DEVICE_ERROR      The device reported an error.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashWriteSingleBlock (
>
> +  IN        NOR_FLASH_INSTANCE  *Instance,
>
> +  IN        EFI_LBA             Lba,
>
> +  IN        UINTN               Offset,
>
> +  IN OUT    UINTN               *NumBytes,
>
> +  IN        UINT8               *Buffer
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +  UINT32      Tmp;
>
> +  UINT32      TmpBuf;
>
> +  UINT32      WordToWrite;
>
> +  UINT32      Mask;
>
> +  BOOLEAN     DoErase;
>
> +  UINTN       BytesToWrite;
>
> +  UINTN       CurOffset;
>
> +  UINTN       WordAddr;
>
> +  UINTN       BlockSize;
>
> +  UINTN       BlockAddress;
>
> +  UINTN       PrevBlockAddress;
>
> +
>
> +  if (Buffer == NULL) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NorFlashWriteSingleBlock: ERROR - Buffer is invalid\n"
>
> +      ));
>
> +    return EFI_OUT_OF_RESOURCES;
>
> +  }
>
> +
>
> +  PrevBlockAddress = 0;
>
> +
[SAMI] Validate that NumBytes is not NULL.
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, "
>
> +    "*NumBytes=0x%x, Buffer @ 0x%08x)\n",
>
> +    Lba,
>
> +    Offset,
>
> +    *NumBytes,
>
> +    Buffer
>
> +    ));
>
> +
>
> +  // Localise the block size to avoid de-referencing pointers all the time
>
> +  BlockSize = Instance->Media.BlockSize;
>
> +
>
> +  // The write must not span block boundaries.
>
> +  // We need to check each variable individually because adding two large
>
> +  // values together overflows.
>
> +  if ((Offset               >= BlockSize) ||
>
> +      (*NumBytes            >  BlockSize) ||
>
> +      ((Offset + *NumBytes) >  BlockSize))
>
> +  {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: "
>
> +      "(Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n",
>
> +      Offset,
>
> +      *NumBytes,
>
> +      BlockSize
>
> +      ));
>
> +    return EFI_BAD_BUFFER_SIZE;
>
> +  }
>
> +
>
> +  // We must have some bytes to write
>
> +  if (*NumBytes == 0) {
>
> +    DEBUG ((
>
> +      DEBUG_ERROR,
>
> +      "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: "
>
> +      "(Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n",
>
> +      Offset,
>
> +      *NumBytes,
>
> +      BlockSize
>
> +      ));
>
> +    return EFI_BAD_BUFFER_SIZE;
>
> +  }
>
> +
>
> +  // Pick 128bytes as a good start for word operations as opposed to erasing the
>
> +  // block and writing the data regardless if an erase is really needed.
>
> +  // It looks like most individual NV variable writes are smaller than 128bytes.
>
> +  if (*NumBytes <= 128) {
>
> +    // Check to see if we need to erase before programming the data into NOR.
>
> +    // If the destination bits are only changing from 1s to 0s we can just write.
>
> +    // After a block is erased all bits in the block is set to 1.
>
> +    // If any byte requires us to erase we just give up and rewrite all of it.
>
> +    DoErase      = FALSE;
>
> +    BytesToWrite = *NumBytes;
>
> +    CurOffset    = Offset;
>
> +
>
> +    while (BytesToWrite > 0) {
>
> +      // Read full word from NOR, splice as required. A word is the smallest
>
> +      // unit we can write.
>
> +      Status = NorFlashRead (
>
> +                 Instance,
>
> +                 Lba,
>
> +                 CurOffset & ~(0x3),
>
> +                 sizeof (Tmp),
>
> +                 &Tmp
>
> +                 );
>
> +      if (EFI_ERROR (Status)) {
>
> +        return EFI_DEVICE_ERROR;
>
> +      }
>
> +
>
> +      // Physical address of word in NOR to write.
>
> +      WordAddr = (CurOffset & ~(0x3)) +
>
> +                 GET_NOR_BLOCK_ADDRESS (
>
> +                   Instance->RegionBaseAddress,
>
> +                   Lba,
>
> +                   BlockSize
>
> +                   );
>
> +
>
> +      // The word of data that is to be written.
>
> +      TmpBuf = ReadUnaligned32 (
>
> +                 (UINT32 *)(Buffer + (*NumBytes - BytesToWrite))
>
> +                 );
>
> +
>
> +      // First do word aligned chunks.
>
> +      if ((CurOffset & 0x3) == 0) {
>
> +        if (BytesToWrite >= 4) {
>
> +          // Is the destination still in 'erased' state?
>
> +          if (~Tmp != 0) {
>
> +            // Check to see if we are only changing bits to zero.
>
> +            if ((Tmp ^ TmpBuf) & TmpBuf) {
>
> +              DoErase = TRUE;
>
> +              break;
>
> +            }
>
> +          }
>
> +
>
> +          // Write this word to NOR
>
> +          WordToWrite   = TmpBuf;
>
> +          CurOffset    += sizeof (TmpBuf);
>
> +          BytesToWrite -= sizeof (TmpBuf);
>
> +        } else {
>
> +          // BytesToWrite < 4. Do small writes and left-overs
>
> +          Mask = ~((~0) << (BytesToWrite * 8));
>
> +          // Mask out the bytes we want.
>
> +          TmpBuf &= Mask;
>
> +          // Is the destination still in 'erased' state?
>
> +          if ((Tmp & Mask) != Mask) {
>
> +            // Check to see if we are only changing bits to zero.
>
> +            if ((Tmp ^ TmpBuf) & TmpBuf) {
>
> +              DoErase = TRUE;
>
> +              break;
>
> +            }
>
> +          }
>
> +
>
> +          // Merge old and new data. Write merged word to NOR
>
> +          WordToWrite  = (Tmp & ~Mask) | TmpBuf;
>
> +          CurOffset   += BytesToWrite;
>
> +          BytesToWrite = 0;
>
> +        }
>
> +      } else {
>
> +        // Do multiple words, but starting unaligned.
>
> +        if (BytesToWrite > (4 - (CurOffset & 0x3))) {
>
> +          Mask = ((~0) << ((CurOffset & 0x3) * 8));
>
> +          // Mask out the bytes we want.
>
> +          TmpBuf &= Mask;
>
> +          // Is the destination still in 'erased' state?
>
> +          if ((Tmp & Mask) != Mask) {
>
> +            // Check to see if we are only changing bits to zero.
>
> +            if ((Tmp ^ TmpBuf) & TmpBuf) {
>
> +              DoErase = TRUE;
>
> +              break;
>
> +            }
>
> +          }
>
> +
>
> +          // Merge old and new data. Write merged word to NOR
>
> +          WordToWrite   = (Tmp & ~Mask) | TmpBuf;
>
> +          BytesToWrite -= (4 - (CurOffset & 0x3));
>
> +          CurOffset    += (4 - (CurOffset & 0x3));
>
> +        } else {
>
> +          // Unaligned and fits in one word.
>
> +          Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
>
> +          // Mask out the bytes we want.
>
> +          TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
>
> +          // Is the destination still in 'erased' state?
>
> +          if ((Tmp & Mask) != Mask) {
>
> +            // Check to see if we are only changing bits to zero.
>
> +            if ((Tmp ^ TmpBuf) & TmpBuf) {
>
> +              DoErase = TRUE;
>
> +              break;
>
> +            }
>
> +          }
>
> +
>
> +          // Merge old and new data. Write merged word to NOR
>
> +          WordToWrite  = (Tmp & ~Mask) | TmpBuf;
>
> +          CurOffset   += BytesToWrite;
>
> +          BytesToWrite = 0;
>
> +        }
>
> +      }
>
> +
>
> +      BlockAddress = GET_NOR_BLOCK_ADDRESS (
>
> +                       Instance->RegionBaseAddress,
>
> +                       Lba,
>
> +                       BlockSize
>
> +                       );
>
> +      if (BlockAddress != PrevBlockAddress) {
>
> +        Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
>
> +        if (EFI_ERROR (Status)) {
>
> +          return EFI_DEVICE_ERROR;
>
> +        }
>
> +
>
> +        PrevBlockAddress = BlockAddress;
>
> +      }
>
> +
>
> +      Status = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
>
> +      if (EFI_ERROR (Status)) {
>
> +        return EFI_DEVICE_ERROR;
>
> +      }
>
> +    }
>
> +
>
> +    // Exit if we got here and could write all the data. Otherwise do the
>
> +    // Erase-Write cycle.
>
> +    if (!DoErase) {
>
> +      return EFI_SUCCESS;
>
> +    }
>
> +  }
>
> +
>
> +  // Check we did get some memory. Buffer is BlockSize.
>
> +  if (Instance->ShadowBuffer == NULL) {
>
> +    DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  // Read NOR Flash data into shadow buffer
>
> +  Status = NorFlashReadBlocks (
>
> +             Instance,
>
> +             Lba,
>
> +             BlockSize,
>
> +             Instance->ShadowBuffer
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    // Return one of the pre-approved error statuses
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  // Put the data at the appropriate location inside the buffer area
>
> +  CopyMem (
>
> +    (VOID *)((UINTN)Instance->ShadowBuffer + Offset),
>
> +    Buffer,
>
> +    *NumBytes
>
> +    );
>
> +
>
> +  // Write the modified buffer back to the NorFlash
>
> +  Status = NorFlashWriteBlocks (
>
> +             Instance,
>
> +             Lba,
>
> +             BlockSize,
>
> +             Instance->ShadowBuffer
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    // Return one of the pre-approved error statuses
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Read JEDEC ID of NOR flash device.
>
> +
>
> +  @param[in]     Instance               NOR flash Instance of variable store region.
>
> +  @param[out]    JedecId                JEDEC ID of NOR flash device.
>
> +                                        Maximum length of JedecId can be upto 6 bytes
>
> +  @retval        EFI_SUCCESS            The write is completed.
>
> +  @retval        EFI_UNSUPPORTED        JEDEC ID retrievel not implemented.
>
> +  @retval        EFI_DEVICE_ERROR       Failed to fetch JEDEC ID.
>
> +  @retval        EFI_INVALID_PARAMETER  Invalid parameters passed.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashReadID (
>
> +  IN  NOR_FLASH_INSTANCE  *Instance,
>
> +  OUT UINT8               *JedecId
>
> +  )
>
> +{
>
> +  UINT32  val;
>
> +
>
> +  if ((Instance == NULL) || (JedecId == NULL)) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  val = (SPINOR_OP_RDID <<
>
> +         CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS) |
>
> +        (CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE <<
>
> +         CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS) |
>
> +        CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES (3);
>
> +
>
> +  if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
>
> +    return EFI_DEVICE_ERROR;
>
> +  }
>
> +
>
> +  val = MmioRead32 (
>
> +          Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET
>
> +          );
>
> +
>
> +  // Manu.ID field
>
> +  JedecId[0] = (UINT8)val;
>
> +  // Type field
>
> +  JedecId[1] = (UINT8)(val >> 8);
>
> +  // Capacity field
>
> +  JedecId[2] = (UINT8)(val >> 16);
>
> +
>
> +  DEBUG ((
>
> +    DEBUG_INFO,
>
> +    "Nor flash detected, Jedec ID, Manu.Id=%x Type=%x Capacity=%x \n",
>
> +    JedecId[0],
>
> +    JedecId[1],
>
> +    JedecId[2]
>
> +    ));
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> +  Nor Flash Reset
>
> +
>
> +  @param[in]         Instance     NOR flash instance.
>
> +
>
> +  @retval            EFI_SUCCESS  Return success on every call.
>
> +**/
>
> +EFI_STATUS
>
> +NorFlashReset (
>
> +  IN  NOR_FLASH_INSTANCE  *Instance
>
> +  )
>
> +{
>
> +  return EFI_SUCCESS;
>
> +}
>


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



[-- Attachment #2: Type: text/html, Size: 39097 bytes --]

  parent reply	other threads:[~2024-05-16 15:24 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-23  5:56 [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 00/14] Split NorFlashDxe driver and add CadenceQspiNorFlashDeviceLib library Sahil Kaushal
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 01/14] Platform/ARM/NorFlashDxe: Move DiskIo related functions out of NorFlash.c Sahil Kaushal
2024-04-24  9:49   ` levi.yun
2024-05-16 15:17   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 02/14] Platform/ARM/NorFlashDxe: Move NorFlashVirtualNotifyEvent Sahil Kaushal
2024-05-16 15:17   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 03/14] Platform/ARM/NorFlashDxe: Add NorFlashCommon.h header file Sahil Kaushal
2024-04-24  9:49   ` levi.yun
2024-05-16 15:17   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 04/14] Platform/ARM/NorFlashDxe: Move flash specific functions to NorFlash.c Sahil Kaushal
2024-04-24  9:49   ` levi.yun
2024-05-16 15:17   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 05/14] Platform/ARM: Create NorFlashDeviceLib library interface for flash specific functions Sahil Kaushal
2024-04-24  9:50   ` levi.yun
2024-05-16 15:18   ` Sami Mujawar
2024-05-21  8:37     ` sahil
2024-05-21 14:05       ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 06/14] Platform/ARM: Add P30NorFlashDeviceLib Library Sahil Kaushal
2024-04-24  9:49   ` levi.yun
2024-05-16 15:18   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 07/14] Platform/ARM/NorFlashDxe: Switch from NorFlash.c to NorFlashDeviceLib Sahil Kaushal
2024-04-24  9:50   ` levi.yun
2024-05-16 15:18   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 08/14] Platform/ARM: Add HostRegisterBaseAddress variable Sahil Kaushal
2024-04-24  9:50   ` levi.yun
2024-05-16 15:22   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 09/14] Platform/ARM: Add optional provision to fetch and print NOR Flash info Sahil Kaushal
2024-04-24  9:51   ` levi.yun
2024-05-16 15:23   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 10/14] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region Sahil Kaushal
2024-04-24  9:50   ` levi.yun
2024-05-16 15:23   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 11/14] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp Sahil Kaushal
2024-04-24  9:50   ` levi.yun
2024-05-16 15:23   ` Sami Mujawar
2024-05-21  9:24     ` sahil
2024-05-21 12:59       ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 12/14] Platform/ARM: Add CadenceQspiNorFlashDeviceLib for NorFlashDxe Sahil Kaushal
2024-04-24  9:55   ` levi.yun
2024-05-02 13:17   ` PierreGondois
2024-05-09  6:25     ` sahil
2024-05-16 15:25       ` Sami Mujawar
2024-05-16 15:24   ` Sami Mujawar [this message]
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 13/14] Platform/ARM/N1Sdp: Persistent storage for N1Sdp Sahil Kaushal
2024-04-24  9:55   ` levi.yun
2024-05-16 15:24   ` Sami Mujawar
2024-04-23  5:56 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 14/14] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver " Sahil Kaushal
2024-04-24  9:51   ` levi.yun
2024-05-16 15:24   ` Sami Mujawar
2024-05-02 13:16 ` [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 00/14] Split NorFlashDxe driver and add CadenceQspiNorFlashDeviceLib library PierreGondois

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1674c97a-a13e-4ae6-ab79-e174b010140d@arm.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox