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