summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0009-Platform-ARM-N1Sdp-manually-poll-QSPI-status-bit-aft.patch
blob: 8e14699585f00efc2f7a413b4953ee5e612c668f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
From 6d274379f584a638c1f2b4b8a19014d4baef1d9f Mon Sep 17 00:00:00 2001
From: sahil <sahil@arm.com>
Date: Thu, 11 Aug 2022 11:26:29 +0530
Subject: [PATCH] Platform/ARM/N1Sdp: manually poll QSPI status bit after
 erase/write

This patch adds a function to poll Nor flash memory's status register
bit (WIP bit) to wait for an erase/write operation to complete.
The polling timeout is set to 1 second.

Upstream-Status: Pending
Signed-off-by: Xueliang Zhong <xueliang.zhong@arm.com>
Signed-off-by: sahil <sahil@arm.com>
Change-Id: Ie678b7586671964ae0f8506a0542d73cbddddfe4
---
 .../Drivers/CadenceQspiDxe/CadenceQspiDxe.inf |  1 +
 .../Drivers/CadenceQspiDxe/CadenceQspiReg.h   |  6 +-
 .../N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c   | 80 ++++++++++++++++++-
 .../N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h   |  5 ++
 4 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf
index 4f20c3ba..7a39eb2d 100644
--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf
+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf
@@ -39,6 +39,7 @@
   MemoryAllocationLib
   NorFlashInfoLib
   NorFlashPlatformLib
+  TimerLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h
index fe3b327c..1971631d 100644
--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h
+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h
@@ -16,13 +16,15 @@
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS         19
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS    16
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT           0x02
-#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_4B         0x03
-#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B         0x02
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS       24
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE          0x01
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_BYTE_3B         0x02
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS       23
 #define CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS     20
+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C             0x8
+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS        7
+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS)
+#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS)
 
 #define CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET          0xA0
 
diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c
index 188c75e2..6832351a 100644
--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c
+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c
@@ -10,6 +10,7 @@
 #include <Library/MemoryAllocationLib.h>
 #include <Library/NorFlashInfoLib.h>
 #include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
 
@@ -184,6 +185,74 @@ FreeInstance:
   return Status;
 }
 
+/**
+  Converts milliseconds into number of ticks of the performance counter.
+
+  @param[in] Milliseconds  Milliseconds to convert into ticks.
+
+  @retval Milliseconds expressed as number of ticks.
+
+**/
+STATIC
+UINT64
+MilliSecondsToTicks (
+  IN UINTN Milliseconds
+  )
+{
+  CONST UINT64  NanoSecondsPerTick = GetTimeInNanoSecond (1);
+
+  return (Milliseconds * 1000000) / NanoSecondsPerTick;
+}
+
+/**
+  Poll Status register for NOR flash erase/write completion.
+
+  @param[in]      Instance           NOR flash Instance.
+
+  @retval         EFI_SUCCESS        Request is executed successfully.
+  @retval         EFI_TIMEOUT        Operation timed out.
+  @retval         EFI_DEVICE_ERROR   Controller operartion failed.
+
+**/
+STATIC
+EFI_STATUS
+NorFlashPollStatusRegister (
+  IN NOR_FLASH_INSTANCE     *Instance
+  )
+{
+  BOOLEAN     SRegDone;
+  UINT32      val;
+
+  val = SPINOR_OP_RDSR << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS |
+      CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS |
+      CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(1) |
+      CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C << CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS;
+
+  CONST UINT64  TickOut =
+    GetPerformanceCounter () + MilliSecondsToTicks (SPINOR_SR_WIP_POLL_TIMEOUT_MS);
+
+  do {
+    if (GetPerformanceCounter () > TickOut) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "NorFlashPollStatusRegister: Timeout waiting for erase/write.\n"
+        ));
+      return EFI_TIMEOUT;
+    }
+
+    if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    SRegDone =
+      (MmioRead8 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET)
+      & SPINOR_SR_WIP) == 0;
+
+  } while (!SRegDone);
+
+  return EFI_SUCCESS;
+}
+
 /**
   Check whether NOR flash opertions are Locked.
 
@@ -305,12 +374,16 @@ NorFlashEraseSingleBlock (
 
   DevConfigVal = SPINOR_OP_BE_4K << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS |
                  CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS |
-                 CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS;
+                 CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(3);
 
   if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, DevConfigVal))) {
     return EFI_DEVICE_ERROR;
   }
 
+  if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) {
+      return EFI_DEVICE_ERROR;
+  }
+
   return EFI_SUCCESS;
 }
 
@@ -383,6 +456,9 @@ NorFlashWriteSingleWord (
     return EFI_DEVICE_ERROR;
   }
   MmioWrite32 (WordAddress, WriteData);
+  if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) {
+    return EFI_DEVICE_ERROR;
+  }
   return EFI_SUCCESS;
 }
 
@@ -907,7 +983,7 @@ NorFlashReadID (
 
   val = SPINOR_OP_RDID << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS |
         CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS |
-        CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS;
+        CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(3);
 
   if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
     return EFI_DEVICE_ERROR;
diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h
index e720937e..eb0afc60 100644
--- a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h
+++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h
@@ -477,8 +477,13 @@ NorFlashReadID (
   OUT UINT8               JedecId[3]
   );
 
+#define SPINOR_SR_WIP                 BIT0  // Write in progress
+
 #define SPINOR_OP_WREN                0x06  // Write enable
 #define SPINOR_OP_BE_4K               0x20  // Erase 4KiB block
 #define SPINOR_OP_RDID                0x9f  // Read JEDEC ID
+#define SPINOR_OP_RDSR                0x05  // Read status register
+
+#define SPINOR_SR_WIP_POLL_TIMEOUT_MS  1000u // Status Register read timeout
 
 #endif /* NOR_FLASH_DXE_H_ */