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
ArmPlatformGetBootMode(VOID)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
ArmPlatformInitialize(IN UINTN MpId)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
ArmPlatformInitializeSystemMemory(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
PrePeiCoreGetMpCoreInfo(OUT UINTN * CoreCount,OUT ARM_CORE_INFO ** ArmCoreTable)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
ArmPlatformGetPlatformPpiList(OUT UINTN * PpiListSize,OUT EFI_PEI_PPI_DESCRIPTOR ** PpiList)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