blob: 8e14699585f00efc2f7a413b4953ee5e612c668f [file] [log] [blame]
Patrick Williams8e7b46e2023-05-01 14:19:06 -05001From 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_ */