]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c
Vlv2TbltDevicePkg: Sync the branch changes to trunk.
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / MultiPlatformLib / BoardClkGens / BoardClkGens.c
CommitLineData
3cbfba02
DW
1/** @file\r
2 Clock generator setting for multiplatform.\r
3\r
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
5 \r\r
6 This program and the accompanying materials are licensed and made available under\r\r
7 the terms and conditions of the BSD License that accompanies this distribution. \r\r
8 The full text of the license may be found at \r\r
9 http://opensource.org/licenses/bsd-license.php. \r\r
10 \r\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
13 \r\r
14\r
15**/\r
16\r
17#include <BoardClkGens.h>\r
18#include <Guid/SetupVariable.h>\r
19#include <Ppi/ReadOnlyVariable2.h>\r
20#include <Library/BaseMemoryLib.h>\r
21\r
22#ifndef __GNUC__\r
23#pragma optimize( "", off )\r
24#endif\r
25\r
26#define CLKGEN_EN 1\r
27#define EFI_DEBUG 1\r
28\r
29CLOCK_GENERATOR_DETAILS mSupportedClockGeneratorTable[] =\r
30{\r
31 { ClockGeneratorCk410, CK410_GENERATOR_ID , CK410_GENERATOR_SPREAD_SPECTRUM_BYTE, CK410_GENERATOR_SPREAD_SPECTRUM_BIT },\r
32 { ClockGeneratorCk505, CK505_GENERATOR_ID , CK505_GENERATOR_SPREAD_SPECTRUM_BYTE, CK505_GENERATOR_SPREAD_SPECTRUM_BIT }\r
33};\r
34\r
35/**\r
36 Configure the clock generator using the SMBUS PPI services.\r
37\r
38 This function performs a block write, and dumps debug information.\r
39\r
40 @param PeiServices General purpose services available to every PEIM.\r
41 @param ClockType Clock generator's model name.\r
42 @param ClockAddress SMBUS address of clock generator.\r
43 @param ConfigurationTableLength Length of configuration table.\r
44 @param ConfigurationTable Pointer of configuration table.\r
45\r
46 @retval EFI_SUCCESS - Operation success.\r
47\r
48**/\r
49EFI_STATUS\r
50ConfigureClockGenerator (\r
51 IN EFI_PEI_SERVICES **PeiServices,\r
52 IN EFI_PEI_SMBUS_PPI *SmbusPpi,\r
53 IN CLOCK_GENERATOR_TYPE ClockType,\r
54 IN UINT8 ClockAddress,\r
55 IN UINTN ConfigurationTableLength,\r
56 IN OUT UINT8 *ConfigurationTable\r
57 )\r
58{\r
59\r
60 EFI_STATUS Status;\r
61 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;\r
62 UINT8 Buffer[MAX_CLOCK_GENERATOR_BUFFER_LENGTH];\r
63 UINTN Length;\r
64 EFI_SMBUS_DEVICE_COMMAND Command;\r
65#if CLKGEN_CONFIG_EXTRA\r
66 UINT8 j;\r
67#endif\r
68\r
69 //\r
70 // Verify input arguments\r
71 //\r
72 ASSERT_EFI_ERROR (ConfigurationTableLength >= 6);\r
73 ASSERT_EFI_ERROR (ConfigurationTableLength <= MAX_CLOCK_GENERATOR_BUFFER_LENGTH);\r
74 ASSERT_EFI_ERROR (ClockType < ClockGeneratorMax);\r
75 ASSERT_EFI_ERROR (ConfigurationTable != NULL);\r
76\r
77 //\r
78 // Read the clock generator\r
79 //\r
80 SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
81 Length = sizeof (Buffer);\r
82 Command = 0;\r
83 Status = SmbusPpi->Execute (\r
84 PeiServices,\r
85 SmbusPpi,\r
86 SlaveAddress,\r
87 Command,\r
88 EfiSmbusReadBlock,\r
89 FALSE,\r
90 &Length,\r
91 Buffer\r
92 );\r
93 ASSERT_EFI_ERROR (Status);\r
94\r
95#ifdef EFI_DEBUG\r
96 {\r
97 UINT8 i;\r
98 for (i = 0; i < sizeof (Buffer); i++) {\r
99 DEBUG((EFI_D_ERROR, "CK505 default Clock Generator Byte %d: %x\n", i, Buffer[i]));\r
100 }\r
101#if CLKGEN_EN\r
102 for (i = 0; i < ConfigurationTableLength; i++) {\r
103 DEBUG((EFI_D_ERROR, "BIOS structure Clock Generator Byte %d: %x\n", i, ConfigurationTable[i]));\r
104 }\r
105#endif\r
106 }\r
107#endif\r
108\r
109 DEBUG((EFI_D_ERROR, "Expected Clock Generator ID is %x, expecting %x\n", mSupportedClockGeneratorTable[ClockType].ClockId,(Buffer[7]&0xF)));\r
110\r
111 //\r
112 // Program clock generator\r
113 //\r
114 Command = 0;\r
115#if CLKGEN_EN\r
116#if CLKGEN_CONFIG_EXTRA\r
117 for (j = 0; j < ConfigurationTableLength; j++) {\r
118 Buffer[j] = ConfigurationTable[j];\r
119 }\r
120\r
121 Buffer[30] = 0x00;\r
122\r
123 Status = SmbusPpi->Execute (\r
124 PeiServices,\r
125 SmbusPpi,\r
126 SlaveAddress,\r
127 Command,\r
128 EfiSmbusWriteBlock,\r
129 FALSE,\r
130 &Length,\r
131 Buffer\r
132 );\r
133#else\r
134 Status = SmbusPpi->Execute (\r
135 PeiServices,\r
136 SmbusPpi,\r
137 SlaveAddress,\r
138 Command,\r
139 EfiSmbusWriteBlock,\r
140 FALSE,\r
141 &ConfigurationTableLength,\r
142 ConfigurationTable\r
143 );\r
144#endif // CLKGEN_CONFIG_EXTRA\r
145#else\r
146 ConfigurationTable[4] = (ConfigurationTable[4] & 0x3) | (Buffer[4] & 0xFC);\r
147 Command = 4;\r
148 Length = 1;\r
149 Status = SmbusPpi->Execute (\r
150 PeiServices,\r
151 SmbusPpi,\r
152 SlaveAddress,\r
153 Command,\r
154 EfiSmbusWriteBlock,\r
155 FALSE,\r
156 &Length,\r
157 &ConfigurationTable[4]\r
158 );\r
159#endif //CLKGEN_EN\r
160 ASSERT_EFI_ERROR (Status);\r
161\r
162 //\r
163 // Dump contents after write\r
164 //\r
165 #ifdef EFI_DEBUG\r
166 {\r
167 UINT8 i;\r
168 SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
169 Length = sizeof (Buffer);\r
170 Command = 0;\r
171 Status = SmbusPpi->Execute (\r
172 PeiServices,\r
173 SmbusPpi,\r
174 SlaveAddress,\r
175 Command,\r
176 EfiSmbusReadBlock,\r
177 FALSE,\r
178 &Length,\r
179 Buffer\r
180 );\r
181\r
182 for (i = 0; i < ConfigurationTableLength; i++) {\r
183 DEBUG((EFI_D_ERROR, "Clock Generator Byte %d: %x\n", i, Buffer[i]));\r
184 }\r
185 }\r
186 #endif\r
187\r
188 return EFI_SUCCESS;\r
189}\r
190\r
191/**\r
192 Configure the clock generator using the SMBUS PPI services.\r
193\r
194 This function performs a block write, and dumps debug information.\r
195\r
196 @param PeiServices General purpose services available to every PEIM.\r
197 @param ClockType Clock generator's model name.\r
198 @param ClockAddress SMBUS address of clock generator.\r
199 @param ConfigurationTableLength Length of configuration table.\r
200 @param ConfigurationTable Pointer of configuration table.\r
201\r
202\r
203 @retval EFI_SUCCESS Operation success.\r
204\r
205**/\r
206UINT8\r
207ReadClockGeneratorID (\r
208 IN EFI_PEI_SERVICES **PeiServices,\r
209 IN EFI_PEI_SMBUS_PPI *SmbusPpi,\r
210 IN UINT8 ClockAddress\r
211 )\r
212{\r
213 EFI_STATUS Status;\r
214 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;\r
215 UINT8 Buffer[MAX_CLOCK_GENERATOR_BUFFER_LENGTH];\r
216 UINTN Length;\r
217 EFI_SMBUS_DEVICE_COMMAND Command;\r
218\r
219 //\r
220 // Read the clock generator\r
221 //\r
222 SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
223 Length = sizeof (Buffer);\r
224 Command = 0;\r
225 Status = SmbusPpi->Execute (\r
226 PeiServices,\r
227 SmbusPpi,\r
228 SlaveAddress,\r
229 Command,\r
230 EfiSmbusReadBlock,\r
231 FALSE,\r
232 &Length,\r
233 Buffer\r
234 );\r
235\r
236 //\r
237 // Sanity check that the requested clock type is present in our supported clocks table\r
238 //\r
239 DEBUG((EFI_D_ERROR, "Expected Clock Generator ID is 0x%x\n", Buffer[7]));\r
240\r
241 return (Buffer[7]);\r
242}\r
243\r
244/**\r
245 Configure the clock generator to enable free-running operation. This keeps\r
246 the clocks from being stopped when the system enters C3 or C4.\r
247\r
248 @param None\r
249\r
250 @retval EFI_SUCCESS The function completed successfully.\r
251\r
252**/\r
253EFI_STATUS\r
254ConfigurePlatformClocks (\r
255 IN EFI_PEI_SERVICES **PeiServices,\r
256 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
257 IN VOID *SmbusPpi\r
258 )\r
259{\r
260 //\r
261 // Comment it out for now\r
262 // Not supported by Hybrid model.\r
263 //\r
264 EFI_STATUS Status;\r
265 UINT8 *ConfigurationTable;\r
266\r
267 CLOCK_GENERATOR_TYPE ClockType = ClockGeneratorCk505;\r
268 UINT8 ConfigurationTable_Desktop[] = CLOCK_GENERATOR_SETTINGS_DESKTOP;\r
269 UINT8 ConfigurationTable_Mobile[] = CLOCK_GENERATOR_SETTINGS_MOBILE;\r
270 UINT8 ConfigurationTable_Tablet[] = CLOCK_GENERATOR_SEETINGS_TABLET;\r
271\r
272 EFI_PLATFORM_INFO_HOB *PlatformInfoHob;\r
273 BOOLEAN EnableSpreadSpectrum;\r
274 UINT8 ClockGenID=0;\r
275 SYSTEM_CONFIGURATION SystemConfiguration;\r
276\r
277 UINTN Length;\r
278 EFI_SMBUS_DEVICE_COMMAND Command;\r
279 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;\r
280 UINT8 Data;\r
281\r
282 UINT8 ClockAddress = CLOCK_GENERATOR_ADDRESS;\r
283 UINTN VariableSize;\r
284 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;\r
285\r
286 //\r
287 // Obtain Platform Info from HOB.\r
288 //\r
289 Status = GetPlatformInfoHob ((CONST EFI_PEI_SERVICES **) PeiServices, &PlatformInfoHob);\r
290 ASSERT_EFI_ERROR (Status);\r
291\r
292 DEBUG((EFI_D_ERROR, "PlatformInfo protocol is working in ConfigurePlatformClocks()...%x\n",PlatformInfoHob->PlatformFlavor));\r
293\r
294 //\r
295 // Locate SMBUS PPI\r
296 //\r
297 Status = (**PeiServices).LocatePpi (\r
298 (CONST EFI_PEI_SERVICES **) PeiServices,\r
299 &gEfiPeiSmbusPpiGuid,\r
300 0,\r
301 NULL,\r
302 &SmbusPpi\r
303 );\r
304 ASSERT_EFI_ERROR (Status);\r
305\r
306 Data = 0;\r
307 SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
308 Length = 1;\r
309 Command = 0x87; //Control Register 7 Vendor ID Check\r
310 Status = ((EFI_PEI_SMBUS_PPI *) SmbusPpi)->Execute (\r
311 PeiServices,\r
312 SmbusPpi,\r
313 SlaveAddress,\r
314 Command,\r
315 EfiSmbusReadByte,\r
316 FALSE,\r
317 &Length,\r
318 &Data\r
319 );\r
320\r
321 if (EFI_ERROR (Status) || ((Data & 0x0F) != CK505_GENERATOR_ID)) {\r
322 DEBUG((EFI_D_ERROR, "Clock Generator CK505 Not Present, vendor ID on board is %x\n",(Data & 0x0F)));\r
323 return EFI_SUCCESS;\r
324}\r
325 ClockGenID = Data & 0x0F;\r
326\r
327 EnableSpreadSpectrum = FALSE;\r
328 VariableSize = sizeof (SYSTEM_CONFIGURATION);\r
329 ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION));\r
330\r
331 Status = (*PeiServices)->LocatePpi (\r
332 (CONST EFI_PEI_SERVICES **) PeiServices,\r
333 &gEfiPeiReadOnlyVariable2PpiGuid,\r
334 0,\r
335 NULL,\r
336 (VOID **) &Variable\r
337 );\r
338 //\r
339 // Use normal setup default from NVRAM variable,\r
340 // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable.\r
341 //\r
342 VariableSize = sizeof(SYSTEM_CONFIGURATION);\r
343 Status = Variable->GetVariable (Variable,\r
344 L"Setup",\r
345 &gEfiSetupVariableGuid,\r
346 NULL,\r
347 &VariableSize,\r
348 &SystemConfiguration);\r
620f2891
TH
349 if (EFI_ERROR (Status) || VariableSize != sizeof(SYSTEM_CONFIGURATION)) {\r
350 //The setup variable is corrupted\r
351 VariableSize = sizeof(SYSTEM_CONFIGURATION);\r
352 Status = Variable->GetVariable(Variable,\r
353 L"SetupRecovery",\r
354 &gEfiSetupVariableGuid,\r
355 NULL,\r
356 &VariableSize,\r
357 &SystemConfiguration\r
358 );\r
359 ASSERT_EFI_ERROR (Status);\r
360 } \r
3cbfba02
DW
361 if(!EFI_ERROR (Status)){\r
362 EnableSpreadSpectrum = SystemConfiguration.EnableClockSpreadSpec;\r
363 }\r
364\r
365 //\r
366 // Perform platform-specific intialization dependent upon Board ID:\r
367 //\r
368 DEBUG((EFI_D_ERROR, "board id is %x, platform id is %x\n",PlatformInfoHob->BoardId,PlatformInfoHob->PlatformFlavor));\r
369\r
370\r
371 switch (PlatformInfoHob->BoardId) {\r
372 case BOARD_ID_MINNOW2:\r
8b7a63e7 373 case BOARD_ID_MINNOW2_TURBOT:\r
3cbfba02
DW
374 default:\r
375 switch(PlatformInfoHob->PlatformFlavor) {\r
376 case FlavorTablet:\r
377 ConfigurationTable = ConfigurationTable_Tablet;\r
378 Length = sizeof (ConfigurationTable_Tablet);\r
379 break;\r
380 case FlavorMobile:\r
381 ConfigurationTable = ConfigurationTable_Mobile;\r
382 Length = sizeof (ConfigurationTable_Mobile);\r
383 break;\r
384 case FlavorDesktop:\r
385 default:\r
386 ConfigurationTable = ConfigurationTable_Desktop;\r
387 Length = sizeof (ConfigurationTable_Desktop);\r
388 break;\r
389 }\r
390 break;\r
391 }\r
392\r
393 //\r
394 // Perform common clock initialization:\r
395 //\r
396 // Program Spread Spectrum function.\r
397 //\r
398 if (EnableSpreadSpectrum)\r
399 {\r
400 ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] |= mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset;\r
401 } else {\r
402 ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] &= ~(mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset);\r
403 }\r
404\r
405\r
406#if CLKGEN_EN\r
407 Status = ConfigureClockGenerator (PeiServices, SmbusPpi, ClockType, ClockAddress, Length, ConfigurationTable);\r
408 ASSERT_EFI_ERROR (Status);\r
409#endif // CLKGEN_EN\r
410 return EFI_SUCCESS;\r
411}\r
412\r
413static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {\r
414 {\r
415 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
416 &gEfiPeiSmbusPpiGuid,\r
417 ConfigurePlatformClocks\r
418 }\r
419};\r
420\r
421EFI_STATUS\r
422InstallPlatformClocksNotify (\r
423 IN CONST EFI_PEI_SERVICES **PeiServices\r
424 )\r
425{\r
426 EFI_STATUS Status;\r
427\r
428 DEBUG ((EFI_D_INFO, "InstallPlatformClocksNotify()...\n"));\r
429\r
430 Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]);\r
431 ASSERT_EFI_ERROR (Status);\r
432 return EFI_SUCCESS;\r
433\r
434}\r
435\r
436#ifndef __GNUC__\r
437#pragma optimize( "", on )\r
438#endif\r