From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:4864:20::343; helo=mail-wm1-x343.google.com; envelope-from=leif.lindholm@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5D5D4211A2074 for ; Wed, 19 Dec 2018 10:13:57 -0800 (PST) Received: by mail-wm1-x343.google.com with SMTP id a62so7009911wmh.4 for ; Wed, 19 Dec 2018 10:13:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=QrG32xr1bv3Lymqa6xQaeQBqKQv9Vz+MA66Lnj1i+fw=; b=eSKgSEDR9dqnwnA1dnOkEsjG+PzMjqgSGJuchWnLaNYQGyeFcoA1G2IHMP33vNRGEC ymxLXsFO041wOPSXQkRzuXzD0ysm1mEqB9fO/TYvG+Ye6KDZYg3p14m9Pnil/VOAdPB5 iW+q0Fc6zwwc6HMMxXEthVq/A70YSgqXNg/Ls= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=QrG32xr1bv3Lymqa6xQaeQBqKQv9Vz+MA66Lnj1i+fw=; b=lBkjj12ENi4d0tvItswQn1Y4WESsm3KvyW90QUTKfUmwcp2xXepUi+eLG0MPYau0G/ yaU70y26ytH69Xb+qfvFmaomM1hGy8q7LZ1EvCaMDFwrnM8fOpHsyF+vjOWCvdPtN+am uryrYvtnMTMyrq9I5aAQi+xWtg6mo1Bp3RBwCPwP31kYWDK5dPobE8wXRQx5NZUldOq/ +Jeo80GajmiW4IEN55ps5r/6JseMJ6LqF6ERFYOJcsB3GoN3rSxqm5Lxso8fK6bw9dB2 FCpLXY9HVqiH1Addsu5cPxtYE/5AePjv9O4ji2PLZTYsdSlaaymrorFQ9kvTOpnolIVr /e9A== X-Gm-Message-State: AA+aEWaCzusMkA+n21OKwgOwfblB7m6YiFwJLVCMdoEV2ctEtbl9Nu5y +SH2aDakOEyDg0xsNHTKd4j8wdjuyY0= X-Google-Smtp-Source: AFSGD/Wk2JxON0WdH9+UEf6v2BGGUYsQjzwn9UTmKYDBU1VS5781q69EDrcodf9ibEl+qg6/0mIO6w== X-Received: by 2002:a1c:b456:: with SMTP id d83mr8508147wmf.115.1545243235429; Wed, 19 Dec 2018 10:13:55 -0800 (PST) Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id h13sm8817609wrp.61.2018.12.19.10.13.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 19 Dec 2018 10:13:54 -0800 (PST) Date: Wed, 19 Dec 2018 18:13:52 +0000 From: Leif Lindholm To: Meenakshi Aggarwal Cc: ard.biesheuvel@linaro.org, michael.d.kinney@intel.com, edk2-devel@lists.01.org, udit.kumar@nxp.com, v.sethi@nxp.com Message-ID: <20181219181352.mjwtpgilicqe4dhb@bivouac.eciton.net> References: <1518771035-6733-1-git-send-email-meenakshi.aggarwal@nxp.com> <1543417315-5763-1-git-send-email-meenakshi.aggarwal@nxp.com> <1543417315-5763-17-git-send-email-meenakshi.aggarwal@nxp.com> MIME-Version: 1.0 In-Reply-To: <1543417315-5763-17-git-send-email-meenakshi.aggarwal@nxp.com> User-Agent: NeoMutt/20170113 (1.7.2) Subject: Re: [PATCH edk2-platforms 16/41] Silicon/NXP : Add support of NorFlashLib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Dec 2018 18:13:57 -0000 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Nov 28, 2018 at 08:31:30PM +0530, Meenakshi Aggarwal wrote: > NorFlashLib interacts with the underlying IFC NOR controller. Expand IFC in commit message. > This will be used by NOR driver for any information > exchange with NOR controller. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Meenakshi Aggarwal On the whole, a big improvement. A few minor style comments and one polite request below. > --- > Silicon/NXP/Include/Library/NorFlashLib.h | 77 +++ > Silicon/NXP/Include/NorFlash.h | 44 ++ > Silicon/NXP/Library/NorFlashLib/CfiCommand.h | 99 ++++ > Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c | 210 +++++++ > Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h | 53 ++ > Silicon/NXP/Library/NorFlashLib/NorFlashLib.c | 696 +++++++++++++++++++++++ > Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf | 43 ++ > 7 files changed, 1222 insertions(+) > create mode 100644 Silicon/NXP/Include/Library/NorFlashLib.h > create mode 100644 Silicon/NXP/Include/NorFlash.h > create mode 100644 Silicon/NXP/Library/NorFlashLib/CfiCommand.h > create mode 100644 Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c > create mode 100644 Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h > create mode 100644 Silicon/NXP/Library/NorFlashLib/NorFlashLib.c > create mode 100644 Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf > > diff --git a/Silicon/NXP/Include/Library/NorFlashLib.h b/Silicon/NXP/Include/Library/NorFlashLib.h > new file mode 100644 > index 0000000..defdc61 > --- /dev/null > +++ b/Silicon/NXP/Include/Library/NorFlashLib.h > @@ -0,0 +1,77 @@ > +/** @file > + > + Copyright (c) 2011-2012, ARM Ltd. All rights reserved. > + Copyright (c) 2016, Freescale Semiconductor. All rights reserved. > + Copyright 2017 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 _NOR_FLASH_LIB_H_ > +#define _NOR_FLASH_LIB_H_ > + > +#include > + > +#define NOR_FLASH_DEVICE_COUNT 1 > + > +typedef struct { > + UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA) > + UINTN RegionBaseAddress; // Start address of one single region > + UINTN Size; > + UINTN BlockSize; > + UINTN MultiByteWordCount; // Maximum Word count that can be written to Nor Flash in multi byte write > + UINTN WordWriteTimeOut; // single byte/word timeout usec > + UINTN BufferWriteTimeOut; // buffer write timeout usec > + UINTN BlockEraseTimeOut; // block erase timeout usec > + UINTN ChipEraseTimeOut; // chip erase timeout usec > +} NorFlashDescription; > + > +EFI_STATUS > +NorFlashPlatformGetDevices ( > + OUT NorFlashDescription **NorFlashDevices, > + OUT UINT32 *Count > + ); > + > +EFI_STATUS > +NorFlashPlatformFlashGetAttributes ( > + OUT NorFlashDescription *NorFlashDevices, > + IN UINT32 Count > + ); > + > +EFI_STATUS > +NorFlashPlatformWriteBuffer ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ); > + > +EFI_STATUS > +NorFlashPlatformEraseSector ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN UINTN SectorAddress > + ); > + > +EFI_STATUS > +NorFlashPlatformRead ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN BufferSizeInBytes, > + OUT UINT8 *Buffer > + ); > + > +EFI_STATUS > +NorFlashPlatformReset ( > + IN UINTN Instance > + ); > + > +#endif /* _NOR_FLASH_LIB_H_ */ > diff --git a/Silicon/NXP/Include/NorFlash.h b/Silicon/NXP/Include/NorFlash.h > new file mode 100644 > index 0000000..8fa41d8 > --- /dev/null > +++ b/Silicon/NXP/Include/NorFlash.h > @@ -0,0 +1,44 @@ > +/** @NorFlash.h > + > + Contains data structure shared by both NOR Library and Driver. > + Copyright 2017 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 __NOR_FLASH_H__ > +#define __NOR_FLASH_H__ > + > +#include > +#include > + > +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; > + > +typedef struct { > + VENDOR_DEVICE_PATH Vendor; > + EFI_DEVICE_PATH_PROTOCOL End; > +} NOR_FLASH_DEVICE_PATH; > + > +struct _NOR_FLASH_INSTANCE { > + UINT32 Signature; > + EFI_HANDLE Handle; > + UINTN DeviceBaseAddress; > + UINTN RegionBaseAddress; > + UINTN Size; > + EFI_LBA StartLba; > + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; > + EFI_BLOCK_IO_MEDIA Media; > + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; > + VOID* ShadowBuffer; > + NOR_FLASH_DEVICE_PATH DevicePath; > +}; > + > + > +#endif /* __NOR_FLASH_H__ */ > diff --git a/Silicon/NXP/Library/NorFlashLib/CfiCommand.h b/Silicon/NXP/Library/NorFlashLib/CfiCommand.h > new file mode 100644 > index 0000000..8543227 > --- /dev/null > +++ b/Silicon/NXP/Library/NorFlashLib/CfiCommand.h I did say last time that we didn't need to worry about turning this library common yet. I want to go back on that slightly: I do want everything in this file that relates to the CFI specification to be submitted as a new edk2/MdePkg/Include/IndustryStandard/Cfi.h > @@ -0,0 +1,99 @@ > +/** @CfiCommand.h > + > + Copyright 2017 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 __CFI_COMMAND_H__ > +#define __CFI_COMMAND_H__ This would then only need to be #ifndef CFI_H_ > + > +// CFI Data "QRY" > +#define CFI_QRY_Q 0x51 > +#define CFI_QRY_R 0x52 > +#define CFI_QRY_Y 0x59 > +#define CFI_QRY 0x515259 > + > +#define ENTER_CFI_QUERY_MODE_ADDR 0x0055 > +#define ENTER_CFI_QUERY_MODE_CMD 0x0098 And I think these would need to be changed to CFI_ENTER_ > + > +#define CFI_QUERY_UNIQUE_QRY_STRING 0x10 > + > +// Offsets for CFI queries > +#define CFI_QUERY_TYP_TIMEOUT_WORD_WRITE 0x1F > +#define CFI_QUERY_TYP_TIMEOUT_MAX_BUFFER_WRITE 0x20 > +#define CFI_QUERY_TYP_TIMEOUT_BLOCK_ERASE 0x21 > +#define CFI_QUERY_TYP_TIMEOUT_CHIP_ERASE 0x22 > +#define CFI_QUERY_MAX_TIMEOUT_WORD_WRITE 0x23 > +#define CFI_QUERY_MAX_TIMEOUT_MAX_BUFFER_WRITE 0x24 > +#define CFI_QUERY_MAX_TIMEOUT_BLOCK_ERASE 0x25 > +#define CFI_QUERY_MAX_TIMEOUT_CHIP_ERASE 0x26 > +#define CFI_QUERY_DEVICE_SIZE 0x27 > +#define CFI_QUERY_MAX_NUM_BYTES_WRITE 0x2A > +#define CFI_QUERY_BLOCK_SIZE 0x2F > + > +// Unlock Address > +#define CMD_UNLOCK_1_ADDR 0x555 > +#define CMD_UNLOCK_2_ADDR 0x2AA And all of these would need to be CFI_CMD_ > + > +// RESET Command > +#define CMD_RESET_FIRST 0xAA > +#define CMD_RESET_SECOND 0x55 > +#define CMD_RESET 0xF0 > + > +// READ Command > + > +// Manufacturer ID > +#define CMD_READ_M_ID_FIRST 0xAA > +#define CMD_READ_M_ID_SECOND 0x55 > +#define CMD_READ_M_ID_THIRD 0x90 > +#define CMD_READ_M_ID_FOURTH 0x01 > + > +// Device ID > +#define CMD_READ_D_ID_FIRST 0xAA > +#define CMD_READ_D_ID_SECOND 0x55 > +#define CMD_READ_D_ID_THIRD 0x90 > +#define CMD_READ_D_ID_FOURTH 0x7E > +#define CMD_READ_D_ID_FIFTH 0x13 > +#define CMD_READ_D_ID_SIXTH 0x00 > + > +// WRITE Command > + > +// PROGRAM Command > +#define CMD_PROGRAM_FIRST 0xAA > +#define CMD_PROGRAM_SECOND 0x55 > +#define CMD_PROGRAM_THIRD 0xA0 > + > +// Write Buffer Command > +#define CMD_WRITE_TO_BUFFER_FIRST 0xAA > +#define CMD_WRITE_TO_BUFFER_SECOND 0x55 > +#define CMD_WRITE_TO_BUFFER_THIRD 0x25 > +#define CMD_WRITE_TO_BUFFER_CONFIRM 0x29 > + > +// ERASE Command > + > +// UNLOCK COMMANDS FOR ERASE > +#define CMD_ERASE_FIRST 0xAA > +#define CMD_ERASE_SECOND 0x55 > +#define CMD_ERASE_THIRD 0x80 > +#define CMD_ERASE_FOURTH 0xAA > +#define CMD_ERASE_FIFTH 0x55 > + > +// Chip Erase Command > +#define CMD_CHIP_ERASE_SIXTH 0x10 > + > +// Sector Erase Command > +#define CMD_SECTOR_ERASE_SIXTH 0x30 > + > +// SUSPEND Command > +#define CMD_PROGRAM_OR_ERASE_SUSPEND 0xB0 > +#define CMD_PROGRAM_OR_ERASE_RESUME 0x30 > + > +#endif // __CFI_COMMAND_H__ (If ther is) Anything in this file which is not covered by the CFI specification, keep it here, under this name. > diff --git a/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c > new file mode 100644 > index 0000000..941d5d4 > --- /dev/null > +++ b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c > @@ -0,0 +1,210 @@ > +/** @CfiNorFlashLib.c > + > + Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved. > + Copyright 2017 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. > + > + **/ > + > +#include > +#include > +#include > + > +#include "CfiCommand.h" > +#include "CfiNorFlashLib.h" > + > +STATIC > +VOID > +NorFlashReadCfiData ( > + IN UINTN DeviceBaseAddress, > + IN UINTN CfiOffset, > + IN UINT32 Count, > + OUT VOID *Data > + ) > +{ > + UINT32 Loop; > + FLASH_DATA *TmpData = (FLASH_DATA *)Data; > + > + for (Loop = 0; Loop < Count; Loop++, TmpData++) { > + *TmpData = mMmioOps->Read ((UINTN)((FLASH_DATA*)DeviceBaseAddress + CfiOffset)); > + CfiOffset++; > + } > +} > + > +/* > + Currently we support only CFI flash devices; Bail-out otherwise > +*/ > +EFI_STATUS > +CfiNorFlashFlashGetAttributes ( > + OUT NorFlashDescription *NorFlashDevices, > + IN UINT32 Index > + ) > +{ > + UINT32 Count; > + FLASH_DATA QryData[QRY_STRING_COUNT]; > + FLASH_DATA BlockSize[BLOCK_SIZE_COUNT]; > + UINTN DeviceBaseAddress; > + FLASH_DATA MaxNumBytes[BLOCK_SIZE_COUNT]; > + FLASH_DATA Size; > + FLASH_DATA HighByteMask; // Masks High byte in a UIN16 word > + FLASH_DATA HighByteShift; // Bitshifts needed to make a byte High Byte in a UIN16 word > + FLASH_DATA Temp1; > + FLASH_DATA Temp2; > + FLASH_DATA Z; > + > + HighByteMask = 0xFF; > + HighByteShift = 8; > + > + for (Count = 0; Count < Index; Count++) { > + > + NorFlashDevices[Count].DeviceBaseAddress = DeviceBaseAddress = PcdGet64 (PcdFlashDeviceBase64); > + > + // Reset flash first > + NorFlashPlatformReset (DeviceBaseAddress); > + > + // Enter the CFI Query Mode > + SEND_NOR_COMMAND ( > + DeviceBaseAddress, > + ENTER_CFI_QUERY_MODE_ADDR, > + ENTER_CFI_QUERY_MODE_CMD > + ); > + > + MemoryFence(); > + > + // Query the unique QRY > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_UNIQUE_QRY_STRING, > + QRY_STRING_COUNT, > + &QryData > + ); > + > + if ((QryData[0] != (FLASH_DATA)CFI_QRY_Q) || > + (QryData[1] != (FLASH_DATA)CFI_QRY_R) || > + (QryData[2] != (FLASH_DATA)CFI_QRY_Y)) { > + DEBUG ((DEBUG_ERROR, "Not a CFI flash (QRY not recvd): " > + "Got = 0x%04x, 0x%04x, 0x%04x\n", > + QryData[0], QryData[1], QryData[2])); > + return EFI_DEVICE_ERROR; > + } > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_DEVICE_SIZE, > + DEVICE_SIZE_COUNT, > + &Size > + ); > + > + // Refer CFI Specification [2^n in number of bytes.] > + NorFlashDevices[Count].Size = 1 << Size; > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_BLOCK_SIZE, > + BLOCK_SIZE_COUNT, > + &BlockSize > + ); > + > + // Refer CFI Specification [Erase block(s) within this region are (z) times 256 bytes in size. > + // The value z = 0 is used for 128-byte block size. > + Z = (FLASH_DATA)((BlockSize[1] << HighByteShift) | (BlockSize[0] & HighByteMask)); > + if (Z == 0) { > + NorFlashDevices[Count].BlockSize = 128; > + } else { > + NorFlashDevices[Count].BlockSize = 256 * Z; > + } > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_MAX_NUM_BYTES_WRITE, > + BLOCK_SIZE_COUNT, > + &MaxNumBytes > + ); > + > + // Refer CFI Specification > + /* from CFI query we get the Max. number of BYTE in multi-byte write = 2^N. > + But our Flash Library is able to read/write in WORD size (2 bytes) which > + is why we need to CONVERT MAX BYTES TO MAX WORDS by diving it by > + width of word size */ > + NorFlashDevices[Count].MultiByteWordCount =\ > + (1 << ((FLASH_DATA)((MaxNumBytes[1] << HighByteShift) | > + (MaxNumBytes[0] & HighByteMask))))/sizeof(FLASH_DATA); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_TYP_TIMEOUT_WORD_WRITE, > + WORD_WRITE_COUNT, > + &Temp1 > + ); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_MAX_TIMEOUT_WORD_WRITE, > + WORD_WRITE_COUNT, > + &Temp2 > + ); > + > + NorFlashDevices[Count].WordWriteTimeOut = (1U << Temp1) * (1U << Temp2); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_TYP_TIMEOUT_MAX_BUFFER_WRITE, > + BUFFER_WRITE_COUNT, > + &Temp1 > + ); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_MAX_TIMEOUT_MAX_BUFFER_WRITE, > + BUFFER_WRITE_COUNT, > + &Temp2 > + ); > + > + NorFlashDevices[Count].BufferWriteTimeOut = (1U << Temp1) * (1U << Temp2); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_TYP_TIMEOUT_BLOCK_ERASE, > + BLOCK_ERASE_COUNT, > + &Temp1 > + ); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_MAX_TIMEOUT_BLOCK_ERASE, > + BLOCK_ERASE_COUNT, > + &Temp2 > + ); > + > + // Converting from millisecond to microseconds > + NorFlashDevices[Count].BlockEraseTimeOut = (1U << Temp1) * (1U << Temp2) * 1000; > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_TYP_TIMEOUT_CHIP_ERASE, > + CHIP_ERASE_COUNT, > + &Temp1 > + ); > + > + NorFlashReadCfiData ( > + DeviceBaseAddress, > + CFI_QUERY_MAX_TIMEOUT_CHIP_ERASE, > + CHIP_ERASE_COUNT, > + &Temp2 > + ); > + > + NorFlashDevices[Count].ChipEraseTimeOut = (1U << Temp1) * (1U << Temp2) * 1000; > + > + // Put device back into Read Array mode (via Reset) > + NorFlashPlatformReset (DeviceBaseAddress); > + } > + > + return EFI_SUCCESS; > +} > diff --git a/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h > new file mode 100644 > index 0000000..710f706 > --- /dev/null > +++ b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h > @@ -0,0 +1,53 @@ > +/** @CfiNorFlashLib.h > + > + Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved. > + Copyright 2017 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 __CFI_NOR_FLASH_LIB_H__ > +#define __CFI_NOR_FLASH_LIB_H__ > + > +#include > +#include > +#include > + > +extern MMIO_OPERATIONS_16 *mMmioOps; > + > +/* > + * Values for the width of the port > + */ > +#define FLASH_CFI_8BIT 0x01 > +#define FLASH_CFI_16BIT 0x02 > +#define FLASH_CFI_32BIT 0x04 > +#define FLASH_CFI_64BIT 0x08 > + > +#define QRY_STRING_COUNT 3 > +#define DEVICE_SIZE_COUNT 1 > +#define BLOCK_SIZE_COUNT 2 > +#define WORD_WRITE_COUNT 1 > +#define BUFFER_WRITE_COUNT 1 > +#define BLOCK_ERASE_COUNT 1 > +#define CHIP_ERASE_COUNT 1 Are any of these part of the CFI specification? If so move them to the new header proposed above, and ensure CFI_ prefix. > + > +#define CREATE_BYTE_OFFSET(OffsetAddr) ((sizeof (FLASH_DATA)) * (OffsetAddr)) > +#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + (OffsetAddr)) > +#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) mMmioOps->Write (CREATE_NOR_ADDRESS (BaseAddr, CREATE_BYTE_OFFSET (Offset)), (Cmd)) > + > +typedef UINT16 FLASH_DATA; > + > +EFI_STATUS > +CfiNorFlashFlashGetAttributes ( > + OUT NorFlashDescription *NorFlashDevices, > + IN UINT32 Index > + ); > + > +#endif //__CFI_NOR_FLASH_LIB_H__ > diff --git a/Silicon/NXP/Library/NorFlashLib/NorFlashLib.c b/Silicon/NXP/Library/NorFlashLib/NorFlashLib.c > new file mode 100644 > index 0000000..c89ddc3 > --- /dev/null > +++ b/Silicon/NXP/Library/NorFlashLib/NorFlashLib.c > @@ -0,0 +1,696 @@ > +/** @NorFlashLib.c > + > + Based on NorFlash implementation available in NorFlashDxe.c > + > + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved. > + Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved. > + Copyright 2017 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. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "CfiCommand.h" > +#include "CfiNorFlashLib.h" > + > +#define GET_BLOCK_OFFSET(Lba) ((Instance->RegionBaseAddress) -\ > + (Instance->DeviceBaseAddress) + ((UINTN)((Lba) * Instance->Media.BlockSize))) > + > +MMIO_OPERATIONS_16 *mMmioOps; > + > +NorFlashDescription mNorFlashDevices[NOR_FLASH_DEVICE_COUNT]; > + > +STATIC VOID > +UnlockEraseAddress ( > + IN UINTN DeviceBaseAddress > + ) > +{ // Issue the Unlock cmds > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_ERASE_FIRST); > + > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_2_ADDR, CMD_ERASE_SECOND); > + > + // Issue a setup command > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_ERASE_THIRD); > + > + // Issue the Unlock cmds > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_ERASE_FOURTH); > + > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_2_ADDR, CMD_ERASE_FIFTH); > + > + return; > +} > + > +STATIC > +UINT64 > +ConvertMicroSecondsToTicks ( > + IN UINTN MicroSeconds > + ) > +{ > + UINT64 TimerTicks64; > + > + TimerTicks64 = 0; > + > + // Calculate counter ticks that represent requested delay: > + // = MicroSeconds x TICKS_PER_MICRO_SEC > + // = MicroSeconds x Timer Frequency(in Hz) x 10^-6 > + // GetPerformanceCounterProperties = Get Arm Timer Frequency in Hz > + TimerTicks64 = DivU64x32 ( > + MultU64x64 ( > + MicroSeconds, > + GetPerformanceCounterProperties (NULL, NULL) > + ), > + 1000000U > + ); > + return TimerTicks64; > +} > + > +/** > + * The following function erases a NOR flash sector. > + **/ > +EFI_STATUS > +NorFlashPlatformEraseSector ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN UINTN SectorAddress > + ) > +{ > + FLASH_DATA EraseStatus1; > + FLASH_DATA EraseStatus2; > + UINT64 Timeout; > + UINT64 SystemCounterVal; > + > + EraseStatus1 = 0; > + EraseStatus2 = 0; > + Timeout = 0; > + > + Timeout = ConvertMicroSecondsToTicks (mNorFlashDevices[Instance->Media.MediaId].BlockEraseTimeOut); > + > + // Request a sector erase by writing two unlock cycles, followed by a > + // setup command and two additional unlock cycles > + > + UnlockEraseAddress (Instance->DeviceBaseAddress); > + > + // Now send the address of the sector to be erased > + SEND_NOR_COMMAND (SectorAddress, 0, CMD_SECTOR_ERASE_SIXTH); > + > + // Wait for erase to complete > + // Read Sector start address twice to detect bit toggle and to > + // determine ERASE DONE (all bits are 1) > + // Get the maximum timer ticks needed to complete the operation > + // Check if operation is complete or not in continous loop? > + // if complete, exit from loop > + // if not check the ticks that have been passed from the begining of loop > + // if Maximum Ticks allocated for operation has passed exit from loop > + > + SystemCounterVal = GetPerformanceCounter (); > + Timeout += SystemCounterVal; > + while (SystemCounterVal < Timeout) { > + if ((EraseStatus1 = mMmioOps->Read (SectorAddress)) > + == (EraseStatus2 = mMmioOps->Read (SectorAddress))) > + { > + if (mMmioOps->Read (SectorAddress) == 0xFFFF) { > + break; > + } > + } > + SystemCounterVal = GetPerformanceCounter (); > + } > + > + if (SystemCounterVal >= Timeout) { > + DEBUG ((DEBUG_ERROR, "%a :Failed to Erase @ SectorAddress 0x%p, Timeout\n", > + __FUNCTION__, SectorAddress)); > + return EFI_DEVICE_ERROR; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +EFI_STATUS > +NorFlashPlatformWriteWord ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN UINTN WordOffset, > + IN FLASH_DATA Word > + ) > +{ > + UINT64 Timeout; > + UINTN TargetAddress; > + UINT64 SystemCounterVal; > + FLASH_DATA Read1; > + FLASH_DATA Read2; > + > + Timeout = 0; > + > + Timeout = ConvertMicroSecondsToTicks (mNorFlashDevices[Instance->Media.MediaId].WordWriteTimeOut); > + > + TargetAddress = CREATE_NOR_ADDRESS ( > + Instance->DeviceBaseAddress, > + CREATE_BYTE_OFFSET (WordOffset) > + ); > + > + // Issue the Unlock cmds > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_PROGRAM_FIRST); > + > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_2_ADDR, CMD_PROGRAM_SECOND); > + > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_PROGRAM_THIRD); > + > + MmioWrite16 (TargetAddress, Word); > + > + // Wait for Write to Complete > + // Read the last written address twice to detect bit toggle and > + // to determine if date is wriiten successfully or not ? > + // Get the maximum timer ticks needed to complete the operation > + // Check if operation is complete or not in continous loop? > + // if complete, exit from loop > + // if not check the ticks that have been passed from the begining of loop > + // if Maximum Ticks allocated for operation has passed, then exit from loop > + > + SystemCounterVal = GetPerformanceCounter (); > + Timeout += SystemCounterVal; > + while (SystemCounterVal < Timeout) { > + if ((Read1 = MmioRead16 (TargetAddress)) > + == (Read2 = MmioRead16 (TargetAddress))) "if" is not a function - when line wrapping, align to preceding test. My preference here would be if ((Read1 = MmioRead16 (TargetAddress)) == (Read2 = MmioRead16 (TargetAddress))) (Please follow this pattern throughout.) > + { And that { at the end of the preceding line. > + if (Word == MmioRead16 (TargetAddress)) { > + break; > + } > + } > + SystemCounterVal = GetPerformanceCounter (); > + } > + > + if (SystemCounterVal >= Timeout) { > + DEBUG ((DEBUG_ERROR, "%a: Failed to Write @ TargetAddress 0x%p, Timeout\n", > + __FUNCTION__, TargetAddress)); > + return EFI_DEVICE_ERROR; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +EFI_STATUS > +NorFlashPlatformWritePageBuffer ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN UINTN PageBufferOffset, > + IN UINTN NumWords, > + IN FLASH_DATA *Buffer > + ) > +{ > + UINT64 Timeout; > + UINTN LastWrittenAddress; > + FLASH_DATA LastWritenData; > + UINTN CurrentOffset; > + UINTN EndOffset; > + UINTN TargetAddress; > + UINT64 SystemCounterVal; > + FLASH_DATA Read1; > + FLASH_DATA Read2; > + > + // Initialize variables > + Timeout = 0; > + LastWrittenAddress = 0; > + LastWritenData = 0; > + CurrentOffset = PageBufferOffset; > + EndOffset = PageBufferOffset + NumWords - 1; > + Timeout = ConvertMicroSecondsToTicks (mNorFlashDevices[Instance->Media.MediaId].BufferWriteTimeOut); > + TargetAddress = CREATE_NOR_ADDRESS ( > + Instance->DeviceBaseAddress, > + CREATE_BYTE_OFFSET (CurrentOffset) > + ); > + > + // don't try with a count of zero > + if (!NumWords) { > + return EFI_SUCCESS; > + } else if (NumWords == 1) { > + return NorFlashPlatformWriteWord (Instance, PageBufferOffset, *Buffer); > + } > + > + // Issue the Unlock cmds > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_WRITE_TO_BUFFER_FIRST); > + > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_2_ADDR, CMD_WRITE_TO_BUFFER_SECOND); > + > + // Write the buffer load > + SEND_NOR_COMMAND (TargetAddress, 0, CMD_WRITE_TO_BUFFER_THIRD); > + > + // Write # of locations to program > + SEND_NOR_COMMAND (TargetAddress, 0, (NumWords - 1)); > + > + // Load Data into Buffer > + while (CurrentOffset <= EndOffset) { > + LastWrittenAddress = CREATE_NOR_ADDRESS ( > + Instance->DeviceBaseAddress, > + CREATE_BYTE_OFFSET (CurrentOffset++) > + ); > + LastWritenData = *Buffer++; > + > + // Write Data > + MmioWrite16 (LastWrittenAddress, LastWritenData); > + } > + > + // Issue the Buffered Program Confirm command > + SEND_NOR_COMMAND (TargetAddress, 0, CMD_WRITE_TO_BUFFER_CONFIRM); > + > + /* Wait for Write to Complete > + Read the last written address twice to detect bit toggle and > + to determine if date is wriiten successfully or not ? > + Get the maximum timer ticks needed to complete the operation > + Check if operation is complete or not in continous loop? > + if complete, exit from loop > + if not check the ticks that have been passed from the begining of loop > + if Maximum Ticks allocated for operation has passed, then exit from loop **/ > + SystemCounterVal = GetPerformanceCounter(); > + Timeout += SystemCounterVal; > + while (SystemCounterVal < Timeout) { > + if ((Read1 = MmioRead16 (LastWrittenAddress)) > + == (Read2 = MmioRead16 (LastWrittenAddress))) OK, it was only this location as well. / Leif > + { > + if (LastWritenData == MmioRead16 (LastWrittenAddress)) { > + break; > + } > + } > + SystemCounterVal = GetPerformanceCounter (); > + } > + > + if (SystemCounterVal >= Timeout) { > + DEBUG ((DEBUG_ERROR, "%a: Failed to Write @LastWrittenAddress 0x%p, Timeout\n", > + __FUNCTION__, LastWrittenAddress)); > + return EFI_DEVICE_ERROR; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +EFI_STATUS > +NorFlashPlatformWriteWordAlignedAddressBuffer ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN UINTN Offset, > + IN UINTN NumWords, > + IN FLASH_DATA *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINTN MultiByteWordCount; > + UINTN Mask; > + UINTN IntWords; > + > + MultiByteWordCount = mNorFlashDevices[Instance->Media.MediaId].MultiByteWordCount; > + Mask = MultiByteWordCount - 1; > + IntWords = NumWords; > + Status = EFI_SUCCESS; > + > + if (Offset & Mask) { > + // program only as much as necessary, so pick the lower of the two numbers > + if (NumWords < (MultiByteWordCount - (Offset & Mask))) { > + IntWords = NumWords; > + } else { > + IntWords = MultiByteWordCount - (Offset & Mask); > + } > + > + // program the first few to get write buffer aligned > + Status = NorFlashPlatformWritePageBuffer (Instance, Offset, IntWords, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Offset += IntWords; // adjust pointers and counter > + NumWords -= IntWords; > + Buffer += IntWords; > + > + if (NumWords == 0) { > + return Status; > + } > + } > + > + while (NumWords >= MultiByteWordCount) {// while big chunks to do > + Status = NorFlashPlatformWritePageBuffer ( > + Instance, > + Offset, > + MultiByteWordCount, > + Buffer > + ); > + if (EFI_ERROR (Status)) { > + return (Status); > + } > + > + Offset += MultiByteWordCount; // adjust pointers and counter > + NumWords -= MultiByteWordCount; > + Buffer += MultiByteWordCount; > + } > + if (NumWords == 0) { > + return (Status); > + } > + > + Status = NorFlashPlatformWritePageBuffer ( > + Instance, > + Offset, > + NumWords, > + Buffer > + ); > + return (Status); > +} > + > +/** > + Writes data to the NOR Flash using the Buffered Programming method. > + > + Write Buffer Programming allows the system to write a maximum of 32 bytes > + in one programming operation. Therefore this function will only handle > + buffers up to 32 bytes. > + To deal with larger buffers, call this function again. > +**/ > +EFI_STATUS > +NorFlashPlatformWriteBuffer ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ) > +{ > + EFI_STATUS Status; > + FLASH_DATA *SrcBuffer; > + UINTN TargetOffsetinBytes; > + UINTN WordsToWrite; > + UINTN Mask; > + UINTN BufferSizeInBytes; > + UINTN IntBytes; > + VOID *CopyFrom; > + VOID *CopyTo; > + FLASH_DATA TempWrite; > + > + SrcBuffer = (FLASH_DATA *)Buffer; > + TargetOffsetinBytes = 0; > + WordsToWrite = 0; > + Mask = sizeof (FLASH_DATA) - 1; > + BufferSizeInBytes = *NumBytes; > + IntBytes = BufferSizeInBytes; // Intermediate Bytes needed to copy for alignment > + TempWrite = 0; > + > + DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=%ld, Offset=0x%x, " > + "*NumBytes=0x%x, Buffer @ 0x%08x)\n", > + __FUNCTION__, Lba, Offset, *NumBytes, Buffer)); > + > + TargetOffsetinBytes = GET_BLOCK_OFFSET (Lba) + (UINTN)(Offset); > + > + if (TargetOffsetinBytes & Mask) { > + // Write only as much as necessary, so pick the lower of the two numbers > + // and call it Intermediate bytes to write to make alignment proper > + if (BufferSizeInBytes < (sizeof (FLASH_DATA) - (TargetOffsetinBytes & Mask))) { > + IntBytes = BufferSizeInBytes; > + } else { > + IntBytes = sizeof (FLASH_DATA) - (TargetOffsetinBytes & Mask); > + } > + > + // Read the first few to get Read buffer aligned > + NorFlashPlatformRead ( > + Instance, > + Lba, > + (TargetOffsetinBytes & ~Mask) - GET_BLOCK_OFFSET (Lba), > + sizeof (TempWrite), > + (UINT8*)&TempWrite > + ); > + > + CopyTo = (UINT8*)&TempWrite; > + CopyTo += (TargetOffsetinBytes & Mask); > + CopyFrom = Buffer; > + > + CopyMem (CopyTo, CopyFrom, IntBytes); > + > + Status = NorFlashPlatformWriteWordAlignedAddressBuffer ( > + Instance, > + (UINTN)((TargetOffsetinBytes & ~Mask) / sizeof (FLASH_DATA)), > + 1, > + &TempWrite); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, "%a : Failed to Write @TargetOffset 0x%x (0x%x)\n", > + __FUNCTION__, TargetOffsetinBytes, Status)); > + goto EXIT; > + } > + > + TargetOffsetinBytes += IntBytes; /* adjust pointers and counter */ > + BufferSizeInBytes -= IntBytes; > + Buffer += IntBytes; > + > + if (BufferSizeInBytes == 0) { > + goto EXIT; > + } > + } > + > + // Write the bytes to CFI width aligned address. > + // Note we can Write number of bytes=CFI width in one operation > + WordsToWrite = BufferSizeInBytes / sizeof (FLASH_DATA); > + SrcBuffer = (FLASH_DATA*)Buffer; > + > + Status = NorFlashPlatformWriteWordAlignedAddressBuffer ( > + Instance, > + (UINTN)(TargetOffsetinBytes/sizeof (FLASH_DATA)), > + WordsToWrite, > + SrcBuffer); > + if (EFI_ERROR(Status)) { > + DEBUG((DEBUG_ERROR, "%a : Failed to Write @ TargetOffset 0x%x (0x%x)\n", > + __FUNCTION__, TargetOffsetinBytes, Status)); > + goto EXIT; > + } > + > + BufferSizeInBytes -= (WordsToWrite * sizeof (FLASH_DATA)); > + Buffer += (WordsToWrite*sizeof (FLASH_DATA)); > + TargetOffsetinBytes += (WordsToWrite * sizeof (FLASH_DATA)); > + > + if (BufferSizeInBytes == 0) { > + goto EXIT; > + } > + > + // Now Write bytes that are remaining and are less than CFI width. > + // Read the first few to get Read buffer aligned > + NorFlashPlatformRead ( > + Instance, > + Lba, > + TargetOffsetinBytes - GET_BLOCK_OFFSET (Lba), > + sizeof (TempWrite), > + (UINT8*)&TempWrite); > + > + CopyFrom = Buffer; > + CopyTo = &TempWrite; > + > + CopyMem (CopyTo, CopyFrom, BufferSizeInBytes); > + > + Status = NorFlashPlatformWriteWordAlignedAddressBuffer ( > + Instance, > + (UINTN)(TargetOffsetinBytes/sizeof (FLASH_DATA)), > + 1, > + &TempWrite > + ); > + > + if (EFI_ERROR(Status)) { > + DEBUG((DEBUG_ERROR, "%a: Failed to Write @TargetOffset 0x%x Status=%d\n", > + __FUNCTION__, TargetOffsetinBytes, Status)); > + goto EXIT; > + } > + > +EXIT: > + // Put device back into Read Array mode (via Reset) > + NorFlashPlatformReset (Instance->DeviceBaseAddress); > + return (Status); > +} > + > +EFI_STATUS > +NorFlashPlatformRead ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN BufferSizeInBytes, > + OUT UINT8 *Buffer > + ) > +{ > + UINTN IntBytes; > + UINTN Mask; > + FLASH_DATA TempRead; > + VOID *CopyFrom; > + VOID *CopyTo; > + UINTN TargetOffsetinBytes; > + FLASH_DATA *ReadData; > + UINTN BlockSize; > + > + IntBytes = BufferSizeInBytes; //Intermediate Bytes needed to copy for alignment > + Mask = sizeof (FLASH_DATA) - 1; > + TempRead = 0; > + TargetOffsetinBytes = (UINTN)(GET_BLOCK_OFFSET (Lba) + Offset); > + BlockSize = Instance->Media.BlockSize; > + > + DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=%ld, Offset=0x%x," > + " BufferSizeInBytes=0x%x, Buffer @ 0x%p)\n", > + __FUNCTION__, Lba, Offset, BufferSizeInBytes, Buffer)); > + > + // The buffer must be valid > + if (Buffer == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Return if we have not any byte to read > + if (BufferSizeInBytes == 0) { > + return EFI_SUCCESS; > + } > + > + if (((Lba * BlockSize) + BufferSizeInBytes) > Instance->Size) { > + DEBUG ((DEBUG_ERROR, "%a : Read will exceed device size.\n", __FUNCTION__)); > + return EFI_INVALID_PARAMETER; > + } > + > + // Put device back into Read Array mode (via Reset) > + NorFlashPlatformReset (Instance->DeviceBaseAddress); > + > + // First Read bytes to make buffer aligned to CFI width > + if (TargetOffsetinBytes & Mask) { > + // Read only as much as necessary, so pick the lower of the two numbers > + if (BufferSizeInBytes < (sizeof (FLASH_DATA) - (TargetOffsetinBytes & Mask))) { > + IntBytes = BufferSizeInBytes; > + } else { > + IntBytes = sizeof (FLASH_DATA) - (TargetOffsetinBytes & Mask); > + } > + > + // Read the first few to get Read buffer aligned > + TempRead = MmioRead16 ( > + CREATE_NOR_ADDRESS ( > + Instance->DeviceBaseAddress, > + CREATE_BYTE_OFFSET ((TargetOffsetinBytes & ~Mask) / sizeof (FLASH_DATA)) > + ) > + ); > + > + CopyFrom = (UINT8*)&TempRead; > + CopyFrom += (TargetOffsetinBytes & Mask); > + CopyTo = Buffer; > + > + CopyMem (CopyTo, CopyFrom, IntBytes); > + > + TargetOffsetinBytes += IntBytes; // adjust pointers and counter > + BufferSizeInBytes -= IntBytes; > + Buffer += IntBytes; > + if (BufferSizeInBytes == 0) { > + return EFI_SUCCESS; > + } > + } > + > + ReadData = (FLASH_DATA*)Buffer; > + > + // Readout the bytes from CFI width aligned address. > + // Note we can read number of bytes=CFI width in one operation > + while (BufferSizeInBytes >= sizeof (FLASH_DATA)) { > + *ReadData = MmioRead16 ( > + CREATE_NOR_ADDRESS ( > + Instance->DeviceBaseAddress, > + CREATE_BYTE_OFFSET (TargetOffsetinBytes / sizeof (FLASH_DATA)) > + ) > + ); > + ReadData += 1; > + BufferSizeInBytes -= sizeof (FLASH_DATA); > + TargetOffsetinBytes += sizeof (FLASH_DATA); > + } > + > + if (BufferSizeInBytes == 0) { > + return EFI_SUCCESS; > + } > + > + // Now read bytes that are remaining and are less than CFI width. > + CopyTo = ReadData; > + // Read the first few to get Read buffer aligned > + TempRead = MmioRead16 ( > + CREATE_NOR_ADDRESS ( > + Instance->DeviceBaseAddress, > + CREATE_BYTE_OFFSET (TargetOffsetinBytes/sizeof (FLASH_DATA)) > + ) > + ); > + CopyFrom = &TempRead; > + > + CopyMem (CopyTo, CopyFrom, BufferSizeInBytes); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +NorFlashPlatformReset ( > + IN UINTN DeviceBaseAddress > + ) > +{ > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR, CMD_RESET_FIRST); > + > + SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_2_ADDR, CMD_RESET_SECOND); > + > + SEND_NOR_COMMAND (DeviceBaseAddress, 0, CMD_RESET); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +NorFlashInitMmioOps ( > + VOID > + ) > +{ > + mMmioOps = GetMmioOperations16 (FixedPcdGetBool (PcdIfcBigEndian)); > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +NorFlashPlatformGetDevices ( > + OUT NorFlashDescription **NorFlashDevices, > + OUT UINT32 *Count > + ) > +{ > + // This is the function to be called, before using > + if ((NorFlashDevices == NULL) || (Count == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Get the number of NOR flash devices supported > + *NorFlashDevices = mNorFlashDevices; > + *Count = NOR_FLASH_DEVICE_COUNT; > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +NorFlashPlatformFlashGetAttributes ( > + OUT NorFlashDescription *NorFlashDevices, > + IN UINT32 Count > + ) > +{ > + EFI_STATUS Status; > + UINT32 Index; > + > + if ((NorFlashDevices == NULL) || (Count == 0)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Check the attributes of the NOR flash slave we are connected to. > + // Currently we support only CFI flash devices. Bail-out otherwise. > + Status = CfiNorFlashFlashGetAttributes (NorFlashDevices, Count); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Limit the Size of Nor Flash that can be programmed > + for (Index = 0; Index < Count; Index++) { > + NorFlashDevices[Index].RegionBaseAddress = PcdGet64 (PcdFlashReservedRegionBase64); > + NorFlashDevices[Index].Size -= (NorFlashDevices[Index].RegionBaseAddress - > + NorFlashDevices[Index].DeviceBaseAddress); > + if ((NorFlashDevices[Index].RegionBaseAddress - NorFlashDevices[Index].DeviceBaseAddress) > + % NorFlashDevices[Index].BlockSize) > + { > + DEBUG ((DEBUG_ERROR, "%a : Reserved Region(0x%p) doesn't start " > + "from block boundry(0x%08x)\n", __FUNCTION__, > + (UINTN)NorFlashDevices[Index].RegionBaseAddress, > + (UINT32)NorFlashDevices[Index].BlockSize)); > + return EFI_DEVICE_ERROR; > + } > + } > + return Status; > +} > diff --git a/Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf b/Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf > new file mode 100644 > index 0000000..e0370b9 > --- /dev/null > +++ b/Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf > @@ -0,0 +1,43 @@ > +# @NorFlashLib.inf > +# > +# Component description file for NorFlashLib module > +# > +# Copyright 2017 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 = 0x0001001A > + BASE_NAME = NorFlashLib > + FILE_GUID = f3176a49-dde1-450d-a909-8580c03b9ba8 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = NorFlashLib > + CONSTRUCTOR = NorFlashInitMmioOps > + > +[Sources.common] > + CfiNorFlashLib.c > + NorFlashLib.c > + > +[LibraryClasses] > + ArmLib > + IoAccessLib > + TimerLib > + > +[Packages] > + ArmPkg/ArmPkg.dec > + MdePkg/MdePkg.dec > + Silicon/NXP/NxpQoriqLs.dec > + > +[Pcd.common] > + gNxpQoriqLsTokenSpaceGuid.PcdFlashDeviceBase64 > + gNxpQoriqLsTokenSpaceGuid.PcdFlashReservedRegionBase64 > + gNxpQoriqLsTokenSpaceGuid.PcdIfcBigEndian > + gNxpQoriqLsTokenSpaceGuid.PcdIfcNandReservedSize > -- > 1.9.1 >