From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=40.107.0.52; helo=eur02-am5-obe.outbound.protection.outlook.com; envelope-from=meenakshi.aggarwal@nxp.com; receiver=edk2-devel@lists.01.org Received: from EUR02-AM5-obe.outbound.protection.outlook.com (mail-eopbgr00052.outbound.protection.outlook.com [40.107.0.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 22E00223230CE for ; Fri, 16 Feb 2018 00:47:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=siNXeqQVB1RELa/DdJrmdZ6Pi8Sda2GkGNoRF/RwRuI=; b=OLPc6rKZVaHXgSuvrQqdlTFcwbmY81ScqahPdVvKpNQO93x3pTGUnXEIYKBFpZRXU74ypgrzBvZMZxzjO3juHbFA/XlrvM7taqK1f0WKrXw3RUsXZMiK2qJbnlDVmQCHCxXyhjjCUPBilsic7ZJJWVphDUdqcY/fuqKwhJ4bL/w= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=meenakshi.aggarwal@nxp.com; Received: from idcbfarm.ap.freescale.net (192.88.169.1) by VI1PR04MB1008.eurprd04.prod.outlook.com (2a01:111:e400:5090::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.485.10; Fri, 16 Feb 2018 08:53:29 +0000 From: Meenakshi To: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, michael.d.kinney@intel.com, edk2-devel@lists.01.org Date: Fri, 16 Feb 2018 14:20:11 +0530 Message-Id: <1518771035-6733-16-git-send-email-meenakshi.aggarwal@nxp.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1518771035-6733-1-git-send-email-meenakshi.aggarwal@nxp.com> References: <1518771035-6733-1-git-send-email-meenakshi.aggarwal@nxp.com> MIME-Version: 1.0 X-Originating-IP: [192.88.169.1] X-ClientProxiedBy: HK2PR02CA0172.apcprd02.prod.outlook.com (2603:1096:201:1f::32) To VI1PR04MB1008.eurprd04.prod.outlook.com (2a01:111:e400:5090::28) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 30a56a89-0111-4f75-551d-08d5751ac1b1 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(4604075)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603307)(7153060)(7193020); SRVR:VI1PR04MB1008; X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB1008; 3:IvMf1pRZEnJG+nO8ViME72Yij6QZFj7oseHrhDTdaFW43raYvbOXGSp2h8kkpBNGplibTOmh3fQdkGUe1+Hc5QngLxAzvwstM/w4A6phdH+TCEZ90oRixYl9f89JYJRGVIkkj++PtxKyGuxeyTaTV34qtr/7PV1vHl/Owc0VK7NzYu/S2wTnaPuBqQFrjL/mHFw8IG3ns4R1vsuQbBPaeg7Iub31GH8XgcKYCXSW8f/yPSliUjs/4nBM9dhTAj75; 25:3oMfTv0oj9MB5czmotTcc0rzv/AzqCwvsOmV+JyQcEzYTLYlbJIFny1D+K1ljZXIzsz4EJxeMYX3JH/YB8ytmXu9/TMyFbY6bxWsztqPJdx54A4KcsmbjuzXHt7IfW7BJAKUkCP8zjlzt463/jlbQdw+Xw0Pl7kPEckYDk6QdhlLWZpDqW2beBlAZ0EoEfgDZ+666xwv4cpQuHtrkFp52kmLxOtX+Ctx9GyhfQPurOQNXaIdw634YQQ4WnFUGFVEMhBoXP4v8wFswxXSbH88qaWoNlTR3JF5l1QdaAhV61QLO5TcZdZDi5zpgAlLdzSCBbxzNFBXt1NzRBpA2YtgRg==; 31:TT3+k2j2SJOMSu+9au8YNTZrBKgUa24/aUZfYBhzG1Weh6qS+iUlSLzcoAHXOtfzSe595TAJk9COmdtQprx3sZuCQwlSLeIMn1zWzRn/gqWJyA0Z7LG9+Ykd15tJoiAfo0Z/dgbuEVxVYVqlsSRYy+p4YSNSncZvqw/RIn5rYF+AiDA5PCJ6gdWgmxIOS1dZMFE67ou6lUArjlXn6x9bGVRJvybInHmX+U6HZ0XDQGI= X-MS-TrafficTypeDiagnostic: VI1PR04MB1008: X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB1008; 20:PpFzVUhyBmEdLw3GI7gaT4n1nKuUrMR0mRWnSFE7bodWfCwYgZ1ballsTM7Imdp7kNasIpOCiNXhLuyIxxjZMVjI8rE81gwebiy4+IyN53BTR6UqHoA3DEupCuUgc8RDMHs9mMZ1oixVyG1BQmSNNmO3yrVg2EKgoHQYv8LcxPghsliG1AiZ+pIVEEM9Foy94BsCDTvqVgPpvN3RSsdnRGj4tj/ZyiLy+jxHDpHlaw22ES4PKQI63/4XjgAxAXIc9UcVleGvSA6+1stVNUveAhbMQJgqlXQ9PXDyYM5ohUxJj+tRsJOlbiiIuDxRBaQkig1edZIhbUKVmIGfTgaui1AgkpT2ZNiHOC1Rf2dsoLc01vVyH6BAMIudnelMA2O0wiwf9n0RH1kN1VtIr0S1ZoMnY98pOqT938uPmJz0Hla1bn/6WXm1t2d2FBnXtxldVz4tdexM6ZBHpS7pSAljFMC8ZMGptOwV7sxe8BVfuurPNi0mgM+57cwvajBN3vju; 4:ChkJlQDYB8AzuWNu9kJBfeHaxow/G2EXFbXY5WKq454qNW5RNk830yzwU0dzBZ4UDqGe3IAeASO91lxUi6IbpgQe4BU2o1vuLnyGVQB67jKfJjdPjNyxlZGe7qRLGUlQVG+lUGAlJ7EOKmxydNg7oUnznNG63YLGXjmpjX9oND3aRiR7FrVtMGnsX6NAkmsk1RwZtgvAa4q3pGVZM+lOMJ7PqAwORsJlBwDdnzqFT1/3ndAClpcvj3z5oCinYlTm+ppHWeYby5t9wybqrSBFGljw49E28l108hGE99J24hkYQfZDU13W6r6Z2FJe0Uaw X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040501)(2401047)(8121501046)(5005006)(93006095)(93001095)(10201501046)(3002001)(3231101)(944501161)(6055026)(6041288)(20161123558120)(20161123564045)(20161123560045)(20161123562045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011); SRVR:VI1PR04MB1008; BCL:0; PCL:0; RULEID:; SRVR:VI1PR04MB1008; X-Forefront-PRVS: 0585417D7B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(376002)(39380400002)(396003)(39860400002)(366004)(199004)(189003)(86362001)(6486002)(8676002)(76176011)(36756003)(53376002)(966005)(4326008)(6116002)(15188155005)(16799955002)(7736002)(386003)(68736007)(186003)(26005)(53936002)(305945005)(16526019)(81156014)(3846002)(6506007)(478600001)(50226002)(16586007)(8936002)(2950100002)(316002)(2906002)(59450400001)(25786009)(97736004)(50466002)(48376002)(105586002)(52116002)(47776003)(81166006)(51416003)(53946003)(5660300001)(6666003)(106356001)(66066001)(6306002)(6512007)(579004)(19627235001); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR04MB1008; H:idcbfarm.ap.freescale.net; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR04MB1008; 23:oHbJXCQ7BnLFxDsAER7VLw7AKTGxN/YrWo/gZX5CN?= =?us-ascii?Q?D6FX0vBPio7WDg+Vw7Fs4xwj77HcodE78w+ZnyroYdTSjv3UXwhyulH0T1WW?= =?us-ascii?Q?S5Dv3JuYBOqnHUeTBQczqiptmibvRuOcUYV4lz534OaBjryh7fJoigf4Mun2?= =?us-ascii?Q?kM+X9mSrfa9Vo65wjJtKzih641N4Y8HcLyg3bJ6a7sR0Hh2SKeLo1Tjuk57u?= =?us-ascii?Q?VKcmw4l8EI/V0+9YofAjecS6bqYow6AUjOo1zocnBYcYwwzRLds+7yAc3XOZ?= =?us-ascii?Q?RFCMWOoBdOG2bEsVSUDRm2X9Bv0WOCpCsDPX7qecP3ndeQyoL1VYdHJQe0pp?= =?us-ascii?Q?1iP6yT4L7I/fYFA0GarIlVITKPVv8SeRiDFnQqiG/cD67DZ2D9Srml0xgUBu?= =?us-ascii?Q?/NDuQ0wyj2b+Y8uA3UjQVnj2qVuyFuvlOXFvQjhTTe4scaMDshOwsJq9bGfI?= =?us-ascii?Q?bet1xh068hBQ29RXT5z6MLo9gwqUTy8j0B1x8wuovT4xInxgV3WLiHK8gjI2?= =?us-ascii?Q?1HobJiAfA7YrbKgW94U0n3eYYjXNpvCP+DHLgLdD0+YO8ibuPHRdjZ+cKs4H?= =?us-ascii?Q?IsSJp5YNq80GqkKbO0tOj+mOiwpGBVMPlv7JFJ95DKRGCcszWij0jovpnpPa?= =?us-ascii?Q?Y6ON12bW2G/X44HrlhVKniddS0uGFbmA33qVgwzEUeKHOgxrUwDtmo4v2CyB?= =?us-ascii?Q?5rm/XzvBCnJfNOfhVJqJLrxWGjZ+1Vnxpsp/jrE+M3tMozDyDqMPuKp3zbGH?= =?us-ascii?Q?GNJ5HgesPJVb89QLU18ni+ZtxEjROh/DwdqbXs+mzSQduBhCYqE5nvl7I4VT?= =?us-ascii?Q?f7iyBP5TgXzTHIcZ2PhD0X3zJWQcWWi6/OqbgUfs6wAdmizH63vZvrRvakN8?= =?us-ascii?Q?o7Bs7Z/VoFhtIayFd6wEOO/+XT7GN1eBykYZUXb8CjKBSkwGPGHYGpZLH9N9?= =?us-ascii?Q?n/ktZtpfMq3ZfgtsNLR2n/FNNlTNQRszTacBdsxxEAGCQ/Rf3WAi2RKZeQtO?= =?us-ascii?Q?04xysuemW0kYinuRqJwUzQ2dr+zD5Mu182jmgWbjUN3f5Weo5BQ57UcEfqv+?= =?us-ascii?Q?bdO4XkelNfFTG5s4Pxm3WirI4IVOhg6PxZwmlQfjqgudiLeZN/4FunlaEcCK?= =?us-ascii?Q?9gOMsmR8Nnl/CHF5GqHyUgXDjrPzg1xQ7z7uiYsI2Xc5PkNKrCMW76idplxU?= =?us-ascii?Q?rjX7yWWfNzp9no0AMXCH7aSVN1oCEwTzB+YkbHLnRoni77m37pwUVKBADqXn?= =?us-ascii?Q?eEtaiEp4CjxsRZnH4NB1dtxcKWBbHiL1zzBtoEkKwAje4ULCDi6VJj1uqWO4?= =?us-ascii?B?UT09?= X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB1008; 6:/L8XyLB6zlO67oNDbG+0IKkrh8IiYB0LkSdQ7M0jo6hqctswEHlMKq3kwi67hcww/jIV74x+5ovi88IJXWefiGCANJ5s0tQzcT0Yj6x/KrlVDdiObl9Rx9cLBpuOCCbhewnSmzP3xAdpzfgyEEoBEVq0Q+STtF1H4AIxOAhTuKsLMyvWCxhSA2fdLT6IjcXwJ2kdDUDDQE9uA4+UGAULeMmkTbO8aQIqVCoCMoZfzl+tDWC2n54fJ7VAn+7JFveFaW9oIDfLNK9pcd8cg38OraqEcUEqRGk3lVSWaWXJDTjj/RgDdOFJZwPKnZk/L2ogTNmIAcofufMnLrfISScJVaB0AuOy9JkzrW0zFoWOWtw=; 5:usyV4y39aCaBgk8Gq1a0Dr4usHdFa4rBlK9atpbyR7XuOi94/rSo+wi7E9HdfDXhHVBSCCSzS4/2oJ2MFtgFwhjcCwxZPtnXEglPOhpG2S52r899xLYh/UjUV8dmRIAkh9s6yrcNFzUKMXUmQMz8+FfF/vOdkXEtY7flZ0P1Eas=; 24:k7r3GB0UFSwqBuAAk5cCtyLhy7m/1sG3PPA5Cu5YwLYr1Nhns3+gO3U/x9RfA59Hyxcs7WCz6Ft4y+smydb4BdF3yGNwHKpURpfjS1MoZ4E=; 7:yFETzrV1ARH0e+VtV7swtjR285zoRYgfOTcL0l8/EYmoP2Cuwv2gwuBZLdau08hUddBodVkVGdPK+3SkhWciSCjXeaHVXifV69CRvzhH04JEWOl0I0uogjdjQnyBAyn/UiZ++NcVrLElFJWYHRwW4weDA4dV+cysrxX3yT4YjngKmCI+Dy87reKL8gqT04gUqlXSpmdBmU/bXp+uHLda1G0LclU9Cu/goCPTThiaVnvlCuGH4szY1SPlftuUAT0C SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2018 08:53:29.0767 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 30a56a89-0111-4f75-551d-08d5751ac1b1 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR04MB1008 Subject: [PATCH edk2-platforms 15/39] Silicon/NXP : Add support of NorFlashLib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Feb 2018 08:47:44 -0000 Content-Type: text/plain From: Meenakshi Aggarwal NorFlashLib interacts with the underlying IFC NOR controller. 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 --- Silicon/NXP/Include/Library/NorFlashLib.h | 77 +++ Silicon/NXP/Include/NorFlash.h | 48 ++ Silicon/NXP/Library/NorFlashLib/CfiCommand.h | 99 ++++ Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c | 233 ++++++++ Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h | 68 +++ Silicon/NXP/Library/NorFlashLib/NorFlashLib.c | 660 +++++++++++++++++++++++ Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf | 41 ++ 7 files changed, 1226 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..888f5c1 --- /dev/null +++ b/Silicon/NXP/Include/NorFlash.h @@ -0,0 +1,48 @@ +/** @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 EFI_STATUS (*NOR_FLASH_INITIALIZE) (NOR_FLASH_INSTANCE* 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; + BOOLEAN Initialized; + NOR_FLASH_INITIALIZE Initialize; + UINTN DeviceBaseAddress; + UINTN RegionBaseAddress; + UINTN Size; + EFI_LBA StartLba; + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; + EFI_BLOCK_IO_MEDIA Media; + BOOLEAN SupportFvb; + 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 @@ -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__ + +// 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 + +#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 + +// 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__ diff --git a/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c new file mode 100644 index 0000000..632e943 --- /dev/null +++ b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.c @@ -0,0 +1,233 @@ +/** @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" + +FLASH_DATA +IfcNorFlashData ( + IN OUT FLASH_DATA Value + ) +{ + if (FixedPcdGetBool (PcdIfcBigEndian)) { + return SwapBytes16 (Value); + } else { + return Value; + } +} + +/** + Write Val at given address. + + @param Val Data to be written. + @param Addr Address where data is to be written. + +**/ +VOID +FlashWriteData ( + IN FLASH_DATA Val, + IN UINTN Addr + ) +{ + *(volatile FLASH_DATA *)(Addr) = (Val); +} + +/** + Check endianness of IFC Controller and depending on swap + the data and write on given address. + + @param Val Data to be written. + @param Addr Address where data is to be written. + +**/ +VOID +FlashWrite ( + IN FLASH_DATA Val, + IN UINTN Addr + ) +{ + FLASH_DATA ShiftVal; + + ShiftVal = IfcNorFlashData (Val); + + *(volatile FLASH_DATA *)(Addr) = (ShiftVal); +} + +/** + Read data from given address. + + @param Addr Address from where data is to be read. + + @return Read Data +**/ +FLASH_DATA +FlashReadData ( + IN UINTN Addr + ) +{ + FLASH_DATA Val; + + Val = *(volatile FLASH_DATA *)(Addr); + + return (Val); +} + +/** + Read data from given address and depending on endianness of IFC Controller + swap the read data. + + @param Addr Address from where data is to be read. + + @return Read Data +**/ +FLASH_DATA +FlashRead ( + IN UINTN Addr + ) +{ + FLASH_DATA Val; + FLASH_DATA ShiftVal; + + Val = *(volatile FLASH_DATA *)(Addr); + ShiftVal = IfcNorFlashData (Val); + + return (ShiftVal); +} + +STATIC +VOID +NorFlashReadCfiData ( + IN UINTN DeviceBaseAddress, + IN UINTN CfiOffset, + IN UINT32 NumberOfShorts, + OUT VOID *Data + ) +{ + UINT32 Count; + FLASH_DATA *TmpData = (FLASH_DATA *)Data; + + for (Count = 0; Count < NumberOfShorts; Count++, TmpData++) { + *TmpData = FLASH_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[3]; + FLASH_DATA BlockSize[2]; + UINTN DeviceBaseAddress; + FLASH_DATA MaxNumBytes[2]; + 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; + + 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); + + ArmDataSynchronizationBarrier (); + + // Query the unique QRY + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_UNIQUE_QRY_STRING, + 3, + &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, + 1, &Size); + // Refer CFI Specification + NorFlashDevices[Count].Size = 1 << Size; + + NorFlashReadCfiData (DeviceBaseAddress, CFI_QUERY_BLOCK_SIZE, + 2, &BlockSize); + // Refer CFI Specification + NorFlashDevices[Count].BlockSize = 256 * ((FLASH_DATA) ((BlockSize[1] << + HighByteShift) | (BlockSize[0] & HighByteMask))); + + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_MAX_NUM_BYTES_WRITE, 2, &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, 1, &Temp1); + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_MAX_TIMEOUT_WORD_WRITE, 1, &Temp2); + NorFlashDevices[Count].WordWriteTimeOut = (1U << Temp1) * (1U << Temp2); + + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_TYP_TIMEOUT_MAX_BUFFER_WRITE, 1, &Temp1); + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_MAX_TIMEOUT_MAX_BUFFER_WRITE, 1, &Temp2); + NorFlashDevices[Count].BufferWriteTimeOut = (1U << Temp1) * (1U << Temp2); + + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_TYP_TIMEOUT_BLOCK_ERASE, 1, &Temp1); + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_MAX_TIMEOUT_BLOCK_ERASE, 1, &Temp2); + NorFlashDevices[Count].BlockEraseTimeOut = + (1U << Temp1) * (1U << Temp2) * 1000; + + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_TYP_TIMEOUT_CHIP_ERASE, 1, &Temp1); + NorFlashReadCfiData (DeviceBaseAddress, + CFI_QUERY_MAX_TIMEOUT_CHIP_ERASE, 1, &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..91d50f0 --- /dev/null +++ b/Silicon/NXP/Library/NorFlashLib/CfiNorFlashLib.h @@ -0,0 +1,68 @@ +/** @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 + +/* + * 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 CREATE_BYTE_OFFSET(OffsetAddr) ((sizeof (FLASH_DATA)) * (OffsetAddr)) +#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + (OffsetAddr)) +#define FLASH_READ(Addr) FlashRead ((Addr)) +#define FLASH_WRITE(Addr, Val) FlashWrite ((Val), (Addr)) +#define FLASH_READ_DATA(Addr) FlashReadData ((Addr)) +#define FLASH_WRITE_DATA(Addr, Val) FlashWriteData ((Val), (Addr)) +#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) FLASH_WRITE (CREATE_NOR_ADDRESS (BaseAddr, CREATE_BYTE_OFFSET (Offset)), (Cmd)) + +typedef UINT16 FLASH_DATA; + +VOID +FlashWrite ( + IN FLASH_DATA Val, + IN UINTN Addr + ); + +FLASH_DATA +FlashRead ( + IN UINTN Addr + ); + +VOID +FlashWriteData ( + IN FLASH_DATA Val, + IN UINTN Addr + ); + +FLASH_DATA +FlashReadData ( + IN UINTN Addr + ); + +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..b74e9eb --- /dev/null +++ b/Silicon/NXP/Library/NorFlashLib/NorFlashLib.c @@ -0,0 +1,660 @@ +/** @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 "CfiCommand.h" +#include "CfiNorFlashLib.h" + +#define GET_BLOCK_OFFSET(Lba) ((Instance->RegionBaseAddress)-\ + (Instance->DeviceBaseAddress)+((UINTN)((Lba) * Instance->Media.BlockSize))) + +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 = FLASH_READ (SectorAddress)) == + (EraseStatus2 = FLASH_READ (SectorAddress))) { + if (0xFFFF == FLASH_READ (SectorAddress)) { + 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); + + FLASH_WRITE_DATA (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 = FLASH_READ_DATA (TargetAddress)) == + (Read2 = FLASH_READ_DATA (TargetAddress))) { + if (Word == FLASH_READ_DATA (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 + FLASH_WRITE_DATA (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 = FLASH_READ_DATA (LastWrittenAddress)) == + (Read2 = FLASH_READ_DATA (LastWrittenAddress))) { + if (LastWritenData == FLASH_READ_DATA (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; + UINT8 *CopyFrom; + UINT8 *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 = (UINT8*)Buffer; + + InternalMemCopyMem (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 = (UINT8*)Buffer; + CopyTo = (UINT8*)&TempWrite; + + InternalMemCopyMem (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; + UINT8 *CopyFrom; + UINT8 *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 = FLASH_READ_DATA (CREATE_NOR_ADDRESS ( + Instance->DeviceBaseAddress, + CREATE_BYTE_OFFSET ((TargetOffsetinBytes & ~Mask)/sizeof (FLASH_DATA)))); + + CopyFrom = (UINT8*)&TempRead; + CopyFrom += (TargetOffsetinBytes & Mask); + CopyTo = (UINT8*)Buffer; + + InternalMemCopyMem (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 = FLASH_READ_DATA (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 = (UINT8*)ReadData; + // Read the first few to get Read buffer aligned + TempRead = FLASH_READ_DATA (CREATE_NOR_ADDRESS ( + Instance->DeviceBaseAddress, + CREATE_BYTE_OFFSET (TargetOffsetinBytes/sizeof (FLASH_DATA)))); + CopyFrom = (UINT8*)&TempRead; + + InternalMemCopyMem (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 +NorFlashPlatformGetDevices ( + OUT NorFlashDescription **NorFlashDevices, + OUT UINT32 *Count + ) +{ + 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..403766a --- /dev/null +++ b/Silicon/NXP/Library/NorFlashLib/NorFlashLib.inf @@ -0,0 +1,41 @@ +# @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 + +[Sources.common] + NorFlashLib.c + CfiNorFlashLib.c + +[LibraryClasses] + ArmLib + 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