1 /** @file 2 * 3 * Copyright (c) 2011-2013, ARM Limited. All rights reserved. 4 * 5 * This program and the accompanying materials 6 * are licensed and made available under the terms and conditions of the BSD License 7 * which accompanies this distribution. The full text of the license may be found at 8 * http://opensource.org/licenses/bsd-license.php 9 * 10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 * 13 **/ 14 15 #include <Library/IoLib.h> 16 #include <Library/ArmPlatformLib.h> 17 #include <Library/DebugLib.h> 18 #include <Library/PcdLib.h> 19 20 #include <Drivers/PL341Dmc.h> 21 #include <Drivers/PL301Axi.h> 22 #include <Drivers/SP804Timer.h> 23 24 #include <Ppi/ArmMpCoreInfo.h> 25 26 #include <ArmPlatform.h> 27 28 ARM_CORE_INFO mVersatileExpressMpCoreInfoCTA9x4[] = { 29 { 30 // Cluster 0, Core 0 31 0x0, 0x0, 32 33 // MP Core MailBox Set/Get/Clear Addresses and Clear Value 34 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG, 35 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG, 36 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG, 37 (UINT64)0xFFFFFFFF 38 }, 39 { 40 // Cluster 0, Core 1 41 0x0, 0x1, 42 43 // MP Core MailBox Set/Get/Clear Addresses and Clear Value 44 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG, 45 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG, 46 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG, 47 (UINT64)0xFFFFFFFF 48 }, 49 { 50 // Cluster 0, Core 2 51 0x0, 0x2, 52 53 // MP Core MailBox Set/Get/Clear Addresses and Clear Value 54 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG, 55 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG, 56 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG, 57 (UINT64)0xFFFFFFFF 58 }, 59 { 60 // Cluster 0, Core 3 61 0x0, 0x3, 62 63 // MP Core MailBox Set/Get/Clear Addresses and Clear Value 64 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG, 65 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG, 66 (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG, 67 (UINT64)0xFFFFFFFF 68 } 69 }; 70 71 // DDR2 timings 72 PL341_DMC_CONFIG DDRTimings = { 73 .MaxChip = 1, 74 .IsUserCfg = TRUE, 75 .User0Cfg = 0x7C924924, 76 .User2Cfg = (TC_UIOLHXC_VALUE << TC_UIOLHNC_SHIFT) | (TC_UIOLHXC_VALUE << TC_UIOLHPC_SHIFT) | (0x1 << TC_UIOHOCT_SHIFT) | (0x1 << TC_UIOHSTOP_SHIFT), 77 .HasQos = TRUE, 78 .RefreshPeriod = 0x3D0, 79 .CasLatency = 0x8, 80 .WriteLatency = 0x3, 81 .t_mrd = 0x2, 82 .t_ras = 0xA, 83 .t_rc = 0xE, 84 .t_rcd = 0x104, 85 .t_rfc = 0x2f32, 86 .t_rp = 0x14, 87 .t_rrd = 0x2, 88 .t_wr = 0x4, 89 .t_wtr = 0x2, 90 .t_xp = 0x2, 91 .t_xsr = 0xC8, 92 .t_esr = 0x14, 93 .MemoryCfg = DMC_MEMORY_CONFIG_ACTIVE_CHIP_1 | DMC_MEMORY_CONFIG_BURST_4 | 94 DMC_MEMORY_CONFIG_ROW_ADDRESS_15 | DMC_MEMORY_CONFIG_COLUMN_ADDRESS_10, 95 .MemoryCfg2 = DMC_MEMORY_CFG2_DQM_INIT | DMC_MEMORY_CFG2_CKE_INIT | 96 DMC_MEMORY_CFG2_BANK_BITS_3 | DMC_MEMORY_CFG2_MEM_WIDTH_32, 97 .MemoryCfg3 = 0x00000001, 98 .ChipCfg0 = 0x00010000, 99 .t_faw = 0x00000A0D, 100 .ModeReg = DDR2_MR_BURST_LENGTH_4 | DDR2_MR_CAS_LATENCY_4 | DDR2_MR_WR_CYCLES_4, 101 .ExtModeReg = DDR_EMR_RTT_50R | (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK), 102 }; 103 104 /** 105 Return the current Boot Mode 106 107 This function returns the boot reason on the platform 108 109 @return Return the current Boot Mode of the platform 110 111 **/ 112 EFI_BOOT_MODE 113 ArmPlatformGetBootMode ( 114 VOID 115 ) 116 { 117 if (MmioRead32(ARM_VE_SYS_FLAGS_NV_REG) == 0) { 118 return BOOT_WITH_FULL_CONFIGURATION; 119 } else { 120 return BOOT_ON_S2_RESUME; 121 } 122 } 123 124 /** 125 Initialize controllers that must setup in the normal world 126 127 This function is called by the ArmPlatformPkg/PrePi or ArmPlatformPkg/PlatformPei 128 in the PEI phase. 129 130 **/ 131 RETURN_STATUS 132 ArmPlatformInitialize ( 133 IN UINTN MpId 134 ) 135 { 136 if (!ArmPlatformIsPrimaryCore (MpId)) { 137 return RETURN_SUCCESS; 138 } 139 140 // Configure periodic timer (TIMER0) for 1MHz operation 141 MmioOr32 (SP810_CTRL_BASE + SP810_SYS_CTRL_REG, SP810_SYS_CTRL_TIMER0_TIMCLK); 142 // Configure 1MHz clock 143 MmioOr32 (SP810_CTRL_BASE + SP810_SYS_CTRL_REG, SP810_SYS_CTRL_TIMER1_TIMCLK); 144 // configure SP810 to use 1MHz clock and disable 145 MmioAndThenOr32 (SP810_CTRL_BASE + SP810_SYS_CTRL_REG, ~SP810_SYS_CTRL_TIMER2_EN, SP810_SYS_CTRL_TIMER2_TIMCLK); 146 // Configure SP810 to use 1MHz clock and disable 147 MmioAndThenOr32 (SP810_CTRL_BASE + SP810_SYS_CTRL_REG, ~SP810_SYS_CTRL_TIMER3_EN, SP810_SYS_CTRL_TIMER3_TIMCLK); 148 149 return RETURN_SUCCESS; 150 } 151 152 /** 153 Initialize the system (or sometimes called permanent) memory 154 155 This memory is generally represented by the DRAM. 156 157 **/ 158 VOID 159 ArmPlatformInitializeSystemMemory ( 160 VOID 161 ) 162 { 163 PL341DmcInit (ARM_VE_DMC_BASE, &DDRTimings); 164 PL301AxiInit (ARM_VE_FAXI_BASE); 165 } 166 167 EFI_STATUS 168 PrePeiCoreGetMpCoreInfo ( 169 OUT UINTN *CoreCount, 170 OUT ARM_CORE_INFO **ArmCoreTable 171 ) 172 { 173 *CoreCount = sizeof(mVersatileExpressMpCoreInfoCTA9x4) / sizeof(ARM_CORE_INFO); 174 *ArmCoreTable = mVersatileExpressMpCoreInfoCTA9x4; 175 176 return EFI_SUCCESS; 177 } 178 179 ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo }; 180 181 EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = { 182 { 183 EFI_PEI_PPI_DESCRIPTOR_PPI, 184 &gArmMpCoreInfoPpiGuid, 185 &mMpCoreInfoPpi 186 } 187 }; 188 189 VOID 190 ArmPlatformGetPlatformPpiList ( 191 OUT UINTN *PpiListSize, 192 OUT EFI_PEI_PPI_DESCRIPTOR **PpiList 193 ) 194 { 195 *PpiListSize = sizeof(gPlatformPpiTable); 196 *PpiList = gPlatformPpiTable; 197 } 198 199