blob: b7f5d208b2368e9149f7529228ac412f452431b2 [file] [log] [blame]
/** @file NorFlash.h
Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __VIRT_NOR_FLASH__
#define __VIRT_NOR_FLASH__
#include <Base.h>
#include <PiDxe.h>
#include <Guid/EventGroup.h>
#include <Protocol/FirmwareVolumeBlock.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeLib.h>
#include <Library/VirtNorFlashPlatformLib.h>
#define NOR_FLASH_ERASE_RETRY 10
// Device access macros
// These are necessary because we use 2 x 16bit parts to make up 32bit data
#define HIGH_16_BITS 0xFFFF0000
#define LOW_16_BITS 0x0000FFFF
#define LOW_8_BITS 0x000000FF
#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
// Each command must be sent simultaneously to both chips,
// i.e. at the lower 16 bits AND at the higher 16 bits
#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
// Status Register Bits
#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
// On chip buffer size for buffered programming operations
// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
#define MAX_BUFFERED_PROG_ITERATIONS 10000000
#define BOUNDARY_OF_32_WORDS 0x7F
// CFI Addresses
#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
#define P30_CFI_ADDR_VENDOR_ID 0x13
// CFI Data
#define CFI_QRY 0x00595251
// READ Commands
#define P30_CMD_READ_DEVICE_ID 0x0090
#define P30_CMD_READ_STATUS_REGISTER 0x0070
#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
#define P30_CMD_READ_ARRAY 0x00FF
#define P30_CMD_READ_CFI_QUERY 0x0098
// WRITE Commands
#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
#define P30_CMD_BEFP_SETUP 0x0080
#define P30_CMD_BEFP_CONFIRM 0x00D0
// ERASE Commands
#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
// SUSPEND Commands
#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
#define P30_CMD_SUSPEND_RESUME 0x00D0
// BLOCK LOCKING / UNLOCKING Commands
#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
#define P30_CMD_LOCK_BLOCK 0x0001
#define P30_CMD_UNLOCK_BLOCK 0x00D0
#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
// PROTECTION Commands
#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
// CONFIGURATION Commands
#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
#pragma pack (1)
typedef struct {
VENDOR_DEVICE_PATH Vendor;
UINT8 Index;
EFI_DEVICE_PATH_PROTOCOL End;
} NOR_FLASH_DEVICE_PATH;
#pragma pack ()
struct _NOR_FLASH_INSTANCE {
UINT32 Signature;
EFI_HANDLE Handle;
UINTN DeviceBaseAddress;
UINTN RegionBaseAddress;
UINTN Size;
EFI_LBA StartLba;
EFI_LBA LastBlock;
UINT32 BlockSize;
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
VOID *ShadowBuffer;
NOR_FLASH_DEVICE_PATH DevicePath;
};
EFI_STATUS
NorFlashReadCfiData (
IN UINTN DeviceBaseAddress,
IN UINTN CFI_Offset,
IN UINT32 NumberOfBytes,
OUT UINT32 *Data
);
EFI_STATUS
NorFlashWriteBuffer (
IN NOR_FLASH_INSTANCE *Instance,
IN UINTN TargetAddress,
IN UINTN BufferSizeInBytes,
IN UINT32 *Buffer
);
//
// NorFlashFvbDxe.c
//
EFI_STATUS
EFIAPI
FvbGetAttributes (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
OUT EFI_FVB_ATTRIBUTES_2 *Attributes
);
EFI_STATUS
EFIAPI
FvbSetAttributes (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
);
EFI_STATUS
EFIAPI
FvbGetPhysicalAddress (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
OUT EFI_PHYSICAL_ADDRESS *Address
);
EFI_STATUS
EFIAPI
FvbGetBlockSize (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
IN EFI_LBA Lba,
OUT UINTN *BlockSize,
OUT UINTN *NumberOfBlocks
);
EFI_STATUS
EFIAPI
FvbRead (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN OUT UINT8 *Buffer
);
EFI_STATUS
EFIAPI
FvbWrite (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
);
EFI_STATUS
EFIAPI
FvbEraseBlocks (
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
...
);
EFI_STATUS
ValidateFvHeader (
IN NOR_FLASH_INSTANCE *Instance
);
EFI_STATUS
InitializeFvAndVariableStoreHeaders (
IN NOR_FLASH_INSTANCE *Instance
);
VOID
EFIAPI
FvbVirtualNotifyEvent (
IN EFI_EVENT Event,
IN VOID *Context
);
//
// NorFlashDxe.c
//
EFI_STATUS
NorFlashWriteFullBlock (
IN NOR_FLASH_INSTANCE *Instance,
IN EFI_LBA Lba,
IN UINT32 *DataBuffer,
IN UINT32 BlockSizeInWords
);
EFI_STATUS
NorFlashUnlockAndEraseSingleBlock (
IN NOR_FLASH_INSTANCE *Instance,
IN UINTN BlockAddress
);
EFI_STATUS
NorFlashCreateInstance (
IN UINTN NorFlashDeviceBase,
IN UINTN NorFlashRegionBase,
IN UINTN NorFlashSize,
IN UINT32 Index,
IN UINT32 BlockSize,
IN BOOLEAN SupportFvb,
OUT NOR_FLASH_INSTANCE **NorFlashInstance
);
EFI_STATUS
EFIAPI
NorFlashFvbInitialize (
IN NOR_FLASH_INSTANCE *Instance
);
//
// NorFlash.c
//
EFI_STATUS
NorFlashWriteSingleBlock (
IN NOR_FLASH_INSTANCE *Instance,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
);
EFI_STATUS
NorFlashWriteBlocks (
IN NOR_FLASH_INSTANCE *Instance,
IN EFI_LBA Lba,
IN UINTN BufferSizeInBytes,
IN VOID *Buffer
);
EFI_STATUS
NorFlashReadBlocks (
IN NOR_FLASH_INSTANCE *Instance,
IN EFI_LBA Lba,
IN UINTN BufferSizeInBytes,
OUT VOID *Buffer
);
EFI_STATUS
NorFlashRead (
IN NOR_FLASH_INSTANCE *Instance,
IN EFI_LBA Lba,
IN UINTN Offset,
IN UINTN BufferSizeInBytes,
OUT VOID *Buffer
);
EFI_STATUS
NorFlashWrite (
IN NOR_FLASH_INSTANCE *Instance,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer
);
EFI_STATUS
NorFlashReset (
IN NOR_FLASH_INSTANCE *Instance
);
EFI_STATUS
NorFlashEraseSingleBlock (
IN NOR_FLASH_INSTANCE *Instance,
IN UINTN BlockAddress
);
EFI_STATUS
NorFlashUnlockSingleBlockIfNecessary (
IN NOR_FLASH_INSTANCE *Instance,
IN UINTN BlockAddress
);
EFI_STATUS
NorFlashWriteSingleWord (
IN NOR_FLASH_INSTANCE *Instance,
IN UINTN WordAddress,
IN UINT32 WriteData
);
VOID
EFIAPI
NorFlashVirtualNotifyEvent (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif /* __VIRT_NOR_FLASH__ */