summaryrefslogtreecommitdiff
path: root/Silicon/Hisilicon/Drivers/NorFlashDxe
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Hisilicon/Drivers/NorFlashDxe')
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c162
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c594
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf64
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c628
-rw-r--r--Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h116
5 files changed, 1564 insertions, 0 deletions
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c
new file mode 100644
index 0000000000..ab3b70caf2
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashConfig.c
@@ -0,0 +1,162 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* 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 "NorFlashHw.h"
+
+
+#define COMMAND_TYPE1 0x1
+#define COMMAND_TYPE2 0x2
+#define COMMAND_TYPE3 0x4
+#define COMMAND_TYPE4 0x8
+#define COMMAND_TYPE5 0x10
+
+
+NOR_FLASH_INFO_TABLE gFlashInfo[]=
+{
+
+ {//S29GL512m
+ 0x00010001,
+ 0x227E227E,
+ 0x22232223,
+ 0x22012201,
+ 1,
+ 0x20000000,
+ 0x20000,
+ 0x0010,
+ COMMAND_TYPE1
+ },
+ {//S29GL1g
+ 0x00010001,
+ 0x227E227E,
+ 0x22282228,
+ 0x22012201,
+ 1,
+ 0x40000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ },
+ {//M29ew512m
+ 0x00890089,
+ 0x227E227E,
+ 0x22232223,
+ 0x22012201,
+ 1,
+ 0x20000000,
+ 0x20000,
+ 0x0010,
+ COMMAND_TYPE1
+ },
+ {//M29EW2g
+ 0x00890089,
+ 0x227E227E,
+ 0x22482248,
+ 0x22012201,
+ 1,
+ 0x80000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ },
+ {
+ 0x00890089,
+ 0x227E227E,
+ 0x22282228,
+ 0x22012201,
+ 1,
+ 0x10000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ },
+ {
+ 0x00890089,
+ 0x227E227E,
+ 0x22282228,
+ 0x22012201,
+ 2,
+ 0x10000000,
+ 0x20000,
+ 0x0020,
+ COMMAND_TYPE1
+ }
+};
+
+
+
+FLASH_COMMAND_RESET gFlashCommandReset[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x00F000F0)
+ }
+
+};
+
+
+FLASH_COMMAND_ID gFlashCommandId[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x0555),
+ (0x00900090),
+ (0x0000),
+
+ (0x0001),
+ (0x000E),
+ (0x000F)
+ }
+};
+
+
+FLASH_COMMAND_WRITE gFlashCommandWrite[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x00250025),
+ (0x00290029)
+ }
+
+};
+
+
+FLASH_COMMAND_ERASE gFlashCommandErase[]=
+{
+ {
+ COMMAND_TYPE1,
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x0555),
+ (0x00800080),
+ (0x0555),
+ (0x00AA00AA),
+ (0x02AA),
+ (0x00550055),
+ (0x00300030)
+ }
+
+};
+
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644
index 0000000000..8b8a5d7a3f
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -0,0 +1,594 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* 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 <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/NorFlashProtocol.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Protocol/Cpu.h>
+#include "NorFlashHw.h"
+
+
+EFI_STATUS Erase(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT32 Length
+ );
+
+EFI_STATUS Write(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ UINT32 ulLength
+ );
+
+EFI_STATUS Read(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 ulLen
+ );
+
+UNI_NOR_FLASH_PROTOCOL gUniNorFlash = {
+ Erase,
+ Write,
+ Read
+};
+
+
+EFI_STATUS
+EFIAPI Read(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 ulLen
+ )
+{
+ UINT32 index;
+ UINT64 ullAddr;
+ UINT32 ullCnt = 0;
+ UINT32 *puiBuffer32 = NULL;
+ UINT32 *puiDst32 = NULL;
+ UINT8 *pucBuffer8 = NULL;
+ UINT8 *pucDst8 = NULL;
+
+ if (Offset + ulLen > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the flash scope!\n", __FUNCTION__,__LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (0 == ulLen)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Length is Zero!\n", __FUNCTION__,__LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (NULL == Buffer)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Buffer is NULL!\n", __FUNCTION__,__LINE__));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+
+ ullAddr = gIndex.Base + Offset;
+
+ pucBuffer8 = (UINT8 *)Buffer;
+ pucDst8 = (UINT8 *)((UINTN)ullAddr);
+
+
+ if (ulLen < FOUR_BYTE_UNIT)
+ {
+ for(index = 0; index< ulLen; index++)
+ {
+ *pucBuffer8++ = *pucDst8++;
+ }
+ }
+ else
+ {
+
+ ullCnt = Offset % FOUR_BYTE_UNIT;
+ ullCnt = FOUR_BYTE_UNIT - ullCnt;
+
+ for(index = 0; index < ullCnt; index++)
+ {
+ *pucBuffer8++ = *pucDst8++;
+ }
+
+ ulLen -= ullCnt;
+
+ puiBuffer32 = (UINT32 *)pucBuffer8;
+ puiDst32 = (UINT32 *)pucDst8;
+ ullCnt = ulLen / FOUR_BYTE_UNIT;
+
+ for(index = 0; index < ullCnt; index++)
+ {
+ *puiBuffer32++ = *puiDst32++;
+ }
+
+ ullCnt = ulLen % FOUR_BYTE_UNIT;
+ pucBuffer8 = (UINT8 *)puiBuffer32;
+ pucDst8 = (UINT8 *)puiDst32;
+
+ for(index = 0; index < ullCnt; index++)
+ {
+ *pucBuffer8++ = *pucDst8++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+static EFI_STATUS WriteAfterErase_Fill(
+ IN const UINT32 Offset,
+ IN const UINT8 *Buffer,
+ IN const UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Loop;
+ UINT32 DataOffset;
+ UINT32 NewOffset;
+ UINT8 *NewDataUnit;
+
+ UINT32 FlashUnitLength;
+
+ FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+ if ((Offset % FlashUnitLength + Length) > FlashUnitLength)
+ {
+ DEBUG ((EFI_D_INFO, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
+ return EFI_UNSUPPORTED;
+ }
+
+
+ Status = gBS->AllocatePool(EfiBootServicesData, FlashUnitLength, (VOID *)&NewDataUnit);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Allocate Pool failed, %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+
+ NewOffset = Offset - (Offset % FlashUnitLength);
+
+ gBS->CopyMem((VOID *)NewDataUnit, (VOID *)(UINTN)(gIndex.Base + NewOffset), FlashUnitLength);
+
+ DataOffset = Offset % FlashUnitLength;
+ for (Loop = 0; Loop < Length; Loop ++)
+ {
+ NewDataUnit[(UINT32)(DataOffset + Loop)] = Buffer[Loop];
+ }
+
+ Status = BufferWrite(NewOffset, (void *)NewDataUnit, FlashUnitLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ (void)gBS->FreePool((VOID *)NewDataUnit);
+ return Status;
+}
+
+
+static EFI_STATUS WriteAfterErase_Final(
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ IN UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Loop;
+ UINT32 FlashUnitLength;
+
+ FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+ if (0 != (Offset % FlashUnitLength))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: Offset must be a multiple of 0x%x!\n", __FUNCTION__,__LINE__,FlashUnitLength));
+ return EFI_UNSUPPORTED;
+ }
+
+
+ Loop = Length / FlashUnitLength;
+ while (Loop --)
+ {
+ Status = BufferWrite(Offset, (void *)Buffer, FlashUnitLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite Failed: %r!\n", __FUNCTION__,__LINE__, Status));
+ return EFI_DEVICE_ERROR;
+ }
+ Offset += FlashUnitLength;
+ Buffer += FlashUnitLength;
+ }
+
+
+ Length = Length % FlashUnitLength;
+ if (Length)
+ {
+ Status = WriteAfterErase_Fill(Offset, Buffer, Length);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase_Fill failed,%r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteAfterErase(
+ UINT32 TempBase,
+ UINT32 Offset,
+ UINT8 *Buffer,
+ UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FlashUnitLength;
+
+ FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+
+ if (Offset % FlashUnitLength)
+ {
+ UINT32 TempLength;
+
+
+ TempLength = FlashUnitLength - (Offset % FlashUnitLength);
+ if (TempLength > Length)
+ {
+ TempLength = Length;
+ }
+ Status = WriteAfterErase_Fill(Offset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ Offset += TempLength;
+ Length -= TempLength;
+ Buffer += TempLength;
+
+ //Desc:if Offset >= gOneFlashSize,modify base
+ if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
+ gIndex.Base = TempBase;
+ Offset = 0;
+ }
+ }
+
+
+ Status = WriteAfterErase_Final(Offset, Buffer, Length);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FlashSectorErase(
+ UINT32 TempBase,
+ UINT32 Offset,
+ UINT32 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SectorOffset;
+ UINT8 *StaticBuffer;
+ UINT8 *Buffer;
+ UINT32 TempOffset;
+ UINT32 TempLength;
+ UINT32 LeftLength;
+
+
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+ LeftLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+ if (LeftLength < Length)
+ {
+ return EFI_UNSUPPORTED;
+ }
+
+
+ SectorOffset = Offset - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+ Status = gBS->AllocatePool(EfiBootServicesData, gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum, (VOID *)&StaticBuffer);
+ if (EFI_ERROR(Status))
+ {
+ return Status;
+ }
+
+ Buffer = StaticBuffer;
+
+ gBS->CopyMem((VOID *)Buffer, (VOID *)(UINTN)(TempBase + SectorOffset),
+ (gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+
+ Status = SectorErase(TempBase, SectorOffset);
+ if (EFI_ERROR(Status))
+ {
+ goto DO;
+ }
+
+
+ TempOffset = SectorOffset;
+ TempLength = Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum);
+
+ Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ goto DO;
+ }
+
+
+ Buffer = Buffer + TempLength + Length;
+ TempOffset = Offset + Length;
+ TempLength = SectorOffset + (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum) - TempOffset;
+
+ Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__,Status));
+ goto DO;
+ }
+
+ (void)gBS->FreePool((VOID *)StaticBuffer);
+ return EFI_SUCCESS;
+
+DO:
+ (void)gBS->FreePool((VOID *)StaticBuffer);
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI Erase(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT32 Length
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 Sectors;
+ UINT32 TempLength;
+ UINT32 TempBase;
+ UINT32 Loop;
+
+
+ if (Offset + Length > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
+ return EFI_ABORTED;
+ }
+ if (0 == Length)
+ {
+ return EFI_SUCCESS;
+ }
+
+
+ Sectors = ((Offset + Length - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
+ TempBase = gIndex.Base;
+
+ //if Offset >= gOneFlashSize,modify base
+ if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ }
+
+ for (Loop = 0; Loop <= Sectors; Loop ++)
+ {
+
+ TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+
+ if (TempLength > Length)
+ {
+ TempLength = Length;
+ }
+
+ Status = FlashSectorErase(TempBase, Offset, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
+ return Status;
+ }
+
+ Offset += TempLength;
+
+ //if Offset >= gOneFlashSize,modify base
+ if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
+ Offset = 0;
+ }
+ Length -= TempLength;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI Write(
+ IN UNI_NOR_FLASH_PROTOCOL *This,
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ UINT32 ulLength
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TempLength;
+ UINT32 TempBase;
+ UINT32 Loop;
+ UINT32 Sectors;
+
+ if((Offset + ulLength) > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (0 == ulLength)
+ {
+ return EFI_SUCCESS;
+ }
+
+
+ Sectors = ((Offset + ulLength - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
+ TempBase = gIndex.Base;
+
+ //if Offset >= gOneFlashSize,modify base
+ if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
+ }
+
+ for (Loop = 0; Loop <= Sectors; Loop ++)
+ {
+
+ TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
+
+
+ if (TempLength > ulLength)
+ {
+ TempLength = ulLength;
+ }
+
+
+ if (TRUE == IsNeedToWrite(TempBase, Offset, Buffer, TempLength))
+ {
+ Status = FlashSectorErase(TempBase, Offset, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
+ return Status;
+ }
+
+
+ Status = WriteAfterErase(TempBase, Offset, Buffer, TempLength);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase Status = %r!\n", __FUNCTION__,__LINE__,Status));
+ return Status;
+ }
+ }
+
+ Offset += TempLength;
+ Buffer += TempLength;
+
+ //if Offset >= gOneFlashSize,modify base
+ if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
+ {
+ TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
+ Offset = 0;
+ }
+ ulLength -= TempLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID SetFlashAttributeToUncache(VOID)
+{
+ EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "LocateProtocol gEfiCpuArchProtocolGuid Status = %r !\n", Status));
+ }
+
+ Status = gCpu->SetMemoryAttributes(
+ gCpu,
+ PcdGet64(PcdNORFlashBase),
+ PcdGet32(PcdNORFlashCachableSize),
+ EFI_MEMORY_UC
+ );
+
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "gCpu->SetMemoryAttributes Status = %r !\n", Status));
+ }
+
+}
+
+EFI_STATUS
+EFIAPI InitializeFlash (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+
+
+ gIndex.Base = (UINT32)PcdGet64(PcdNORFlashBase);
+
+ SetFlashAttributeToUncache();
+ Status = FlashInit(gIndex.Base);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG((EFI_D_ERROR, "Init Flash Error !\n"));
+ return Status;
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Init Flash OK!\n"));
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gUniNorFlashProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gUniNorFlash);
+ if(EFI_SUCCESS != Status)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Install Protocol Interface %r!\n", __FUNCTION__,__LINE__,Status));
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100644
index 0000000000..254e27eeac
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -0,0 +1,64 @@
+#/** @file
+#
+# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015, Linaro Limited. All rights reserved.
+#
+# 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 = 0x00010005
+ BASE_NAME = NorFlashDxe
+ FILE_GUID = E29977F9-20A4-4551-B0EC-BCE246592E73
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeFlash
+
+[Sources.common]
+ NorFlashDxe.c
+ NorFlashHw.c
+ NorFlashConfig.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DebugLib
+ BaseLib
+ DebugLib
+ IoLib
+ SerialPortLib
+ ArmLib
+ CacheMaintenanceLib
+ UefiLib
+ PrintLib
+ PcdLib
+
+ DxeServicesTableLib
+[Guids]
+
+[Protocols]
+ gUniNorFlashProtocolGuid
+ gEfiCpuArchProtocolGuid
+
+[Pcd]
+ gHisiTokenSpaceGuid.PcdNORFlashBase
+ gHisiTokenSpaceGuid.PcdNORFlashCachableSize
+
+
+[Depex]
+ TRUE
+
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c
new file mode 100644
index 0000000000..3aeaeb9091
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.c
@@ -0,0 +1,628 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* 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 <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include "NorFlashHw.h"
+
+
+BOOLEAN gFlashBusy = FALSE;
+FLASH_INDEX gIndex = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+UINT32 PortReadData (
+ UINT32 Index,
+ UINT32 FlashAddr
+ )
+{
+
+ switch (gFlashInfo[Index].ParallelNum)
+ {
+ case 2:
+ return MmioRead32 (FlashAddr);
+ case 1:
+ return MmioRead16 (FlashAddr);
+
+ default:
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__));
+ return 0xffffffff;
+ }
+}
+
+EFI_STATUS
+PortWriteData (
+ UINT32 Index,
+ UINT32 FlashAddr,
+ UINT32 InputData
+ )
+{
+
+ switch (gFlashInfo[Index].ParallelNum)
+ {
+ case 2:
+ MmioWrite32 (FlashAddr, InputData);
+ break;
+ case 1:
+ MmioWrite16 (FlashAddr, InputData);
+ break;
+ default:
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+UINT32 PortAdjustData(
+ UINT32 Index,
+ UINT32 ulInputData
+ )
+{
+
+ switch (gFlashInfo[Index].ParallelNum)
+ {
+ case 2:
+ return ulInputData;
+ case 1:
+ return (0x0000ffff & ulInputData );
+ default:
+ DEBUG((EFI_D_ERROR,"[FLASH_S29GL256N_PortAdjustData]: Error--illegal g_ulFlashS29Gl256NPortWidth!\n\r"));
+ return 0xffffffff;
+ }
+}
+
+
+EFI_STATUS GetCommandIndex(
+ UINT32 Index
+ )
+{
+ UINT32 CommandCount = 0;
+ UINT32 i;
+ UINT8 Flag = 1;
+
+ CommandCount = sizeof(gFlashCommandReset) / sizeof(FLASH_COMMAND_RESET);
+ for(i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandReset[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.ReIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Reset Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CommandCount = sizeof(gFlashCommandId) / sizeof(FLASH_COMMAND_ID);
+ for(Flag = 1,i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandId[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.IdIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get ID Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CommandCount = sizeof(gFlashCommandWrite) / sizeof(FLASH_COMMAND_WRITE);
+ for(Flag = 1, i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandWrite[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.WIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Write Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CommandCount = sizeof(gFlashCommandErase) / sizeof(FLASH_COMMAND_ERASE);
+ for(Flag = 1, i = 0;i < CommandCount; i ++ )
+ {
+ if(gFlashInfo[Index].CommandType & gFlashCommandErase[i].CommandType)
+ {
+ Flag = 0;
+ gIndex.WIndex = i;
+ break;
+ }
+ }
+
+ if(Flag)
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Erase Command!\n", __FUNCTION__,__LINE__));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID FlashReset(UINT32 Base)
+{
+ (VOID)PortWriteData(gIndex.InfIndex, Base, gFlashCommandReset[gIndex.ReIndex].ResetData);
+ (void)gBS->Stall(20000);
+}
+
+
+void GetManufacturerID(UINT32 Index, UINT32 Base, UINT8 *pbyData)
+{
+
+ UINT32 dwAddr;
+
+ FlashReset(Base);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[Index].ParallelNum);
+ (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[Index].ParallelNum);
+ (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[Index].ParallelNum);
+ (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3);
+
+ *pbyData = (UINT8)PortReadData(Index, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[Index].ParallelNum));
+
+ FlashReset(Base); //must reset to return to the read mode
+}
+
+
+EFI_STATUS FlashInit(UINT32 Base)
+{
+ UINT32 FlashCount = 0;
+ UINT32 i = 0;
+ EFI_STATUS Status;
+ UINT8 Flag = 1;
+ UINT32 TempData = 0;
+ UINT32 TempDev1 = 0;
+ UINT32 TempDev2 = 0;
+ UINT32 TempDev3 = 0;
+ UINT32 dwAddr;
+
+ FlashCount = sizeof(gFlashInfo) / sizeof(NOR_FLASH_INFO_TABLE);
+ for(;i < FlashCount; i ++ )
+ {
+
+ Status = GetCommandIndex(i);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Get Command Index %r!\n", __FUNCTION__,__LINE__, Status));
+ return Status;
+ }
+
+ FlashReset(Base);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[i].ParallelNum);
+ (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[i].ParallelNum);
+ (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2);
+
+ dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[i].ParallelNum);
+ (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3);
+ //Get manufacture ID
+ TempData = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[i].ParallelNum));
+
+ //Get Device Id
+ TempDev1 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress1 << gFlashInfo[i].ParallelNum));
+ TempDev2 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress2 << gFlashInfo[i].ParallelNum));
+ TempDev3 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress3 << gFlashInfo[i].ParallelNum));
+ DEBUG ((EFI_D_ERROR, "[cdtest]manufactor ID 0x%x!\n",TempData));
+ DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 1 0x%x!\n",TempDev1));
+ DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 2 0x%x!\n",TempDev2));
+ DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 3 0x%x!\n",TempDev3));
+
+ FlashReset(Base);
+
+
+ if((0xffffffff != TempData)
+ && (PortAdjustData(i, gFlashInfo[i].ManufacturerID) == TempData))
+ {
+ if((0xffffffff != TempDev1)
+ && (PortAdjustData(i, gFlashInfo[i].DeviceID1) == TempDev1))
+ {
+ if((0xffffffff != TempDev2)
+ && (PortAdjustData(i, gFlashInfo[i].DeviceID2) == TempDev2))
+ {
+ if((0xffffffff != TempDev3)
+ && (PortAdjustData(i, gFlashInfo[i].DeviceID3) == TempDev3))
+ {
+ Flag = 0;
+ gIndex.InfIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(Flag)
+ {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+static BOOLEAN width8IsAll(
+ const UINT64 Base,
+ const UINT64 Offset,
+ const UINT64 Length,
+ const UINT8 Value
+)
+{
+ UINT64 NewAddr = Base + Offset;
+ UINT64 NewLength = Length;
+ while (NewLength --)
+ {
+ if (*(UINT8 *)(UINTN)NewAddr == Value)
+ {
+ NewAddr ++;
+ continue;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+
+EFI_STATUS BufferWriteCommand(UINTN Base, UINTN Offset, void *pData)
+{
+ UINT32 dwCommAddr;
+ UINT32 *pdwData;
+ UINT16 *pwData;
+ UINT32 dwLoop;
+ UINT32 ulWriteWordCount;
+ UINT32 dwAddr;
+
+ if(gFlashBusy)
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
+ return EFI_NOT_READY;
+ }
+ gFlashBusy = TRUE;
+
+ if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum)
+ {
+ pdwData = (UINT32 *)pData;
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1);
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2);
+
+ //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ dwAddr = (UINT32)Base + Offset;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3);
+
+
+ ulWriteWordCount = ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << 16) | (gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount);
+
+
+ for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++)
+ {
+ dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ MmioWrite32 (dwCommAddr, *pdwData);
+ pdwData ++;
+ }
+
+ dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash);
+
+
+
+ }
+ else
+ {
+ pwData = (UINT16 *)pData;
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1);
+
+ dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2);
+
+ //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ dwAddr = (UINT32)Base + Offset;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3);
+
+
+ ulWriteWordCount = gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount);
+
+
+ for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++)
+ {
+ dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ MmioWrite16 (dwCommAddr, *pwData);
+ pwData ++;
+ }
+
+ dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash);
+
+ }
+
+ (void)gBS->Stall(200);
+
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS SectorEraseCommand(UINTN Base, UINTN Offset)
+{
+ UINT32 dwAddr;
+
+ if(gFlashBusy)
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
+ return EFI_NOT_READY;
+ }
+
+ gFlashBusy = TRUE;
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep1);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep2);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep3 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep3);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep4 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep4);
+
+ dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep5 << gFlashInfo[gIndex.InfIndex].ParallelNum);
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep5);
+
+ dwAddr = (UINT32)Base + Offset;
+ (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep6);
+
+ (void)gBS->Stall(500000);
+
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS CompleteCheck(UINT32 Base, UINT32 Offset, void *pData, UINT32 Length)
+{
+ UINT32 dwTestAddr;
+ UINT32 dwTestData;
+ UINT32 dwTemp = 0;
+ UINT32 dwTemp1 = 0;
+ UINT32 i;
+ UINT32 dwTimeOut = 3000000;
+
+ if(gFlashBusy)
+ {
+ DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
+ return EFI_NOT_READY;
+ }
+ gFlashBusy = TRUE;
+
+ if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum)
+ {
+ dwTestAddr = Base + Offset + Length - sizeof(UINT32);
+ dwTestData = *((UINT32 *)((UINT8 *)pData + Length - sizeof(UINT32)));
+
+ while(dwTimeOut--)
+ {
+ dwTemp1 = MmioRead32 (dwTestAddr);
+ if (dwTestData == dwTemp1)
+ {
+ dwTemp = MmioRead32 (dwTestAddr);
+ dwTemp1 = MmioRead32 (dwTestAddr);
+ if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1))
+ {
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+ }
+ }
+
+ (void)gBS->Stall(1);
+ }
+
+ if((UINT16)(dwTemp1 >> 16) != (UINT16)(dwTestData >> 16))
+ {
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip1 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1));
+ }
+ if((UINT16)(dwTemp1) != (UINT16)(dwTestData))
+ {
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip2 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1));
+ }
+ }
+ else
+ {
+ dwTestAddr = Base + Offset + Length - sizeof(UINT16);
+ dwTestData = *((UINT16 *)((UINT8 *)pData + Length - sizeof(UINT16)));
+
+ while(dwTimeOut--)
+ {
+ dwTemp1 = MmioRead16 (dwTestAddr);
+ if (dwTestData == dwTemp1)
+ {
+ dwTemp = MmioRead16 (dwTestAddr);
+ dwTemp1 = MmioRead16 (dwTestAddr);
+ if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1))
+ {
+ gFlashBusy = FALSE;
+ return EFI_SUCCESS;
+ }
+ }
+
+ (void)gBS->Stall(1);
+ }
+ }
+
+ for(i = 0; i < 5; i ++)
+ {
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: flash %x\n",PortReadData(gIndex.InfIndex, dwTestAddr)));
+ }
+
+ FlashReset(Base);
+
+ gFlashBusy = FALSE;
+ DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: timeout address %x, buffer %x, flash %x\n", Offset, dwTestData, dwTemp1));
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS IsNeedToWrite(
+ IN UINT32 Base,
+ IN UINT32 Offset,
+ IN UINT8 *Buffer,
+ IN UINT32 Length
+ )
+{
+ UINTN NewAddr = Base + Offset;
+ UINT8 FlashData = 0;
+ UINT8 BufferData = 0;
+
+ for(; Length > 0; Length --)
+ {
+ BufferData = *Buffer;
+ //lint -epn -e511
+ FlashData = *(UINT8 *)NewAddr;
+ if (BufferData != FlashData)
+ {
+ return TRUE;
+ }
+ NewAddr ++;
+ Buffer ++;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length)
+{
+ EFI_STATUS Status;
+ UINT32 dwLoop;
+ UINT32 Retry = 3;
+
+ if (FALSE == IsNeedToWrite(gIndex.Base, Offset, (UINT8 *)pData, Length))
+ {
+ return EFI_SUCCESS;
+ }
+
+ do
+ {
+ (void)BufferWriteCommand(gIndex.Base, Offset, pData);
+ Status = CompleteCheck(gIndex.Base, Offset, pData, Length);
+
+
+ if (EFI_SUCCESS == Status)
+ {
+ for (dwLoop = 0; dwLoop < Length; dwLoop ++)
+ {
+ if (*(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop) != *((UINT8 *)pData + dwLoop))
+ {
+ DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: address %x, buffer %x, flash %x\n", Offset, *((UINT8 *)pData + dwLoop), *(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop)));
+ Status = EFI_ABORTED;
+ continue;
+ }
+ }
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: complete check failed, %r\n", Status));
+ continue;
+ }
+ } while ((Retry--) && EFI_ERROR(Status));
+
+ return Status;
+}
+
+
+EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset)
+{
+ UINT8 gTemp[FLASH_MAX_UNIT];
+ UINT64 dwLoop = FLASH_MAX_UNIT - 1;
+ UINT32 Retry = 3;
+ EFI_STATUS Status;
+
+ do
+ {
+ gTemp[dwLoop] = 0xFF;
+ }while (dwLoop --);
+
+ do
+ {
+ (void)SectorEraseCommand(Base, Offset);
+ Status = CompleteCheck(Base, Offset, (void *)gTemp, FLASH_MAX_UNIT);
+
+
+ if (EFI_SUCCESS == Status)
+ {
+
+ if (width8IsAll(Base,Offset - (Offset % gFlashInfo[gIndex.InfIndex].BlockSize), gFlashInfo[gIndex.InfIndex].BlockSize, 0xFF))
+ {
+ return EFI_SUCCESS;
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: not all address equal 0xFF\n"));
+
+ Status = EFI_ABORTED;
+ continue;
+ }
+ }
+ else
+ {
+ DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: complete check failed, %r\n", Status));
+ continue;
+ }
+ }while ((Retry--) && EFI_ERROR(Status));
+
+ if(Retry)
+ {
+ //do nothing for pclint
+ }
+
+ return Status;
+}
diff --git a/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h
new file mode 100644
index 0000000000..36c0c9ec23
--- /dev/null
+++ b/Silicon/Hisilicon/Drivers/NorFlashDxe/NorFlashHw.h
@@ -0,0 +1,116 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro Limited. All rights reserved.
+*
+* 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_HW_H_
+#define _NOR_FLASH_HW_H_
+
+#include <Uefi/UefiBaseType.h>
+
+
+#define FOUR_BYTE_UNIT 4
+#define FLASH_MAX_UNIT 4
+
+#define FLASH_DEVICE_NUM 0x10
+
+
+
+typedef struct {
+ UINT32 ManufacturerID;
+ UINT32 DeviceID1;
+ UINT32 DeviceID2;
+ UINT32 DeviceID3;
+ UINT8 ParallelNum;
+ UINT32 SingleChipSize;
+ UINT32 BlockSize;
+ UINT32 BufferProgramSize;
+ UINT32 CommandType;
+}NOR_FLASH_INFO_TABLE;
+
+/*Define Command Address And Data*/
+/*reset*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 ResetData;
+}FLASH_COMMAND_RESET;
+
+/*manufacture ID & Device ID*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 ManuIDAddressStep1;
+ UINT32 ManuIDDataStep1;
+ UINT32 ManuIDAddressStep2;
+ UINT32 ManuIDDataStep2;
+ UINT32 ManuIDAddressStep3;
+ UINT32 ManuIDDataStep3;
+ UINT32 ManuIDAddress;
+
+ UINT32 DeviceIDAddress1;
+ UINT32 DeviceIDAddress2;
+ UINT32 DeviceIDAddress3;
+}FLASH_COMMAND_ID;
+
+/*Write Buffer*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 BufferProgramAddressStep1;
+ UINT32 BufferProgramDataStep1;
+ UINT32 BufferProgramAddressStep2;
+ UINT32 BufferProgramDataStep2;
+ UINT32 BufferProgramDataStep3;
+ UINT32 BufferProgramtoFlash;
+}FLASH_COMMAND_WRITE;
+
+/*erase*/
+typedef struct {
+ UINT32 CommandType;
+ UINT32 SectorEraseAddressStep1;
+ UINT32 SectorEraseDataStep1;
+ UINT32 SectorEraseAddressStep2;
+ UINT32 SectorEraseDataStep2;
+ UINT32 SectorEraseAddressStep3;
+ UINT32 SectorEraseDataStep3;
+ UINT32 SectorEraseAddressStep4;
+ UINT32 SectorEraseDataStep4;
+ UINT32 SectorEraseAddressStep5;
+ UINT32 SectorEraseDataStep5;
+ UINT32 SectorEraseDataStep6;
+}FLASH_COMMAND_ERASE;
+
+
+typedef struct {
+ UINT32 Base;
+ UINT32 InfIndex;
+ UINT32 ReIndex;
+ UINT32 IdIndex;
+ UINT32 WIndex;
+ UINT32 EIndex;
+}FLASH_INDEX;
+
+
+extern EFI_STATUS FlashInit(UINT32 Base);
+extern EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset);
+extern EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length);
+extern EFI_STATUS IsNeedToWrite(UINT32 Base, UINT32 Offset, UINT8 *Buffer, UINT32 Length);
+
+
+extern NOR_FLASH_INFO_TABLE gFlashInfo[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_RESET gFlashCommandReset[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_ID gFlashCommandId[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_WRITE gFlashCommandWrite[FLASH_DEVICE_NUM];
+extern FLASH_COMMAND_ERASE gFlashCommandErase[FLASH_DEVICE_NUM];
+extern FLASH_INDEX gIndex;
+
+
+#endif