1From 6d274379f584a638c1f2b4b8a19014d4baef1d9f Mon Sep 17 00:00:00 2001 2From: sahil <sahil@arm.com> 3Date: Thu, 11 Aug 2022 11:26:29 +0530 4Subject: [PATCH] Platform/ARM/N1Sdp: manually poll QSPI status bit after 5 erase/write 6 7This patch adds a function to poll Nor flash memory's status register 8bit (WIP bit) to wait for an erase/write operation to complete. 9The polling timeout is set to 1 second. 10 11Upstream-Status: Pending 12Signed-off-by: Xueliang Zhong <xueliang.zhong@arm.com> 13Signed-off-by: sahil <sahil@arm.com> 14Change-Id: Ie678b7586671964ae0f8506a0542d73cbddddfe4 15--- 16 .../Drivers/CadenceQspiDxe/CadenceQspiDxe.inf | 1 + 17 .../Drivers/CadenceQspiDxe/CadenceQspiReg.h | 6 +- 18 .../N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c | 80 ++++++++++++++++++- 19 .../N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h | 5 ++ 20 4 files changed, 88 insertions(+), 4 deletions(-) 21 22diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf 23index 4f20c3ba..7a39eb2d 100644 24--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf 25+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf 26@@ -39,6 +39,7 @@ 27 MemoryAllocationLib 28 NorFlashInfoLib 29 NorFlashPlatformLib 30+ TimerLib 31 UefiBootServicesTableLib 32 UefiDriverEntryPoint 33 UefiLib 34diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h 35index fe3b327c..1971631d 100644 36--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h 37+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h 38@@ -16,13 +16,15 @@ 39 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS 19 40 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS 16 41 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT 0x02 42-#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_4B 0x03 43-#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B 0x02 44 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS 24 45 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE 0x01 46 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_BYTE_3B 0x02 47 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS 23 48 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS 20 49+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C 0x8 50+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS 7 51+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS) 52+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS) 53 54 #define CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET 0xA0 55 56diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c 57index 188c75e2..6832351a 100644 58--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c 59+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c 60@@ -10,6 +10,7 @@ 61 #include <Library/MemoryAllocationLib.h> 62 #include <Library/NorFlashInfoLib.h> 63 #include <Library/PcdLib.h> 64+#include <Library/TimerLib.h> 65 #include <Library/UefiBootServicesTableLib.h> 66 #include <Library/UefiLib.h> 67 68@@ -184,6 +185,74 @@ FreeInstance: 69 return Status; 70 } 71 72+/** 73+ Converts milliseconds into number of ticks of the performance counter. 74+ 75+ @param[in] Milliseconds Milliseconds to convert into ticks. 76+ 77+ @retval Milliseconds expressed as number of ticks. 78+ 79+**/ 80+STATIC 81+UINT64 82+MilliSecondsToTicks ( 83+ IN UINTN Milliseconds 84+ ) 85+{ 86+ CONST UINT64 NanoSecondsPerTick = GetTimeInNanoSecond (1); 87+ 88+ return (Milliseconds * 1000000) / NanoSecondsPerTick; 89+} 90+ 91+/** 92+ Poll Status register for NOR flash erase/write completion. 93+ 94+ @param[in] Instance NOR flash Instance. 95+ 96+ @retval EFI_SUCCESS Request is executed successfully. 97+ @retval EFI_TIMEOUT Operation timed out. 98+ @retval EFI_DEVICE_ERROR Controller operartion failed. 99+ 100+**/ 101+STATIC 102+EFI_STATUS 103+NorFlashPollStatusRegister ( 104+ IN NOR_FLASH_INSTANCE *Instance 105+ ) 106+{ 107+ BOOLEAN SRegDone; 108+ UINT32 val; 109+ 110+ val = SPINOR_OP_RDSR << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | 111+ CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS | 112+ CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(1) | 113+ CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C << CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS; 114+ 115+ CONST UINT64 TickOut = 116+ GetPerformanceCounter () + MilliSecondsToTicks (SPINOR_SR_WIP_POLL_TIMEOUT_MS); 117+ 118+ do { 119+ if (GetPerformanceCounter () > TickOut) { 120+ DEBUG (( 121+ DEBUG_ERROR, 122+ "NorFlashPollStatusRegister: Timeout waiting for erase/write.\n" 123+ )); 124+ return EFI_TIMEOUT; 125+ } 126+ 127+ if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { 128+ return EFI_DEVICE_ERROR; 129+ } 130+ 131+ SRegDone = 132+ (MmioRead8 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET) 133+ & SPINOR_SR_WIP) == 0; 134+ 135+ } while (!SRegDone); 136+ 137+ return EFI_SUCCESS; 138+} 139+ 140 /** 141 Check whether NOR flash opertions are Locked. 142 143@@ -305,12 +374,16 @@ NorFlashEraseSingleBlock ( 144 145 DevConfigVal = SPINOR_OP_BE_4K << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | 146 CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS | 147- CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS; 148+ CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(3); 149 150 if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, DevConfigVal))) { 151 return EFI_DEVICE_ERROR; 152 } 153 154+ if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) { 155+ return EFI_DEVICE_ERROR; 156+ } 157+ 158 return EFI_SUCCESS; 159 } 160 161@@ -383,6 +456,9 @@ NorFlashWriteSingleWord ( 162 return EFI_DEVICE_ERROR; 163 } 164 MmioWrite32 (WordAddress, WriteData); 165+ if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) { 166+ return EFI_DEVICE_ERROR; 167+ } 168 return EFI_SUCCESS; 169 } 170 171@@ -907,7 +983,7 @@ NorFlashReadID ( 172 173 val = SPINOR_OP_RDID << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | 174 CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS | 175- CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS; 176+ CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(3); 177 178 if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { 179 return EFI_DEVICE_ERROR; 180diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h 181index e720937e..eb0afc60 100644 182--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h 183+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h 184@@ -477,8 +477,13 @@ NorFlashReadID ( 185 OUT UINT8 JedecId[3] 186 ); 187 188+#define SPINOR_SR_WIP BIT0 // Write in progress 189+ 190 #define SPINOR_OP_WREN 0x06 // Write enable 191 #define SPINOR_OP_BE_4K 0x20 // Erase 4KiB block 192 #define SPINOR_OP_RDID 0x9f // Read JEDEC ID 193+#define SPINOR_OP_RDSR 0x05 // Read status register 194+ 195+#define SPINOR_SR_WIP_POLL_TIMEOUT_MS 1000u // Status Register read timeout 196 197 #endif /* NOR_FLASH_DXE_H_ */ 198