]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c
Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
[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
349\r
350 if(!EFI_ERROR (Status)){\r
351 EnableSpreadSpectrum = SystemConfiguration.EnableClockSpreadSpec;\r
352 }\r
353\r
354 //\r
355 // Perform platform-specific intialization dependent upon Board ID:\r
356 //\r
357 DEBUG((EFI_D_ERROR, "board id is %x, platform id is %x\n",PlatformInfoHob->BoardId,PlatformInfoHob->PlatformFlavor));\r
358\r
359\r
360 switch (PlatformInfoHob->BoardId) {\r
361 case BOARD_ID_MINNOW2:\r
362 default:\r
363 switch(PlatformInfoHob->PlatformFlavor) {\r
364 case FlavorTablet:\r
365 ConfigurationTable = ConfigurationTable_Tablet;\r
366 Length = sizeof (ConfigurationTable_Tablet);\r
367 break;\r
368 case FlavorMobile:\r
369 ConfigurationTable = ConfigurationTable_Mobile;\r
370 Length = sizeof (ConfigurationTable_Mobile);\r
371 break;\r
372 case FlavorDesktop:\r
373 default:\r
374 ConfigurationTable = ConfigurationTable_Desktop;\r
375 Length = sizeof (ConfigurationTable_Desktop);\r
376 break;\r
377 }\r
378 break;\r
379 }\r
380\r
381 //\r
382 // Perform common clock initialization:\r
383 //\r
384 // Program Spread Spectrum function.\r
385 //\r
386 if (EnableSpreadSpectrum)\r
387 {\r
388 ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] |= mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset;\r
389 } else {\r
390 ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] &= ~(mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset);\r
391 }\r
392\r
393\r
394#if CLKGEN_EN\r
395 Status = ConfigureClockGenerator (PeiServices, SmbusPpi, ClockType, ClockAddress, Length, ConfigurationTable);\r
396 ASSERT_EFI_ERROR (Status);\r
397#endif // CLKGEN_EN\r
398 return EFI_SUCCESS;\r
399}\r
400\r
401static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {\r
402 {\r
403 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
404 &gEfiPeiSmbusPpiGuid,\r
405 ConfigurePlatformClocks\r
406 }\r
407};\r
408\r
409EFI_STATUS\r
410InstallPlatformClocksNotify (\r
411 IN CONST EFI_PEI_SERVICES **PeiServices\r
412 )\r
413{\r
414 EFI_STATUS Status;\r
415\r
416 DEBUG ((EFI_D_INFO, "InstallPlatformClocksNotify()...\n"));\r
417\r
418 Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]);\r
419 ASSERT_EFI_ERROR (Status);\r
420 return EFI_SUCCESS;\r
421\r
422}\r
423\r
424#ifndef __GNUC__\r
425#pragma optimize( "", on )\r
426#endif\r