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