[edk2,v8,edk-platforms,2/6] Platform/HiKey960: do basic initialization

Message ID 1527819672-23760-1-git-send-email-haojian.zhuang@linaro.org
State New
Headers show
Series
  • Untitled series #11858
Related show

Commit Message

Haojian Zhuang June 1, 2018, 2:21 a.m.
Do some basic initliazation on peripherals, such as pins and
regulators.

The hardcoding code is taken from non-open reference code.
Can't fix it for lack of documents.

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

---
 Silicon/Hisilicon/Hi3660/Hi3660.dec                     |  32 +++
 Platform/Hisilicon/HiKey960/HiKey960.dsc                |   2 +
 Platform/Hisilicon/HiKey960/HiKey960.fdf                |   2 +
 Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf |  47 +++++
 Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.h   |  23 +++
 Silicon/Hisilicon/Hi3660/Include/Hi3660.h               | 195 +++++++++++++++++++
 Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.c   | 204 ++++++++++++++++++++
 7 files changed, 505 insertions(+)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Leif Lindholm June 1, 2018, 4:43 p.m. | #1
Thanks.

Series:
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>


Pushed as ba32985a06..0923068a48.

On Fri, Jun 01, 2018 at 10:21:12AM +0800, Haojian Zhuang wrote:
> Do some basic initliazation on peripherals, such as pins and

> regulators.

> 

> The hardcoding code is taken from non-open reference code.

> Can't fix it for lack of documents.

> 

> Cc: Leif Lindholm <leif.lindholm@linaro.org>

> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> Contributed-under: TianoCore Contribution Agreement 1.1

> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

> ---

>  Silicon/Hisilicon/Hi3660/Hi3660.dec                     |  32 +++

>  Platform/Hisilicon/HiKey960/HiKey960.dsc                |   2 +

>  Platform/Hisilicon/HiKey960/HiKey960.fdf                |   2 +

>  Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf |  47 +++++

>  Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.h   |  23 +++

>  Silicon/Hisilicon/Hi3660/Include/Hi3660.h               | 195 +++++++++++++++++++

>  Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.c   | 204 ++++++++++++++++++++

>  7 files changed, 505 insertions(+)

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

diff --git a/Silicon/Hisilicon/Hi3660/Hi3660.dec b/Silicon/Hisilicon/Hi3660/Hi3660.dec
new file mode 100644
index 000000000000..72de61e0635c
--- /dev/null
+++ b/Silicon/Hisilicon/Hi3660/Hi3660.dec
@@ -0,0 +1,32 @@ 
+#
+#  Copyright (c) 2018, 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]
+  DEC_SPECIFICATION              = 0x0001001a
+  PACKAGE_NAME                   = Hi3660
+  PACKAGE_GUID                   = e457ba7c-faba-4dea-b274-f5962d016c79
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+  Include                        # Root include for the package
+
+[Guids.common]
+  gHi3660TokenSpaceGuid      =  { 0x4abc73fa, 0x8a49, 0x4d2c, { 0x95, 0x44, 0x17, 0x87, 0x29, 0x06, 0x20, 0xb4 } }
diff --git a/Platform/Hisilicon/HiKey960/HiKey960.dsc b/Platform/Hisilicon/HiKey960/HiKey960.dsc
index 3da1b8556321..6cc1c1edf453 100644
--- a/Platform/Hisilicon/HiKey960/HiKey960.dsc
+++ b/Platform/Hisilicon/HiKey960/HiKey960.dsc
@@ -182,6 +182,8 @@  [Components.common]
   Platform/Hisilicon/HiKey960/HiKey960GpioDxe/HiKey960GpioDxe.inf
   ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
 
+  Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf
+
   #
   # USB Host Support
   #
diff --git a/Platform/Hisilicon/HiKey960/HiKey960.fdf b/Platform/Hisilicon/HiKey960/HiKey960.fdf
index 162dbaaf2646..b7d70b010598 100644
--- a/Platform/Hisilicon/HiKey960/HiKey960.fdf
+++ b/Platform/Hisilicon/HiKey960/HiKey960.fdf
@@ -123,6 +123,8 @@  [FV.FvMain]
   INF Platform/Hisilicon/HiKey960/HiKey960GpioDxe/HiKey960GpioDxe.inf
   INF ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
 
+  INF Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf
+
   #
   # USB Host Support
   #
