diff options
Diffstat (limited to 'SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib')
11 files changed, 2516 insertions, 0 deletions
diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/Board.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/Board.c new file mode 100644 index 000000000..364101071 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/Board.c @@ -0,0 +1,226 @@ +/** @file +* +* Copyright (c) 2012, Samsung Electronics Co. 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 <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> + +#include <Ppi/ArmMpCoreInfo.h> +#include <Drivers/PL341Dmc.h> +#include <Platform/ArmPlatform.h> + +/** + Return if Trustzone is supported by your platform + + A non-zero value must be returned if you want to support a Secure World on your platform. + ArmPlatformSecTrustzoneInit() will later set up the secure regions. + This function can return 0 even if Trustzone is supported by your processor. In this case, + the platform will continue to run in Secure World. + + @return A non-zero value if Trustzone supported. + +**/ +UINTN ArmPlatformTrustzoneSupported(VOID) { + // There is no Trustzone controllers (TZPC & TZASC) and no Secure Memory on RTSM + return TRUE; +} + +/** + Initialize the Secure peripherals and memory regions + + If Trustzone is supported by your platform then this function makes the required initialization + of the secure peripherals and memory regions. + +**/ +VOID ArmPlatformSecTrustzoneInit( + IN UINTN MpId +) +{ + UINT32 TZPCBase; + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC0_OFFSET; + MmioWrite32((TZPCBase + 0x00),0x00); + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC1_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC2_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC3_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC4_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC5_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC6_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC7_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC8_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC9_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + +} + +/** + Remap the memory at 0x0 + + Some platform requires or gives the ability to remap the memory at the address 0x0. + This function can do nothing if this feature is not relevant to your platform. + +**/ +VOID ArmPlatformBootRemapping(VOID) { + // Disable memory remapping and return to normal mapping + MmioOr32 (ARM_EB_SYSCTRL, BIT8); //EB_SP810_CTRL_BASE +} + + +/** + 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. + +**/ +VOID +ArmPlatformNormalInitialize ( + VOID + ) +{ + // Nothing to do here +} + +/** + Initialize controllers that must setup in the normal world + + This function is called by the ArmPlatformPkg/PrePi or ArmPlatformPkg/PlatformPei + 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) { + // We do not need to initialize the System Memory on RTSM +} + +EFI_STATUS +PrePeiCoreGetMpCoreInfo ( + OUT UINTN *CoreCount, + OUT ARM_CORE_INFO **ArmCoreTable + ) +{ +#if 0 + UINT32 ProcType; + + ProcType = MmioRead32 (ARM_VE_SYS_PROCID0_REG) & ARM_VE_SYS_PROC_ID_MASK; + if ((ProcType == ARM_VE_SYS_PROC_ID_CORTEX_A9) || (ProcType == ARM_VE_SYS_PROC_ID_CORTEX_A15)) { + // Only support one cluster + *CoreCount = ArmGetCpuCountPerCluster (); + *ArmCoreTable = mVersatileExpressMpCoreInfoTable; + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +#endif + 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/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.S b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.S new file mode 100755 index 000000000..e47146e47 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.S @@ -0,0 +1,468 @@ +/* + * (C) Copyright 2012 Samsung Electronics Co. Ltd + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <Platform/ArmPlatform.h> +#include <Platform/Arndale5250.h> +#include <Platform/Exynos5250_Evt1.h> +#include <Platform/Arndale5250_Val.h> +#include <AutoGen.h> + +GCC_ASM_EXPORT(ArmPlatformClockInitialize) +GCC_ASM_EXPORT(ArmPlatformTZPCInitialize) +GCC_ASM_EXPORT(ArmPlatformSecBootAction) + +wait_pll_lock: + ldr r1, [r0, r2] + tst r1, #(1<<29) + beq wait_pll_lock + mov pc, lr + +wait_mux_state: + add r2, r2, #0x200 + +check_mux_state: + ldr r1, [r0, r2] + orr r4, r1, r3 + cmp r1, r4 + bne check_mux_state + mov pc, lr + +wait_div_state: + add r2, r2, #0x100 + +check_div_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_div_state + mov pc, lr + +ASM_PFX(ArmPlatformClockInitialize): + + @push {lr} + mov r12, lr + + ldr r0, =Exynos5250_CMU_BASE @0x1001_0000 + +@ CMU_CPU MUX / DIV + ldr r2, =CLK_SRC_CPU_OFFSET + ldr r3, =0x00000001 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x00000001 + bl wait_mux_state + + ldr r2, =CLK_SRC_CORE1_OFFSET + ldr r3, =0x100 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x00000100 + bl wait_mux_state + + ldr r2, =CLK_SRC_TOP2_OFFSET + ldr r3, =0x10011100 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x10011100 + bl wait_mux_state + + ldr r2, =CLK_SRC_CDREX_OFFSET + ldr r3, =0x1 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x00000001 + bl wait_mux_state + +@ Set PLL locktime + ldr r1, =APLL_LOCK_VAL + ldr r2, =APLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =MPLL_LOCK_VAL + ldr r2, =MPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =BPLL_LOCK_VAL + ldr r2, =BPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =CPLL_LOCK_VAL + ldr r2, =CPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =GPLL_LOCK_VAL + ldr r2, =GPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =EPLL_LOCK_VAL + ldr r2, =EPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =VPLL_LOCK_VAL + ldr r2, =VPLL_LOCK_OFFSET + str r1, [r0, r2] + +@ Set BPLL, MPLL Fixed Divider 2 + ldr r1, =0x00 + ldr r2, =PLL_DIV2_SEL_OFFSET + str r1, [r0, r2] + +@ ARM_CLK + ldr r2, =CLK_SRC_CPU_OFFSET + ldr r3, =0x00100000 + str r3, [r0, r2] + ldr r3, =0x00200000 + bl wait_mux_state + + ldr r1, =CLK_DIV_CPU0_VAL @0x01147720 + ldr r2, =CLK_DIV_CPU0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_CPU1_VAL @0x20 + ldr r2, =CLK_DIV_CPU1_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ Set APLL + ldr r1, =APLL_CON1_VAL + ldr r2, =APLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =APLL_CON0_VAL + ldr r2, =APLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set MPLL @800Mhz + ldr r1, =MPLL_CON1_VAL + ldr r2, =MPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =MPLL_CON0_VAL + ldr r2, =MPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set BPLL @800Mhz + ldr r1, =BPLL_CON1_VAL + ldr r2, =BPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =BPLL_CON0_VAL + ldr r2, =BPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set CPLL @333Mhz + ldr r1, =CPLL_CON1_VAL + ldr r2, =CPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =CPLL_CON0_VAL + ldr r2, =CPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set GPLL @533Mhz + ldr r1, =GPLL_CON1_VAL + ldr r2, =GPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =GPLL_CON0_VAL + ldr r2, =GPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set EPLL @96Mhz + ldr r1, =EPLL_CON2_VAL + ldr r2, =EPLL_CON2_OFFSET + str r1, [r0, r2] + ldr r1, =EPLL_CON1_VAL + ldr r2, =EPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =EPLL_CON0_VAL + ldr r2, =EPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set VPLL @300Mhz + ldr r1, =VPLL_CON2_VAL + ldr r2, =VPLL_CON2_OFFSET + str r1, [r0, r2] + ldr r1, =VPLL_CON1_VAL + ldr r2, =VPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =VPLL_CON0_VAL + ldr r2, =VPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ CMU_CORE MUX / DIV + ldr r2, =CLK_SRC_CORE0_OFFSET + ldr r3, =CLK_SRC_CORE0_VAL + str r3, [r0, r2] + + ldr r1, =CLK_DIV_CORE0_VAL + ldr r2, =CLK_DIV_CORE0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_CORE1_VAL + ldr r2, =CLK_DIV_CORE1_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_SYSRGT_VAL + ldr r2, =CLK_DIV_SYSRGT_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_ACP DIV + ldr r1, =CLK_DIV_ACP_VAL + ldr r2, =CLK_DIV_ACP_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_SYSLFT_VAL + ldr r2, =CLK_DIV_SYSLFT_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + ldr r2, =CLK_DIV_STAT_SYSLFT_OFFSET +check_div_syslft_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_div_syslft_state + +@ CMU_TOP SRC + ldr r2, =CLK_SRC_TOP0_OFFSET + ldr r3, =CLK_SRC_TOP0_VAL + str r3, [r0, r2] + + ldr r2, =CLK_SRC_TOP1_OFFSET + ldr r3, =CLK_SRC_TOP1_VAL + str r3, [r0, r2] + + ldr r2, =CLK_SRC_TOP2_OFFSET + ldr r3, =0x01100000 + str r3, [r0, r2] + + ldr r2, =CLK_SRC_TOP3_OFFSET + ldr r3, =CLK_SRC_TOP3_VAL + ldr r1, [r0, r2] + str r3, [r0, r2] + +@ CMU_TOP MUX / DIV + ldr r1, =CLK_DIV_TOP0_VAL + ldr r2, =CLK_DIV_TOP0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_TOP1_VAL + ldr r2, =CLK_DIV_TOP1_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_LEX SRC / DIV + ldr r2, =CLK_SRC_LEX_OFFSET + ldr r3, =CLK_SRC_LEX_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x1 + bl wait_mux_state + + ldr r1, =CLK_DIV_LEX_VAL + ldr r2, =CLK_DIV_LEX_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_R0X DIV + ldr r1, =CLK_DIV_R0X_VAL + ldr r2, =CLK_DIV_R0X_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_R1X DIV + ldr r1, =CLK_DIV_R1X_VAL + ldr r2, =CLK_DIV_R1X_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_CDREX MUX / DIV + ldr r2, =CLK_SRC_CDREX_OFFSET + ldr r3, =0x0 + str r3, [r0, r2] + + ldr r1, =0x71720071 + ldr r2, =CLK_DIV_CDREX_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@CMU_CPU SRC + ldr r2, =CLK_SRC_CPU_OFFSET + ldr r3, =CLK_SRC_CPU_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + + ldr r2, =CLK_SRC_TOP2_OFFSET + ldr r3, =CLK_SRC_TOP2_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + + ldr r2, =CLK_SRC_CORE1_OFFSET + ldr r3, =CLK_SRC_CORE1_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + + ldr r1, =0x66666 + ldr r2, =CLK_SRC_FSYS_OFFSET + str r1, [r0, r2] + + ldr r1, =0x0BB00000 + ldr r2, =CLK_DIV_FSYS0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@disable CLKOUT_CMU + ldr r1, =0x0 + ldr r2, =CLKOUT_CMU_CPU_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_CORE_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_ACP_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_TOP_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_LEX_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_R0X_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_R1X_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_CDREX_OFFSET + str r1, [r0, r2] + + ldr r0, =ELFIN_POWER_BASE +@power down FSYS_ARM + ldr r1, =0x0 + ldr r2, =FSYS_ARM_CONFIGURATION_OFFSET + str r1, [r0, r2] + +@disable SATA_PHY_CONTROL + ldr r1, =0x0 + ldr r2, =SATA_PHY_CONTROL_OFFSET + str r1, [r0, r2] + + @pop {lr} + mov lr, r12 + + bx lr + +ASM_PFX(ArmPlatformTZPCInitialize): + ldr r0, =Exynos5250_TZPC0_BASE + mov r1, #0x0 + str r1, [r0] + mov r1, #0xff + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC1_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC2_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC3_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC4_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC5_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC6_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC7_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC8_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC9_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + + bx lr + +/** + Call at the beginning of the platform boot up + + This function allows the firmware platform to do extra actions at the early + stage of the platform power up. + + Note: This function must be implemented in assembler as there is no stack set up yet + +**/ +ASM_PFX(ArmPlatformSecBootAction): + bx lr + + diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.asm b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.asm new file mode 100644 index 000000000..056a3e7e9 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.asm @@ -0,0 +1,52 @@ +// +// Copyright (c) 2011, ARM 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 <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/ArmPlatformLib.h> +#include <AutoGen.h> +#include <ArmPlatform.h> + + INCLUDE AsmMacroIoLib.inc + + EXPORT ArmPlatformSecBootAction + EXPORT ArmPlatformInitializeBootMemory + + PRESERVE8 + AREA RTSMVExpressBootMode, CODE, READONLY + +/** + Call at the beginning of the platform boot up + + This function allows the firmware platform to do extra actions at the early + stage of the platform power up. + + Note: This function must be implemented in assembler as there is no stack set up yet + +**/ +ArmPlatformSecBootAction + bx lr + +/** + Initialize the memory where the initial stacks will reside + + This memory can contain the initial stacks (Secure and Secure Monitor stacks). + In some platform, this region is already initialized and the implementation of this function can + do nothing. This memory can also represent the Secure RAM. + This function is called before the satck has been set up. Its implementation must ensure the stack + pointer is not used (probably required to use assembly language) + +**/ +ArmPlatformInitializeBootMemory + // The SMC does not need to be initialized for RTSM + bx lr diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.S b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.S new file mode 100644 index 000000000..d5858630f --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.S @@ -0,0 +1,96 @@ +# +# Copyright (c) 2012, Sasmsung 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 <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/PcdLib.h> +#include <Library/ArmLib.h> +#include <AutoGen.h> +#.include AsmMacroIoLib.inc + +#include <Chipset/ArmCortexA9.h> + +.text +.align 2 + +GCC_ASM_EXPORT(ArmGetCpuCountPerCluster) +GCC_ASM_EXPORT(ArmPlatformGetCorePosition) +GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore) +GCC_ASM_EXPORT(ArmPlatformPeiBootAction) + +# IN None +# OUT r0 = SCU Base Address +ASM_PFX(ArmGetScuBaseAddress): + # Read Configuration Base Address Register. ArmCBar cannot be called to get + # the Configuration BAR as a stack is not necessary setup. The SCU is at the + # offset 0x0000 from the Private Memory Region. + mrc p15, 4, r0, c15, c0, 0 + bx lr + +# IN None +# OUT r0 = number of cores present in the system +ASM_PFX(ArmGetCpuCountPerCluster): + stmfd SP!, {r1-r2} + + # Read CP15 MIDR + mrc p15, 0, r1, c0, c0, 0 + + # Check if the CPU is A15 + mov r1, r1, LSR #4 + LoadConstantToReg (ARM_CPU_TYPE_MASK, r0) + and r1, r1, r0 + + LoadConstantToReg (ARM_CPU_TYPE_A15, r0) + cmp r1, r0 + beq _Read_cp15_reg + +_CPU_is_not_A15: + mov r2, lr @ Save link register + bl ArmGetScuBaseAddress @ Read SCU Base Address + mov lr, r2 @ Restore link register val + ldr r0, [r0, #A9_SCU_CONFIG_OFFSET] @ Read SCU Config reg to get CPU count + b _Return + +_Read_cp15_reg: + mrc p15, 1, r0, c9, c0, 2 @ Read C9 register of CP15 to get CPU count + lsr r0, #24 + +_Return: + and r0, r0, #3 + # Add '1' to the number of CPU on the Cluster + add r0, r0, #1 + ldmfd SP!, {r1-r2} + bx lr + +ASM_PFX(ArmPlatformIsPrimaryCore): + #last 2 bit of mpid register in 5250 is CPU ID + ldr r1, =0x3 + and r0, r0, r1 + #id for core0 should be 0 + ldr r1, =0x0 + cmp r0, r1 + moveq r0, #1 + movne r0, #0 + mov pc, lr + +ASM_PFX(ArmPlatformGetCorePosition): + and r1, r0, #0x03 //cpu core mask last 2 bits + and r0, r0, #(0x0f<<8) //cpu cluster mask bit 8-11 + add r0, r1, r0, LSR #7 + mov pc, lr + + +ASM_PFX(ArmPlatformPeiBootAction): + mov pc, lr + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.asm b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.asm new file mode 100644 index 000000000..bf81f142a --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.asm @@ -0,0 +1,73 @@ +// +// Copyright (c) 2011, ARM 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 <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/PcdLib.h> + +#include <Chipset/ArmCortexA9.h> + +#include <AutoGen.h> + + INCLUDE AsmMacroIoLib.inc + + EXPORT ArmGetCpuCountPerCluster + + AREA RTSMHelper, CODE, READONLY + +// IN None +// OUT r0 = SCU Base Address +ArmGetScuBaseAddress + // Read Configuration Base Address Register. ArmCBar cannot be called to get + // the Configuration BAR as a stack is not necessary setup. The SCU is at the + // offset 0x0000 from the Private Memory Region. + mrc p15, 4, r0, c15, c0, 0 + bx lr + +// IN None +// OUT r0 = number of cores present in the system +ArmGetCpuCountPerCluster + stmfd SP!, {r1-r2} + + // Read CP15 MIDR + mrc p15, 0, r1, c0, c0, 0 + + // Check if the CPU is A15 + mov r1, r1, LSR #4 + mov r0, #ARM_CPU_TYPE_MASK + and r1, r1, r0 + + mov r0, #ARM_CPU_TYPE_A15 + cmp r1, r0 + beq _Read_cp15_reg + +_CPU_is_not_A15 + mov r2, lr ; Save link register + bl ArmGetScuBaseAddress ; Read SCU Base Address + mov lr, r2 ; Restore link register val + ldr r0, [r0, #A9_SCU_CONFIG_OFFSET] ; Read SCU Config reg to get CPU count + b _Return + +_Read_cp15_reg + mrc p15, 1, r0, c9, c0, 2 ; Read C9 register of CP15 to get CPU count + lsr r0, #24 + + +_Return + and r0, r0, #3 + // Add '1' to the number of CPU on the Cluster + add r0, r0, #1 + ldmfd SP!, {r1-r2} + bx lr + + END diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf new file mode 100755 index 000000000..9ac255abc --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf @@ -0,0 +1,69 @@ +#/* @file +# Copyright (c) 2012, Samsung Electronics Co. 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 = BoardLib + FILE_GUID = 736343a0-1d96-11e0-aaaa-0002a5d5c51b + 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 + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + +[LibraryClasses] + IoLib + ArmLib + MemoryAllocationLib + +[Sources.common] + Board.c + BoardMem.c + BoardHelper.asm | RVCT + BoardHelper.S | GCC + +[Protocols] + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdStandalone + +[FixedPcd] + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + gArmTokenSpaceGuid.PcdFvBaseAddress + + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + gArmTokenSpaceGuid.PcdTrustzoneSupport + + gExynosPkgTokenSpaceGuid.PcdTZPCBase + gExynosPkgTokenSpaceGuid.PcdFrameBufferBase + gExynosPkgTokenSpaceGuid.PcdFrameBufferSize + + gExynosPkgTokenSpaceGuid.PcdMpSharedArgsBase + gExynosPkgTokenSpaceGuid.PcdMpSharedArgsSize + + gExynosPkgTokenSpaceGuid.PcdSmemBaseAddress + gExynosPkgTokenSpaceGuid.PcdSmemSize + + gExynosPkgTokenSpaceGuid.PcdiRamBootBase + gExynosPkgTokenSpaceGuid.PcdiRamBootSize + gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase +# gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferSize diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardMem.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardMem.c new file mode 100755 index 000000000..051776d42 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardMem.c @@ -0,0 +1,221 @@ +/** @file +* +* Copyright (c) 2012, Samsung Electronics Co. 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 <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <ArmPlatform.h> + +// Number of Virtual Memory Map Descriptors without a Logic Tile +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 9 + +// DDR attributes +#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK +#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED +#define DDR_ATTRIBUTES_SECURE_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK +#define DDR_ATTRIBUTES_SECURE_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED + +// Logical Region 1 +#define SOC_REGISTERS_IROM_PHYSICAL_BASE 0x00000000 +#define SOC_REGISTERS_IROM_PHYSICAL_LENGTH 0x02010000 +#define SOC_REGISTERS_IROM_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE +#define SOC_REGISTERS_IROM_SECURE_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + +// Logical Region 2 +#define SOC_REGISTERS_SFR_PHYSICAL_BASE 0x10000000 +#define SOC_REGISTERS_SFR_PHYSICAL_LENGTH 0x08FFFFFF +#define SOC_REGISTERS_SFR_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE +#define SOC_REGISTERS_SFR_SECURE_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + +/** + 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 = 0; + ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; + + DEBUG ((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + + UINTN MemoryBase_Pcd = PcdGet32(PcdSystemMemoryBase); + UINTN MemorySize_Pcd = PcdGet32(PcdSystemMemorySize); + UINTN FrameBufferBase_Pcd = PcdGet32(PcdFrameBufferBase); + UINTN FrameBufferSize_Pcd = PcdGet32(PcdFrameBufferSize); + UINTN MpSharedArgsBase_Pcd = PcdGet32(PcdMpSharedArgsBase); + UINTN MpSharedArgsSize_Pcd = PcdGet32(PcdMpSharedArgsSize); + UINTN FdBaseAddress_Pcd = PcdGet32(PcdFdBaseAddress); + UINTN FdSize_Pcd = PcdGet32(PcdFdSize); + UINTN SmemBase_Pcd = PcdGet32(PcdSmemBaseAddress); + UINTN SmemSize_Pcd = PcdGet32(PcdSmemSize); + UINTN iRamBootBase_Pcd = PcdGet32(PcdiRamBootBase); + UINTN iRamBootSize_Pcd = PcdGet32(PcdiRamBootSize); + BOOLEAN TrustzoneSupport_Pcd = PcdGetBool (PcdTrustzoneSupport); + UINT32 Nsacr = ArmReadNsacr(); + UINTN EmmcDMABufferBase_Pcd = PcdGet32(PcdEmmcDMABufferBase); + + // Checking Secure mode + if(Nsacr == 0x0) // Secure mode + { + TrustzoneSupport_Pcd = FALSE; + } + + // Check if SMC TZASC is enabled. If Trustzone not enabled then all the entries remain in Secure World. + // As this value can be changed in the Board Configuration file, the UEFI firmware needs to work for both case + + + 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 = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_CACHED : DDR_ATTRIBUTES_SECURE_CACHED); + } else { + CacheAttributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + } + + // FD region : 0x40000000 - 0x40200000 + // Map in the FD region (includes SEC), the stack, and the exception vector region + VirtualMemoryTable[Index].PhysicalBase = FdBaseAddress_Pcd; + VirtualMemoryTable[Index].VirtualBase = FdBaseAddress_Pcd; + VirtualMemoryTable[Index].Length = FdSize_Pcd; // need to check + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + DEBUG ((EFI_D_ERROR, "FD region : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // SMEM : 0x40200000 - 0x40300000 + // Shared memory 1MB (0x4000_0000 -- 0x4010_0000) + VirtualMemoryTable[++Index].PhysicalBase = SmemBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = SmemBase_Pcd; + VirtualMemoryTable[Index].Length = SmemSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "SMEM : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // EMMC : 0x40300000 - 0x40400000 + // EMMC (0x4030_0000 - 0x404_0000) (1MB) + VirtualMemoryTable[++Index].PhysicalBase = EmmcDMABufferBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = EmmcDMABufferBase_Pcd; + VirtualMemoryTable[Index].Length = 0x00100000; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "EMMC : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + + // DDR : 0x40400000 - 0x4E000000 + // DDR (0x4040_0000 - 0x4E00_0000) (511MB) + VirtualMemoryTable[++Index].PhysicalBase = 0x40400000; + VirtualMemoryTable[Index].VirtualBase = 0x40400000; + VirtualMemoryTable[Index].Length = 0x0DC00000; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + DEBUG ((EFI_D_ERROR, "DDR : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // MpParkShared: 0x4D00_0000 - 0x4D10_0000 + // MpParkSahred (0x4D00_0000 - 0x4D10_0000) + VirtualMemoryTable[++Index].PhysicalBase = MpSharedArgsBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = MpSharedArgsBase_Pcd; + VirtualMemoryTable[Index].Length = MpSharedArgsSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "FrameBuffer: 0x%8X - 0x%8X\n", VirtualMemoryTable[Index].PhysicalBase, + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // FrameBuffer: 0x4E000000 - 0x50000000 + // Framebuffer (0x4E00_0000 - 0x5000_0000) + VirtualMemoryTable[++Index].PhysicalBase = FrameBufferBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = FrameBufferBase_Pcd; + VirtualMemoryTable[Index].Length = FrameBufferSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "FrameBuffer: 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // DDR : 0x50000000 - 0xA0000000 + // DDR (0x5000_0000 - 0x8000_0000) (512MB) + VirtualMemoryTable[++Index].PhysicalBase = MemoryBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = MemoryBase_Pcd; + VirtualMemoryTable[Index].Length = MemorySize_Pcd; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + DEBUG ((EFI_D_ERROR, "DDR : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // SFR : 0x10000000 - 0x14000000 + // SFR + VirtualMemoryTable[++Index].PhysicalBase = SOC_REGISTERS_SFR_PHYSICAL_BASE; + VirtualMemoryTable[Index].VirtualBase = SOC_REGISTERS_SFR_PHYSICAL_BASE; + VirtualMemoryTable[Index].Length = SOC_REGISTERS_SFR_PHYSICAL_LENGTH; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? SOC_REGISTERS_SFR_ATTRIBUTES : SOC_REGISTERS_SFR_SECURE_ATTRIBUTES); + DEBUG ((EFI_D_ERROR, "SFR : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // iRAM : 0x02020000 - 0x02040000 + // iRAM + VirtualMemoryTable[++Index].PhysicalBase = iRamBootBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = iRamBootBase_Pcd; + VirtualMemoryTable[Index].Length = iRamBootSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE : ARM_MEMORY_REGION_ATTRIBUTE_DEVICE); + DEBUG ((EFI_D_ERROR, "iRAM : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // iROM : 0x00000000 - 0x02010000 + // iROM + VirtualMemoryTable[++Index].PhysicalBase = SOC_REGISTERS_IROM_PHYSICAL_BASE; + VirtualMemoryTable[Index].VirtualBase = SOC_REGISTERS_IROM_PHYSICAL_BASE; + VirtualMemoryTable[Index].Length = SOC_REGISTERS_IROM_PHYSICAL_LENGTH; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? SOC_REGISTERS_IROM_ATTRIBUTES : SOC_REGISTERS_IROM_SECURE_ATTRIBUTES); + DEBUG ((EFI_D_ERROR, "iROM : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // End of Table + VirtualMemoryTable[++Index].PhysicalBase = 0; + VirtualMemoryTable[Index].VirtualBase = 0; + VirtualMemoryTable[Index].Length = 0; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0; + + *VirtualMemoryMap = VirtualMemoryTable; + DEBUG ((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +/** + Return the EFI Memory Map provided by extension memory on your platform + + This EFI Memory Map of the System Memory is used by MemoryInitPei module to create the Resource + Descriptor HOBs used by DXE core. + TODO: CompleteMe .... say this is the memory not covered by the System Memory PCDs + + @param[out] EfiMemoryMap Array of ARM_SYSTEM_MEMORY_REGION_DESCRIPTOR describing an + EFI Memory region. This array must be ended by a zero-filled entry + +**/ +EFI_STATUS +ArmPlatformGetAdditionalSystemMemory ( + OUT ARM_SYSTEM_MEMORY_REGION_DESCRIPTOR** EfiMemoryMap + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSec.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSec.c new file mode 100644 index 000000000..374712722 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSec.c @@ -0,0 +1,52 @@ +/** @file +* +* Copyright (c) 2012, Samsung Electronics Co. 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 <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Drivers/PL310L2Cache.h> +#include <Drivers/PL341Dmc.h> + + +/** + Initialize controllers that must setup at the early stage + + Some peripherals must be initialized in Secure World. + For example, some L2x0 requires to be initialized in Secure World + +**/ +VOID +ArmPlatformSecInitialize ( + VOID + ) +{ + return; +} + +/** + Call before jumping to Normal World + + This function allows the firmware platform to do extra actions before + jumping to the Normal World + +**/ +VOID +ArmPlatformSecExtraAction ( + IN UINTN MpId, + OUT UINTN* JumpAddress + ) +{ + *JumpAddress = PcdGet32(PcdFvBaseAddress); +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf new file mode 100755 index 000000000..aeaba6eb2 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf @@ -0,0 +1,60 @@ +#/* @file +# Copyright (c) 2012, Samsung Electronics Co. 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 = BoardSecLib + FILE_GUID = 6e02ebe0-1d96-11e0-b9cb-0002a5d5c51b + 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 + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + +[LibraryClasses] + IoLib + ArmLib + +[Sources.common] + Board.c + BoardSec.c + mem_init_ddr3.S | GCC + BoardBoot.S | GCC + BoardBoot.asm | RVCT + BoardHelper.asm | RVCT + BoardHelper.S | GCC + +[Protocols] + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdStandalone + +[FixedPcd] + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize + gArmTokenSpaceGuid.PcdFvBaseAddress + + gExynosPkgTokenSpaceGuid.PcdiRamBootBase + gExynosPkgTokenSpaceGuid.PcdiRamBootSize + gExynosPkgTokenSpaceGuid.PcdTZPCBase + + gArmTokenSpaceGuid.PcdFdSize + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdL2x0ControllerBase diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/dmc_init.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/dmc_init.c new file mode 100644 index 000000000..297dd6edf --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/dmc_init.c @@ -0,0 +1,787 @@ +/* + * (C) Copyright 2012 Samsung Electronics Co. Ltd + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +void dmc_delay(UINT32); +void mem_ctrl_init_done(); + +#define Outp32(addr, data) (*(volatile UINT32 *)(addr) = (data)) +#define Inp32(addr) ((*(volatile UINT32 *)(addr))) + +#define CONFIG_DMC_CALIBRATION +#define CONFIG_ODTOFF_GATELEVELINGON +#define POP_TYPE 1 +#define PRO_PKGINFO 0 + +void DMC_Delay(UINT32 x) +{ + dmc_delay(x); +} + +void CMU_SetMemClk(UINT32 nMEMCLK) +{ + volatile UINT32 uBits; + + // MEM Clock = 800 MHz + + // MCLK_DPHY(0:8), MCLK_CDREX(0:4), BPLL(0:0) + uBits = (0 << 8) | (0 << 4) | (1 << 0); + Outp32(0x10030200, uBits); // rCLK_SRC_CDREX + + // MCLK_DPHY = 800 / 1 = 800 + // MCLK_CDREX = 800 / 1 = 800 + // ACLK_CDREX = MCLK_CDREX / 2 = 400 + // PCLK_CDREX = 800 / 1 / 6 = 133 + + // MCLK_CDREX2(1/1:28), ACLK_SFRTZASCP(1/2:24), MCLK_DPHY(1/1:20), MCLK_CDREX(1/1:16), PCLK_CDREX(1/6:4), ACLK_CDREX(1/2:0) + uBits = (0 << 28) | (1 << 24) | (0 << 20) | (0 << 16) | (5 << 4) | (1 << 0); + Outp32(0x10030500, uBits); // rCLK_DIV_CDREX + + // MPLL(0:8) + uBits = (1 << 8); + Outp32(0x10014204, Inp32(0x10014204) & ~uBits); // rCLK_SRC_CORE1 + + // Setting MPLL [P,M,S] + // + uBits = (1 << 21) | (3 << 12) | (8 << 8); + Outp32(0x10014104, uBits); // rMPLL_CON1 + + // ENABLE(1), MDIV(200), PDIV(3), SDIV(0) + uBits = (1 << 31) | (200 << 16) | (3 << 8) | (0 << 0); // MPLL=1600MHz(3:200:0) + Outp32(0x10014100, uBits); // rMPLL_CON0 + + while ((Inp32(0x10014100) & (1 << 29)) == 0); + + // MPLL(1:8) + uBits = (1 << 8); + Outp32(0x10014204, Inp32(0x10014204) | uBits); // rCLK_SRC_CORE1 + +} + +void DMC_CaTraining(int ch) +{ + unsigned char code; + int find_vmw; + unsigned int phyBase; + unsigned int ioRdOffset; + unsigned int temp, mr41, mr48, vwml, vwmr, vwmc; + unsigned int lock; + unsigned int resp_mr41, resp_mr48; + UINT32 pkg_type = PRO_PKGINFO; + + + phyBase = 0x10c00000+(0x10000 * ch); + ioRdOffset = 0x150 + (0x4 * ch); + + temp = Inp32( phyBase + 0x0000 ); + temp |= (1 << 16); + Outp32( phyBase + 0x0000, temp ); + + temp = Inp32( phyBase + 0x0008 ); + temp |= (1 << 23); + Outp32( phyBase + 0x0008, temp ); + + code = 0x8; + find_vmw = 0; + vwml = vwmr = vwmc = 0; + + if (pkg_type == POP_TYPE) { + resp_mr41 = 0x5555; + resp_mr48 = 0x0101; + } else { + if ( ch == 0 ) { + resp_mr41 = 0x69C5; + resp_mr48 = 0x4040; + } else { + resp_mr41 = 0xD14E; + resp_mr48 = 0x8008; + } + } + + while (1) { + + //- code update + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFFFFFF00; + temp |= code; + Outp32( phyBase + 0x0028, temp ); + + //- resync + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + temp |= 0x01000000; + Outp32( phyBase + 0x0028, temp ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + + if(ch == 0) { + Outp32( 0x10DD0000+0x0010, 0x50690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x50690 + //Outp32( 0x10DD0000+0x0010, 0x001050690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x50690 + } else { + Outp32( 0x10DD0000+0x0010, 0x10050690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x10050690 + //Outp32( 0x10DD0000+0x0010, 0x10150690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x10050690 + } + + Outp32( 0x10DD0000+0x0160, 0x3FF011 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=1 + Outp32( 0x10DD0000+0x0164, 0x1 ); //- Set DMC.CACAL_CONFIG1.cacal_csn=1 + DMC_Delay(0x100); + + mr41 = Inp32( 0x10DD0000 + ioRdOffset ); + mr41 &= 0xFFFF; + + Outp32( 0x10DD0000+0x0160, 0x3FF010 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=0 + DMC_Delay(0x100); + + if( ch == 0 ) { + Outp32( 0x10DD0000+0x0010, 0x60300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x60300 + //Outp32( 0x10DD0000+0x0010, 0x001060300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x60300 + } else { + Outp32( 0x10DD0000+0x0010, 0x10060300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x10060300 + //Outp32( 0x10DD0000+0x0010, 0x10160300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x10060300 + } + + Outp32( 0x10DD0000+0x0160, 0x3FF011 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=1 + Outp32( 0x10DD0000+0x0164, 0x1 ); //- Set DMC.CACAL_CONFIG1.cacal_csn=1 + DMC_Delay(0x100); + + mr48 = Inp32( 0x10DD0000 + ioRdOffset ); + + if (pkg_type == POP_TYPE) { + mr48 &= 0x0303; + } else { + if ( ch == 0 ) { + mr48 &= 0xC060; + } else { + mr48 &= 0x8418; + } + } + + Outp32( 0x10DD0000+0x0160, 0x3FF010 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=0 + DMC_Delay(0x100); + + if( (find_vmw == 0) && (mr41 == resp_mr41 ) && ( mr48 == resp_mr48 ) ) { + find_vmw = 0x1; + vwml = code; + } + + if( (find_vmw == 1) && ( (mr41 != resp_mr41 ) || ( mr48 != resp_mr48 ) ) ) { + find_vmw = 0x3; + vwmr = code - 1; + + if( ch == 0 ) { + Outp32( 0x10DD0000+0x0010, 0x50AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + //Outp32( 0x10DD0000+0x0010, 0x001050AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + } else { + Outp32( 0x10DD0000+0x0010, 0x10050AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + //Outp32( 0x10DD0000+0x0010, 0x10150AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + } + //DMC_Delay(0x10000); + break; + } + + code++; + + if(code == 255) { + while(1); + } + } + + vwmc = (vwml + vwmr) / 2; + +#if 1 + { + UINT32 lock_force; + UINT32 temp = 0; + + lock_force = (Inp32( phyBase + 0x30 ) >> 8) & 0x7F; + + temp = ((vwml & 0xFF) << 16) | + ((vwmr & 0xFF) << 8) | + ((vwmc & 0xFF)); + + if(ch == 0) { + Outp32(0x10040818, temp); + } + else { + Outp32(0x1004081C, temp); + } + } +#endif + + //- code update + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFFFFFF00; + temp |= vwmc; + Outp32( phyBase + 0x0028, temp ); + + //- resync + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + temp |= 0x01000000; + Outp32( phyBase + 0x0028, temp ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + + temp = Inp32( phyBase+0x0000 ); + temp &= 0xFFFEFFFF; + Outp32( phyBase + 0x0000, temp ); + +#if 1 + + //- vmwc convert to offsetd value. + + lock = Inp32( phyBase + 0x0034 ); + lock &= 0x1FF00; + lock >>= 8; + + if( (lock & 0x3) == 0x3 ) { + lock++; + } + + code = vwmc - (lock >> 2); + + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFFFFFF00; + temp |= code; + Outp32( phyBase + 0x0028, temp ); + + temp = Inp32( phyBase + 0x0008 ); + temp &= 0xFF7FFFFF; + Outp32( phyBase + 0x0008, temp ); +#endif +} + +static void DMC_ZqInit(UINT8 dq, UINT8 ck, UINT8 cke, UINT8 cs, UINT8 ca) +{ + UINT32 temp; + UINT32 zqBase; + int ch; + + for( ch = 0; ch < 2; ch++ ) { + + zqBase = 0x10c00000 + ( 0x10000 * ch ); + + temp = Inp32( zqBase + 0x40 ); + temp &= 0xF8FBFFF1; + temp |= ( ( dq & 0x7 ) << 24 ); + temp |= ( ( 1 << 18 ) | ( 1 << 2 ) ); + + Outp32( zqBase + 0x40, temp ); + + temp |= (1 << 1); + + Outp32( zqBase + 0x40, temp ); + + while( ( Inp32( zqBase + 0x48 ) & 0x5 ) != 0x1 ); + + temp = Inp32( zqBase + 0x40 ); + + temp &= ~( 1 << 18 ); + + Outp32( zqBase + 0x40, temp ); + + temp = ( ( ck & 0x7 ) << 9 ) | ( ( cke & 0x7 ) << 6 ) | + ( ( cs & 0x7 ) << 3 ) | ( ca & 0x7 ); + + Outp32( zqBase + 0xA0, temp ); + } +} + +void mem_ctrl_init_lpddr3(UINT32 nMEMCLK) +{ + UINT32 lock, temp; + UINT32 pkg_type = PRO_PKGINFO; + + //- + //-PHASE 1 : PHY DLL Initialization + //- + //-2) Set the right value to PHY_CON0.ctrl_ddr_mode + Outp32( 0x10C00000+0x0000, 0x17021A40 ); //- PHY0.CON0[12:11].ctrl_ddr_mode=LPDDR3 + Outp32( 0x10C10000+0x0000, 0x17021A40 ); //- PHY1.CON0[12:11].ctrl_ddr_mode=LPDDR3 + //-3) Enable CA swap when POP is used + Outp32( 0x10C00000+0x0000, 0x17021A00 ); //- PHY0.CON0.ctrl_atgate=0x0 + Outp32( 0x10C10000+0x0000, 0x17021A00 ); //- PHY1.CON0.ctrl_atgate=0x0 + + if (pkg_type == POP_TYPE) { + Outp32( 0x10030A20, 0x80000000 ); //- LPDDR3PHY_CON3[31]=1. + Outp32( 0x10C00000+0x0064, 0x1 ); //- PHY0.CON24[0]=1 + Outp32( 0x10C10000+0x0064, 0x1 ); //- PHY0.CON24[0]=1 + } else { + Outp32( 0x10030A20, 0x00000000 ); //- LPDDR3PHY_CON3[31]=0. + Outp32( 0x10C00000+0x0064, 0x0 ); //- PHY0.CON24[0]=0 + Outp32( 0x10C10000+0x0064, 0x0 ); //- PHY0.CON24[0]=0 + } + //-4) Set PHY for DQS pull-down mode + Outp32( 0x10C00000+0x0038, 0x0F ); //- PHY0.CON14.ctrl_pulld_dq=0x0, ctrl_pulld_dqs=0x0F + Outp32( 0x10C10000+0x0038, 0x0F ); //- PHY1.CON14.ctrl_pulld_dq=0x0, ctrl_pulld_dqs=0x0F + //-5) Set PHY_CON42.ctrl_bstlen and PHY_CON42.ctrl_rdlat + Outp32( 0x10C00000+0x00ac, 0x80C ); //- PHY0.CON42.ctrl_bstlen[12:8]=0x8, ctrl_rdlat[4:0]=0x0C + Outp32( 0x10C10000+0x00ac, 0x80C ); //- PHY1.CON42.ctrl_bstlen[12:8]=0x8, ctrl_rdlat[4:0]=0x0C + Outp32( 0x10C00000+0x006C, 0x7107F ); //- PHY0.CON26.T_wrdata_en[20:16]=0x7 + Outp32( 0x10C10000+0x006C, 0x7107F ); //- PHY1.CON26.T_wrdata_en[20:16]=0x7 + Outp32( 0x10C00000+0x0000, 0x17021A00 ); //- Set PHY0.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C00000+0x0040, 0x8080304 ); //- Set PHY0.PHY_CON16.zq_term. + Outp32( 0x10C10000+0x0000, 0x17021A00 ); //- Set PHY1.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C10000+0x0040, 0x8080304 ); //- Set PHY1.PHY_CON16.zq_term. + Outp32( 0x10030B00, 0x1 ); //- Set 0x1003_0B00[0]=0x1 + //-6) ZQ calibration + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0040, 0xE0C0304 ); //- Set PHY0.CON16.zq_mode_dds=0x6000000 + Outp32( 0x10C00000+0x0040, 0xE0C0304 ); //- Set PHY0.CON16.zq_manual_mode=1 + Outp32( 0x10C00000+0x0040, 0xE0C0306 ); //- Set PHY0.CON16.zq_manual_str + while( ( Inp32( 0x10C00000+0x0048 ) & 0x1 ) != 0x1 ); //- Wait for PHY0.CON17.zq_done + Outp32( 0x10C00000+0x0040, 0xE080304 ); //- Set PHY0.CON16.zq_clk_en=0 + Outp32( 0x10C10000+0x0040, 0xE0C0304 ); //- Set PHY1.CON16.zq_mode_dds=0x6000000 + Outp32( 0x10C10000+0x0040, 0xE0C0304 ); //- Set PHY1.CON16.zq_manual_mode=1 + Outp32( 0x10C10000+0x0040, 0xE0C0306 ); //- Set PHY1.CON16.zq_manual_str + while( ( Inp32( 0x10C10000+0x0048 ) & 0x1 ) != 0x1 ); //- Wait for PHY1.CON17.zq_done + Outp32( 0x10C10000+0x0040, 0xE080304 ); //- Set PHY1.CON16.zq_clk_en=0 + Outp32( 0x10C00000+0x00A0, 0xDB6 ); //- PHY0.CON39[11:0]=0xDB6 + Outp32( 0x10C10000+0x00A0, 0xDB6 ); //- PHY1.CON39[11:0]=0xDB6 + } else { + DMC_ZqInit(0x4, 0x4, 0x4, 0x4, 0x4); + } + + //-7) Set CONCONTROL. At this moment, assert the dfi_init_start field to high. + Outp32( 0x10DD0000+0x0000, 0xFFF2100 ); //- rdfetch=0x2 + Outp32( 0x10DD0000+0x0000, 0x1FFF2100 ); //- assert dfi_init_start + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0000, 0xFFF2100 ); //- deassert dfi_init_start + //- + //-PHASE 2 : Setting Controller Register + //- + //-8) Set MEMCONTROL. At this moment, switch OFF all low power feature. + Outp32( 0x10DD0000+0x0004, 0x312700 ); //- memcontrol + //-9) Set the MEMBASECONFIG0 register. + //- If there are two external memory chips set the MEMBASECONFIG1 register. + Outp32( 0x10DD0000+0x010C, 0x4007C0 ); //- chipbase0=0x40, mask=0x7C0 + Outp32( 0x10DD0000+0x0110, 0x8007C0 ); //- chipbase1=0x80, mask=0x7C0 + Outp32( 0x10DD0000+0x0008, 0x1323 ); //- memconfig0 + Outp32( 0x10DD0000+0x000C, 0x1323 ); //- memconfig1 + //-10) Set the PRECHCONFIG register + Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- DMC.PRECHCONFIG[15:0]=(0x0|0x0) + //-11) Set the TIMINGAREF, TIMINGROW, TIMINGDATA, and TIMINGPOWER registers + //- according to memory AC parameters. + Outp32( 0x10DD0000+0x00F0, 0x7 ); //- iv_size=0x7 + Outp32( 0x10DD0000+0x0030, 0x5D ); //- tREFI=0x5D + Outp32( 0x10DD0000+0x0034, 0x34498692 ); //- DMC.TIMINGROW=0x34498692 + Outp32( 0x10DD0000+0x0038, 0x3630560C ); //- DMC.TIMINGDATA=0x3630560C + Outp32( 0x10DD0000+0x003C, 0x50380336 ); //- DMC.TIMINGPOWER=0x50380336 + Outp32( 0x10DD0000+0x0004, 0x312700 ); //- + //-12) Set the QOSCONTROL0~15 and BRBQOSCONFIG register if Qos Scheme is required. + Outp32( 0x10DD0000+0x60, 0xFFF ); //- QOS#0.=0xFFF + Outp32( 0x10DD0000+0x68, 0xFFF ); //- QOS#1.=0xFFF + Outp32( 0x10DD0000+0x70, 0xFFF ); //- QOS#2.=0xFFF + Outp32( 0x10DD0000+0x78, 0xFFF ); //- QOS#3.=0xFFF + Outp32( 0x10DD0000+0x80, 0xFFF ); //- QOS#4.=0xFFF + Outp32( 0x10DD0000+0x88, 0xFFF ); //- QOS#5.=0xFFF + Outp32( 0x10DD0000+0x90, 0xFFF ); //- QOS#6.=0xFFF + Outp32( 0x10DD0000+0x98, 0xFFF ); //- QOS#7.=0xFFF + Outp32( 0x10DD0000+0xA0, 0xFFF ); //- QOS#8.=0xFFF + Outp32( 0x10DD0000+0xA8, 0xFFF ); //- QOS#9.=0xFFF + Outp32( 0x10DD0000+0xB0, 0xFFF ); //- QOS#10.=0xFFF + Outp32( 0x10DD0000+0xB8, 0xFFF ); //- QOS#11.=0xFFF + Outp32( 0x10DD0000+0xC0, 0xFFF ); //- QOS#12.=0xFFF + Outp32( 0x10DD0000+0xC8, 0xFFF ); //- QOS#13.=0xFFF + Outp32( 0x10DD0000+0xD0, 0xFFF ); //- QOS#14.=0xFFF + Outp32( 0x10DD0000+0xD8, 0x0 ); //- QOS#15.=0xFFF + //-13) Set the PHY_CON4.ctrl_offsetr0~3 and PHY_CON6.ctrl_offsetw0~3 to 0x7F. + Outp32( 0x10C00000+0x0010, 0x7F7F7F7F ); //- offsetr=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + Outp32( 0x10C10000+0x0010, 0x7F7F7F7F ); //- offsetr=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + Outp32( 0x10C00000+0x0018, 0x7F7F7F7F ); //- offsetw=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + Outp32( 0x10C10000+0x0018, 0x7F7F7F7F ); //- offsetw=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + //-14) Set the PHY_CON4.ctrl_offsetd value to 0x7F. + Outp32( 0x10C00000+0x0028, 0x7F ); //- offsetd=0x7F + Outp32( 0x10C10000+0x0028, 0x7F ); //- offsetd=0x7F + //-15) + //-16) + Outp32( 0x10C00000+0x0030, 0x10107F70 ); //- lock forcing=0x7F + Outp32( 0x10C10000+0x0030, 0x10107F70 ); //- lock forcing=0x7F + Outp32( 0x10C00000+0x0030, 0x10107F50 ); //- disable ctrl_dll_on + Outp32( 0x10C10000+0x0030, 0x10107F50 ); //- disable ctrl_dll_on + DMC_Delay(0x100); //- wait 1ms + //-18) Update the DLL information. + Outp32( 0x10DD0000+0x0018, 0x8 ); //- fp_resync=1 + Outp32( 0x10DD0000+0x0018, 0x0 ); //- fp_resync=0 + //- + //-PHASE 3 : Memory Initialization + //- + //-18)~26) + Outp32( 0x10DD0000+0x0010, 0x7000000 ); //- port:0x0, cs:0x0 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x71C00 ); //- port:0x0, cs:0x0 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x10BFC ); //- port:0x0, cs:0x0 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x50C ); //- port:0x0, cs:0x0 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x868 ); //- port:0x0, cs:0x0 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0xC04 ); //- port:0x0, cs:0x0 mr3 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x7100000 ); //- port:0x0, cs:0x1 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x171C00 ); //- port:0x0, cs:0x1 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x110BFC ); //- port:0x0, cs:0x1 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10050C ); //- port:0x0, cs:0x1 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x100868 ); //- port:0x0, cs:0x1 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x100C04 ); //- port:0x0, cs:0x1 mr3 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x17000000 ); //- port:0x1, cs:0x0 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10071C00 ); //- port:0x1, cs:0x0 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x10010BFC ); //- port:0x1, cs:0x0 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x1000050C ); //- port:0x1, cs:0x0 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10000868 ); //- port:0x1, cs:0x0 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10000C04 ); //- port:0x1, cs:0x0 mr3 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x17100000 ); //- port:0x1, cs:0x1 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10171C00 ); //- port:0x1, cs:0x1 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x10110BFC ); //- port:0x1, cs:0x1 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x1010050C ); //- port:0x1, cs:0x1 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10100868 ); //- port:0x1, cs:0x1 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10100C04 ); //- port:0x1, cs:0x1 mr3 command + DMC_Delay(0x100); //- wait 1ms + //-27) Return to the memory operating frequency. + CMU_SetMemClk(800); + + //-28) Set the PHY_CON4.ctrl_offsetr0~3 and PHY_CON6.ctrl_offsetw0~3 to 0x8. + Outp32( 0x10C00000+0x0010, 0x8080808 ); //- offsetr=0:0x08, 1:0x08, 2:0x08, 3:0x08 + Outp32( 0x10C10000+0x0010, 0x8080808 ); //- offsetr=0:0x08, 1:0x08, 2:0x08, 3:0x08 + Outp32( 0x10C00000+0x0018, 0x8080808 ); //- offsetw=0:0x08, 1:0x08, 2:0x08, 3:0x08 + Outp32( 0x10C10000+0x0018, 0x8080808 ); //- offsetw=0:0x08, 1:0x08, 2:0x08, 3:0x08 + //-29) Set the PHY_CON4.ctrl_offsetd value to 0x8. + Outp32( 0x10C00000+0x0028, 0x8 ); //- offsetd=0x08 + Outp32( 0x10C10000+0x0028, 0x8 ); //- offsetd=0x08 + //-30)~34) + Outp32( 0x10C00000+0x0030, 0x10107F70 ); //- ctrl_dll_on[5] = 1 + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10C00000+0x0030, 0x10107F30 ); //- ctrl_start[6] = 0 + Outp32( 0x10C00000+0x0030, 0x10107F70 ); //- ctrl_start[6] = 1 + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10C10000+0x0030, 0x10107F70 ); //- ctrl_dll_on[5] = 1 + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10C10000+0x0030, 0x10107F30 ); //- ctrl_start[6] = 0 + Outp32( 0x10C10000+0x0030, 0x10107F70 ); //- ctrl_start[6] = 1 + DMC_Delay(0x100); //- wait 1ms + //-35)~36) + Outp32( 0x10DD0000+0x0000, 0x1FFF2100 ); //- assert dfi_init_start + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC ) != 0xC ); //- Wait for DMC.dfi_init_complete_ch0/1 + Outp32( 0x10DD0000+0x0000, 0xFFF2100 ); //- deassert dfi_init_start + //-37) Update the DLL information. + Outp32( 0x10DD0000+0x0018, 0x8 ); //- fp_resync=1 + Outp32( 0x10DD0000+0x0018, 0x0 ); //- fp_resync=0 + +#if defined(CONFIG_DMC_CALIBRATION) + //-38) Do leveing and calibration + //-39) Perform these steps + //- - a. Update PHYCON12.ctrl_force with by using PHY_CON13.ctrl_lock_value[9:2] + lock = (Inp32(0x10c00034) >> 8) & 0xFF; + if((lock & 0x3) == 0x3) { + lock++; + } + + temp = Inp32(0x10c00030) & 0xFFFF80FF; + temp |= ((lock >> 2) << 8); + Outp32( 0x10c00000 + 0x0030, temp); + + lock = (Inp32(0x10c10034) >> 8) & 0xFF; + if((lock & 0x3) == 0x3) { + lock++; + } + + temp = Inp32(0x10c10030) & 0xFFFF80FF; + temp |= ((lock >> 2) << 8); + Outp32( 0x10c10000 + 0x0030, temp); + + //- - b. Enable PHY_CON0.ctrl_atgate + Outp32( 0x10C00000+0x0000, 0x17021A40 ); //- PHY0.CON0.ctrl_atgate=1. + Outp32( 0x10C10000+0x0000, 0x17021A40 ); //- PHY1.CON0.ctrl_atgate=1. + //- - d. Enable PHY_CON0.p0_cmd_en + Outp32( 0x10C00000+0x0000, 0x17025A40 ); //- PHY0.CON0.p0_cmd_en=1. + Outp32( 0x10C10000+0x0000, 0x17025A40 ); //- PHY1.CON0.p0_cmd_en=1. + //- - e. Enable PHY_CON2.InitDeskewEn + Outp32( 0x10C00000+0x0008, 0x10044 ); //- PHY0.CON2.InitDeskewEn=1. + Outp32( 0x10C10000+0x0008, 0x10044 ); //- PHY1.CON2.InitDeskewEn=1. + //- - f. Enable PHY_CON0.byte_rdlvl_en + Outp32( 0x10C00000+0x0000, 0x17027A40 ); //- + Outp32( 0x10C10000+0x0000, 0x17027A40 ); //- + + //- - c. Disable PHY_CON12.ctrl_dll_on + temp = Inp32(0x10c00030) & 0xFFFFFFDF; + Outp32( 0x10c00030, temp ); + temp = Inp32(0x10c10030) & 0xFFFFFFDF; + Outp32( 0x10c10030, temp ); + DMC_Delay(0x100); //- wait 1ms + + //-CA Training. + DMC_CaTraining(0); + DMC_CaTraining(1); + + if (pkg_type == POP_TYPE) { + //-Read DQ Calibration. + Outp32( 0x10C00000+0x0004, 0x92F0001 ); //- Set PHY0.CON1.rdlvl_rddata_adj + Outp32( 0x10C10000+0x0004, 0x92F0001 ); //- Set PHY1.CON1.rdlvl_rddata_adj + Outp32( 0x10C00000+0x005C, 0x00000041 ); //- PHY0.CON22.lpddr2_addr=0x041 + Outp32( 0x10C10000+0x005C, 0x00000041 ); //- PHY1.CON22.lpddr2_addr=0x041 + Outp32( 0x10C00000+0x0008, 0x2010044 ); //- Set PHY0.CON2.rdlvl_en + Outp32( 0x10C10000+0x0008, 0x2010044 ); //- Set PHY1.CON2.rdlvl_en + Outp32( 0x10DD0000+0x00F8, 0x2 ); //- DMC.RDLVLCONFIG.ctrl_rdlvl_data_en=1 + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC000 ) != 0xC000 ); //- Wait DMC.rdlvl_complete_ch0/1 + Outp32( 0x10DD0000+0x00F8, 0x0 ); //- Set DMC.RDLVLCONFIG.ctrl_rdlvl_data_en=0 + + Outp32(0x10C00000 + 0x0014, 0xC); + while( Inp32(0x10C00000 + 0x0058) != 0); + + Outp32(0x10C10000 + 0x0014, 0xC); + while( Inp32(0x10C00000 + 0x0058) != 0); + + Outp32(0x10C00000 + 0x0014, 0x0); + Outp32(0x10C10000 + 0x0014, 0x0); + + //-Write DQ Calibration. + while( ( Inp32( 0x10DD0000+0x0048 ) & 0x3 ) != 0x0 ); //- Wait for DMC.chip_busy_state CH0 + while( ( Inp32( 0x10DD0000+0x004C ) & 0x3 ) != 0x0 ); //- Wait for DMC.chip_busy_state CH1 + Outp32( 0x10DD0000+0x00F4, 0x1 ); //- DMC.WRTRACONFIG + Outp32( 0x10C00000+0x005C, 0x204 ); //- + Outp32( 0x10C10000+0x005C, 0x204 ); //- + Outp32( 0x10C00000+0x0004, 0x92F00FF ); //-Set "rdlvl_rddata_adj" to 0x0001 or 0x0100 in PHY_CON1[15:0] + Outp32( 0x10C10000+0x0004, 0x92F00FF ); //-Set "rdlvl_rddata_adj" to 0x0001 or 0x0100 in PHY_CON1[15:0] + Outp32( 0x10C00000+0x0008, 0x6010044 ); //- + Outp32( 0x10C10000+0x0008, 0x6010044 ); //- + Outp32( 0x10C00000+0x0008, 0xE010044 ); //- + Outp32( 0x10C10000+0x0008, 0xE010044 ); //- + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC000 ) != 0xC000 ); //- Wait DMC.rdlvl_complete_ch0/1 + Outp32( 0x10C00000+0x0008, 0x6010044 ); //- + Outp32( 0x10C10000+0x0008, 0x6010044 ); //- + + Outp32(0x10C00000 + 0x0014, 0xC); + while( Inp32(0x10C00000 + 0x0058) != 0); + + Outp32(0x10C10000 + 0x0014, 0xC); + while( Inp32(0x10C10000 + 0x0058) != 0); + + Outp32(0x10C00000 + 0x0014, 0x0); + Outp32(0x10C10000 + 0x0014, 0x0); + } + + //-43) Enable PHY_CON12.ctrl_dll_on + temp = Inp32( 0x10c00030) | 0x20; + Outp32( 0x10c00030, temp ); + //while( ( Inp32(0x10c00030) & 0x1 ) != 0x1 ); + + temp = Inp32( 0x10c10030) | 0x20; + Outp32( 0x10c10030, temp ); + //while( ( Inp32(0x10c10030) & 0x1 ) != 0x1 ); + + //-44) Disable PHY_CON.ctrl_atgate when POP is used + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0000, 0x17027A00 ); //- PHY0.CON0.ctrl_atgate=0x0 + Outp32( 0x10C10000+0x0000, 0x17027A00 ); //- PHY1.CON0.ctrl_atgate=0x0 + } + Outp32( 0x10C00000+0x0000, 0x17127A00 ); //- Set PHY0.CON0.ctrl_upd_range=0x1 + Outp32( 0x10C10000+0x0000, 0x17127A00 ); //- Set PHY1.CON0.ctrl_upd_range=0x1 + + //-45) Enable PHY_CON2.DLLDeSkewEn + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0008, 0x6011044 ); //- PHY0.CON2.DllDeskewEn=1. + Outp32( 0x10C10000+0x0008, 0x6011044 ); //- PHY1.CON2.DllDeskewEn=1. + } else { + Outp32( 0x10C00000+0x0008, 0x11044 ); //- PHY0.CON2.DllDeskewEn=1. + Outp32( 0x10C10000+0x0008, 0x11044 ); //- PHY1.CON2.DllDeskewEn=1. + } + //-46) Update the DLL information + Outp32( 0x10DD0000+0x0018, 0x8 ); //- fp_resync=1 + Outp32( 0x10DD0000+0x0018, 0x0 ); //- fp_resync=0 +#endif + + //-47) ODT is not supported in LPDDR2/LPDDR3 + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0000, 0x17127A00 ); //- Set PHY0.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C00000+0x0040, 0xE080304 ); //- Set PHY0.PHY_CON16.zq_term. + Outp32( 0x10C10000+0x0000, 0x17127A00 ); //- Set PHY1.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C10000+0x0040, 0xE080304 ); //- Set PHY1.PHY_CON16.zq_term. + } + + //-48) Issue the PALL command to memory + Outp32( 0x10DD0000+0x0010, 0x1000000 ); //- send PALL to port=0x0, cs=0x0 + Outp32( 0x10DD0000+0x0010, 0x1100000 ); //- send PALL to port=0x0, cs=0x1 + Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- send PALL to port=0x1, cs=0x0 + Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- send PALL to port=0x1, cs=0x1 + //-49) Set the MEMCONTROL if power-down modes are required. + Outp32( 0x10DD0000+0x0004, 0x312700 ); //- DMC.MEMCONTROL.tp_en=0x0. + Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- DMC.PRECHCONFIG.tp_cnt=0xFF + Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- DMC.PWRDNCONFIG.dsref_cyc=0xFFFF0000 + Outp32( 0x10DD0000+0x0004, 0x312720 ); //- Set DMC.MEMCONTROL.dsref_en=0x20. + Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- Set DMC.PWRDNCONFIG.dpwrdn_cyc=0xFF + Outp32( 0x10DD0000+0x0004, 0x312722 ); //- Set DMC.MEMCONTROL.dpwrdn_en=0x2., dpwrdn_type=0x0 + Outp32( 0x10DD0000+0x0004, 0x312723 ); //- DMC.MEMCONTROL.clk_stop_en=0x1. + Outp32( 0x10DD0000+0x0000, 0xFFF2108 ); //- Set DMC.PHYCONTROL.io_pd_con=0x1. + //-50) Set the CONCONTROL to turn on an auto refresh counter. + Outp32( 0x10DD0000+0x0000, 0xFFF2128 ); //- aref enabled + + mem_ctrl_init_done(); + +} + +void mem_ctrl_init_ddr3(UINT32 nMEMCLK) +{ + UINT32 ap_odt, dram_odt; + +#if defined(CONFIG_ODTOFF_GATELEVELINGON) + ap_odt = 0xE2C0000; + dram_odt = 0x2; +#else // ODT On and Gate Leveling Off + ap_odt = 0xE240000; + dram_odt = 0x42; +#endif + + CMU_SetMemClk(nMEMCLK); + + DMC_Delay(0x10000); // wait 300ms + Outp32( 0x10030A10, 0x00000000 ); //- PHY_RESET[0]=0 + DMC_Delay(100); + Outp32( 0x10030A10, 0x00000001 ); //- PHY_RESET[0]=1 + DMC_Delay(100); + Outp32( 0x10C00000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + Outp32( 0x10C10000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + Outp32( 0x10C00000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + Outp32( 0x10C10000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + Outp32( 0x10C00000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + Outp32( 0x10C10000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + Outp32( 0x10C00000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + Outp32( 0x10C10000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + Outp32( 0x10C00000+0x0040, ap_odt|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + Outp32( 0x10C10000+0x0040, ap_odt|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + while( ( Inp32( 0x10C00000+0x0048 ) & 0x1 ) != 0x1 ); //- PHY0: wait for zq_done + while( ( Inp32( 0x10C10000+0x0048 ) & 0x1 ) != 0x1 ); //- PHY1: wait for zq_done + Outp32( 0x10C00000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + Outp32( 0x10C10000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + Outp32( 0x10C00000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + Outp32( 0x10C10000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + Outp32( 0x10DD0000+0x0000, 0x1FFF0000|(0x3<<12) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3 + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + Outp32( 0x10C00000+0x0010, 0x8080808 ); //- ctrl_offsetr + Outp32( 0x10C10000+0x0010, 0x8080808 ); //- ctrl_offsetr + Outp32( 0x10C00000+0x0018, 0x8080808 ); //- ctrl_offsetw + Outp32( 0x10C10000+0x0018, 0x8080808 ); //- ctrl_offsetw + Outp32( 0x10C00000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + Outp32( 0x10C10000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + Outp32( 0x10C00000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + Outp32( 0x10C10000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + DMC_Delay(100); + Outp32( 0x10C00000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + Outp32( 0x10C10000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + DMC_Delay(100); + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC ) != 0xC ); //- wait dfi_init_complete + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + Outp32( 0x10DD0000+0x0000, 0x0FFF0000|(0x3<<12) ); //- dfi_init_start[28]=0, rd_fetch[14:12]=3 + Outp32( 0x10DD0000+0x00F0, 0x7 ); //- channel interleaving + Outp32( 0x10DD0000+0x0008, 0x00001333 ); //- bank interleaving + Outp32( 0x10DD0000+0x000C, 0x00001333 ); //- bank interleaving + Outp32( 0x10DD0000+0x010C, 0x00400780 ); //- chip_base[26:16]=40, chip_mask[10:0]=780 + Outp32( 0x10DD0000+0x0110, 0x00800780 ); //- chip_base[26:16]=80, chip_mask[10:0]=780 + Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- precharge policy counter + Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- low power counter + Outp32( 0x10DD0000+0x0030, 0x000000bb ); //- refresh counter + Outp32( 0x10DD0000+0x0034, 0x8C36650E ); //- timing row + Outp32( 0x10DD0000+0x0038, 0x3630580B ); //- timing data + Outp32( 0x10DD0000+0x003C, 0x41000A44 ); //- timing power + // Set the QOSCONTROL0~15 and BRBQOSCONFIG register if Qos Scheme is required. + Outp32( 0x10DD0000+0x60, 0xFFF ); //- QOS#0.=0xFFF + Outp32( 0x10DD0000+0x68, 0xFFF ); //- QOS#1.=0xFFF + Outp32( 0x10DD0000+0x70, 0xFFF ); //- QOS#2.=0xFFF + Outp32( 0x10DD0000+0x78, 0xFFF ); //- QOS#3.=0xFFF + Outp32( 0x10DD0000+0x80, 0xFFF ); //- QOS#4.=0xFFF + Outp32( 0x10DD0000+0x88, 0xFFF ); //- QOS#5.=0xFFF + Outp32( 0x10DD0000+0x90, 0xFFF ); //- QOS#6.=0xFFF + Outp32( 0x10DD0000+0x98, 0xFFF ); //- QOS#7.=0xFFF + Outp32( 0x10DD0000+0xA0, 0xFFF ); //- QOS#8.=0xFFF + Outp32( 0x10DD0000+0xA8, 0xFFF ); //- QOS#9.=0xFFF + Outp32( 0x10DD0000+0xB0, 0xFFF ); //- QOS#10.=0xFFF + Outp32( 0x10DD0000+0xB8, 0xFFF ); //- QOS#11.=0xFFF + Outp32( 0x10DD0000+0xC0, 0xFFF ); //- QOS#12.=0xFFF + Outp32( 0x10DD0000+0xC8, 0xFFF ); //- QOS#13.=0xFFF + Outp32( 0x10DD0000+0xD0, 0xFFF ); //- QOS#14.=0xFFF + Outp32( 0x10DD0000+0xD8, 0x0 ); //- QOS#15.=0xFFF + Outp32( 0x10DD0000+0x0010, 0x01000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x01100000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x07000000 ); + Outp32( 0x10DD0000+0x0010, 0x00020000|0x18 ); + Outp32( 0x10DD0000+0x0010, 0x00030000 ); + Outp32( 0x10DD0000+0x0010, 0x00010000|dram_odt ); + Outp32( 0x10DD0000+0x0010, 0x00000000|0xD70 ); + Outp32( 0x10DD0000+0x0010, 0x0a000000 ); //- ZQInit + Outp32( 0x10DD0000+0x0010, 0x17000000 ); + Outp32( 0x10DD0000+0x0010, 0x10020000|0x18 ); + Outp32( 0x10DD0000+0x0010, 0x10030000 ); + Outp32( 0x10DD0000+0x0010, 0x10010000|dram_odt ); + Outp32( 0x10DD0000+0x0010, 0x10000000|0xD70 ); + Outp32( 0x10DD0000+0x0010, 0x1a000000 ); //- ZQInit + +#if defined(CONFIG_ODTOFF_GATELEVELINGON) + Outp32( 0x10C00000+0x0000, 386009664 ); // ctrl_atgate=1 + Outp32( 0x10C10000+0x0000, 386009664 ); // ctrl_atgate=1 + Outp32( 0x10C00000+0x0000, 386026048 ); // p0_cmd_en=1 + Outp32( 0x10C10000+0x0000, 386026048 ); // p0_cmd_en=1 + Outp32( 0x10C00000+0x0008, 65604 ); // InitDeskewEn=1 + Outp32( 0x10C10000+0x0008, 65604 ); // InitDeskewEn=1 + Outp32( 0x10C00000+0x0000, 386034240 ); // byte_rdlvl_en=1 + Outp32( 0x10C10000+0x0000, 386034240 ); // byte_rdlvl_en=1 + Outp32( 0x10C00000+0x0030, 0x10100050+0x1900 ); //- ctrl_force[14:8], ctrl_dll_on[5]=0 + Outp32( 0x10C10000+0x0030, 0x10100050+0x1900 ); //- ctrl_force[14:8], ctrl_dll_on[5]=0 + Outp32( 0x10C00000+0x0008, 16842820 ); // rdlvl_gate_en=1 + Outp32( 0x10C10000+0x0008, 16842820 ); // rdlvl_gate_en=1 + Outp32( 0x10C00000+0x0000, 386034496 ); // ctrl_shgate=1 + Outp32( 0x10C10000+0x0000, 386034496 ); // ctrl_shgate=1 + Outp32( 0x10C00000+0x0004, 0x9010100 ); // ctrl_gateduradj=0 + Outp32( 0x10C10000+0x0004, 0x9010100 ); // ctrl_gateduradj=0 + Outp32( 0x10DD0000+0x00f8, 0x00000001 ); //- ctrl_rdlvl_data_en[1]=1 + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC000 ) != 0xC000 ); //- Rdlvl_complete_ch1[15]=1, Rdlvl_complete_ch0[14]=1 + Outp32( 0x10DD0000+0x00f8, 0x00000000 ); //- ctrl_rdlvl_data_en[1]=0 + Outp32( 0x10C00000+0x0038, 0x00000000 ); //- ctrl_pulld_dq[11:8]=0x0, ctrl_pulld_dqs[3:0]=0x0 + Outp32( 0x10C10000+0x0038, 0x00000000 ); //- ctrl_pulld_dq[11:8]=0x0, ctrl_pulld_dqs[3:0]=0x0 + Outp32( 0x10C00000+0x0030, 0x10100070+0x1900 ); //- ctrl_force[14:8], ctrl_start[6]=1, ctrl_dll_on[5]=1 + Outp32( 0x10C10000+0x0030, 0x10100070+0x1900 ); //- ctrl_force[14:8], ctrl_start[6]=1, ctrl_dll_on[5]=1 + DMC_Delay(100); + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- ctrl_shgate[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- ctrl_shgate[29]=1, fp_resync[3]=0 + Outp32( 0x10DD0000+0x0010, 0x01000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x01100000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- Issue PALL +#endif + Outp32( 0x10DD0000+0x0004, 0x00302620 ); //- bl[22:20]=8, mem_type[11:8]=7, dsref_en[5]=1, dpwrdn_en[1]=1, clk_stop_en[0]=1 + Outp32( 0x10DD0000+0x0000, 0x0FFF0020|(0x3<<12) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3, aref_en[5]=1 + + mem_ctrl_init_done(); +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/mem_init_ddr3.S b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/mem_init_ddr3.S new file mode 100755 index 000000000..a86b192e3 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/mem_init_ddr3.S @@ -0,0 +1,412 @@ +/* + * (C) Copyright 2012 Samsung Electronics Co. Ltd + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <Platform/ArmPlatform.h> +#include <Platform/Arndale5250.h> +#include <Platform/Exynos5250_Evt1.h> +#include <Platform/Arndale5250_Val.h> +#include <AutoGen.h> + +GCC_ASM_EXPORT(ArmPlatformSecBootMemoryInit) +GCC_ASM_EXPORT(ArmPlatformClockInitialize) +GCC_ASM_EXPORT(ArmPlatformTZPCInitialize) +GCC_ASM_EXPORT(ArmPlatformSecBootAction) + +#define MCLK_CDREX_800 1 +#define CONFIG_LOW_POWER_CTRL 1 +@#define CONFIG_DMC_BRB +#define LPDDR3PHY_CTRL_CON3 0x20A20 + +ASM_PFX(ArmPlatformSecBootMemoryInit): + @push {lr} + mov r12, lr + + @Outp32( 0x10030200, 0. ); //- rCLK_SRC_CDREX + ldr r0, =0x10030200 + ldr r1, =0 + str r1, [r0] + @Outp32( 0x10030500, 16777297. ); //- rCLK_DIV_CDREX + ldr r0, =0x10030500 + ldr r1, =16777297 + str r1, [r0] + @Outp32( 0x10014104, 2111488. ); // rMPLL_CON1 + ldr r0, =0x10014104 + ldr r1, =2111488 + str r1, [r0] + @Outp32( 0x10014100, 2160591616. ); // rMPLL_CON0 + ldr r0, =0x10014100 + ldr r1, =2182417408 + str r1, [r0] +@DMC_Delay(0x10000); // wait 300ms + bl delay100 + bl delay100 + bl delay100 + @Outp32( 0x10014204, 256. ); // + ldr r0, =0x10014204 + ldr r1, =256 + str r1, [r0] +@DMC_Delay(0x10000); // wait 300ms + bl delay100 + bl delay100 + bl delay100 + @Outp32( 0x10030A10, 0x00000000 ); //- PHY_RESET[0]=0 + ldr r0, =0x10030A10 + ldr r1, =0x00000000 + str r1, [r0] +@DMC_Delay(1ms); + bl delay + @Outp32( 0x10030A10, 0x00000001 ); //- PHY_RESET[0]=1 + ldr r0, =0x10030A10 + ldr r1, =0x00000001 + str r1, [r0] +@DMC_Delay(1ms); + bl delay + @Outp32( 0x10C00000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + ldr r0, =(0x10C00000+0x00a0) + ldr r1, =0x000006db + str r1, [r0] + @Outp32( 0x10C10000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + ldr r0, =(0x10C10000+0x00a0) + ldr r1, =0x000006db + str r1, [r0] + @Outp32( 0x10C00000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + ldr r0, =(0x10C00000+0x00ac) + ldr r1, =0x0000080b + str r1, [r0] + @Outp32( 0x10C10000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + ldr r0, =(0x10C10000+0x00ac) + ldr r1, =0x0000080b + str r1, [r0] + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0306) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0306) + str r1, [r0] +@DMC_Delay(1ms); + bl delay + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C00000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + ldr r0, =(0x10C00000+0x0038) + ldr r1, =(0x0000000f) + str r1, [r0] + @Outp32( 0x10C10000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + ldr r0, =(0x10C10000+0x0038) + ldr r1, =(0x0000000f) + str r1, [r0] + @Outp32( 0x10DD0000+0x0000, 0x1FFF0000|(0x3<<12.) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3 + ldr r0, =(0x10DD0000+0x0000) + ldr r1, =(0x1FFF0000|(0x3<<12)) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000008) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000000) + str r1, [r0] + @Outp32( 0x10C00000+0x0010, 0x8080808 ); //- ctrl_offsetr + ldr r0, =(0x10C00000+0x0010) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C10000+0x0010, 0x8080808 ); //- ctrl_offsetr + ldr r0, =(0x10C10000+0x0010) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C00000+0x0018, 0x8080808 ); //- ctrl_offsetw + ldr r0, =(0x10C00000+0x0018) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C10000+0x0018, 0x8080808 ); //- ctrl_offsetw + ldr r0, =(0x10C10000+0x0018) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C00000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + ldr r0, =(0x10C00000+0x0028) + ldr r1, =(0x8) + str r1, [r0] + @Outp32( 0x10C10000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + ldr r0, =(0x10C10000+0x0028) + ldr r1, =(0x8) + str r1, [r0] + @Outp32( 0x10C00000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + ldr r0, =(0x10C00000+0x0030) + ldr r1, =(0x10100030) + str r1, [r0] + @Outp32( 0x10C10000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + ldr r0, =(0x10C10000+0x0030) + ldr r1, =(0x10100030) + str r1, [r0] +@DMC_Delay(1ms); +bl delay + @Outp32( 0x10C00000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + ldr r0, =(0x10C00000+0x0030) + ldr r1, =(0x10100070) + str r1, [r0] + @Outp32( 0x10C10000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + ldr r0, =(0x10C10000+0x0030) + ldr r1, =(0x10100070) + str r1, [r0] +@DMC_Delay(1ms); +bl delay +@DMC_Delay(1ms); +bl delay + @Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000008) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000000) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000008) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000000) + str r1, [r0] + @Outp32( 0x10DD0000+0x0000, 0x0FFF0000|(0x3<<12.) ); //- dfi_init_start[28]=0, rd_fetch[14:12]=3 + ldr r0, =(0x10DD0000+0x0000) + ldr r1, =(0x0FFF0000|(0x3<<12)) + str r1, [r0] + @Outp32( 0x10DD0000+0x00F0, 0x3 ); //- channel interleaving + ldr r0, =(0x10DD0000+0x00F0) + ldr r1, =(0x3) + str r1, [r0] + @Outp32( 0x10DD0000+0x0008, 0x00001333 ); //- bank interleaving + ldr r0, =(0x10DD0000+0x0008) + ldr r1, =(0x00001333) + str r1, [r0] + @Outp32( 0x10DD0000+0x000C, 0x00001333 ); //- bank interleaving + ldr r0, =(0x10DD0000+0x000C) + ldr r1, =(0x00001333) + str r1, [r0] + @Outp32( 0x10DD0000+0x010C, 0x00400780 ); //- chip_base[26:16]=40, chip_mask[10:0]=780 + ldr r0, =(0x10DD0000+0x010C) + ldr r1, =(0x00400780) + str r1, [r0] + @Outp32( 0x10DD0000+0x0110, 0x00800780 ); //- chip_base[26:16]=80, chip_mask[10:0]=780 + ldr r0, =(0x10DD0000+0x0110) + ldr r1, =(0x00800780) + str r1, [r0] + @Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- precharge policy counter + ldr r0, =(0x10DD0000+0x0014) + ldr r1, =(0xFF000000) + str r1, [r0] + @Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- low power counter + ldr r0, =(0x10DD0000+0x0028) + ldr r1, =(0xFFFF00FF) + str r1, [r0] + @Outp32( 0x10DD0000+0x0030, 0x000000bb ); //- refresh counter + ldr r0, =(0x10DD0000+0x0030) + ldr r1, =(0x000000bb) + str r1, [r0] + @Outp32( 0x10DD0000+0x0034, 0x8C36650E ); //- timing row + ldr r0, =(0x10DD0000+0x0034) + ldr r1, =(0x8C36650E) + str r1, [r0] + @Outp32( 0x10DD0000+0x0038, 0x3630580B ); //- timing data + ldr r0, =(0x10DD0000+0x0038) + ldr r1, =(0x3630580B) + str r1, [r0] + @Outp32( 0x10DD0000+0x003C, 0x41000A44 ); //- timing power + ldr r0, =(0x10DD0000+0x003C) + ldr r1, =(0x41000A44) + str r1, [r0] + @Outp32( 0x10DD0000+0x0010, 0x01000000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x01000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x01100000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x01100000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x11000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x11100000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x07000000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x07000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00020000|0x18 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00020000|0x18) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00030000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00030000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00010000|0x42 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00010000|0x42) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00000000|0xD70 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00000000|0xD70) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x0a000000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x0a000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x17000000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x17000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10020000|0x18 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10020000|0x18) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10030000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10030000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10010000|0x42 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10010000|0x42) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10000000|0xD70 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10000000|0xD70) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x1a000000 ); //- ZQInit + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x1a000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0004, 0x00302620 ); //- bl[22:20]=8, mem_type[11:8]=7, dsref_en[5]=1, dpwrdn_en[1]=1, clk_stop_en[0]=1 + ldr r0, =(0x10DD0000+0x0004) + ldr r1, =(0x00302620) + str r1, [r0] + @Outp32( 0x10DD0000+0x0000, 0x0FFF0020|(0x3<<12.) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3, aref_en[5]=1 + ldr r0, =(0x10DD0000+0x0000) + ldr r1, =(0x0FFF0020|(0x3<<12)) + str r1, [r0] + +#if defined(CONFIG_DMC_BRB) + /* DMC BRB QoS */ + ldr r0, =DMC_CTRL_BASE + ldr r1, =0x66668666 + str r1, [r0, #DMC_BRBRSVCONFIG] + ldr r1, =0xFF + str r1, [r0, #DMC_BRBRSVCONTROL] + ldr r1, =0x1 + str r1, [r0, #DMC_BRBQOSCONFIG] +#endif + @pop {lr} + mov lr, r12 + mov pc, lr + + .globl dmc_delay +dmc_delay: + subs r0, r0, #1 + bne dmc_delay + mov pc, lr + +delay100: + mov r2, #0x10000 +delayloop100: + subs r2, r2, #1 + bne delayloop100 + mov pc, lr + +delay: + mov r2, #0x100 +delayloop: + subs r2, r2, #1 + bne delayloop + mov pc, lr + +wait_pll_lock: + ldr r1, [r0, r2] + tst r1, #(1<<29) + beq wait_pll_lock + mov pc, lr + +wait_mux_state: + add r2, r2, #0x200 +check_mux_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_mux_state + mov pc, lr + +wait_div_state: + add r2, r2, #0x100 +check_div_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_div_state + mov pc, lr |