TianoCore EDK2 master
Loading...
Searching...
No Matches
SpiNorFlash.c
Go to the documentation of this file.
1
10#include <Base.h>
11#include <Library/BaseLib.h>
13#include <Library/DebugLib.h>
14#include <Library/TimerLib.h>
16#include <Protocol/SpiIo.h>
18#include "SpiNorFlash.h"
19
34UINT32
36 IN SPI_NOR_FLASH_INSTANCE *Instance,
37 IN UINT8 Opcode,
38 IN UINT32 DummyBytes,
39 IN UINT8 AddressBytesSupported,
40 IN BOOLEAN UseAddress,
41 IN UINT32 Address,
42 IN UINT32 WriteBytes,
43 IN UINT8 *WriteBuffer
44 )
45{
46 UINT32 AddressSize;
47 UINT32 BigEndianAddress;
48 UINT32 Index;
49 UINT8 SfdpAddressBytes;
50
51 SfdpAddressBytes = (UINT8)Instance->SfdpBasicFlash->AddressBytes;
52
53 // Copy Opcode into Write Buffer
54 Instance->SpiTransactionWriteBuffer[0] = Opcode;
55 Index = 1;
56 if (UseAddress) {
57 if (AddressBytesSupported == SPI_ADDR_3BYTE_ONLY) {
58 if (SfdpAddressBytes != 0) {
59 // Check if the supported address length is already initiated.
60 if ((SfdpAddressBytes != SPI_ADDR_3BYTE_ONLY) && (SfdpAddressBytes != SPI_ADDR_3OR4BYTE)) {
61 DEBUG ((DEBUG_ERROR, "%a: Unsupported Address Bytes: 0x%x, SFDP is: 0x%x\n", __func__, AddressBytesSupported, SfdpAddressBytes));
62 ASSERT (FALSE);
63 }
64 }
65
66 AddressSize = 3;
67 } else if (AddressBytesSupported == SPI_ADDR_4BYTE_ONLY) {
68 if (SfdpAddressBytes != 0) {
69 // Check if the supported address length is already initiated.
70 if ((SfdpAddressBytes != SPI_ADDR_4BYTE_ONLY) && (SfdpAddressBytes != SPI_ADDR_3OR4BYTE)) {
71 DEBUG ((DEBUG_ERROR, "%a: Unsupported Address Bytes: 0x%x, SFDP is: 0x%x\n", __func__, AddressBytesSupported, SfdpAddressBytes));
72 ASSERT (FALSE);
73 }
74 }
75
76 AddressSize = 4;
77 } else if (AddressBytesSupported == SPI_ADDR_3OR4BYTE) {
78 if (SfdpAddressBytes != 0) {
79 // Check if the supported address length is already initiated.
80 if (SfdpAddressBytes != SPI_ADDR_3OR4BYTE) {
81 DEBUG ((DEBUG_ERROR, "%a: Unsupported Address Bytes: 0x%x, SFDP is: 0x%x\n", __func__, AddressBytesSupported, SfdpAddressBytes));
82 ASSERT (FALSE);
83 }
84 }
85
86 if (Instance->Protocol.FlashSize <= SIZE_16MB) {
87 AddressSize = 3;
88 } else {
89 // SPI part is > 16MB use 4-byte addressing.
90 AddressSize = 4;
91 }
92 } else {
93 DEBUG ((DEBUG_ERROR, "%a: Invalid Address Bytes\n", __func__));
94 ASSERT (FALSE);
95 }
96
97 BigEndianAddress = SwapBytes32 ((UINT32)Address);
98 BigEndianAddress >>= ((sizeof (UINT32) - AddressSize) * 8);
99 CopyMem (
100 &Instance->SpiTransactionWriteBuffer[Index],
101 &BigEndianAddress,
102 AddressSize
103 );
104 Index += AddressSize;
105 }
106
107 if (SfdpAddressBytes == SPI_ADDR_3OR4BYTE) {
108 //
109 // TODO:
110 // We may need to enter/exit 4-Byte mode if SPI flash
111 // device is currently operated in 3-Bytes mode.
112 //
113 }
114
115 // Fill DummyBytes
116 if (DummyBytes != 0) {
117 SetMem (
118 &Instance->SpiTransactionWriteBuffer[Index],
119 DummyBytes,
120 0
121 );
122 Index += DummyBytes;
123 }
124
125 // Fill Data
126 if (WriteBytes > 0) {
127 CopyMem (
128 &Instance->SpiTransactionWriteBuffer[Index],
129 WriteBuffer,
130 WriteBytes
131 );
132 Index += WriteBytes;
133 }
134
135 return Index;
136}
137
152EFIAPI
154 IN SPI_NOR_FLASH_INSTANCE *Instance,
155 IN UINT32 LengthInBytes,
156 OUT UINT8 *FlashStatus
157 )
158{
159 EFI_STATUS Status;
160 UINT32 TransactionBufferLength;
161
162 // Read Status register
163 TransactionBufferLength = FillWriteBuffer (
164 Instance,
165 SPI_FLASH_RDSR,
166 SPI_FLASH_RDSR_DUMMY,
167 SPI_FLASH_RDSR_ADDR_BYTES,
168 FALSE,
169 0,
170 0,
171 NULL
172 );
173 Status = Instance->SpiIo->Transaction (
174 Instance->SpiIo,
176 FALSE,
177 0,
178 1,
179 8,
180 TransactionBufferLength,
181 Instance->SpiTransactionWriteBuffer,
182 1,
183 FlashStatus
184 );
185 ASSERT_EFI_ERROR (Status);
186 return Status;
187}
188
199 IN SPI_NOR_FLASH_INSTANCE *Instance
200 )
201{
202 EFI_STATUS Status;
203 UINT32 TransactionBufferLength;
204
205 TransactionBufferLength = FillWriteBuffer (
206 Instance,
207 Instance->WriteEnableLatchCommand,
208 SPI_FLASH_WREN_DUMMY,
209 SPI_FLASH_WREN_ADDR_BYTES,
210 FALSE,
211 0,
212 0,
213 NULL
214 );
215 Status = Instance->SpiIo->Transaction (
216 Instance->SpiIo,
218 FALSE,
219 0,
220 1,
221 8,
222 TransactionBufferLength,
223 Instance->SpiTransactionWriteBuffer,
224 0,
225 NULL
226 );
227 if (EFI_ERROR (Status)) {
228 DEBUG ((DEBUG_ERROR, "%a: Set WEL fail.\n", __func__));
229 ASSERT (FALSE);
230 }
231
232 return Status;
233}
234
247 IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
248 IN UINT32 Timeout,
249 IN UINT32 RetryCount
250 )
251{
252 EFI_STATUS Status;
253 UINT8 DeviceStatus;
254 UINT32 AlreadyDelayedInMicroseconds;
255
256 if (Timeout == 0) {
257 return EFI_SUCCESS;
258 }
259
260 if (RetryCount == 0) {
261 RetryCount = 1;
262 }
263
264 do {
265 AlreadyDelayedInMicroseconds = 0;
266 while (AlreadyDelayedInMicroseconds < Timeout) {
267 Status = InternalReadStatus (SpiNorFlashInstance, 1, &DeviceStatus);
268 if (EFI_ERROR (Status)) {
269 DEBUG ((DEBUG_ERROR, "%a: Read status error\n", __func__));
270 ASSERT (FALSE);
271 return Status;
272 }
273
274 if ((DeviceStatus & SPI_FLASH_SR_WIP) == SPI_FLASH_SR_NOT_WIP) {
275 return Status;
276 }
277
278 MicroSecondDelay (FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds));
279 AlreadyDelayedInMicroseconds += FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds);
280 }
281
282 RetryCount--;
283 } while (RetryCount > 0);
284
285 DEBUG ((DEBUG_ERROR, "%a: Timeout error\n", __func__));
286 return EFI_DEVICE_ERROR;
287}
288
302 IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
303 IN UINT32 Timeout,
304 IN UINT32 RetryCount
305 )
306{
307 EFI_STATUS Status;
308 UINT8 DeviceStatus;
309 UINT32 AlreadyDelayedInMicroseconds;
310
311 if (Timeout == 0) {
312 return EFI_SUCCESS;
313 }
314
315 if (RetryCount == 0) {
316 RetryCount = 1;
317 }
318
319 do {
320 AlreadyDelayedInMicroseconds = 0;
321 while (AlreadyDelayedInMicroseconds < Timeout) {
322 Status = InternalReadStatus (SpiNorFlashInstance, 1, &DeviceStatus);
323 if (EFI_ERROR (Status)) {
324 DEBUG ((DEBUG_ERROR, "%a: Fail to read WEL.\n", __func__));
325 ASSERT_EFI_ERROR (Status);
326 return Status;
327 }
328
329 if ((DeviceStatus & (SPI_FLASH_SR_WIP | SPI_FLASH_SR_WEL)) == SPI_FLASH_SR_WEL) {
330 return Status;
331 }
332
333 MicroSecondDelay (FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds));
334 AlreadyDelayedInMicroseconds += FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds);
335 }
336
337 RetryCount--;
338 } while (RetryCount > 0);
339
340 DEBUG ((DEBUG_ERROR, "%a: Timeout error\n", __func__));
341 return EFI_DEVICE_ERROR;
342}
343
357 IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
358 IN UINT32 Timeout,
359 IN UINT32 RetryCount
360 )
361{
362 EFI_STATUS Status;
363 UINT8 DeviceStatus;
364 UINT32 AlreadyDelayedInMicroseconds;
365
366 if (Timeout == 0) {
367 return EFI_SUCCESS;
368 }
369
370 if (RetryCount == 0) {
371 RetryCount = 1;
372 }
373
374 do {
375 AlreadyDelayedInMicroseconds = 0;
376 while (AlreadyDelayedInMicroseconds < Timeout) {
377 Status = InternalReadStatus (SpiNorFlashInstance, 1, &DeviceStatus);
378 ASSERT_EFI_ERROR (Status);
379 if (EFI_ERROR (Status) ||
380 ((DeviceStatus & (SPI_FLASH_SR_WIP | SPI_FLASH_SR_WEL)) == SPI_FLASH_SR_NOT_WIP))
381 {
382 return Status;
383 }
384
385 MicroSecondDelay (FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds));
386 AlreadyDelayedInMicroseconds += FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds);
387 }
388
389 RetryCount--;
390 } while (RetryCount > 0);
391
392 DEBUG ((DEBUG_ERROR, "SpiNorFlash:%a: Timeout error\n", __func__));
393 return EFI_DEVICE_ERROR;
394}
395
414EFIAPI
417 OUT UINT8 *Buffer
418 )
419{
420 EFI_STATUS Status;
421 SPI_NOR_FLASH_INSTANCE *Instance;
422 UINT32 TransactionBufferLength;
423
424 DEBUG ((DEBUG_INFO, "%a: Entry\n", __func__));
425
426 if (Buffer == NULL) {
427 return EFI_INVALID_PARAMETER;
428 }
429
430 Instance = SPI_NOR_FLASH_FROM_THIS (This);
431
432 // Check not WIP
433 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
434
435 if (!EFI_ERROR (Status)) {
436 TransactionBufferLength = FillWriteBuffer (
437 Instance,
438 SPI_FLASH_RDID,
439 SPI_FLASH_RDID_DUMMY,
440 SPI_FLASH_RDID_ADDR_BYTES,
441 FALSE,
442 0,
443 0,
444 NULL
445 );
446 Status = Instance->SpiIo->Transaction (
447 Instance->SpiIo,
449 FALSE,
450 0,
451 1,
452 8,
453 TransactionBufferLength,
454 Instance->SpiTransactionWriteBuffer,
455 3,
456 Buffer
457 );
458 ASSERT_EFI_ERROR (Status);
459 }
460
461 return Status;
462}
463
483EFIAPI
486 IN UINT32 FlashAddress,
487 IN UINT32 LengthInBytes,
488 OUT UINT8 *Buffer
489 )
490{
491 EFI_STATUS Status;
492 SPI_NOR_FLASH_INSTANCE *Instance;
493 UINT32 ByteCounter;
494 UINT32 CurrentAddress;
495 UINT8 *CurrentBuffer;
496 UINT32 Length;
497 UINT32 TransactionBufferLength;
498 UINT32 MaximumTransferBytes;
499
500 DEBUG ((DEBUG_INFO, "%a: Entry\n", __func__));
501
502 Status = EFI_DEVICE_ERROR;
503 if ((Buffer == NULL) ||
504 (FlashAddress >= This->FlashSize) ||
505 (LengthInBytes > This->FlashSize - FlashAddress))
506 {
507 return EFI_INVALID_PARAMETER;
508 }
509
510 Instance = SPI_NOR_FLASH_FROM_THIS (This);
511 MaximumTransferBytes = Instance->SpiIo->MaximumTransferBytes;
512
513 CurrentBuffer = Buffer;
514 Length = 0;
515 for (ByteCounter = 0; ByteCounter < LengthInBytes;) {
516 CurrentAddress = FlashAddress + ByteCounter;
517 CurrentBuffer = Buffer + ByteCounter;
518 Length = LengthInBytes - ByteCounter;
519 // Length must be MaximumTransferBytes or less
520 if (Length > MaximumTransferBytes) {
521 Length = MaximumTransferBytes;
522 }
523
524 // Check not WIP
525 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
526 if (EFI_ERROR (Status)) {
527 break;
528 }
529
530 TransactionBufferLength = FillWriteBuffer (
531 Instance,
533 SPI_FLASH_READ_DUMMY,
534 SPI_FLASH_READ_ADDR_BYTES,
535 TRUE,
536 CurrentAddress,
537 0,
538 NULL
539 );
540 Status = Instance->SpiIo->Transaction (
541 Instance->SpiIo,
543 FALSE,
544 0,
545 1,
546 8,
547 TransactionBufferLength,
548 Instance->SpiTransactionWriteBuffer,
549 Length,
550 CurrentBuffer
551 );
552 ASSERT_EFI_ERROR (Status);
553 ByteCounter += Length;
554 }
555
556 return Status;
557}
558
578EFIAPI
579ReadData (
581 IN UINT32 FlashAddress,
582 IN UINT32 LengthInBytes,
583 OUT UINT8 *Buffer
584 )
585{
586 EFI_STATUS Status;
587 SPI_NOR_FLASH_INSTANCE *Instance;
588 UINT32 ByteCounter;
589 UINT32 CurrentAddress;
590 UINT8 *CurrentBuffer;
591 UINT32 Length;
592 UINT32 TransactionBufferLength;
593 UINT32 MaximumTransferBytes;
594 UINT8 FastReadInstruction;
595 UINT8 FastReadWaitStateDummyClocks;
596 UINT8 FastReadModeClock;
597
598 DEBUG ((DEBUG_INFO, "%a: Entry, Read address = 0x%08x, Length = 0x%08x\n", __func__, FlashAddress, LengthInBytes));
599
600 Status = EFI_DEVICE_ERROR;
601 if ((Buffer == NULL) ||
602 (FlashAddress >= This->FlashSize) ||
603 (LengthInBytes > This->FlashSize - FlashAddress))
604 {
605 return EFI_INVALID_PARAMETER;
606 }
607
608 Instance = SPI_NOR_FLASH_FROM_THIS (This);
609 MaximumTransferBytes = Instance->SpiIo->MaximumTransferBytes;
610
611 //
612 // Initial the default read operation parameters.
613 //
614 FastReadInstruction = SPI_FLASH_FAST_READ;
615 FastReadWaitStateDummyClocks = SPI_FLASH_FAST_READ_DUMMY * 8;
616 FastReadModeClock = 0;
617 //
618 // Override by the Fast Read capabiity table.
619 //
620 // Get the first supported fast read comamnd.
621 // This will be the standard fast read command (0x0b),
622 // which is the first fast read command added to the
623 // supported list.
624 // TODO: The mechanism to choose the advanced fast read
625 // is not determined yet in this version of
626 // SpiNorFlash driver.
627 Status = GetFastReadParameter (
628 Instance,
629 &FastReadInstruction,
630 &FastReadModeClock,
631 &FastReadWaitStateDummyClocks
632 );
633 if (!EFI_ERROR (Status)) {
634 DEBUG ((DEBUG_VERBOSE, " Use below Fast Read mode:\n"));
635 } else {
636 DEBUG ((DEBUG_VERBOSE, " Use the default Fast Read mode:\n"));
637 }
638
639 DEBUG ((DEBUG_VERBOSE, " Instruction : 0x%x\n", FastReadInstruction));
640 DEBUG ((DEBUG_VERBOSE, " Mode Clock : 0x%x\n", FastReadModeClock));
641 DEBUG ((DEBUG_VERBOSE, " Wait States (Dummy Clocks) in clock: 0x%x\n", FastReadWaitStateDummyClocks));
642 DEBUG ((DEBUG_VERBOSE, " Supported erase address bytes by device: 0x%02x.\n", Instance->SfdpBasicFlash->AddressBytes));
643 DEBUG ((DEBUG_VERBOSE, " (00: 3-Byte, 01: 3 or 4-Byte. 10: 4-Byte)\n"));
644
645 CurrentBuffer = Buffer;
646 Length = 0;
647 for (ByteCounter = 0; ByteCounter < LengthInBytes;) {
648 CurrentAddress = FlashAddress + ByteCounter;
649 CurrentBuffer = Buffer + ByteCounter;
650 Length = LengthInBytes - ByteCounter;
651 // Length must be MaximumTransferBytes or less
652 if (Length > MaximumTransferBytes) {
653 Length = MaximumTransferBytes;
654 }
655
656 // Check not WIP
657 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
658 if (EFI_ERROR (Status)) {
659 break;
660 }
661
662 TransactionBufferLength = FillWriteBuffer (
663 Instance,
664 FastReadInstruction,
665 FastReadWaitStateDummyClocks / 8,
666 (UINT8)Instance->SfdpBasicFlash->AddressBytes,
667 TRUE,
668 CurrentAddress,
669 0,
670 NULL
671 );
672 Status = Instance->SpiIo->Transaction (
673 Instance->SpiIo,
675 FALSE,
676 0,
677 1,
678 8,
679 TransactionBufferLength,
680 Instance->SpiTransactionWriteBuffer,
681 Length,
682 CurrentBuffer
683 );
684 ASSERT_EFI_ERROR (Status);
685 ByteCounter += Length;
686 }
687
688 return Status;
689}
690
706EFIAPI
709 IN UINT32 LengthInBytes,
710 OUT UINT8 *FlashStatus
711 )
712{
713 EFI_STATUS Status;
714 SPI_NOR_FLASH_INSTANCE *Instance;
715
716 if (LengthInBytes != 1) {
717 return EFI_INVALID_PARAMETER;
718 }
719
720 Instance = SPI_NOR_FLASH_FROM_THIS (This);
721
722 Status = InternalReadStatus (Instance, LengthInBytes, FlashStatus);
723
724 return Status;
725}
726
743EFIAPI
746 IN UINT32 LengthInBytes,
747 IN UINT8 *FlashStatus
748 )
749{
750 EFI_STATUS Status;
751 SPI_NOR_FLASH_INSTANCE *Instance;
752 UINT32 TransactionBufferLength;
753
754 if (LengthInBytes != 1) {
755 return EFI_INVALID_PARAMETER;
756 }
757
758 Instance = SPI_NOR_FLASH_FROM_THIS (This);
759
760 // Check not WIP
761 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
762
763 // Set Write Enable
764 if (!EFI_ERROR (Status)) {
765 if (Instance->WriteEnableLatchRequired) {
766 Status = SetWel (Instance);
767 DEBUG ((DEBUG_ERROR, "%a: set Write Enable Error.\n", __func__));
768 ASSERT_EFI_ERROR (Status);
769 // Check not WIP & WEL enabled
770 Status = WaitWelNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
771 }
772
773 // Write the Status Register
774 if (!EFI_ERROR (Status)) {
775 TransactionBufferLength = FillWriteBuffer (
776 Instance,
777 SPI_FLASH_WRSR,
778 SPI_FLASH_WRSR_DUMMY,
779 SPI_FLASH_WRSR_ADDR_BYTES,
780 FALSE,
781 0,
782 0,
783 NULL
784 );
785 Status = Instance->SpiIo->Transaction (
786 Instance->SpiIo,
788 FALSE,
789 0,
790 1,
791 8,
792 TransactionBufferLength,
793 Instance->SpiTransactionWriteBuffer,
794 0,
795 NULL
796 );
797 ASSERT_EFI_ERROR (Status);
798 }
799 }
800
801 return Status;
802}
803
825EFIAPI
826WriteData (
828 IN UINT32 FlashAddress,
829 IN UINT32 LengthInBytes,
830 IN UINT8 *Buffer
831 )
832{
833 EFI_STATUS Status;
834 SPI_NOR_FLASH_INSTANCE *Instance;
835 UINT32 ByteCounter;
836 UINT32 CurrentAddress;
837 UINT32 Length;
838 UINT32 BytesUntilBoundary;
839 UINT8 *CurrentBuffer;
840 UINT32 TransactionBufferLength;
841 UINT32 MaximumTransferBytes;
842 UINT32 SpiFlashPageSize;
843
844 DEBUG ((DEBUG_INFO, "%a: Entry: Write address = 0x%08x, Length = 0x%08x\n", __func__, FlashAddress, LengthInBytes));
845
846 Status = EFI_DEVICE_ERROR;
847 if ((Buffer == NULL) ||
848 (LengthInBytes == 0) ||
849 (FlashAddress >= This->FlashSize) ||
850 (LengthInBytes > This->FlashSize - FlashAddress))
851 {
852 return EFI_INVALID_PARAMETER;
853 }
854
855 Instance = SPI_NOR_FLASH_FROM_THIS (This);
856 MaximumTransferBytes = Instance->SpiIo->MaximumTransferBytes;
857 if (Instance->SfdpBasicFlashByteCount >= 11 * 4) {
858 // JESD216C spec DWORD 11
859 SpiFlashPageSize = 1 << Instance->SfdpBasicFlash->PageSize;
860 } else {
861 SpiFlashPageSize = 256;
862 }
863
864 CurrentBuffer = Buffer;
865 Length = 0;
866 for (ByteCounter = 0; ByteCounter < LengthInBytes;) {
867 CurrentAddress = FlashAddress + ByteCounter;
868 CurrentBuffer = Buffer + ByteCounter;
869 Length = LengthInBytes - ByteCounter;
870 // Length must be MaximumTransferBytes or less
871 if (Length > MaximumTransferBytes) {
872 Length = MaximumTransferBytes;
873 }
874
875 // Cannot cross SpiFlashPageSize boundary
876 BytesUntilBoundary = SpiFlashPageSize
877 - (CurrentAddress % SpiFlashPageSize);
878 if ((BytesUntilBoundary != 0) && (Length > BytesUntilBoundary)) {
879 Length = BytesUntilBoundary;
880 }
881
882 // Check not WIP
883 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
884 if (EFI_ERROR (Status)) {
885 break;
886 }
887
888 if (Instance->WriteEnableLatchRequired) {
889 // Set Write Enable
890 Status = SetWel (Instance);
891 ASSERT_EFI_ERROR (Status);
892 if (EFI_ERROR (Status)) {
893 break;
894 }
895
896 // Check not WIP & WEL enabled
897 Status = WaitWelNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
898 if (EFI_ERROR (Status)) {
899 break;
900 }
901 }
902
903 // Write Data
904 TransactionBufferLength = FillWriteBuffer (
905 Instance,
906 SPI_FLASH_PP,
907 SPI_FLASH_PP_DUMMY,
908 SPI_FLASH_PP_ADDR_BYTES,
909 TRUE,
910 CurrentAddress,
911 Length,
912 CurrentBuffer
913 );
914 Status = Instance->SpiIo->Transaction (
915 Instance->SpiIo,
917 FALSE,
918 0,
919 1,
920 8,
921 TransactionBufferLength,
922 Instance->SpiTransactionWriteBuffer,
923 0,
924 NULL
925 );
926 ASSERT_EFI_ERROR (Status);
927 if (EFI_ERROR (Status)) {
928 break;
929 }
930
931 if (Instance->WriteEnableLatchRequired) {
932 // Check not WIP & not WEL
933 Status = WaitNotWelNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
934 if (EFI_ERROR (Status)) {
935 break;
936 }
937 } else {
938 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
939 if (EFI_ERROR (Status)) {
940 break;
941 }
942 }
943
944 ByteCounter += Length;
945 }
946
947 return Status;
948}
949
970EFIAPI
973 IN UINT32 FlashAddress,
974 IN UINT32 BlockCount
975 )
976{
977 EFI_STATUS Status;
978 SPI_NOR_FLASH_INSTANCE *Instance;
979 UINT8 Opcode;
980 UINT32 Dummy;
981 UINT32 ByteCounter;
982 UINT32 EraseLength;
983 UINT32 TotalEraseLength;
984 UINT32 CurrentAddress;
985 UINT32 TransactionBufferLength;
986 UINT32 BlockCountToErase;
987 UINT32 BlockSizeToErase;
988 UINT8 BlockEraseCommand;
989 UINT32 TypicalEraseTime;
990 UINT64 MaximumEraseTimeout;
991 SFDP_SECTOR_REGION_RECORD *FlashRegion;
992
993 DEBUG ((DEBUG_INFO, "%a: Entry: Erase address = 0x%08x, Block count = 0x%x\n", __func__, FlashAddress, BlockCount));
994
995 Status = EFI_DEVICE_ERROR;
996 Instance = SPI_NOR_FLASH_FROM_THIS (This);
997
998 // Get the region of this flash address.
999 Status = GetRegionByFlashAddress (Instance, FlashAddress, &FlashRegion);
1000 if (EFI_ERROR (Status)) {
1001 DEBUG ((DEBUG_ERROR, " Failed to get the flash region of this flash address.\n"));
1002 ASSERT (FALSE);
1003 return Status;
1004 }
1005
1006 CurrentAddress = FlashAddress;
1007 BlockCountToErase = BlockCount;
1008 BlockSizeToErase = FlashRegion->SectorSize; // This is also the minimum block erase size.
1009 TotalEraseLength = BlockCountToErase * FlashRegion->SectorSize;
1010 if ((FlashAddress + TotalEraseLength) > (FlashRegion->RegionAddress + FlashRegion->RegionTotalSize)) {
1011 DEBUG ((DEBUG_ERROR, " The blocks to erase exceeds the region boundary.\n"));
1012 return EFI_INVALID_PARAMETER;
1013 }
1014
1015 DEBUG ((DEBUG_VERBOSE, " Region starting address: 0x%08x.\n", FlashRegion->RegionAddress));
1016 DEBUG ((DEBUG_VERBOSE, " Region size : 0x%08x.\n", FlashRegion->RegionTotalSize));
1017 DEBUG ((DEBUG_VERBOSE, " Region sector size : 0x%08x.\n", FlashRegion->SectorSize));
1018 DEBUG ((DEBUG_VERBOSE, " Supported erase address bytes by device: 0x%02x.\n", Instance->SfdpBasicFlash->AddressBytes));
1019 DEBUG ((DEBUG_VERBOSE, " (00: 3-Byte, 01: 3 or 4-Byte. 10: 4-Byte)\n"));
1020
1021 // Loop until all blocks are erased.
1022 ByteCounter = 0;
1023 while (ByteCounter < TotalEraseLength) {
1024 CurrentAddress = FlashAddress + ByteCounter;
1025
1026 // Is this the whole device erase.
1027 if (TotalEraseLength == This->FlashSize) {
1028 Opcode = SPI_FLASH_CE;
1029 Dummy = SPI_FLASH_CE_DUMMY;
1030 EraseLength = TotalEraseLength;
1031 DEBUG ((DEBUG_VERBOSE, " This is the chip erase.\n"));
1032 } else {
1033 //
1034 // Get the erase block attributes.
1035 //
1036 Status = GetEraseBlockAttribute (
1037 Instance,
1038 FlashRegion,
1039 CurrentAddress,
1040 TotalEraseLength - ByteCounter,
1041 &BlockSizeToErase,
1042 &BlockCountToErase,
1043 &BlockEraseCommand,
1044 &TypicalEraseTime,
1045 &MaximumEraseTimeout
1046 );
1047 if (EFI_ERROR (Status)) {
1048 DEBUG ((DEBUG_ERROR, " Failed to get erase block attribute.\n"));
1049 ASSERT (FALSE);
1050 }
1051
1052 Opcode = BlockEraseCommand;
1053 Dummy = SPI_FLASH_BE_DUMMY;
1054 EraseLength = BlockCountToErase * BlockSizeToErase;
1055 DEBUG ((
1056 DEBUG_VERBOSE,
1057 " Erase command 0x%02x at adddress 0x%08x for length 0x%08x.\n",
1058 BlockEraseCommand,
1059 CurrentAddress,
1060 EraseLength
1061 ));
1062 }
1063
1064 //
1065 // Process the erase command.
1066 //
1067
1068 // Check not WIP
1069 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
1070 if (EFI_ERROR (Status)) {
1071 break;
1072 }
1073
1074 if (Instance->WriteEnableLatchRequired) {
1075 // Set Write Enable
1076 Status = SetWel (Instance);
1077 if (EFI_ERROR (Status)) {
1078 break;
1079 }
1080
1081 // Check not WIP & WEL enabled
1082 Status = WaitWelNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
1083 if (EFI_ERROR (Status)) {
1084 break;
1085 }
1086 }
1087
1088 // Erase Block
1089 TransactionBufferLength = FillWriteBuffer (
1090 Instance,
1091 Opcode,
1092 Dummy,
1093 (UINT8)Instance->SfdpBasicFlash->AddressBytes,
1094 TRUE,
1095 CurrentAddress,
1096 0,
1097 NULL
1098 );
1099 Status = Instance->SpiIo->Transaction (
1100 Instance->SpiIo,
1102 FALSE,
1103 0,
1104 1,
1105 8,
1106 TransactionBufferLength,
1107 Instance->SpiTransactionWriteBuffer,
1108 0,
1109 NULL
1110 );
1111 ASSERT_EFI_ERROR (Status);
1112 if (EFI_ERROR (Status)) {
1113 break;
1114 } else {
1115 DEBUG ((DEBUG_VERBOSE, "Erase command sucessfully.\n"));
1116 }
1117
1118 if (Instance->WriteEnableLatchRequired) {
1119 //
1120 // Check not WIP & not WEL
1121 // Use the timeout value calculated by SPI NOR flash SFDP.
1122 //
1123 Status = WaitNotWelNotWip (Instance, (UINT32)MaximumEraseTimeout * 1000, FixedPcdGet32 (PcdSpiNorFlashOperationRetryCount));
1124 if (EFI_ERROR (Status)) {
1125 break;
1126 }
1127 } else {
1128 //
1129 // Use the timeout value calculated by SPI NOR flash SFDP.
1130 //
1131 Status = WaitNotWip (Instance, (UINT32)MaximumEraseTimeout * 1000, FixedPcdGet32 (PcdSpiNorFlashOperationRetryCount));
1132 if (EFI_ERROR (Status)) {
1133 break;
1134 }
1135 }
1136
1137 ByteCounter += EraseLength;
1138 }
1139
1140 return Status;
1141}
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define FixedPcdGet32(TokenName)
Definition: PcdLib.h:92
@ SPI_TRANSACTION_WRITE_ONLY
Definition: SpiIo.h:37
@ SPI_TRANSACTION_WRITE_THEN_READ
Definition: SpiIo.h:51
EFI_STATUS EFIAPI ReadStatus(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 LengthInBytes, OUT UINT8 *FlashStatus)
Definition: SpiNorFlash.c:707
EFI_STATUS EFIAPI InternalReadStatus(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT32 LengthInBytes, OUT UINT8 *FlashStatus)
Definition: SpiNorFlash.c:153
EFI_STATUS WaitNotWip(IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance, IN UINT32 Timeout, IN UINT32 RetryCount)
Definition: SpiNorFlash.c:246
EFI_STATUS EFIAPI WriteStatus(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 LengthInBytes, IN UINT8 *FlashStatus)
Definition: SpiNorFlash.c:744
EFI_STATUS WaitNotWelNotWip(IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance, IN UINT32 Timeout, IN UINT32 RetryCount)
Definition: SpiNorFlash.c:356
EFI_STATUS EFIAPI LfReadData(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 FlashAddress, IN UINT32 LengthInBytes, OUT UINT8 *Buffer)
Definition: SpiNorFlash.c:484
EFI_STATUS EFIAPI GetFlashId(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, OUT UINT8 *Buffer)
Definition: SpiNorFlash.c:415
EFI_STATUS EFIAPI Erase(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 FlashAddress, IN UINT32 BlockCount)
Definition: SpiNorFlash.c:971
EFI_STATUS WaitWelNotWip(IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance, IN UINT32 Timeout, IN UINT32 RetryCount)
Definition: SpiNorFlash.c:301
EFI_STATUS SetWel(IN SPI_NOR_FLASH_INSTANCE *Instance)
Definition: SpiNorFlash.c:198
UINT32 FillWriteBuffer(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT8 Opcode, IN UINT32 DummyBytes, IN UINT8 AddressBytesSupported, IN BOOLEAN UseAddress, IN UINT32 Address, IN UINT32 WriteBytes, IN UINT8 *WriteBuffer)
Definition: SpiNorFlash.c:35
EFI_STATUS GetFastReadParameter(IN SPI_NOR_FLASH_INSTANCE *Instance, IN OUT UINT8 *FastReadInstruction, IN OUT UINT8 *FastReadModeBits, IN OUT UINT8 *FastReadDummyClocks)
EFI_STATUS GetEraseBlockAttribute(IN SPI_NOR_FLASH_INSTANCE *Instance, IN SFDP_SECTOR_REGION_RECORD *FlashRegion, IN UINT32 FlashAddress, IN UINT32 RemainingSize, IN OUT UINT32 *BlockSizeToErase, IN OUT UINT32 *BlockCountToErase, OUT UINT8 *BlockEraseCommand, OUT UINT32 *TypicalTime, OUT UINT64 *MaximumTimeout)
EFI_STATUS GetRegionByFlashAddress(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT32 FlashAddress, OUT SFDP_SECTOR_REGION_RECORD **FlashRegion)
#define SPI_FLASH_READ
#define SPI_ADDR_3BYTE_ONLY
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
UINT32 MaximumTransferBytes
Definition: SpiIo.h:265
EFI_SPI_IO_PROTOCOL_TRANSACTION Transaction
Definition: SpiIo.h:288
UINT32 RegionAddress
Region starting address.
UINT32 SectorSize
Sector size in byte (Minimum blcok erase size)
UINT32 RegionTotalSize
Region total size in bytes.
BOOLEAN WriteEnableLatchRequired
Wether Write Enable Latch is supported.