diff --git a/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf b/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf
new file mode 100644
index 000000000000..a1a7d005ce8b
--- /dev/null
+++ b/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.inf
@@ -0,0 +1,47 @@ 
+#
+#  Copyright (c) 2018, 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                    = 0x0001001a
+  BASE_NAME                      = HiKey960Dxe
+  FILE_GUID                      = 6d824b2c-640e-4643-b9f2-9c09e8bff429
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = HiKey960EntryPoint
+
+[Sources.common]
+  HiKey960Dxe.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Hisilicon/Hi3660/Hi3660.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  CacheMaintenanceLib
+  DxeServicesTableLib
+  IoLib
+  PcdLib
+  TimerLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Protocols]
+  gEmbeddedGpioProtocolGuid
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+
+[Depex]
+  TRUE
diff --git a/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.h b/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.h
new file mode 100644
index 000000000000..ae8bdd5c8140
--- /dev/null
+++ b/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.h
@@ -0,0 +1,23 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Linaro Ltd. 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 __HIKEY960DXE_H__
+#define __HIKEY960DXE_H__
+
+enum {
+  BOOT_MODE_RECOVERY  = 0,
+  BOOT_MODE_MASK = 1,
+};
+
+#endif /* __HIKEY960DXE_H__ */
diff --git a/Silicon/Hisilicon/Hi3660/Include/Hi3660.h b/Silicon/Hisilicon/Hi3660/Include/Hi3660.h
new file mode 100644
index 000000000000..5fbf32267657
--- /dev/null
+++ b/Silicon/Hisilicon/Hi3660/Include/Hi3660.h
@@ -0,0 +1,195 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Linaro Ltd. 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 __HI3660_H__
+#define __HI3660_H__
+
+#define HKADC_SSI_REG_BASE                      0xE82B8000
+
+#define PCTRL_REG_BASE                          0xE8A09000
+
+#define PCTRL_CTRL3                             (PCTRL_REG_BASE + 0x010)
+#define PCTRL_CTRL24                            (PCTRL_REG_BASE + 0x064)
+
+#define PCTRL_CTRL3_USB_TXCO_EN                 (1 << 1)
+#define PCTRL_CTRL24_USB3PHY_3MUX1_SEL          (1 << 25)
+
+#define SCTRL_REG_BASE                          0xFFF0A000
+
+#define SCTRL_SCFPLLCTRL0                       (SCTRL_REG_BASE + 0x120)
+#define SCTRL_SCFPLLCTRL0_FPLL0_EN              (1 << 0)
+
+#define SCTRL_BAK_DATA0                         (SCTRL_REG_BASE + 0x40C)
+
+#define USB3OTG_BC_REG_BASE                     0xFF200000
+
+#define USB3OTG_CTRL0                           (USB3OTG_BC_REG_BASE + 0x000)
+#define USB3OTG_CTRL2                           (USB3OTG_BC_REG_BASE + 0x008)
+#define USB3OTG_CTRL3                           (USB3OTG_BC_REG_BASE + 0x00C)
+#define USB3OTG_CTRL4                           (USB3OTG_BC_REG_BASE + 0x010)
+#define USB3OTG_CTRL6                           (USB3OTG_BC_REG_BASE + 0x018)
+#define USB3OTG_CTRL7                           (USB3OTG_BC_REG_BASE + 0x01C)
+#define USB3OTG_PHY_CR_STS                      (USB3OTG_BC_REG_BASE + 0x050)
+#define USB3OTG_PHY_CR_CTRL                     (USB3OTG_BC_REG_BASE + 0x054)
+
+#define USB3OTG_CTRL0_SC_USB3PHY_ABB_GT_EN      (1 << 15)
+#define USB3OTG_CTRL2_TEST_POWERDOWN_SSP        (1 << 1)
+#define USB3OTG_CTRL2_TEST_POWERDOWN_HSP        (1 << 0)
+#define USB3OTG_CTRL3_VBUSVLDEXT                (1 << 6)
+#define USB3OTG_CTRL3_VBUSVLDEXTSEL             (1 << 5)
+#define USB3OTG_CTRL7_REF_SSP_EN                (1 << 16)
+#define USB3OTG_PHY_CR_DATA_OUT(x)              (((x) & 0xFFFF) << 1)
+#define USB3OTG_PHY_CR_ACK                      (1 << 0)
+#define USB3OTG_PHY_CR_DATA_IN(x)               (((x) & 0xFFFF) << 4)
+#define USB3OTG_PHY_CR_WRITE                    (1 << 3)
+#define USB3OTG_PHY_CR_READ                     (1 << 2)
+#define USB3OTG_PHY_CR_CAP_DATA                 (1 << 1)
+#define USB3OTG_PHY_CR_CAP_ADDR                 (1 << 0)
+
+#define PMU_REG_BASE                            0xFFF34000
+#define PMIC_LDO9_VSET_REG                      (PMU_REG_BASE + (0x068 << 2))
+#define LDO9_VSET_MASK                          (7 << 0)
+
+#define PMIC_LDO16_ONOFF_ECO_REG                (PMU_REG_BASE + (0x078 << 2))
+#define LDO16_ONOFF_ECO_LDO16_ENABLE            BIT1
+#define LDO16_ONOFF_ECO_ECO_ENABLE              BIT0
+
+#define PMIC_LDO16_VSET_REG                     (PMU_REG_BASE + (0x079 << 2))
+#define LDO16_VSET_MASK                         (7 << 0)
+
+#define PMIC_HARDWARE_CTRL0                     (PMU_REG_BASE + (0x0C5 << 2))
+#define PMIC_OSC32K_ONOFF_CTRL                  (PMU_REG_BASE + (0x0CC << 2))
+
+#define PMIC_HARDWARE_CTRL0_WIFI_CLK            (1 << 5)
+#define PMIC_OSC32K_ONOFF_CTRL_EN_32K           (1 << 1)
+
+
+#define CRG_REG_BASE                            0xFFF35000
+
+#define CRG_PEREN0                              (CRG_REG_BASE + 0x000)
+#define CRG_PEREN2                              (CRG_REG_BASE + 0x020)
+#define CRG_PERDIS2                             (CRG_REG_BASE + 0x024)
+#define CRG_PERCLKEN2                           (CRG_REG_BASE + 0x028)
+#define CRG_PERSTAT2                            (CRG_REG_BASE + 0x02C)
+#define CRG_PEREN4                              (CRG_REG_BASE + 0x040)
+#define CRG_PERDIS4                             (CRG_REG_BASE + 0x044)
+#define CRG_PERCLKEN4                           (CRG_REG_BASE + 0x048)
+#define CRG_PERSTAT4                            (CRG_REG_BASE + 0x04C)
+#define CRG_PERRSTEN2                           (CRG_REG_BASE + 0x078)
+#define CRG_PERRSTDIS2                          (CRG_REG_BASE + 0x07C)
+#define CRG_PERRSTSTAT2                         (CRG_REG_BASE + 0x080)
+#define CRG_PERRSTEN3                           (CRG_REG_BASE + 0x084)
+#define CRG_PERRSTDIS3                          (CRG_REG_BASE + 0x088)
+#define CRG_PERRSTSTAT3                         (CRG_REG_BASE + 0x08C)
+#define CRG_PERRSTEN4                           (CRG_REG_BASE + 0x090)
+#define CRG_PERRSTDIS4                          (CRG_REG_BASE + 0x094)
+#define CRG_PERRSTSTAT4                         (CRG_REG_BASE + 0x098)
+#define CRG_CLKDIV4                             (CRG_REG_BASE + 0x0B8)
+#define CRG_ISOEN                               (CRG_REG_BASE + 0x144)
+#define CRG_ISODIS                              (CRG_REG_BASE + 0x148)
+#define CRG_ISOSTAT                             (CRG_REG_BASE + 0x14C)
+
+#define PERI_UFS_BIT                            (1 << 12)
+#define PERI_ARST_UFS_BIT                       (1 << 7)
+
+#define PEREN0_GT_HCLK_SD                       BIT30
+
+#define PEREN2_HKADCSSI                         BIT24
+
+#define PEREN4_GT_CLK_SD                        BIT17
+#define PEREN4_GT_ACLK_USB3OTG                  (1 << 1)
+#define PEREN4_GT_CLK_USB3OTG_REF               (1 << 0)
+
+#define PERRSTEN2_HKADCSSI                      BIT24
+
+#define PERRSTEN4_SD                            BIT18
+
+#define PERRSTEN4_USB3OTG_MUX                   (1 << 8)
+#define PERRSTEN4_USB3OTG_AHBIF                 (1 << 7)
+#define PERRSTEN4_USB3OTG_32K                   (1 << 6)
+#define PERRSTEN4_USB3OTG                       (1 << 5)
+#define PERRSTEN4_USB3OTGPHY_POR                (1 << 3)
+
+#define PERISOEN_USB_REFCLK_ISO_EN              (1 << 25)
+
+#define CLKDIV4_SC_SEL_SD_MASK                  (7 << 4)
+#define CLKDIV4_SC_DIV_SD_MASK                  0xf
+#define CLKDIV4_SC_MASK_SHIFT                   16
+#define CLKDIV4_SC_SEL_SD(x)                    (((x) & 0x7) << 4)
+#define CLKDIV4_SC_DIV_SD(x)                    ((x) & 0xf)
+
+#define CRG_CLKDIV16_OFFSET                     0x0E8
+#define SC_DIV_UFSPHY_CFG_MASK                  (0x3 << 9)
+#define SC_DIV_UFSPHY_CFG(x)                    (((x) & 0x3) << 9)
+
+#define CRG_CLKDIV17_OFFSET                     0x0EC
+#define SC_DIV_UFS_PERIBUS                      (1 << 14)
+
+#define IOMG_MMC0_REG_BASE                      0xFF37E000
+#define IOMG_MMC0_000_REG                       (IOMG_MMC0_REG_BASE + 0x000)
+#define IOMG_MMC0_001_REG                       (IOMG_MMC0_REG_BASE + 0x004)
+#define IOMG_MMC0_002_REG                       (IOMG_MMC0_REG_BASE + 0x008)
+#define IOMG_MMC0_003_REG                       (IOMG_MMC0_REG_BASE + 0x00C)
+#define IOMG_MMC0_004_REG                       (IOMG_MMC0_REG_BASE + 0x010)
+#define IOMG_MMC0_005_REG                       (IOMG_MMC0_REG_BASE + 0x014)
+
+#define IOCG_MMC0_REG_BASE                      0xFF37E800
+#define IOCG_MMC0_000_REG                       (IOCG_MMC0_REG_BASE + 0x000)
+#define IOCG_MMC0_001_REG                       (IOCG_MMC0_REG_BASE + 0x004)
+#define IOCG_MMC0_002_REG                       (IOCG_MMC0_REG_BASE + 0x008)
+#define IOCG_MMC0_003_REG                       (IOCG_MMC0_REG_BASE + 0x00C)
+#define IOCG_MMC0_004_REG                       (IOCG_MMC0_REG_BASE + 0x010)
+#define IOCG_MMC0_005_REG                       (IOCG_MMC0_REG_BASE + 0x014)
+
+#define IOMG_AO_REG_BASE                        0xFFF11000
+#define IOMG_AO_006_REG                         (IOMG_AO_REG_BASE + 0x018)
+
+#define IOMG_FUNC0                              0
+#define IOMG_FUNC1                              1
+#define IOCG_PULLUP                             BIT0
+#define IOCG_PULLDOWN                           BIT1
+#define IOCG_DRIVE(x)                           ((x) << 4)
+
+#define UFS_SYS_REG_BASE                        0xFF3B1000
+
+#define UFS_SYS_PSW_POWER_CTRL_OFFSET           0x004
+#define UFS_SYS_PHY_ISO_EN_OFFSET               0x008
+#define UFS_SYS_HC_LP_CTRL_OFFSET               0x00C
+#define UFS_SYS_PHY_CLK_CTRL_OFFSET             0x010
+#define UFS_SYS_PSW_CLK_CTRL_OFFSET             0x014
+#define UFS_SYS_CLOCK_GATE_BYPASS_OFFSET        0x018
+#define UFS_SYS_RESET_CTRL_EN_OFFSET            0x01C
+#define UFS_SYS_MONITOR_HH_OFFSET               0x03C
+#define UFS_SYS_UFS_SYSCTRL_OFFSET              0x05C
+#define UFS_SYS_UFS_DEVICE_RESET_CTRL_OFFSET    0x060
+#define UFS_SYS_UFS_APB_ADDR_MASK_OFFSET        0x064
+
+#define BIT_UFS_PSW_ISO_CTRL                    (1 << 16)
+#define BIT_UFS_PSW_MTCMOS_EN                   (1 << 0)
+#define BIT_UFS_REFCLK_ISO_EN                   (1 << 16)
+#define BIT_UFS_PHY_ISO_CTRL                    (1 << 0)
+#define BIT_SYSCTRL_LP_ISOL_EN                  (1 << 16)
+#define BIT_SYSCTRL_PWR_READY                   (1 << 8)
+#define BIT_SYSCTRL_REF_CLOCK_EN                (1 << 24)
+#define MASK_SYSCTRL_REF_CLOCK_SEL              (3 << 8)
+#define MASK_SYSCTRL_CFG_CLOCK_FREQ             (0xFF)
+#define BIT_SYSCTRL_PSW_CLK_EN                  (1 << 4)
+#define MASK_UFS_CLK_GATE_BYPASS                (0x3F)
+#define BIT_SYSCTRL_LP_RESET_N                  (1 << 0)
+#define BIT_UFS_REFCLK_SRC_SE1                  (1 << 0)
+#define MASK_UFS_SYSCTRL_BYPASS                 (0x3F << 16)
+#define MASK_UFS_DEVICE_RESET                   (1 << 16)
+#define BIT_UFS_DEVICE_RESET                    (1 << 0)
+
+#endif /* __HI3660_H__ */
diff --git a/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.c b/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.c
new file mode 100644
index 000000000000..43c041aefa43
--- /dev/null
+++ b/Platform/Hisilicon/HiKey960/HiKey960Dxe/HiKey960Dxe.c
@@ -0,0 +1,204 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Linaro Ltd. 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 <Guid/EventGroup.h>
+
+#include <Hi3660.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "HiKey960Dxe.h"
+
+STATIC
+VOID
+InitSdCard (
+  IN VOID
+  )
+{
+  UINT32        Data;
+
+  //
+  // LDO16
+  // 000: 1.75V, 001: 1.8V, 010: 2.4V, 011: 2.6V, 100: 2.7V,
+  // 101: 2.85V, 110: 2.95V, 111: 3.0V.
+  //
+  Data = MmioRead32 (PMIC_LDO16_VSET_REG) & LDO16_VSET_MASK;
+  Data |= 6;
+  MmioWrite32 (PMIC_LDO16_VSET_REG, Data);
+  MmioOr32 (PMIC_LDO16_ONOFF_ECO_REG, LDO16_ONOFF_ECO_LDO16_ENABLE);
+  //
+  // wait regulator stable
+  //
+  MicroSecondDelay (100);
+
+  //
+  // LDO9
+  // 000: 1.75V, 001: 1.8V, 010: 1.825V, 011: 2.8V, 100: 2.85V,
+  // 101: 2.95V, 110: 3.0V, 111: 3.3V.
+  //
+  Data = MmioRead32 (PMIC_LDO9_VSET_REG) & LDO9_VSET_MASK;
+  Data |= 5;
+  MmioWrite32 (PMIC_LDO9_VSET_REG, Data);
+  MmioOr32 (PMU_REG_BASE + (0x6a << 2), 2);
+  //
+  // wait regulator stable
+  //
+  MicroSecondDelay (100);
+
+  //
+  // GPIO203
+  //
+  MmioWrite32 (IOMG_AO_REG_BASE + (24 << 2), 0); // GPIO function
+
+  //
+  // SD pinmux
+  //
+  MmioWrite32 (IOMG_MMC0_000_REG, IOMG_FUNC1); // SD_CLK
+  MmioWrite32 (IOMG_MMC0_001_REG, IOMG_FUNC1); // SD_CMD
+  MmioWrite32 (IOMG_MMC0_002_REG, IOMG_FUNC1); // SD_DATA0
+  MmioWrite32 (IOMG_MMC0_003_REG, IOMG_FUNC1); // SD_DATA1
+  MmioWrite32 (IOMG_MMC0_004_REG, IOMG_FUNC1); // SD_DATA2
+  MmioWrite32 (IOMG_MMC0_005_REG, IOMG_FUNC1); // SD_DATA3
+  MmioWrite32 (IOCG_MMC0_000_REG, IOCG_DRIVE (15)); // SD_CLK float with 32mA
+  MmioWrite32 (IOCG_MMC0_001_REG, IOCG_PULLUP | IOCG_DRIVE (8)); // SD_CMD
+  MmioWrite32 (IOCG_MMC0_002_REG, IOCG_PULLUP | IOCG_DRIVE (8)); // SD_DATA0
+  MmioWrite32 (IOCG_MMC0_003_REG, IOCG_PULLUP | IOCG_DRIVE (8)); // SD_DATA1
+  MmioWrite32 (IOCG_MMC0_004_REG, IOCG_PULLUP | IOCG_DRIVE (8)); // SD_DATA2
+  MmioWrite32 (IOCG_MMC0_005_REG, IOCG_PULLUP | IOCG_DRIVE (8)); // SD_DATA3
+
+  //
+  // SC_SEL_SD:
+  //   0xx: 3.2MHz, 100: PPLL0, 101: PPLL1, 11x: PPLL2.
+  // SC_DIV_SD:
+  //   divider = value + 1
+  //
+  do {
+    MmioOr32 (
+      CRG_CLKDIV4,
+      CLKDIV4_SC_SEL_SD (7) |
+      (CLKDIV4_SC_SEL_SD_MASK << CLKDIV4_SC_MASK_SHIFT)
+      );
+    Data = MmioRead32 (CRG_CLKDIV4) & CLKDIV4_SC_SEL_SD_MASK;
+  } while (Data != CLKDIV4_SC_SEL_SD (7));
+
+  //
+  // Unreset SD controller
+  //
+  MmioWrite32 (CRG_PERRSTDIS4, PERRSTEN4_SD);
+  do {
+    Data = MmioRead32 (CRG_PERRSTSTAT4);
+  } while ((Data & PERRSTEN4_SD) == PERRSTEN4_SD);
+  //
+  // Enable SD controller clock
+  //
+  MmioOr32 (CRG_PEREN0, PEREN0_GT_HCLK_SD);
+  MmioOr32 (CRG_PEREN4, PEREN4_GT_CLK_SD);
+  do {
+    Data = MmioRead32 (CRG_PERCLKEN4);
+  } while ((Data & PEREN4_GT_CLK_SD) != PEREN4_GT_CLK_SD);
+}
+
+VOID
+InitPeripherals (
+  IN VOID
+  )
+{
+  //
+  // Enable FPLL0
+  //
+  MmioOr32 (SCTRL_SCFPLLCTRL0, SCTRL_SCFPLLCTRL0_FPLL0_EN);
+
+  InitSdCard ();
+
+  //
+  // Enable wifi clock
+  //
+  MmioOr32 (PMIC_HARDWARE_CTRL0, PMIC_HARDWARE_CTRL0_WIFI_CLK);
+  MmioOr32 (PMIC_OSC32K_ONOFF_CTRL, PMIC_OSC32K_ONOFF_CTRL_EN_32K);
+}
+
+/**
+  Notification function of the event defined as belonging to the
+  EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in
+  the entry point of the driver.
+
+  This function is called when an event belonging to the
+  EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an
+  event is signalled once at the end of the dispatching of all
+  drivers (end of the so called DXE phase).
+
+  @param[in]  Event    Event declared in the entry point of the driver whose
+                       notification function is being invoked.
+  @param[in]  Context  NULL
+**/
+STATIC
+VOID
+OnEndOfDxe (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  UINT32        BootMode;
+  VOID          *RecoveryStr;
+  VOID          *SwitchStr;
+
+  BootMode = MmioRead32 (SCTRL_BAK_DATA0) & BOOT_MODE_MASK;
+  if (BootMode == BOOT_MODE_RECOVERY) {
+    RecoveryStr = "WARNING: CAN NOT BOOT KERNEL IN RECOVERY MODE!\r\n";
+    SwitchStr = "Switch to normal boot mode, then reboot to boot kernel.\r\n";
+    SerialPortWrite (RecoveryStr, AsciiStrLen (RecoveryStr));
+    SerialPortWrite (SwitchStr, AsciiStrLen (SwitchStr));
+  }
+}
+
+EFI_STATUS
+EFIAPI
+HiKey960EntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS            Status;
+  EFI_EVENT             EndOfDxeEvent;
+
+  InitPeripherals ();
+
+  //
+  // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.
+  // The "OnEndOfDxe()" function is declared as the call back function.
+  // It will be called at the end of the DXE phase when an event of the
+  // same group is signalled to inform about the end of the DXE phase.
+  // Install the INSTALL_FDT_PROTOCOL protocol.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  OnEndOfDxe,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  return Status;
+}