From 600081b52debde8d06585fdaf09fac16d323670f Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Thu, 3 Aug 2017 12:24:30 +0100 Subject: Platform,Silicon: Import Hisilicon D02,D03,D05 and HiKey Imported from commit efd798c1eb of https://git.linaro.org/uefi/OpenPlatformPkg.git Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Leif Lindholm --- .../ArmPlatformLibHisilicon/AArch64/Helper.S | 61 ++ .../ArmPlatformLibHisilicon/ArmPlatformLib.c | 107 +++ .../ArmPlatformLibHisilicon/ArmPlatformLib.inf | 69 ++ .../ArmPlatformLibHisilicon/ArmPlatformLibMem.c | 97 +++ .../ArmPlatformLibHisilicon/ArmPlatformLibSec.inf | 56 ++ Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c | 53 ++ Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf | 47 + .../Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c | 104 +++ .../Library/CpldIoLib/CpldIoLibRuntime.inf | 51 ++ .../DS3231RealTimeClockLib/DS3231RealTimeClock.h | 178 ++++ .../DS3231RealTimeClockLib.c | 433 +++++++++ .../DS3231RealTimeClockLib.inf | 48 + .../Dw8250SerialPortLib/Dw8250SerialPortLib.c | 302 +++++++ .../Dw8250SerialPortLib/Dw8250SerialPortLib.h | 116 +++ .../Dw8250SerialPortLib/Dw8250SerialPortLib.inf | 45 + .../Dw8250SerialPortRuntimeLib.c | 356 ++++++++ .../Dw8250SerialPortRuntimeLib.h | 116 +++ .../Dw8250SerialPortRuntimeLib.inf | 52 ++ Silicon/Hisilicon/Library/I2CLib/I2CHw.h | 269 ++++++ Silicon/Hisilicon/Library/I2CLib/I2CLib.c | 655 ++++++++++++++ Silicon/Hisilicon/Library/I2CLib/I2CLib.inf | 49 ++ Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c | 35 + Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h | 29 + Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c | 109 +++ Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf | 51 ++ .../Library/PlatformIntelBdsLib/IntelBdsPlatform.c | 963 +++++++++++++++++++++ .../Library/PlatformIntelBdsLib/IntelBdsPlatform.h | 61 ++ .../PlatformIntelBdsLib/IntelBdsPlatformCommon.c | 118 +++ .../PlatformIntelBdsLib/IntelBdsPlatformCommon.h | 27 + .../PlatformIntelBdsLib/PlatformIntelBdsLib.inf | 84 ++ .../VirtualRealTimeClockLib/RealTimeClockLib.c | 429 +++++++++ .../VirtualRealTimeClockLib/RealTimeClockLib.inf | 47 + 32 files changed, 5217 insertions(+) create mode 100644 Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S create mode 100644 Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c create mode 100644 Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf create mode 100644 Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c create mode 100644 Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf create mode 100644 Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c create mode 100644 Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf create mode 100644 Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c create mode 100644 Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf create mode 100644 Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h create mode 100644 Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c create mode 100644 Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf create mode 100644 Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c create mode 100644 Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h create mode 100644 Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf create mode 100644 Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c create mode 100644 Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h create mode 100644 Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CHw.h create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CLib.c create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CLib.inf create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c create mode 100644 Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf create mode 100644 Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c create mode 100644 Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h create mode 100644 Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c create mode 100644 Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h create mode 100644 Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf create mode 100644 Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c create mode 100644 Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf (limited to 'Silicon/Hisilicon/Library') diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S new file mode 100644 index 0000000000..3422df279c --- /dev/null +++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/AArch64/Helper.S @@ -0,0 +1,61 @@ +// +// Copyright (c) 2011-2013, ARM Limited. All rights reserved. +// 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. +// +// Based on the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ +// +// + +#include +#include + +ASM_FUNC(ArmPlatformPeiBootAction) + ret + +//UINTN +//ArmPlatformGetPrimaryCoreMpId ( +// VOID +// ); +ASM_FUNC(ArmPlatformGetPrimaryCoreMpId) + MOV32 (w0, FixedPcdGet32(PcdArmPrimaryCore)) + ret + +# IN None +# OUT x0 = number of cores present in the system +ASM_FUNC(ArmGetCpuCountPerCluster) + MOV32 (w0, FixedPcdGet32(PcdCoreCount)) + ret + +//UINTN +//ArmPlatformIsPrimaryCore ( +// IN UINTN MpId +// ); +ASM_FUNC(ArmPlatformIsPrimaryCore) + MOV32 (w1, FixedPcdGet32(PcdArmPrimaryCoreMask)) + and x0, x0, x1 + MOV32 (w1, FixedPcdGet32(PcdArmPrimaryCore)) + cmp w0, w1 + cset x0, eq + ret + +//UINTN +//ArmPlatformGetCorePosition ( +// IN UINTN MpId +// ); +// With this function: CorePos = (ClusterId * 4) + CoreId +ASM_FUNC(ArmPlatformGetCorePosition) + and x1, x0, #ARM_CORE_MASK + and x0, x0, #ARM_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c new file mode 100644 index 0000000000..07ab0d1dc2 --- /dev/null +++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.c @@ -0,0 +1,107 @@ +/** @file +* +* Copyright (c) 2011-2013, ARM Limited. All rights reserved. +* 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. +* +* Based on the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ +* +**/ + +#include +#include +#include +#include + +#include + +UINTN +ArmGetCpuCountPerCluster ( + VOID + ); + +extern EFI_STATUS MemInitEntry (VOID); + +/** + Return the current Boot Mode + + This function returns the boot reason on the platform + + @return Return the current Boot Mode of the platform + +**/ +EFI_BOOT_MODE +ArmPlatformGetBootMode ( + VOID + ) +{ + return BOOT_WITH_FULL_CONFIGURATION; +} + +/** + Initialize controllers that must setup in the normal world + + This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim + in the PEI phase. + +**/ +RETURN_STATUS +ArmPlatformInitialize ( + IN UINTN MpId + ) +{ + return RETURN_SUCCESS; +} + +/** + Initialize the system (or sometimes called permanent) memory + + This memory is generally represented by the DRAM. + +**/ +VOID +ArmPlatformInitializeSystemMemory ( + VOID + ) +{ + // Nothing to do here +} + +EFI_STATUS +PrePeiCoreGetMpCoreInfo ( + OUT UINTN *CoreCount, + OUT ARM_CORE_INFO **ArmCoreTable + ) +{ + return EFI_UNSUPPORTED; +} + +// Needs to be declared in the file. Otherwise gArmMpCoreInfoPpiGuid is undefined in the contect of PrePeiCore +EFI_GUID mArmMpCoreInfoPpiGuid = ARM_MP_CORE_INFO_PPI_GUID; +ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo }; + +EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &mArmMpCoreInfoPpiGuid, + &mMpCoreInfoPpi + } +}; + +VOID +ArmPlatformGetPlatformPpiList ( + OUT UINTN *PpiListSize, + OUT EFI_PEI_PPI_DESCRIPTOR **PpiList + ) +{ + *PpiListSize = sizeof(gPlatformPpiTable); + *PpiList = gPlatformPpiTable; +} diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf new file mode 100644 index 0000000000..f4dc68f762 --- /dev/null +++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLib.inf @@ -0,0 +1,69 @@ +#/* @file +# Copyright (c) 2011-2014, ARM Limited. All rights reserved. +# 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. +# +# Based on the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmPlatformLibPv660 + FILE_GUID = 6887500D-32AD-41cd-855E-F8A5D5B0D4D2 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + IoLib + ArmLib + MemoryAllocationLib + SerialPortLib + +[Sources.common] + ArmPlatformLib.c + ArmPlatformLibMem.c + +[Sources.AARCH64] + AArch64/Helper.S + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdNorFlashRemapping + +[FixedPcd] + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + gArmTokenSpaceGuid.PcdFvBaseAddress + + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + + gArmPlatformTokenSpaceGuid.PcdCoreCount + + gHisiTokenSpaceGuid.PcdNORFlashBase + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase + gHisiTokenSpaceGuid.PcdSysControlBaseAddress + gHisiTokenSpaceGuid.PcdPeriSubctrlAddress + gArmPlatformTokenSpaceGuid.PcdSP805WatchdogBase + diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c new file mode 100644 index 0000000000..b7bc75dc74 --- /dev/null +++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibMem.c @@ -0,0 +1,97 @@ +/** @file +* +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. +* 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. +* +* Based on the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ +* +**/ + +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 32 + +// DDR attributes +#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK +#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED + +/** + Return the Virtual Memory Map of your platform + + This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform. + + @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to- + Virtual Memory mapping. This array must be ended by a zero-filled + entry + +**/ +VOID +ArmPlatformGetVirtualMemoryMap ( + IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap + ) +{ + ARM_MEMORY_REGION_ATTRIBUTES CacheAttributes; + UINTN Index; + ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; + EFI_PEI_HOB_POINTERS NextHob; + + ASSERT (VirtualMemoryMap != NULL); + + VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages(EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)); + if (VirtualMemoryTable == NULL) { + return; + } + + if (FeaturePcdGet(PcdCacheEnable) == TRUE) { + CacheAttributes = DDR_ATTRIBUTES_CACHED; + } else { + CacheAttributes = DDR_ATTRIBUTES_UNCACHED; + } + + Index = OemSetVirtualMapDesc(VirtualMemoryTable, CacheAttributes); + + // Search for System Memory Hob that contains the EFI resource system memory + NextHob.Raw = GetHobList (); + while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) + { + if (NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) + { + if (NextHob.ResourceDescriptor->PhysicalStart > BASE_4GB) + { + VirtualMemoryTable[++Index].PhysicalBase = NextHob.ResourceDescriptor->PhysicalStart; + VirtualMemoryTable[Index].VirtualBase = NextHob.ResourceDescriptor->PhysicalStart; + VirtualMemoryTable[Index].Length =NextHob.ResourceDescriptor->ResourceLength; + VirtualMemoryTable[Index].Attributes = CacheAttributes; + } + } + + NextHob.Raw = GET_NEXT_HOB (NextHob); + } + + // End of Table + VirtualMemoryTable[++Index].PhysicalBase = 0; + VirtualMemoryTable[Index].VirtualBase = 0; + VirtualMemoryTable[Index].Length = 0; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0; + + ASSERT((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS); + DEBUG((EFI_D_INFO, "[%a]:[%dL] discriptor count=%d\n", __FUNCTION__, __LINE__, Index+1)); + + *VirtualMemoryMap = VirtualMemoryTable; +} diff --git a/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf new file mode 100644 index 0000000000..fa308bd066 --- /dev/null +++ b/Silicon/Hisilicon/Library/ArmPlatformLibHisilicon/ArmPlatformLibSec.inf @@ -0,0 +1,56 @@ +#/* @file +# Copyright (c) 2011-2012, ARM Limited. All rights reserved. +# 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. +# +# Based on the files under ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmPlatformLibPv660Sec + FILE_GUID = a79eed97-4b98-4974-9690-37b32d6a5b56 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + +[LibraryClasses] + IoLib + ArmLib + SerialPortLib + +[Sources.common] + ArmPlatformLib.c + +[Sources.AARCH64] + AArch64/Helper.S + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdNorFlashRemapping + +[FixedPcd] + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + gArmTokenSpaceGuid.PcdFvBaseAddress + + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + + gArmPlatformTokenSpaceGuid.PcdCoreCount diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c new file mode 100644 index 0000000000..72bb7f5305 --- /dev/null +++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.c @@ -0,0 +1,53 @@ +/** @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 +#include +#include +#include +#include + + +VOID WriteCpldReg(UINTN ulRegAddr, UINT8 ulValue) +{ + MmioWrite8 (ulRegAddr + PcdGet64(PcdCpldBaseAddress), ulValue); +} + + +UINT8 ReadCpldReg(UINTN ulRegAddr) +{ + return MmioRead8 (ulRegAddr + PcdGet64(PcdCpldBaseAddress)); +} + + +VOID ReadCpldBytes(UINT16 Addr, UINT8 *Data, UINT8 Bytes) +{ + UINT8 i; + + for(i = 0;i < Bytes; i++) + { + *(Data + i) = ReadCpldReg(Addr + i); + } +} + +VOID WriteCpldBytes(UINT16 Addr, UINT8 *Data, UINT8 Bytes) +{ + UINT8 i; + + for(i = 0; i < Bytes; i++) + { + WriteCpldReg(Addr + i, *(Data + i)); + } +} diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf new file mode 100644 index 0000000000..d3378a020b --- /dev/null +++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf @@ -0,0 +1,47 @@ +#/** @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 = CpldIoLib + FILE_GUID = 4633665C-0029-464E-9788-58B8D49FF57E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpldIoLib + +[Sources.common] + CpldIoLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Silicon/Hisilicon/HisiPkg.dec + + +[LibraryClasses] + DebugLib + IoLib + BaseLib + ArmLib + TimerLib + +[BuildOptions] + +[Pcd] + gHisiTokenSpaceGuid.PcdCpldBaseAddress diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c new file mode 100644 index 0000000000..d3275276c2 --- /dev/null +++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.c @@ -0,0 +1,104 @@ +/** @file +* +* Copyright (c) 2016, Hisilicon Limited. All rights reserved. +* Copyright (c) 2016, 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 +#include +#include +#include +#include +#include +#include +#include +#include + +UINTN mCpldRegAddr; +EFI_EVENT mCpldVirtualAddressChangeEvent; + + +VOID +EFIAPI +CpldVirtualAddressChange ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0, (VOID **) &mCpldRegAddr); + + return; +} + +RETURN_STATUS +EFIAPI +CpldRuntimeLibConstructor ( + VOID +) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0}; + + mCpldRegAddr = PcdGet64(PcdCpldBaseAddress); + Status = gDS->GetMemorySpaceDescriptor(mCpldRegAddr,&desp); + if(EFI_ERROR(Status)){ + DEBUG ((EFI_D_ERROR, "[%a]:[%dL] GetMemorySpaceDescriptor failed: %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + desp.Attributes |= EFI_MEMORY_RUNTIME; + Status = gDS->SetMemorySpaceAttributes(mCpldRegAddr,0x10000, desp.Attributes); + if(EFI_ERROR(Status)){ + DEBUG ((EFI_D_ERROR, "[%a]:[%dL] SetMemorySpaceAttributes failed: %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + // + // Register notify function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + CpldVirtualAddressChange, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mCpldVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +EFI_STATUS +EFIAPI +CpldRuntimeLibDestructor ( + VOID + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + if(!mCpldVirtualAddressChangeEvent ){ + return Status; + } + + Status = gBS->CloseEvent(mCpldVirtualAddressChangeEvent); + return Status; +} + +VOID WriteCpldReg(UINTN ulRegAddr, UINT8 ulValue) +{ + MmioWrite8 (ulRegAddr + mCpldRegAddr, ulValue); +} + +UINT8 ReadCpldReg(UINTN ulRegAddr) +{ + return MmioRead8 (ulRegAddr + mCpldRegAddr); +} + + diff --git a/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf new file mode 100644 index 0000000000..34c464f4f0 --- /dev/null +++ b/Silicon/Hisilicon/Library/CpldIoLib/CpldIoLibRuntime.inf @@ -0,0 +1,51 @@ +#/** @file +# +# Copyright (c) 2016, Hisilicon Limited. All rights reserved. +# Copyright (c) 2016, 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 = CpldIoLibRuntime + FILE_GUID = C0939398-4AF5-43d0-B6FF-37996D642C04 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpldIoLib + CONSTRUCTOR = CpldRuntimeLibConstructor + DESTRUCTOR = CpldRuntimeLibDestructor + +[Sources.common] + CpldIoLibRuntime.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Hisilicon/HisiPkg.dec + + +[LibraryClasses] + UefiRuntimeLib + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + IoLib + BaseLib + TimerLib + PcdLib + +[BuildOptions] + +[Guids] + gEfiEventVirtualAddressChangeGuid +[Pcd] + gHisiTokenSpaceGuid.PcdCpldBaseAddress diff --git a/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h new file mode 100644 index 0000000000..d1e6c41dd7 --- /dev/null +++ b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClock.h @@ -0,0 +1,178 @@ +/** @file +* +* Copyright (c) 2011, ARM Limited. All rights reserved. +* 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. +* +* Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf +**/ + + +#ifndef __DS3231_REAL_TIME_CLOCK_H__ +#define __DS3231_REAL_TIME_CLOCK_H__ + +#define DS3231_REGADDR_SECONDS 0x00 +#define DS3231_REGADDR_MIUTES 0x01 +#define DS3231_REGADDR_HOURS 0x02 +#define DS3231_REGADDR_DAY 0x03 +#define DS3231_REGADDR_DATE 0x04 +#define DS3231_REGADDR_MONTH 0x05 +#define DS3231_REGADDR_YEAR 0x06 +#define DS3231_REGADDR_ALARM1SEC 0x07 +#define DS3231_REGADDR_ALARM1MIN 0x08 +#define DS3231_REGADDR_ALARM1HOUR 0x09 +#define DS3231_REGADDR_ALARM1DAY 0x0A +#define DS3231_REGADDR_ALARM2MIN 0x0B +#define DS3231_REGADDR_ALARM2HOUR 0x0C +#define DS3231_REGADDR_ALARM2DAY 0x0D +#define DS3231_REGADDR_CONTROL 0x0E +#define DS3231_REGADDR_STATUS 0x0F +#define DS3231_REGADDR_AGOFFSET 0x10 +#define DS3231_REGADDR_TEMPMSB 0x11 +#define DS3231_REGADDR_TEMPLSB 0x12 + + +typedef union { + struct{ + UINT8 A1IE:1; + UINT8 A2IE:1; + UINT8 INTCN:1; + UINT8 RSV:2; + UINT8 CONV:1; + UINT8 BBSQW:1; + UINT8 EOSC_N:1; + }bits; + UINT8 u8; +}RTC_DS3231_CONTROL; + +typedef union { + struct{ + UINT8 A1F:1; + UINT8 A2F:1; + UINT8 BSY:1; + UINT8 EN32KHZ:2; + UINT8 Rsv:3; + UINT8 OSF:1; + }bits; + UINT8 u8; +}RTC_DS3231_STATUS; + + +typedef union { + struct{ + UINT8 Data:7; + UINT8 Sign:1; + }bits; + UINT8 u8; +}RTC_DS3231_AGOFFSET; + +typedef union { + struct{ + UINT8 Data:7; + UINT8 Sign:1; + }bits; + UINT8 u8; +}RTC_DS3231_TEMPMSB; + + +typedef union { + struct{ + UINT8 Rsv:6; + UINT8 Data:2; + }bits; + UINT8 u8; +}RTC_DS3231_TEMPLSB; + +typedef union { + struct{ + UINT8 Seconds:4; + UINT8 Seconds10:3; + UINT8 Rsv:1; + }bits; + UINT8 u8; +}RTC_DS3231_SECONDS; + +typedef union { + struct{ + UINT8 Minutes:4; + UINT8 Minutes10:3; + UINT8 Rsv:1; + }bits; + UINT8 u8; +}RTC_DS3231_MINUTES; + +typedef union { + struct{ + UINT8 Hour:4; + UINT8 Hours10:1; + UINT8 PM_20Hours:1; + UINT8 Hour24_n:1; + UINT8 Rsv:1; + }bits; + UINT8 u8; +}RTC_DS3231_HOURS; + +typedef union { + struct{ + UINT8 Day:3; + UINT8 Rsv:5; + }bits; + UINT8 u8; +}RTC_DS3231_DAY; + +typedef union { + struct{ + UINT8 Month:4; + UINT8 Month10:1; + UINT8 Rsv:2; + UINT8 Century:1; + }bits; + UINT8 u8; +}RTC_DS3231_MONTH; + +typedef union { + struct{ + UINT8 Year:4; + UINT8 Year10:4; + }bits; + UINT8 u8; +}RTC_DS3231_YEAR; + +typedef union { + struct{ + UINT8 Seconds:4; + UINT8 Seconds10:3; + UINT8 A1M1:1; + }bits; + UINT8 u8; +}RTC_DS3231_ALARM1SEC; + +typedef union { + struct{ + UINT8 Minutes:4; + UINT8 Minutes10:3; + UINT8 A1M2:1; + }bits; + UINT8 u8; +}RTC_DS3231_ALARM1MIN; + +typedef union { + struct{ + UINT8 Hour:4; + UINT8 Hours10:1; + UINT8 PM_20Hours:1; + UINT8 Hours24:1; + UINT8 A1M3:1; + }bits; + UINT8 u8; +}RTC_DS3231_ALARM1HOUR; + +#endif diff --git a/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c new file mode 100644 index 0000000000..02d6d7f14d --- /dev/null +++ b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.c @@ -0,0 +1,433 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Currently this driver does not support runtime virtual calling. + + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ Copyright (c) 2011-2013, ARM Ltd. All rights reserved.
+ 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. + + Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf + +**/ + +#include +#include +#include +#include +#include +#include +// Use EfiAtRuntime to check stage +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DS3231RealTimeClock.h" + +extern I2C_DEVICE gDS3231RtcDevice; + +STATIC BOOLEAN mDS3231Initialized = FALSE; + +EFI_STATUS +IdentifyDS3231 ( + VOID + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + return Status; +} + +EFI_STATUS +InitializeDS3231 ( + VOID + ) +{ + EFI_STATUS Status; + I2C_DEVICE Dev; + RTC_DS3231_CONTROL Temp; + RTC_DS3231_HOURS Hours; + + // Prepare the hardware + (VOID)IdentifyDS3231(); + + (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev)); + + Status = I2CInit(Dev.Socket,Dev.Port,Normal); + if (EFI_ERROR (Status)) { + goto EXIT; + } + // Ensure interrupts are masked. We do not want RTC interrupts in UEFI + Status = I2CRead(&Dev,DS3231_REGADDR_CONTROL,1,&Temp.u8); + if (EFI_ERROR (Status)) { + goto EXIT; + } + Temp.bits.INTCN = 0; + Status = I2CWrite(&Dev,DS3231_REGADDR_CONTROL,1,&Temp.u8); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + MicroSecondDelay(2000); + Status = I2CRead(&Dev,DS3231_REGADDR_HOURS,1,&Hours.u8); + if (EFI_ERROR (Status)) { + goto EXIT; + } + Hours.bits.Hour24_n = 0; + Status = I2CWrite(&Dev,DS3231_REGADDR_HOURS,1,&Hours.u8); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + + mDS3231Initialized = TRUE; + + EXIT: + return Status; +} + + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. +**/ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT8 Temp; + UINT8 BaseHour = 0; + UINT16 BaseYear = 1900; + + I2C_DEVICE Dev; + + // Ensure Time is a valid pointer + if (NULL == Time) { + return EFI_INVALID_PARAMETER; + } + + // Initialize the hardware if not already done + if (!mDS3231Initialized) { + Status = InitializeDS3231 (); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + } + + (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev)); + + + Status |= I2CRead(&Dev,DS3231_REGADDR_MONTH,1,&Temp); + + Time->Month = ((Temp>>4)&1)*10+(Temp&0x0F); + + + if(Temp&0x80){ + BaseYear = 2000; + } + + Status |= I2CRead(&Dev,DS3231_REGADDR_YEAR,1,&Temp); + + Time->Year = BaseYear+(Temp>>4) *10 + (Temp&0x0F); + + + Status |= I2CRead(&Dev,DS3231_REGADDR_DATE,1,&Temp); + + Time->Day = ((Temp>>4)&3) *10 + (Temp&0x0F); + + + Status |= I2CRead(&Dev,DS3231_REGADDR_HOURS,1,&Temp); + + BaseHour = 0; + if((Temp&0x30) == 0x30){ + return EFI_DEVICE_ERROR; + }else if(Temp&0x20){ + BaseHour = 20; + }else if(Temp&0x10){ + BaseHour = 10; + } + Time->Hour = BaseHour + (Temp&0x0F); + + + Status |= I2CRead(&Dev,DS3231_REGADDR_MIUTES,1,&Temp); + + Time->Minute = ((Temp>>4)&7) * 10 + (Temp&0x0F); + + + Status |= I2CRead(&Dev,DS3231_REGADDR_SECONDS,1,&Temp); + + Time->Second = (Temp>>4) * 10 + (Temp&0x0F); + + Time->Nanosecond = 0; + Time->Daylight = 0; + Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; + + if((EFI_ERROR(Status)) || (!IsTimeValid(Time)) || ((Time->Year - BaseYear) > 99)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + I2C_DEVICE Dev; + UINT8 Temp; + UINT16 BaseYear = 1900; + + // Check the input parameters are within the range specified by UEFI + if(!IsTimeValid(Time)){ + return EFI_INVALID_PARAMETER; + } + + // Initialize the hardware if not already done + if (!mDS3231Initialized) { + Status = InitializeDS3231 (); + if (EFI_ERROR (Status)) { + goto EXIT; + } + } + + (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev)); + + Temp = ((Time->Second/10)<<4) | (Time->Second%10); + MicroSecondDelay(1000); + Status = I2CWrite(&Dev,DS3231_REGADDR_SECONDS,1,&Temp); + if(EFI_ERROR (Status)){ + goto EXIT; + } + + Temp = ((Time->Minute/10)<<4) | (Time->Minute%10); + MicroSecondDelay(1000); + Status = I2CWrite(&Dev,DS3231_REGADDR_MIUTES,1,&Temp); + if(EFI_ERROR (Status)){ + goto EXIT; + } + + Temp = 0; + if(Time->Hour > 19){ + Temp = 2; + } else if(Time->Hour > 9){ + Temp = 1; + } + Temp = (Temp << 4) | (Time->Hour%10); + MicroSecondDelay(1000); + Status = I2CWrite(&Dev,DS3231_REGADDR_HOURS,1,&Temp); + if(EFI_ERROR (Status)){ + goto EXIT; + } + + Temp = ((Time->Day/10)<<4) | (Time->Day%10); + MicroSecondDelay(1000); + Status = I2CWrite(&Dev,DS3231_REGADDR_DATE,1,&Temp); + if(EFI_ERROR (Status)){ + goto EXIT; + } + + Temp = 0; + if(Time->Year >= 2000){ + Temp = 0x8; + BaseYear = 2000; + } + + if(Time->Month > 9){ + Temp |= 0x1; + } + Temp = (Temp<<4) | (Time->Month%10); + MicroSecondDelay(1000); + Status = I2CWrite(&Dev,DS3231_REGADDR_MONTH,1,&Temp); + if(EFI_ERROR (Status)){ + goto EXIT; + } + + Temp = (((Time->Year-BaseYear)/10)<<4) | (Time->Year%10); + MicroSecondDelay(1000); + Status = I2CWrite(&Dev,DS3231_REGADDR_YEAR,1,&Temp); + if(EFI_ERROR (Status)){ + goto EXIT; + } + + EXIT: + return Status; +} + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + + EFI_TIME EfiTime; + + // Setup the setters and getters + gRT->GetTime = LibGetTime; + gRT->SetTime = LibSetTime; + gRT->GetWakeupTime = LibGetWakeupTime; + gRT->SetWakeupTime = LibSetWakeupTime; + + Status = gRT->GetTime (&EfiTime, NULL); + if(EFI_ERROR (Status) || (EfiTime.Year < 2000) || (EfiTime.Year > 2099)){ + EfiTime.Year = 2000; + EfiTime.Month = 1; + EfiTime.Day = 1; + EfiTime.Hour = 0; + EfiTime.Minute = 0; + EfiTime.Second = 0; + EfiTime.Nanosecond = 0; + EfiTime.Daylight = 0; + EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; + + Status = gRT->SetTime(&EfiTime); + if (EFI_ERROR(Status)) + { + DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status : %r\n", __FUNCTION__, __LINE__, Status)); + } + } + + // Install the protocol + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiRealTimeClockArchProtocolGuid, NULL, + NULL + ); + + return Status; +} + + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Only needed if you are going to support the OS calling RTC functions in virtual mode. + // You will need to call EfiConvertPointer (). To convert any stored physical addresses + // to virtual address. After the OS transitions to calling in virtual mode, all future + // runtime calls will be made in virtual mode. + // + return; +} diff --git a/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf new file mode 100644 index 0000000000..6faefb1128 --- /dev/null +++ b/Silicon/Hisilicon/Library/DS3231RealTimeClockLib/DS3231RealTimeClockLib.inf @@ -0,0 +1,48 @@ +#/** @file +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# Copyright (c) 2011-2013, ARM Ltd. All rights reserved.
+# 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. +# +# +# Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DS3231RealTimeClockLib + FILE_GUID = 470DFB96-E205-4515-A75E-2E60F853E79D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RealTimeClockLib + +[Sources.common] + DS3231RealTimeClockLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + IoLib + UefiLib + DebugLib + PcdLib + I2CLib + TimeBaseLib + TimerLib +# Use EFiAtRuntime to check stage + UefiRuntimeLib + +[Pcd] + diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c new file mode 100644 index 0000000000..ce70ca5ee1 --- /dev/null +++ b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c @@ -0,0 +1,302 @@ +/** @file + UART Serial Port library functions + + Copyright (c) 2006 - 2009, Intel Corporation + Copyright (c) 2015 - 2016, Hisilicon Limited. All rights reserved. + Copyright (c) 2015 - 2016, Linaro Limited. All rights reserved. + 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. + + Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +**/ +#include +#include +#include +#include +#include + +#include "Dw8250SerialPortLib.h" + + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfuly initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serail device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + UINT32 ulUartClkFreq; + + MmioWrite8 (UART_LCR_REG, UART_LCR_DLS8); + MmioWrite8 (UART_FCR_REG, UART_FCR_EN | UART_FCR_RXCLR | UART_FCR_TXCLR); + MmioWrite8 (UART_LCR_REG, UART_LCR_DLAB | UART_LCR_DLS8); + + ulUartClkFreq = PcdGet32(PcdUartClkInHz); + + MmioWrite8 (UART_DLL_REG, (ulUartClkFreq / (16 * (UINT32)BAUDRATE) ) & 0xff); + MmioWrite8 (UART_DLH_REG, ((ulUartClkFreq/ (16 * (UINT32)BAUDRATE) ) >> 8 ) & 0xff); + MmioWrite8 (UART_LCR_REG, UART_LCR_DLS8); + MmioWrite8 (UART_IEL_REG, 0x00); + + return RETURN_SUCCESS; +} + + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation failed. + + If Buffer is NULL, then ASSERT(). + + If NumberOfBytes is zero, then return 0. + + @param Buffer Pointer to the data buffer to be written. + @param NumberOfBytes Number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while (NumberOfBytes--) { + + SerialPortWriteChar(*Buffer); + Buffer++; + } + + return Result; +} + + +/** + Reads data from a serial device into a buffer. + + @param Buffer Pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes Number of bytes to read from the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + + if (NULL == Buffer) { + return 0; + } + + Result = 0; + + while (NumberOfBytes--) { + // + // Wait for the serail port to be ready. + // + *Buffer=SerialPortReadChar(); + Buffer++ ; + Result++; + } + + return Result; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls aserial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + + return (BOOLEAN) ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR); + +} + + +VOID SerialPortWriteChar(UINT8 scShowChar) +{ + UINT32 ulLoop = 0; + + while(ulLoop < (UINT32)UART_SEND_DELAY) + { + + if ((MmioRead8 (UART_USR_REG) & 0x02) == 0x02) + { + break; + } + + ulLoop++; + } + MmioWrite8 (UART_THR_REG, (UINT8)scShowChar); + + ulLoop = 0; + while(ulLoop < (UINT32)UART_SEND_DELAY) + { + if ((MmioRead8 (UART_USR_REG) & 0x04) == 0x04) + { + break; + } + ulLoop++; + } + + return; +} + + +UINT8 SerialPortReadChar(VOID) +{ + UINT8 recvchar = 0; + + while(1) + { + if ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR) + { + break; + } + } + + recvchar = MmioRead8 (UART_RBR_REG); + + return recvchar; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Set the serial device control bits. + + @param Control Control bits which are to be set on the serial device. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Get the serial device control bits. + + @param Control Control signals read from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + + if (SerialPortPoll ()) { + // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY + *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } else { + *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + return EFI_SUCCESS; +} + diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h new file mode 100644 index 0000000000..5e80257289 --- /dev/null +++ b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.h @@ -0,0 +1,116 @@ +/** @file +* +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. +* Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015-2016, 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. +* +* Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +**/ + +#ifndef __DW8250_SERIALPORTLIB_H__ +#define __DW8250_SERIALPORTLIB_H__ + + +#define SERIAL_0_BASE_ADR (PcdGet64(PcdSerialRegisterBase)) + + +#define UART_SEND_DELAY (PcdGet32(PcdSerialPortSendDelay)) +#define BAUDRATE (PcdGet64(PcdUartDefaultBaudRate)) + + +#define UART_THR_REG (SERIAL_0_BASE_ADR + UART_THR) +#define UART_RBR_REG (SERIAL_0_BASE_ADR + UART_RBR) +#define UART_DLL_REG (SERIAL_0_BASE_ADR + UART_DLL) +#define UART_DLH_REG (SERIAL_0_BASE_ADR + UART_DLH) +#define UART_IEL_REG (SERIAL_0_BASE_ADR + UART_IEL) +#define UART_IIR_REG (SERIAL_0_BASE_ADR + UART_IIR) +#define UART_FCR_REG (SERIAL_0_BASE_ADR + UART_FCR) +#define UART_LCR_REG (SERIAL_0_BASE_ADR + UART_LCR) +#define UART_LSR_REG (SERIAL_0_BASE_ADR + UART_LSR) +#define UART_USR_REG (SERIAL_0_BASE_ADR + UART_USR) + + +#define UART_RBR 0x00 +#define UART_THR 0x00 +#define UART_DLL 0x00 +#define UART_DLH 0x04 +#define UART_IEL 0x04 +#define UART_IIR 0x08 +#define UART_FCR 0x08 +#define UART_LCR 0x0C +#define UART_MCR 0x10 +#define UART_LSR 0x14 +#define UART_USR 0x7C + +/* register definitions */ + +#define UART_FCR_EN 0x01 +#define UART_FCR_RXCLR 0x02 +#define UART_FCR_TXCLR 0x04 +#define UART_FCR_CLEARFIFO 0x00 +#define UART_FCR_RXL1 0x00 +#define UART_FCR_RXL4 0x40 +#define UART_FCR_RXL8 0x80 +#define UART_FCR_RXL14 0xc0 +#define UART_FCR_TXL0 0x00 +#define UART_FCR_TXL4 0x20 +#define UART_FCR_TXL8 0x30 +#define UART_FCR_TXL14 0x10 + +/*LCR Name: Line Control Register fields*/ +#define UART_LCR_DLAB 0x80 +#define UART_LCR_EPS 0x10 +#define UART_LCR_PEN 0x08 +#define UART_LCR_STOP 0x04 +#define UART_LCR_DLS8 0x03 +#define UART_LCR_DLS7 0x02 +#define UART_LCR_DLS6 0x01 +#define UART_LCR_DLS5 0x00 + + +#define UART_DLH_AND_DLL_WIDTH 0xFF + + +#define UART_IER_PTIME 0x80 +#define UART_IER_ELSI 0x04 +#define UART_IER_ETBEI 0x02 +#define UART_IER_ERBFI 0x01 + + +#define UART_IIR_FIFOSE 0xC0 + + +#define UART_IIR_InterruptID 0x01 +#define UART_IIR_INTIDTE 0x02 +#define UART_IIR_INTIDRA 0x04 +#define UART_IIR_INTIDRLS 0x06 +#define UART_IIR_INTMASK 0x0f +#define UART_IIR_RDA 0x04 +#define UART_IIR_TE 0x02 + +#define UART_LSR_TEMT 0x40 +#define UART_LSR_THRE 0x20 +#define UART_LSR_BI 0x10 +#define UART_LSR_FE 0x08 +#define UART_LSR_PE 0x04 +#define UART_LSR_R 0x02 +#define UART_LSR_DR 0x01 + + +#define UART_USR_BUSY 0x01 + +#define FIFO_MAXSIZE 32 + +extern UINT8 SerialPortReadChar(VOID); +extern VOID SerialPortWriteChar(UINT8 scShowChar); + +#endif + diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf new file mode 100644 index 0000000000..d7957ea499 --- /dev/null +++ b/Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf @@ -0,0 +1,45 @@ +#/** @file +# +# Copyright (c) 2011, ARM Ltd. All rights reserved.
+# Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015-2016, 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. +# +# Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Dw8250SerialPortLib + FILE_GUID = 16D53E86-7EA6-47bd-861F-511ED9B8ABE0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + + +[Sources.common] + Dw8250SerialPortLib.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + BaseLib + IoLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gHisiTokenSpaceGuid.PcdSerialPortSendDelay + gHisiTokenSpaceGuid.PcdUartClkInHz diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c new file mode 100644 index 0000000000..d092659228 --- /dev/null +++ b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.c @@ -0,0 +1,356 @@ +/** @file +* +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. +* 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. +* +* Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +**/ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "Dw8250SerialPortRuntimeLib.h" + +UINT64 mSerialRegBaseAddr = 0; + +EFI_EVENT mSerialVirtualAddressChangeEvent = NULL; + +VOID +EFIAPI +SerialVirtualAddressChangeCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0, (VOID **) &mSerialRegBaseAddr); + + return; +} + + +EFI_STATUS +EFIAPI +SerialPortLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + if(!mSerialVirtualAddressChangeEvent ){ + return Status; + } + + Status = gBS->CloseEvent(mSerialVirtualAddressChangeEvent); + return Status; +} + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfuly initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serail device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0}; + + mSerialRegBaseAddr = PcdGet64(PcdSerialRegisterBase); + + Status = gDS->GetMemorySpaceDescriptor(PcdGet64(PcdSerialRegisterBase),&desp); + if(EFI_ERROR(Status)){ + return Status; + } + desp.Attributes |= EFI_MEMORY_RUNTIME; + Status = gDS->SetMemorySpaceAttributes(PcdGet64(PcdSerialRegisterBase),PcdGet64(PcdSerialRegisterSpaceSize), desp.Attributes); + if(EFI_ERROR(Status)){ + return Status; + } + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + SerialVirtualAddressChangeCallBack, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mSerialVirtualAddressChangeEvent + ); + + if(EFI_ERROR(Status)){ + mSerialVirtualAddressChangeEvent = NULL; + } + + return Status; +} + + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation failed. + + If Buffer is NULL, then ASSERT(). + + If NumberOfBytes is zero, then return 0. + + @param Buffer Pointer to the data buffer to be written. + @param NumberOfBytes Number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while (NumberOfBytes--) { + + SerialPortWriteChar(*Buffer); + Buffer++; + } + + return Result; +} + + +/** + Reads data from a serial device into a buffer. + + @param Buffer Pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes Number of bytes to read from the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + + if (NULL == Buffer) { + return 0; + } + + Result = 0; + + while (NumberOfBytes--) { + // + // Wait for the serail port to be ready. + // + *Buffer=SerialPortReadChar(); + Buffer++ ; + Result++; + } + + return Result; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls aserial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + + return (BOOLEAN) ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR); + +} + + +VOID SerialPortWriteChar(UINT8 scShowChar) +{ + UINT32 ulLoop = 0; + + while(ulLoop < (UINT32)UART_SEND_DELAY) + { + + if ((MmioRead8 (UART_USR_REG) & 0x02) == 0x02) + { + break; + } + + ulLoop++; + } + MmioWrite8 (UART_THR_REG, (UINT8)scShowChar); + + ulLoop = 0; + while(ulLoop < (UINT32)UART_SEND_DELAY) + { + if ((MmioRead8 (UART_USR_REG) & 0x04) == 0x04) + { + break; + } + ulLoop++; + } + + return; +} + + +UINT8 SerialPortReadChar(VOID) +{ + UINT8 recvchar = 0; + + do + { + if ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR) { + break; + } + + }while(MmioRead8 (UART_USR_REG) & UART_USR_BUSY); + + recvchar = MmioRead8 (UART_RBR_REG); + + return recvchar; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Set the serial device control bits. + + @param Control Control bits which are to be set on the serial device. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Get the serial device control bits. + + @param Control Control signals read from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + + if (SerialPortPoll ()) { + // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY + *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } else { + *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + return EFI_SUCCESS; +} + diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h new file mode 100644 index 0000000000..f5dcb9ec8d --- /dev/null +++ b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.h @@ -0,0 +1,116 @@ +/** @file +* +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. +* Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved. +* Copyright (c) 2015-2016, 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. +* +* Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +**/ + +#ifndef __DW8250_SERIALPORTLIB_H__ +#define __DW8250_SERIALPORTLIB_H__ + + +#define SERIAL_0_BASE_ADR (mSerialRegBaseAddr) + + +#define UART_SEND_DELAY (PcdGet32(PcdSerialPortSendDelay)) +#define BAUDRATE (PcdGet64(PcdUartDefaultBaudRate)) + + +#define UART_THR_REG (SERIAL_0_BASE_ADR + UART_THR) +#define UART_RBR_REG (SERIAL_0_BASE_ADR + UART_RBR) +#define UART_DLL_REG (SERIAL_0_BASE_ADR + UART_DLL) +#define UART_DLH_REG (SERIAL_0_BASE_ADR + UART_DLH) +#define UART_IEL_REG (SERIAL_0_BASE_ADR + UART_IEL) +#define UART_IIR_REG (SERIAL_0_BASE_ADR + UART_IIR) +#define UART_FCR_REG (SERIAL_0_BASE_ADR + UART_FCR) +#define UART_LCR_REG (SERIAL_0_BASE_ADR + UART_LCR) +#define UART_LSR_REG (SERIAL_0_BASE_ADR + UART_LSR) +#define UART_USR_REG (SERIAL_0_BASE_ADR + UART_USR) + + +#define UART_RBR 0x00 +#define UART_THR 0x00 +#define UART_DLL 0x00 +#define UART_DLH 0x04 +#define UART_IEL 0x04 +#define UART_IIR 0x08 +#define UART_FCR 0x08 +#define UART_LCR 0x0C +#define UART_MCR 0x10 +#define UART_LSR 0x14 +#define UART_USR 0x7C + +/* register definitions */ + +#define UART_FCR_EN 0x01 +#define UART_FCR_RXCLR 0x02 +#define UART_FCR_TXCLR 0x04 +#define UART_FCR_CLEARFIFO 0x00 +#define UART_FCR_RXL1 0x00 +#define UART_FCR_RXL4 0x40 +#define UART_FCR_RXL8 0x80 +#define UART_FCR_RXL14 0xc0 +#define UART_FCR_TXL0 0x00 +#define UART_FCR_TXL4 0x20 +#define UART_FCR_TXL8 0x30 +#define UART_FCR_TXL14 0x10 + +/*LCR Name: Line Control Register fields*/ +#define UART_LCR_DLAB 0x80 +#define UART_LCR_EPS 0x10 +#define UART_LCR_PEN 0x08 +#define UART_LCR_STOP 0x04 +#define UART_LCR_DLS8 0x03 +#define UART_LCR_DLS7 0x02 +#define UART_LCR_DLS6 0x01 +#define UART_LCR_DLS5 0x00 + + +#define UART_DLH_AND_DLL_WIDTH 0xFF + + +#define UART_IER_PTIME 0x80 +#define UART_IER_ELSI 0x04 +#define UART_IER_ETBEI 0x02 +#define UART_IER_ERBFI 0x01 + + +#define UART_IIR_FIFOSE 0xC0 + + +#define UART_IIR_InterruptID 0x01 +#define UART_IIR_INTIDTE 0x02 +#define UART_IIR_INTIDRA 0x04 +#define UART_IIR_INTIDRLS 0x06 +#define UART_IIR_INTMASK 0x0f +#define UART_IIR_RDA 0x04 +#define UART_IIR_TE 0x02 + +#define UART_LSR_TEMT 0x40 +#define UART_LSR_THRE 0x20 +#define UART_LSR_BI 0x10 +#define UART_LSR_FE 0x08 +#define UART_LSR_PE 0x04 +#define UART_LSR_R 0x02 +#define UART_LSR_DR 0x01 + + +#define UART_USR_BUSY 0x01 + +#define FIFO_MAXSIZE 32 + +extern UINT8 SerialPortReadChar(VOID); +extern VOID SerialPortWriteChar(UINT8 scShowChar); + +#endif + diff --git a/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf new file mode 100644 index 0000000000..2cedcb1004 --- /dev/null +++ b/Silicon/Hisilicon/Library/Dw8250SerialPortRuntimeLib/Dw8250SerialPortRuntimeLib.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2011, ARM Ltd. All rights reserved.
+# Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015-2016, 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. +# +# Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Dw8250SerialPortLib + FILE_GUID = 16D53E86-7EA6-47bd-861F-511ED9B8ABE0 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + DESTRUCTOR = SerialPortLibDestructor + +[Sources.common] + Dw8250SerialPortRuntimeLib.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + BaseLib + IoLib + UefiRuntimeLib + UefiBootServicesTableLib + DxeServicesTableLib + +[Guids] + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase + gHisiTokenSpaceGuid.PcdSerialRegisterSpaceSize + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gHisiTokenSpaceGuid.PcdSerialPortSendDelay + gHisiTokenSpaceGuid.PcdUartClkInHz diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CHw.h b/Silicon/Hisilicon/Library/I2CLib/I2CHw.h new file mode 100644 index 0000000000..aa561e929c --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CHw.h @@ -0,0 +1,269 @@ +/** @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 _I2C_HW_H_ +#define _I2C_HW_H_ + +#include +#include + +#define I2C_READ_TIMEOUT 500 +#define I2C_DRV_ONCE_WRITE_BYTES_NUM 8 +#define I2C_DRV_ONCE_READ_BYTES_NUM 8 +#define I2C_READ_SIGNAL 0x0100 +#define I2C_TXRX_THRESHOLD 0x7 +#define I2C_SS_SCLHCNT 0x493 +#define I2C_SS_SCLLCNT 0x4fe +#define I2C_CMD_STOP_BIT BIT9 + +#define I2C_REG_WRITE(reg,data) \ + MmioWrite32 ((reg), (data)) + +#define I2C_REG_READ(reg,result) \ + (result) = MmioRead32 ((reg)) + + #define I2C_CON_OFFSET 0x0 + #define I2C_TAR_OFFSET 0x4 + #define I2C_SAR_OFFSET 0x8 + #define I2C_DATA_CMD_OFFSET 0x10 + #define I2C_SS_SCL_HCNT_OFFSET 0x14 + #define I2C_SS_SCL_LCNT_OFFSET 0x18 + #define I2C_FS_SCL_HCNT_OFFSET 0x1c + #define I2C_FS_SCL_LCNT_OFFSET 0x20 + #define I2C_INTR_STAT_OFFSET 0x2c + #define I2C_INTR_MASK_OFFSET 0x30 + #define I2C_RAW_INTR_STAT_OFFSET 0x34 + #define I2C_RX_TL_OFFSET 0x38 + #define I2C_TX_TL_OFFSET 0x3c + #define I2C_CLR_INTR_OFFSET 0x40 + #define I2C_CLR_RX_UNDER_OFFSET 0x44 + #define I2C_CLR_RX_OVER_OFFSET 0x48 + #define I2C_CLR_TX_OVER_OFFSET 0x4c + #define I2C_CLR_RD_REQ_OFFSET 0x50 + #define I2C_CLR_TX_ABRT_OFFSET 0x54 + #define I2C_CLR_RX_DONE_OFFSET 0x58 + #define I2C_CLR_ACTIVITY_OFFSET 0x5c + #define I2C_CLR_STOP_DET_OFFSET 0x60 + #define I2C_CLR_START_DET_OFFSET 0x64 + #define I2C_CLR_GEN_CALL_OFFSET 0x68 + #define I2C_ENABLE_OFFSET 0x6c + #define I2C_STATUS_OFFSET 0x70 + #define I2C_TXFLR_OFFSET 0x74 + #define I2C_RXFLR_OFFSET 0x78 + #define I2C_SDA_HOLD 0x7c + #define I2C_TX_ABRT_SOURCE_OFFSET 0x80 + #define I2C_SLV_DATA_ONLY_OFFSET 0x84 + #define I2C_DMA_CR_OFFSET 0x88 + #define I2C_DMA_TDLR_OFFSET 0x8c + #define I2C_DMA_RDLR_OFFSET 0x90 + #define I2C_SDA_SETUP_OFFSET 0x94 + #define I2C_ACK_GENERAL_CALL_OFFSET 0x98 + #define I2C_ENABLE_STATUS_OFFSET 0x9c + + + typedef union tagI2c0Con + { + struct + { + UINT32 master : 1 ; + UINT32 spedd : 2 ; + UINT32 slave_10bit : 1 ; + UINT32 master_10bit : 1 ; + UINT32 restart_en : 1 ; + UINT32 slave_disable : 1 ; + UINT32 Reserved_0 : 25 ; + } bits; + UINT32 Val32; + } I2C0_CON_U; + + + typedef union tagI2c0Tar + { + struct + { + UINT32 ic_tar : 10 ; + UINT32 gc_or_start : 1 ; + UINT32 special : 1 ; + UINT32 ic_10bitaddr_master : 1 ; + UINT32 Reserved_1 : 19 ; + } bits; + UINT32 Val32; + } I2C0_TAR_U; + + + typedef union tagI2c0DataCmd + { + struct + { + UINT32 dat : 8 ; + UINT32 cmd : 1 ; + UINT32 Reserved_5 : 23 ; + } bits; + UINT32 Val32; + } I2C0_DATA_CMD_U; + + + typedef union tagI2c0SsSclHcnt + { + struct + { + UINT32 ic_ss_scl_hcnt : 16 ; + UINT32 Reserved_7 : 16 ; + } bits; + UINT32 Val32; + } I2C0_SS_SCL_HCNT_U; + + + typedef union tagI2c0SsSclLcnt + { + struct + { + UINT32 ic_ss_scl_lcnt : 16 ; + UINT32 Reserved_9 : 16 ; + } bits; + UINT32 Val32; + } I2C0_SS_SCL_LCNT_U; + + + typedef union tagI2c0FsSclHcnt + { + struct + { + UINT32 ic_fs_scl_hcnt : 16 ; + UINT32 Reserved_11 : 16 ; + } bits; + UINT32 Val32; + } I2C0_FS_SCL_HCNT_U; + + + typedef union tagI2c0FsSclLcnt + { + struct + { + UINT32 ic_fs_scl_lcnt : 16 ; + UINT32 Reserved_13 : 16 ; + } bits; + UINT32 Val32; + } I2C0_FS_SCL_LCNT_U; + + + typedef union tagI2c0IntrMask + { + struct + { + UINT32 m_rx_under : 1 ; + UINT32 m_rx_over : 1 ; + UINT32 m_rx_full : 1 ; + UINT32 m_tx_over : 1 ; + UINT32 m_tx_empty : 1 ; + UINT32 m_rd_req : 1 ; + UINT32 m_tx_abrt : 1 ; + UINT32 m_rx_done : 1 ; + UINT32 m_activity : 1 ; + UINT32 m_stop_det : 1 ; + UINT32 m_start_det : 1 ; + UINT32 m_gen_call : 1 ; + UINT32 Reserved_17 : 20 ; + } bits; + UINT32 Val32; + } I2C0_INTR_MASK_U; + + + typedef union tagI2c0RxTl + { + struct + { + UINT32 rx_tl : 8 ; + UINT32 Reserved_21 : 24 ; + } bits; + UINT32 Val32; + } I2C0_RX_TL_U; + + + typedef union tagI2c0TxTl + { + struct + { + UINT32 tx_tl : 8 ; + UINT32 Reserved_23 : 24 ; + } bits; + UINT32 Val32; + } I2C0_TX_TL_U; + + + typedef union tagI2c0Enable + { + struct + { + UINT32 enable : 1 ; + UINT32 Reserved_47 : 31 ; + } bits; + UINT32 Val32; + } I2C0_ENABLE_U; + + + typedef union tagI2c0Status + { + struct + { + UINT32 activity : 1 ; + UINT32 tfnf : 1 ; + UINT32 tfe : 1 ; + UINT32 rfne : 1 ; + UINT32 rff : 1 ; + UINT32 mst_activity : 1 ; + UINT32 slv_activity : 1 ; + UINT32 Reserved_49 : 25 ; + } bits; + UINT32 Val32; + } I2C0_STATUS_U; + + + typedef union tagI2c0Txflr + { + struct + { + UINT32 txflr : 4 ; + UINT32 Reserved_51 : 28 ; + } bits; + UINT32 Val32; + } I2C0_TXFLR_U; + + + typedef union tagI2c0Rxflr + { + struct + { + UINT32 rxflr : 4 ; + UINT32 Reserved_53 : 28 ; + } bits; + UINT32 Val32; + } I2C0_RXFLR_U; + + + typedef union tagI2c0EnableStatus + { + struct + { + UINT32 ic_en : 1 ; + UINT32 slv_disable_while_busy: 1 ; + UINT32 slv_rx_data_lost : 1 ; + UINT32 Reserved_69 : 29 ; + } bits; + UINT32 Val32; + } I2C0_ENABLE_STATUS_U; + + +#endif diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLib.c b/Silicon/Hisilicon/Library/I2CLib/I2CLib.c new file mode 100644 index 0000000000..b5b388d756 --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CLib.c @@ -0,0 +1,655 @@ +/** @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 +#include +#include +#include +#include +#include +#include + +#include + +#include "I2CLibInternal.h" +#include "I2CHw.h" + +VOID I2C_Delay(UINT32 ulCount) +{ + MicroSecondDelay(ulCount); + return; +} + + +EFI_STATUS +EFIAPI +I2C_Disable(UINT32 Socket,UINT8 Port) +{ + UINT32 ulTimeCnt = I2C_READ_TIMEOUT; + I2C0_STATUS_U I2cStatusReg; + I2C0_ENABLE_U I2cEnableReg; + I2C0_ENABLE_STATUS_U I2cEnableStatusReg; + + UINTN Base = GetI2cBase(Socket, Port); + + I2C_REG_READ((Base + I2C_STATUS_OFFSET), I2cStatusReg.Val32); + + while (I2cStatusReg.bits.activity) + { + I2C_Delay(10000); + + ulTimeCnt--; + I2C_REG_READ(Base + I2C_STATUS_OFFSET, I2cStatusReg.Val32); + if (0 == ulTimeCnt) + { + return EFI_DEVICE_ERROR; + } + } + + + I2C_REG_READ(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32); + I2cEnableReg.bits.enable = 0; + I2C_REG_WRITE(Base + I2C_ENABLE_OFFSET,I2cEnableReg.Val32); + + I2C_REG_READ(Base + I2C_ENABLE_OFFSET,I2cEnableStatusReg.Val32); + if (0 == I2cEnableStatusReg.bits.ic_en) + { + return EFI_SUCCESS; + } + else + { + return EFI_DEVICE_ERROR; + } +} + + +EFI_STATUS +EFIAPI +I2C_Enable(UINT32 Socket,UINT8 Port) +{ + I2C0_ENABLE_U I2cEnableReg; + I2C0_ENABLE_STATUS_U I2cEnableStatusReg; + + UINTN Base = GetI2cBase(Socket, Port); + + + I2C_REG_READ(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32); + I2cEnableReg.bits.enable = 1; + I2C_REG_WRITE(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32); + + + I2C_REG_READ(Base + I2C_ENABLE_STATUS_OFFSET, I2cEnableStatusReg.Val32); + if (1 == I2cEnableStatusReg.bits.ic_en) + { + return EFI_SUCCESS; + } + else + { + return EFI_DEVICE_ERROR; + } +} + +void I2C_SetTarget(UINT32 Socket,UINT8 Port,UINT32 I2cDeviceAddr) +{ + I2C0_TAR_U I2cTargetReg; + UINTN Base = GetI2cBase(Socket, Port); + + + I2C_REG_READ(Base + I2C_TAR_OFFSET, I2cTargetReg.Val32); + I2cTargetReg.bits.ic_tar = I2cDeviceAddr; + I2C_REG_WRITE(Base + I2C_TAR_OFFSET, I2cTargetReg.Val32); + + return; +} + + +EFI_STATUS +EFIAPI +I2CInit(UINT32 Socket, UINT32 Port, SPEED_MODE SpeedMode) +{ + I2C0_CON_U I2cControlReg; + I2C0_SS_SCL_HCNT_U I2cStandardSpeedSclHighCount; + I2C0_SS_SCL_LCNT_U I2cStandardSpeedSclLowCount; + I2C0_RX_TL_U I2cRxFifoReg; + I2C0_TX_TL_U I2cTxFifoReg; + I2C0_INTR_MASK_U I2cIntrMask; + EFI_STATUS Status; + + UINTN Base = GetI2cBase(Socket, Port); + + if((Socket >= MAX_SOCKET) || (Port >= I2C_PORT_MAX) || (SpeedMode >= SPEED_MODE_MAX)){ + return EFI_INVALID_PARAMETER; + } + + + Status = I2C_Disable(Socket,Port); + if(EFI_ERROR(Status)) + { + return EFI_DEVICE_ERROR; + } + + + I2C_REG_READ(Base + I2C_CON_OFFSET, I2cControlReg.Val32); + I2cControlReg.bits.master = 1; + I2cControlReg.bits.spedd = 0x1; + I2cControlReg.bits.restart_en = 1; + I2cControlReg.bits.slave_disable = 1; + I2C_REG_WRITE(Base + I2C_CON_OFFSET,I2cControlReg.Val32); + + + if(Normal == SpeedMode) + { + I2C_REG_READ(Base + I2C_SS_SCL_HCNT_OFFSET,I2cStandardSpeedSclHighCount.Val32); + I2cStandardSpeedSclHighCount.bits.ic_ss_scl_hcnt = I2C_SS_SCLHCNT; + I2C_REG_WRITE(Base + I2C_SS_SCL_HCNT_OFFSET, I2cStandardSpeedSclHighCount.Val32); + I2C_REG_READ(Base + I2C_SS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32); + I2cStandardSpeedSclLowCount.bits.ic_ss_scl_lcnt = I2C_SS_SCLLCNT; + I2C_REG_WRITE(Base + I2C_SS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32); + } + else + { + I2C_REG_READ(Base + I2C_FS_SCL_HCNT_OFFSET,I2cStandardSpeedSclHighCount.Val32); + I2cStandardSpeedSclHighCount.bits.ic_ss_scl_hcnt = I2C_SS_SCLHCNT; + I2C_REG_WRITE(Base + I2C_FS_SCL_HCNT_OFFSET, I2cStandardSpeedSclHighCount.Val32); + I2C_REG_READ(Base + I2C_FS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32); + I2cStandardSpeedSclLowCount.bits.ic_ss_scl_lcnt = I2C_SS_SCLLCNT; + I2C_REG_WRITE(Base + I2C_FS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32); + } + + + I2C_REG_READ(Base + I2C_RX_TL_OFFSET, I2cRxFifoReg.Val32); + I2cRxFifoReg.bits.rx_tl = I2C_TXRX_THRESHOLD; + I2C_REG_WRITE(Base + I2C_RX_TL_OFFSET, I2cRxFifoReg.Val32); + I2C_REG_READ(Base + I2C_TX_TL_OFFSET,I2cTxFifoReg.Val32); + I2cTxFifoReg.bits.tx_tl = I2C_TXRX_THRESHOLD; + I2C_REG_WRITE(Base + I2C_TX_TL_OFFSET, I2cTxFifoReg.Val32); + + + I2C_REG_READ(Base + I2C_INTR_MASK_OFFSET, I2cIntrMask.Val32); + I2cIntrMask.Val32 = 0x0; + I2C_REG_WRITE(Base + I2C_INTR_MASK_OFFSET, I2cIntrMask.Val32); + + + Status = I2C_Enable(Socket,Port); + if(EFI_ERROR(Status)) + { + return EFI_DEVICE_ERROR; + } + + return I2cLibRuntimeSetup (Socket, Port); +} + +EFI_STATUS +EFIAPI +I2CSdaConfig(UINT32 Socket, UINT32 Port) +{ + + UINTN Base = GetI2cBase(Socket, Port); + + if((Socket >= MAX_SOCKET) || (Port >= I2C_PORT_MAX)){ + return EFI_INVALID_PARAMETER; + } + + I2C_REG_WRITE(Base + I2C_SDA_HOLD, 0x14); + + return EFI_SUCCESS; +} + + + +UINT32 I2C_GetTxStatus(UINT32 Socket,UINT8 Port) +{ + I2C0_TXFLR_U ulFifo; + UINTN Base = GetI2cBase(Socket, Port); + + I2C_REG_READ(Base + I2C_TXFLR_OFFSET, ulFifo.Val32); + return ulFifo.bits.txflr; +} + +UINT32 +I2C_GetRxStatus(UINT32 Socket,UINT8 Port) +{ + I2C0_RXFLR_U ulFifo; + UINTN Base = GetI2cBase(Socket, Port); + + I2C_REG_READ(Base + I2C_RXFLR_OFFSET, ulFifo.Val32); + return ulFifo.bits.rxflr; +} + +EFI_STATUS +EFIAPI +WriteBeforeRead(I2C_DEVICE *I2cInfo, UINT32 ulLength, UINT8 *pBuf) +{ + UINT32 ulFifo; + UINT32 ulCnt; + UINT32 ulTimes = 0; + + UINTN Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port); + + + I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress); + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + while(0 != ulFifo) + { + I2C_Delay(2); + if(++ulTimes > I2C_READ_TIMEOUT) + { + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + for(ulCnt = 0; ulCnt < ulLength; ulCnt++) + { + ulTimes = 0; + while(ulFifo > I2C_TXRX_THRESHOLD) + { + I2C_Delay(2); + if(++ulTimes > I2C_READ_TIMEOUT) + { + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++); + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + ulTimes = 0; + while(0 != ulFifo) + { + I2C_Delay(2); + + if(++ulTimes > I2C_READ_TIMEOUT) + { + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +I2CWrite(I2C_DEVICE *I2cInfo, UINT16 InfoOffset, UINT32 ulLength, UINT8 *pBuf) +{ + UINT32 ulFifo; + UINT32 ulTimes = 0; + UINT32 Idx; + UINTN Base; + + + if(I2cInfo->Port >= I2C_PORT_MAX) + { + return EFI_INVALID_PARAMETER; + } + + Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port); + + (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port); + + I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress); + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + while(0 != ulFifo) + { + I2C_Delay(2); + if(++ulTimes > I2C_READ_TIMEOUT) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + + if(I2cInfo->DeviceType) + { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff); + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff); + } + else + { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff); + } + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + ulTimes = 0; + while(0 != ulFifo) + { + I2C_Delay(2); + if(++ulTimes > I2C_READ_TIMEOUT) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + for(Idx = 0; Idx < ulLength; Idx++) + { + ulTimes = 0; + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + while(ulFifo > I2C_TXRX_THRESHOLD) + { + I2C_Delay(2); + if(++ulTimes > I2C_READ_TIMEOUT) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + if (Idx < ulLength - 1) { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (*pBuf++)); + } else { + //Send command stop bit for the last transfer + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (*pBuf++) | I2C_CMD_STOP_BIT); + } + } + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + ulTimes = 0; + while(0 != ulFifo) + { + I2C_Delay(2); + + if(++ulTimes > I2C_READ_TIMEOUT) + { + DEBUG ((EFI_D_ERROR, "I2C Write try to finished,time out!\n")); + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +I2CRead(I2C_DEVICE *I2cInfo, UINT16 InfoOffset,UINT32 ulRxLen,UINT8 *pBuf) +{ + UINT32 ulFifo; + UINT32 ulTimes = 0; + UINT8 I2CWAddr[2]; + EFI_STATUS Status; + UINT32 Idx = 0; + UINTN Base; + + + if(I2cInfo->Port >= I2C_PORT_MAX) + { + return EFI_INVALID_PARAMETER; + } + + (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port); + Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port); + if(I2cInfo->DeviceType) + { + I2CWAddr[0] = (InfoOffset >> 8) & 0xff; + I2CWAddr[1] = (InfoOffset & 0xff); + Status = WriteBeforeRead(I2cInfo, 2,I2CWAddr); + if(EFI_ERROR(Status)) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_ABORTED; + } + } + else + { + I2CWAddr[0] = (InfoOffset & 0xff); + Status = WriteBeforeRead(I2cInfo, 1,I2CWAddr); + if(EFI_ERROR(Status)) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_ABORTED; + } + } + + I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress); + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + while(0 != ulFifo) + { + I2C_Delay(2); + + while(++ulTimes > I2C_READ_TIMEOUT) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + while (ulRxLen > 0) { + if (ulRxLen > 1) { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL); + } else { + //Send command stop bit for the last transfer + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL | I2C_CMD_STOP_BIT); + } + + ulTimes = 0; + do { + I2C_Delay(2); + + while(++ulTimes > I2C_READ_TIMEOUT) { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetRxStatus(I2cInfo->Socket,I2cInfo->Port); + }while(0 == ulFifo); + + I2C_REG_READ(Base + I2C_DATA_CMD_OFFSET, pBuf[Idx++]); + + ulRxLen --; + } + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +I2CReadMultiByte(I2C_DEVICE *I2cInfo, UINT32 InfoOffset,UINT32 ulRxLen,UINT8 *pBuf) +{ + UINT32 ulCnt; + UINT16 usTotalLen = 0; + UINT32 ulFifo; + UINT32 ulTimes = 0; + UINT8 I2CWAddr[4]; + EFI_STATUS Status; + UINT32 BytesLeft; + UINT32 Idx = 0; + UINTN Base; + + + if(I2cInfo->Port >= I2C_PORT_MAX) + { + return EFI_INVALID_PARAMETER; + } + + (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port); + Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port); + if(I2cInfo->DeviceType == DEVICE_TYPE_E2PROM) + { + I2CWAddr[0] = (InfoOffset >> 8) & 0xff; + I2CWAddr[1] = (InfoOffset & 0xff); + Status = WriteBeforeRead(I2cInfo, 2,I2CWAddr); + if(EFI_ERROR(Status)) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_ABORTED; + } + } + + else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_3BYTE_OPERANDS) + { + I2CWAddr[0] = (InfoOffset >> 16) & 0xff; + I2CWAddr[1] = (InfoOffset >> 8) & 0xff; + I2CWAddr[2] = (InfoOffset & 0xff); + Status = WriteBeforeRead(I2cInfo, 3,I2CWAddr); + if(EFI_ERROR(Status)) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_ABORTED; + } + } + + else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_4BYTE_OPERANDS) + { + I2CWAddr[0] = (InfoOffset >> 24) & 0xff; + I2CWAddr[1] = (InfoOffset >> 16) & 0xff; + I2CWAddr[2] = (InfoOffset >> 8) & 0xff; + I2CWAddr[3] = (InfoOffset & 0xff); + Status = WriteBeforeRead(I2cInfo, 4,I2CWAddr); + if(EFI_ERROR(Status)) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_ABORTED; + } + } + + else + { + I2CWAddr[0] = (InfoOffset & 0xff); + Status = WriteBeforeRead(I2cInfo, 1,I2CWAddr); + if(EFI_ERROR(Status)) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_ABORTED; + } + } + + + I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress); + usTotalLen = ulRxLen; + BytesLeft = usTotalLen; + + for(ulCnt = 0; ulCnt < BytesLeft; ulCnt++) { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL); + } + + + for(ulCnt = 0; ulCnt < BytesLeft; ulCnt++) { + ulTimes = 0; + do { + I2C_Delay(2); + + while(++ulTimes > I2C_READ_TIMEOUT) { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetRxStatus(I2cInfo->Socket,I2cInfo->Port); + }while(0 == ulFifo); + + I2C_REG_READ(Base + I2C_DATA_CMD_OFFSET, pBuf[Idx++]); + } + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +I2CWriteMultiByte(I2C_DEVICE *I2cInfo, UINT32 InfoOffset, UINT32 ulLength, UINT8 *pBuf) +{ + UINT32 ulFifo; + UINT32 ulTimes = 0; + UINT32 Idx; + UINTN Base; + + + if(I2cInfo->Port >= I2C_PORT_MAX) + { + return EFI_INVALID_PARAMETER; + } + + Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port); + + (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port); + + I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress); + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + while(0 != ulFifo) + { + I2C_Delay(2); + if(++ulTimes > I2C_READ_TIMEOUT) + { + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + + + if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_3BYTE_OPERANDS) + { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 16) & 0xff); + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff); + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff); + } + + else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_4BYTE_OPERANDS) + { + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 24) & 0xff); + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 16) & 0xff); + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff); + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff); + } + + else + { + + } + + ulTimes = 0; + for(Idx = 0; Idx < ulLength; Idx++) + { + + I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++); + + } + + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + ulTimes = 0; + while(0 != ulFifo) + { + I2C_Delay(2); + + if(++ulTimes > I2C_READ_TIMEOUT) + { + DEBUG ((EFI_D_ERROR, "I2C Write try to finished,time out!\n")); + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + return EFI_TIMEOUT; + } + ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); + } + (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port); + + return EFI_SUCCESS; +} + diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLib.inf b/Silicon/Hisilicon/Library/I2CLib/I2CLib.inf new file mode 100644 index 0000000000..7f9512467a --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CLib.inf @@ -0,0 +1,49 @@ +#/** @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 = I2CLib + FILE_GUID = FC5651CA-55D8-4fd2-B6D3-A284D993ABA2 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = I2CLib + +[Sources.common] + I2CLib.c + I2CLibCommon.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Silicon/Hisilicon/HisiPkg.dec + + +[LibraryClasses] + DebugLib + IoLib + BaseLib + ArmLib + TimerLib + + PlatformSysCtrlLib + +[BuildOptions] + +[Pcd] + diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c b/Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c new file mode 100644 index 0000000000..499c2d7a22 --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibCommon.c @@ -0,0 +1,35 @@ +/** @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 +#include +#include +#include + +#include +#include "I2CLibInternal.h" + +UINTN GetI2cBase (UINT32 Socket, UINT8 Port) +{ + return PlatformGetI2cBase(Socket, Port); +} + +EFI_STATUS +I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port) +{ + return EFI_SUCCESS; +} + + diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h b/Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h new file mode 100644 index 0000000000..14297296e9 --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibInternal.h @@ -0,0 +1,29 @@ +/** @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 _I2C_LIB_INTERNAL_H_ +#define _I2C_LIB_INTERNAL_H_ + +#include +#include + +UINTN GetI2cBase (UINT32 Socket, UINT8 Port); + +EFI_STATUS +I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port); + + +#endif + diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c new file mode 100644 index 0000000000..678b5a0082 --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c @@ -0,0 +1,109 @@ +/** @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 +#include +#include +#include +#include +#include +#include + +#include +#include "I2CLibInternal.h" + +STATIC EFI_EVENT mI2cLibVirtualAddrChangeEvent; + +STATIC UINTN gI2cBase[MAX_SOCKET][I2C_PORT_MAX]; + +UINTN GetI2cBase (UINT32 Socket, UINT8 Port) +{ + if (gI2cBase[Socket][Port] == 0) { + gI2cBase[Socket][Port] = PlatformGetI2cBase(Socket, Port); + } + + return gI2cBase[Socket][Port]; +} + +VOID +EFIAPI +I2cLibVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 Socket; + UINT8 Port; + + // We assume that all I2C ports used in one runtime driver need to be + // converted into virtual address. + for (Socket = 0; Socket < MAX_SOCKET; Socket++) { + for (Port = 0; Port < I2C_PORT_MAX; Port++) { + if (gI2cBase[Socket][Port] != 0) { + EfiConvertPointer (0x0, (VOID **)&gI2cBase[Socket][Port]); + } + } + } + + return; +} + +EFI_STATUS +I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port) +{ + EFI_STATUS Status; + + UINTN Base = GetI2cBase (Socket, Port); + + // Declare the controller as EFI_MEMORY_RUNTIME + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Base, SIZE_64KB, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "[%a:%d] AddMemorySpace failed: %r\n", __FUNCTION__, __LINE__, Status)); + } + + Status = gDS->SetMemorySpaceAttributes (Base, SIZE_64KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[%a:%d] SetMemorySpaceAttributes failed: %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + + // + // Register for the virtual address change event + // + // Only create event once + if (mI2cLibVirtualAddrChangeEvent == NULL) { + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + I2cLibVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mI2cLibVirtualAddrChangeEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[%a:%d] Create event failed: %r\n", __FUNCTION__, __LINE__, Status)); + return Status; + } + } + + return EFI_SUCCESS; +} + + diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf new file mode 100644 index 0000000000..4990072558 --- /dev/null +++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.inf @@ -0,0 +1,51 @@ +#/** @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 = I2CLibRuntime + FILE_GUID = FC5651CA-55D8-4fd2-B6D3-A284D993ABA2 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = I2CLib + +[Sources.common] + I2CLib.c + I2CLibRuntime.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Silicon/Hisilicon/HisiPkg.dec + + +[LibraryClasses] + DebugLib + IoLib + BaseLib + ArmLib + TimerLib + DxeServicesTableLib + UefiRuntimeLib + + PlatformSysCtrlLib + +[BuildOptions] + +[Pcd] + diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c new file mode 100644 index 0000000000..dc23e46c1f --- /dev/null +++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c @@ -0,0 +1,963 @@ +/** @file + Implementation for PlatformBdsLib library class interfaces. + + Copyright (C) 2015, Red Hat, Inc. + Copyright (c) 2014, ARM Ltd. All rights reserved.
+ Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
+ 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. + + Based on the files under ArmVirtPkg/Library/PlatformIntelBdsLib/ + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "IntelBdsPlatform.h" + +GUID gOemBootVaraibleGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99, + 0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8} }; + +//3CEF354A-3B7A-4519-AD70-72A134698311 +GUID gEblFileGuid = {0x3CEF354A, 0x3B7A, 0x4519, {0xAD, 0x70, + 0x72, 0xA1, 0x34, 0x69, 0x83, 0x11} }; + +// Need to keep the same with FlashStartOs.inf +// 282cae50-940e-11e5-b7b8-774201c0f2d8 +GUID gFlashStartOsAppGuid = { 0x282cae50, 0x940e, 0x11e5, {0xb7, 0xb8, + 0x77, 0x42, 0x01, 0xc0, 0xf2, 0xd8} }; + +// Need to keep the same with EslStartOs.inf +// 8880a72c-9411-11e5-b6f0-97310bc151d1 +GUID gEslStartOsAppGuid = { 0x8880a72c, 0x9411, 0x11e5, {0xb6, 0xf0, + 0x97, 0x31, 0x0b, 0xc1, 0x51, 0xd1} }; + +EFI_STATUS +BdsDeleteAllInvalidEfiBootOption ( + VOID + ); + +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } + + +#pragma pack (1) +typedef struct { + VENDOR_DEVICE_PATH SerialDxe; + UART_DEVICE_PATH Uart; + VENDOR_DEFINED_DEVICE_PATH Vt100; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_SERIAL_CONSOLE; +#pragma pack () + +#define SERIAL_DXE_FILE_GUID { \ + 0xD3987D4B, 0x971A, 0x435F, \ + { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \ + } + +STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { + // + // VENDOR_DEVICE_PATH SerialDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SERIAL_DXE_FILE_GUID + }, + + // + // UART_DEVICE_PATH Uart + // + { + { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, + 0, // Reserved + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits + FixedPcdGet8 (PcdUartDefaultParity), // Parity + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + }, + + // + // VENDOR_DEFINED_DEVICE_PATH Vt100 + // + { + { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, + DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) + }, + EFI_VT_100_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + + +#pragma pack (1) +typedef struct { + USB_CLASS_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_USB_KEYBOARD; +#pragma pack () + +STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { + // + // USB_CLASS_DEVICE_PATH Keyboard + // + { + { + MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, + DP_NODE_LEN (USB_CLASS_DEVICE_PATH) + }, + 0xFFFF, // VendorId: any + 0xFFFF, // ProductId: any + 3, // DeviceClass: HID + 1, // DeviceSubClass: boot + 1 // DeviceProtocol: keyboard + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC +UINT16 +GetBBSTypeFromFileSysPath ( + IN CHAR16 *UsbPathTxt, + IN CHAR16 *FileSysPathTxt, + IN EFI_DEVICE_PATH_PROTOCOL *FileSysPath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + + if (StrnCmp (UsbPathTxt, FileSysPathTxt, StrLen (UsbPathTxt)) == 0) { + Node = FileSysPath; + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (Node) == MEDIA_CDROM_DP)) { + return BBS_TYPE_CDROM; + } + Node = NextDevicePathNode (Node); + } + } + + return BBS_TYPE_UNKNOWN; +} + +STATIC +UINT16 +GetBBSTypeFromUsbPath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *UsbPath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *FileSystemHandles; + UINTN NumberFileSystemHandles; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *FileSysPath; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + CHAR16 *UsbPathTxt; + CHAR16 *FileSysPathTxt; + UINT16 Result; + + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevPathToText); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Locate DevicePathToTextPro %r\n", Status)); + return BBS_TYPE_UNKNOWN; + } + + Result = BBS_TYPE_UNKNOWN; + UsbPathTxt = DevPathToText->ConvertDevicePathToText (UsbPath, TRUE, TRUE); + if (UsbPathTxt == NULL) { + return Result; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberFileSystemHandles, + &FileSystemHandles + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Locate SimpleFileSystemProtocol error(%r)\n", Status)); + FreePool (UsbPathTxt); + return BBS_TYPE_UNKNOWN; + } + + for (Index = 0; Index < NumberFileSystemHandles; Index++) { + FileSysPath = DevicePathFromHandle (FileSystemHandles[Index]); + FileSysPathTxt = DevPathToText->ConvertDevicePathToText (FileSysPath, TRUE, TRUE); + + if (FileSysPathTxt == NULL) { + continue; + } + + Result = GetBBSTypeFromFileSysPath (UsbPathTxt, FileSysPathTxt, FileSysPath); + FreePool (FileSysPathTxt); + + if (Result != BBS_TYPE_UNKNOWN) { + break; + } + } + + if (NumberFileSystemHandles != 0) { + FreePool (FileSystemHandles); + } + + FreePool (UsbPathTxt); + + return Result; +} + +STATIC +UINT16 +GetBBSTypeFromMessagingDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *Node + ) +{ + VENDOR_DEVICE_PATH *Vendor; + UINT16 Result; + + Result = BBS_TYPE_UNKNOWN; + + switch (DevicePathSubType (Node)) { + case MSG_MAC_ADDR_DP: + Result = BBS_TYPE_EMBEDDED_NETWORK; + break; + + case MSG_USB_DP: + Result = GetBBSTypeFromUsbPath (DevicePath); + if (Result == BBS_TYPE_UNKNOWN) { + Result = BBS_TYPE_USB; + } + break; + + case MSG_SATA_DP: + Result = BBS_TYPE_HARDDRIVE; + break; + + case MSG_VENDOR_DP: + Vendor = (VENDOR_DEVICE_PATH *) (Node); + if ((&Vendor->Guid) != NULL) { + if (CompareGuid (&Vendor->Guid, &((EFI_GUID) DEVICE_PATH_MESSAGING_SAS))) { + Result = BBS_TYPE_HARDDRIVE; + } + } + break; + + default: + Result = BBS_TYPE_UNKNOWN; + break; + } + + return Result; +} + +STATIC +UINT16 +GetBBSTypeByDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + UINT16 Result; + + Result = BBS_TYPE_UNKNOWN; + if (DevicePath == NULL) { + return Result; + } + + Node = DevicePath; + while (!IsDevicePathEnd (Node)) { + switch (DevicePathType (Node)) { + case MEDIA_DEVICE_PATH: + if (DevicePathSubType (Node) == MEDIA_CDROM_DP) { + Result = BBS_TYPE_CDROM; + } + break; + + case MESSAGING_DEVICE_PATH: + Result = GetBBSTypeFromMessagingDevicePath (DevicePath, Node); + break; + + default: + Result = BBS_TYPE_UNKNOWN; + break; + } + + if (Result != BBS_TYPE_UNKNOWN) { + break; + } + + Node = NextDevicePathNode (Node); + } + + return Result; +} + +STATIC +EFI_STATUS +GetBmcBootOptionsSetting ( + OUT IPMI_GET_BOOT_OPTION *BmcBootOpt + ) +{ + EFI_STATUS Status; + + Status = IpmiCmdGetSysBootOptions (BmcBootOpt); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Get iBMC BootOpts %r!\n", Status)); + return Status; + } + + if (BmcBootOpt->BootFlagsValid != BOOT_OPTION_BOOT_FLAG_VALID) { + return EFI_NOT_FOUND; + } + + if (BmcBootOpt->Persistent) { + BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_VALID; + } else { + BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_INVALID; + } + + Status = IpmiCmdSetSysBootOptions (BmcBootOpt); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Set iBMC BootOpts %r!\n", Status)); + } + + return Status; +} + +STATIC +VOID +RestoreBootOrder ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 *BootOrder; + UINTN BootOrderSize; + + GetVariable2 (L"BootOrderBackup", &gOemBootVaraibleGuid, (VOID **) &BootOrder, &BootOrderSize); + if (BootOrder == NULL) { + return ; + } + + Print (L"Restore BootOrder(%d).\n", BootOrderSize / sizeof (UINT16)); + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SetVariable BootOrder %r!\n", Status)); + } + + Status = gRT->SetVariable ( + L"BootOrderBackup", + &gOemBootVaraibleGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status)); + } + + FreePool (BootOrder); + + return; +} + + +VOID +RestoreBootOrderOnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // restore BootOrder variable in normal condition. + RestoreBootOrder (); +} + +STATIC +VOID +UpdateBootOrder ( + IN UINT16 *NewOrder, + IN UINT16 *BootOrder, + IN UINTN BootOrderSize + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gRT->SetVariable ( + L"BootOrderBackup", + &gOemBootVaraibleGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (EFI_ERROR (Status)) { + return; + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + NewOrder + ); + if (EFI_ERROR (Status)) { + return; + } + + // Register notify function to restore BootOrder variable on ReadyToBoot Event. + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RestoreBootOrderOnReadyToBoot, + NULL, + &gEfiEventReadyToBootGuid, + &Event + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Create ready to boot event %r!\n", Status)); + } + + return; +} + +STATIC +VOID +SetBootOrder ( + IN UINT16 BootType + ) +{ + UINT16 *NewOrder; + UINT16 *RemainBoots; + UINT16 *BootOrder; + UINTN BootOrderSize; + CHAR16 OptionName[sizeof ("Boot####")]; + UINTN Index; + LIST_ENTRY BootOptionList; + BDS_COMMON_OPTION *Option; + UINTN SelectCnt; + UINTN RemainCnt; + + InitializeListHead (&BootOptionList); + + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); + if (BootOrder == NULL) { + return ; + } + + NewOrder = AllocatePool (BootOrderSize); + RemainBoots = AllocatePool (BootOrderSize); + if ((NewOrder == NULL) || (RemainBoots == NULL)) { + DEBUG ((DEBUG_ERROR, "Out of resources.")); + goto Exit; + } + + SelectCnt = 0; + RemainCnt = 0; + + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); + Option = BdsLibVariableToOption (&BootOptionList, OptionName); + if (Option == NULL) { + DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index])); + continue; + } + + if (GetBBSTypeByDevicePath (Option->DevicePath) == BootType) { + NewOrder[SelectCnt++] = BootOrder[Index]; + } else { + RemainBoots[RemainCnt++] = BootOrder[Index]; + } + } + + if (SelectCnt != 0) { + // append RemainBoots to NewOrder + for (Index = 0; Index < RemainCnt; Index++) { + NewOrder[SelectCnt + Index] = RemainBoots[Index]; + } + + if (CompareMem (NewOrder, BootOrder, BootOrderSize) != 0) { + UpdateBootOrder (NewOrder, BootOrder, BootOrderSize); + } + } + +Exit: + FreePool (BootOrder); + if (NewOrder != NULL) { + FreePool (NewOrder); + } + if (RemainBoots != NULL) { + FreePool (RemainBoots); + } + + return ; +} + +STATIC +VOID +HandleBmcBootType ( + VOID + ) +{ + EFI_STATUS Status; + IPMI_GET_BOOT_OPTION BmcBootOpt; + UINT16 BootType; + + Status = GetBmcBootOptionsSetting (&BmcBootOpt); + if (EFI_ERROR (Status)) { + return; + } + + Print (L"Boot Type from BMC is %x\n", BmcBootOpt.BootDeviceSelector); + + switch (BmcBootOpt.BootDeviceSelector) { + case ForcePxe: + BootType = BBS_TYPE_EMBEDDED_NETWORK; + break; + + case ForcePrimaryRemovableMedia: + BootType = BBS_TYPE_USB; + break; + + case ForceDefaultHardDisk: + BootType = BBS_TYPE_HARDDRIVE; + break; + + case ForceDefaultCD: + BootType = BBS_TYPE_CDROM; + break; + + default: + return; + } + + SetBootOrder (BootType); +} + +// +// BDS Platform Functions +// +/** + Platform Bds init. Include the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformBdsInit ( + VOID + ) +{ + //Signal EndofDxe Event + EfiEventGroupSignal(&gEfiEndOfDxeEventGroupGuid); + + // restore BootOrder variable if previous BMC boot override attempt + // left it in a modified state + RestoreBootOrder (); +} + + +/** + Check if the handle satisfies a particular condition. + + @param[in] Handle The handle to check. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. + + @retval TRUE The condition is satisfied. + @retval FALSE Otherwise. This includes the case when the condition could not + be fully evaluated due to an error. +**/ +typedef +BOOLEAN +(EFIAPI *FILTER_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + + +/** + Process a handle. + + @param[in] Handle The handle to process. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. +**/ +typedef +VOID +(EFIAPI *CALLBACK_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + Locate all handles that carry the specified protocol, filter them with a + callback function, and pass each handle that passes the filter to another + callback. + + @param[in] ProtocolGuid The protocol to look for. + + @param[in] Filter The filter function to pass each handle to. If this + parameter is NULL, then all handles are processed. + + @param[in] Process The callback function to pass each handle to that + clears the filter. +**/ +STATIC +VOID +FilterAndProcess ( + IN EFI_GUID *ProtocolGuid, + IN FILTER_FUNCTION Filter OPTIONAL, + IN CALLBACK_FUNCTION Process + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINTN Idx; + + Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, + NULL /* SearchKey */, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + // + // This is not an error, just an informative condition. + // + DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, + Status)); + return; + } + + ASSERT (NoHandles > 0); + for (Idx = 0; Idx < NoHandles; ++Idx) { + CHAR16 *DevicePathText; + STATIC CHAR16 Fallback[] = L""; + + // + // The ConvertDevicePathToText() function handles NULL input transparently. + // + DevicePathText = ConvertDevicePathToText ( + DevicePathFromHandle (Handles[Idx]), + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevicePathText == NULL) { + DevicePathText = Fallback; + } + + if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { + Process (Handles[Idx], DevicePathText); + } + + if (DevicePathText != Fallback) { + FreePool (DevicePathText); + } + } + gBS->FreePool (Handles); +} + + +/** + This FILTER_FUNCTION checks if a handle corresponds to a PCI display device. +**/ +STATIC +BOOLEAN +EFIAPI +IsPciDisplay ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid, + (VOID**)&PciIo); + if (EFI_ERROR (Status)) { + // + // This is not an error worth reporting. + // + return FALSE; + } + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */, + sizeof Pci / sizeof (UINT32), &Pci); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status)); + return FALSE; + } + + return IS_PCI_DISPLAY (&Pci); +} + + +/** + This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking + the matching driver to produce all first-level child handles. +**/ +STATIC +VOID +EFIAPI +Connect ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + + Status = gBS->ConnectController ( + Handle, // ControllerHandle + NULL, // DriverImageHandle + NULL, // RemainingDevicePath -- produce all children + FALSE // Recursive + ); + DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n", + __FUNCTION__, ReportText, Status)); +} + + +/** + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the + handle, and adds it to ConOut and ErrOut. +**/ +STATIC +VOID +EFIAPI +AddOutput ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + if (DevicePath == NULL) { + DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n", + __FUNCTION__, ReportText, Handle)); + return; + } + + Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, + ReportText)); +} + + +/** + The function will execute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specific + policy action. + + @param DriverOptionList The header of the driver option link list + @param BootOptionList The header of the boot option link list + @param ProcessCapsules A pointer to ProcessCapsules() + @param BaseMemoryTest A pointer to BaseMemoryTest() + +**/ +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + IN LIST_ENTRY *DriverOptionList, + IN LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +{ + EFI_STATUS Status; + // + // Locate the PCI root bridges and make the PCI bus driver connect each, + // non-recursively. This will produce a number of child handles with PciIo on + // them. + // + FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); + + // + // Find all display class PCI devices (using the handles from the previous + // step), and connect them non-recursively. This should produce a number of + // child handles with GOPs on them. + // + FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); + + // + // Now add the device path of all handles with GOP on them to ConOut and + // ErrOut. + // + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); + + // + // Add the hardcoded short-form USB keyboard device path to ConIn. + // + BdsLibUpdateConsoleVariable (L"ConIn", + (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); + + // + // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. + // + BdsLibUpdateConsoleVariable (L"ConIn", + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + BdsLibUpdateConsoleVariable (L"ConOut", + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + BdsLibUpdateConsoleVariable (L"ErrOut", + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + + // + // Connect the consoles based on the above variables. + // + BdsLibConnectAllDefaultConsoles (); + + // + // Show the splash screen. + // + EnableQuietBoot (PcdGetPtr (PcdLogoFile)); + + // + // Connect the rest of the devices. + // + BdsLibConnectAll (); + + // + // Add memory test to convert memory above 4GB to be tested + // + Status = BaseMemoryTest (QUICK); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[%a:%d] - Base memory test failed: %r\n", __FUNCTION__, __LINE__, Status)); + } + + // + // Process QEMU's -kernel command line option. Note that the kernel booted + // this way should receive ACPI tables, which is why we connect all devices + // first (see above) -- PCI enumeration blocks ACPI table installation, if + // there is a PCI host. + // + //TryRunningQemuKernel (); + + BdsLibEnumerateAllBootOption (BootOptionList); + + // Add Flash Start OS and ESL Start OS boot option + (VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gFlashStartOsAppGuid, L"Flash Start OS"); + (VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gEslStartOsAppGuid, L"ESL Start OS"); + + // Add EBL as boot option + (VOID) HwBdsLibRegisterAppBootOption (BootOptionList, &gEblFileGuid, L"Embedded Boot Loader (EBL)"); + + // Remove EFI Misc Device Boot Options + BdsDeleteAllInvalidEfiBootOption (); + + //SetBootOrderFromQemu (BootOptionList); + // + // The BootOrder variable may have changed, reload the in-memory list with + // it. + // + BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); + + //PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE); + Print (L"Press Enter to boot OS immediately.\n"); + Print (L"Press any other key in %d seconds to stop automatical booting...\n", PcdGet16(PcdPlatformBootTimeOut)); + PlatformBdsEnterFrontPage (PcdGet16(PcdPlatformBootTimeOut), TRUE); + HandleBmcBootType (); +} + +/** + Hook point after a boot attempt succeeds. We don't expect a boot option to + return, so the UEFI 2.0 specification defines that you will default to an + interactive mode and stop processing the BootOrder list in this case. This + is also a platform implementation and can be customized by IBV/OEM. + + @param Option Pointer to Boot Option that succeeded to boot. + +**/ +VOID +EFIAPI +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +{ +} + +/** + Hook point after a boot attempt fails. + + @param Option Pointer to Boot Option that failed to boot. + @param Status Status returned from failed boot. + @param ExitData Exit data returned from failed boot. + @param ExitDataSize Exit data size returned from failed boot. + +**/ +VOID +EFIAPI +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +{ +} + +/** + This function locks platform flash that is not allowed to be updated during normal boot path. + The flash layout is platform specific. +**/ +VOID +EFIAPI +PlatformBdsLockNonUpdatableFlash ( + VOID + ) +{ + return; +} diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h new file mode 100644 index 0000000000..4a912627a9 --- /dev/null +++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.h @@ -0,0 +1,61 @@ +/** @file + Head file for BDS Platform specific code + + Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
+ 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. + + Based on the files under ArmVirtPkg/Library/PlatformIntelBdsLib/ + +**/ + +#ifndef _INTEL_BDS_PLATFORM_H_ +#define _INTEL_BDS_PLATFORM_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "IntelBdsPlatformCommon.h" + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + +/** + Download the kernel, the initial ramdisk, and the kernel command line from + QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two + image files, and load and start the kernel from it. + + The kernel will be instructed via its command line to load the initrd from + the same Simple FileSystem. + + @retval EFI_NOT_FOUND Kernel image was not found. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_PROTOCOL_ERROR Unterminated kernel command line. + + @return Error codes from any of the underlying + functions. On success, the function doesn't + return. +**/ +EFI_STATUS +EFIAPI +TryRunningQemuKernel ( + VOID + ); + +#endif // _INTEL_BDS_PLATFORM_H diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c new file mode 100644 index 0000000000..9ea701db11 --- /dev/null +++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.c @@ -0,0 +1,118 @@ +/** @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 "IntelBdsPlatform.h" +#include +#include +#include + +VOID +EFIAPI +BdsLibBuildOptionFromApp ( + IN EFI_HANDLE Handle, + IN OUT LIST_ENTRY *BdsBootOptionList, + IN GUID *FileGuid, + IN CHAR16 *Description + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode; + + DevicePath = DevicePathFromHandle (Handle); + + // + // Build the shell device path + // + EfiInitializeFwVolDevicepathNode (&ShellNode, FileGuid); + + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode); + + // + // Create and register the shell boot option + // + BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, Description, L"BootOrder"); + +} +EFI_STATUS +EFIAPI +HwBdsLibRegisterAppBootOption ( + IN OUT LIST_ENTRY *BdsBootOptionList, + IN GUID *FileGuid, + IN CHAR16 *Description + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + EFI_FV_FILETYPE Type; + UINTN Size; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Count = 0; + + // + // Check if we have on flash shell + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + for (Index = 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if no shell file in the FV + // + continue; + } + // + // Build the shell boot option + // + BdsLibBuildOptionFromApp (FvHandleBuffer[Index], BdsBootOptionList, + FileGuid, Description); + + Count++; + } + + if (FvHandleCount != 0) { + FreePool (FvHandleBuffer); + } + + if (Count == 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h new file mode 100644 index 0000000000..73b901ab51 --- /dev/null +++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatformCommon.h @@ -0,0 +1,27 @@ +/** @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 _HW_BDS_LIB_H_ +#define _HW_BDS_LIB_H_ + +EFI_STATUS +EFIAPI +HwBdsLibRegisterAppBootOption ( + IN OUT LIST_ENTRY *BdsBootOptionList, + IN GUID *FileGuid, + IN CHAR16 *Description + ); + +#endif diff --git a/Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf new file mode 100644 index 0000000000..0feec06392 --- /dev/null +++ b/Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf @@ -0,0 +1,84 @@ +## @file +# Implementation for PlatformBdsLib library class interfaces. +# +# Copyright (C) 2015, Red Hat, Inc. +# Copyright (c) 2014, ARM Ltd. All rights reserved.
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# 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. +# +# Based on the files under ArmVirtPkg/Library/PlatformIntelBdsLib/ +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformIntelBdsLib + FILE_GUID = 46DF84EB-F603-4D39-99D8-E1E86B50BCC2 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + IntelBdsPlatform.c + IntelBdsPlatformCommon.c + +[Packages] + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + GenericBdsLib + IpmiCmdLib + MemoryAllocationLib + PcdLib + PrintLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiLib + +[FixedPcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + +[Guids] + gEfiEndOfDxeEventGroupGuid + gEfiEventReadyToBootGuid + gEfiFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiDevicePathToTextProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiPciRootBridgeIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid diff --git a/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c new file mode 100644 index 0000000000..1d93d7ebba --- /dev/null +++ b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.c @@ -0,0 +1,429 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ 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. + + Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +STATIC CONST CHAR16 mTimeZoneVariableName[] = L"PV660VirtualRtcTimeZone"; +STATIC CONST CHAR16 mDaylightVariableName[] = L"PV660VirtualRtcDaylight"; +STATIC EFI_EVENT mRtcVirtualAddrChangeEvent; +STATIC EFI_RUNTIME_SERVICES *mRT; + + +STATIC INTN mEpochDiff = 0; + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. +**/ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT64 Temp; + UINT32 EpochSeconds; + INT16 TimeZone = 0; + UINT8 Daylight = 0; + UINTN Size; + + // Ensure Time is a valid pointer + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + } + + ArmArchTimerReadReg(CntPct,&Temp); + + // UINT32 force convertion for PC-LINT + EpochSeconds = mEpochDiff + Temp / (UINT32) PcdGet32(PcdArmArchTimerFreqInHz); + + // Get the current time zone information from non-volatile storage + Size = sizeof (TimeZone); + Status = mRT->GetVariable ( + (CHAR16 *)mTimeZoneVariableName, + &gEfiCallerIdGuid, + NULL, + &Size, + (VOID *)&TimeZone + ); + + if (EFI_ERROR (Status)) { + ASSERT(Status != EFI_INVALID_PARAMETER); + ASSERT(Status != EFI_BUFFER_TOO_SMALL); + + if (Status != EFI_NOT_FOUND) + goto EXIT; + + // The time zone variable does not exist in non-volatile storage, so create it. + Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; + // Store it + Status = mRT->SetVariable ( + (CHAR16 *)mTimeZoneVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + (VOID *)&(Time->TimeZone) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_ERROR, + "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", + mTimeZoneVariableName, + Status + )); + goto EXIT; + } + } else { + // Got the time zone + Time->TimeZone = TimeZone; + + // Check TimeZone bounds: -1440 to 1440 or 2047 + if (((Time->TimeZone < -1440) || (Time->TimeZone > 1440)) + && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) { + Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; + } + + // Adjust for the correct time zone + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + EpochSeconds += Time->TimeZone * SEC_PER_MIN; + } + } + + // Get the current daylight information from non-volatile storage + Size = sizeof (Daylight); + Status = mRT->GetVariable ( + (CHAR16 *)mDaylightVariableName, + &gEfiCallerIdGuid, + NULL, + &Size, + (VOID *)&Daylight + ); + + if (EFI_ERROR (Status)) { + ASSERT(Status != EFI_INVALID_PARAMETER); + ASSERT(Status != EFI_BUFFER_TOO_SMALL); + + if (Status != EFI_NOT_FOUND) + goto EXIT; + + // The daylight variable does not exist in non-volatile storage, so create it. + Time->Daylight = 0; + // Store it + Status = mRT->SetVariable ( + (CHAR16 *)mDaylightVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + (VOID *)&(Time->Daylight) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_ERROR, + "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", + mDaylightVariableName, + Status + )); + goto EXIT; + } + } else { + // Got the daylight information + Time->Daylight = Daylight; + + // Adjust for the correct period + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { + // Convert to adjusted time, i.e. spring forwards one hour + EpochSeconds += SEC_PER_HOUR; + } + } + + // Convert from internal 32-bit time to UEFI time + EpochToEfiTime (EpochSeconds, Time); + + // Update the Capabilities info + if (Capabilities != NULL) { + Capabilities->Resolution = 1; + // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000 + + Capabilities->Accuracy = PcdGet32 (PcdArmArchTimerFreqInHz); + // FALSE: Setting the time does not clear the values below the resolution level + Capabilities->SetsToZero = FALSE; + } + + EXIT: + return Status; +} + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + EFI_STATUS Status; + UINTN EpochSeconds; + UINTN Temp; + + // Check the input parameters are within the range specified by UEFI + if (!IsTimeValid (Time)) { + Status = EFI_INVALID_PARAMETER; + goto EXIT; + } + + // Because the PL031 is a 32-bit counter counting seconds, + // the maximum time span is just over 136 years. + // Time is stored in Unix Epoch format, so it starts in 1970, + // Therefore it can not exceed the year 2106. + if ((Time->Year < 1970) || (Time->Year >= 2106)) { + Status = EFI_UNSUPPORTED; + goto EXIT; + } + + EpochSeconds = EfiTimeToEpoch (Time); + + // Adjust for the correct time zone, i.e. convert to UTC time zone + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + EpochSeconds -= Time->TimeZone * SEC_PER_MIN; + } + + // TODO: Automatic Daylight activation + + // Adjust for the correct period + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { + // Convert to un-adjusted time, i.e. fall back one hour + EpochSeconds -= SEC_PER_HOUR; + } + + ArmArchTimerReadReg(CntPct,&Temp); + + // UINT32 force convertion for PC-LINT + mEpochDiff = EpochSeconds - Temp / (UINT32) PcdGet32(PcdArmArchTimerFreqInHz); + + // The accesses to Variable Services can be very slow, because we may be writing to Flash. + // Do this after having set the RTC. + + // Save the current time zone information into non-volatile storage + Status = mRT->SetVariable ( + (CHAR16 *)mTimeZoneVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (Time->TimeZone), + (VOID *)&(Time->TimeZone) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_ERROR, + "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", + mTimeZoneVariableName, + Status + )); + goto EXIT; + } + + // Save the current daylight information into non-volatile storage + Status = mRT->SetVariable ( + (CHAR16 *)mDaylightVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(Time->Daylight), + (VOID *)&(Time->Daylight) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_ERROR, + "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", + mDaylightVariableName, + Status + )); + goto EXIT; + } + + EXIT: + return Status; +} + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Only needed if you are going to support the OS calling RTC functions in virtual mode. + // You will need to call EfiConvertPointer (). To convert any stored physical addresses + // to virtual address. After the OS transitions to calling in virtual mode, all future + // runtime calls will be made in virtual mode. + // + EfiConvertPointer (0x0, (VOID**)&mRT); + return; +} + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + // Setup the setters and getters + gRT->GetTime = LibGetTime; + gRT->SetTime = LibSetTime; + gRT->GetWakeupTime = LibGetWakeupTime; + gRT->SetWakeupTime = LibSetWakeupTime; + + mRT = gRT; + + // Install the protocol + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiRealTimeClockArchProtocolGuid, NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for the virtual address change event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + LibRtcVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mRtcVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf new file mode 100644 index 0000000000..35c01bff4f --- /dev/null +++ b/Silicon/Hisilicon/Library/VirtualRealTimeClockLib/RealTimeClockLib.inf @@ -0,0 +1,47 @@ +#/** @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 = RealTimeClockLibVirtual + FILE_GUID = 432B35C1-A0CC-4720-A4B9-1EFD70050107 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RealTimeClockLib + +[Sources.common] + RealTimeClockLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + OpenPlatformPkg/OpenPlatformPkg.dec + +[LibraryClasses] + IoLib + UefiLib + DebugLib + PcdLib + DxeServicesTableLib + TimeBaseLib + UefiRuntimeLib + ArmLib + +[Guids] + gEfiEventVirtualAddressChangeGuid + +[Pcd] + gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz -- cgit v1.2.3