2 Clock generator setting for multiplatform.
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <BoardClkGens.h>
18 #include <Guid/SetupVariable.h>
19 #include <Ppi/ReadOnlyVariable2.h>
20 #include <Library/BaseMemoryLib.h>
23 #pragma optimize( "", off )
29 CLOCK_GENERATOR_DETAILS mSupportedClockGeneratorTable
[] =
31 { ClockGeneratorCk410
, CK410_GENERATOR_ID
, CK410_GENERATOR_SPREAD_SPECTRUM_BYTE
, CK410_GENERATOR_SPREAD_SPECTRUM_BIT
},
32 { ClockGeneratorCk505
, CK505_GENERATOR_ID
, CK505_GENERATOR_SPREAD_SPECTRUM_BYTE
, CK505_GENERATOR_SPREAD_SPECTRUM_BIT
}
36 Configure the clock generator using the SMBUS PPI services.
38 This function performs a block write, and dumps debug information.
40 @param PeiServices General purpose services available to every PEIM.
41 @param ClockType Clock generator's model name.
42 @param ClockAddress SMBUS address of clock generator.
43 @param ConfigurationTableLength Length of configuration table.
44 @param ConfigurationTable Pointer of configuration table.
46 @retval EFI_SUCCESS - Operation success.
50 ConfigureClockGenerator (
51 IN EFI_PEI_SERVICES
**PeiServices
,
52 IN EFI_PEI_SMBUS_PPI
*SmbusPpi
,
53 IN CLOCK_GENERATOR_TYPE ClockType
,
54 IN UINT8 ClockAddress
,
55 IN UINTN ConfigurationTableLength
,
56 IN OUT UINT8
*ConfigurationTable
61 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress
;
62 UINT8 Buffer
[MAX_CLOCK_GENERATOR_BUFFER_LENGTH
];
64 EFI_SMBUS_DEVICE_COMMAND Command
;
65 #if CLKGEN_CONFIG_EXTRA
70 // Verify input arguments
72 ASSERT (ConfigurationTableLength
>= 6);
73 ASSERT (ConfigurationTableLength
<= MAX_CLOCK_GENERATOR_BUFFER_LENGTH
);
74 ASSERT (ClockType
< ClockGeneratorMax
);
75 ASSERT (ConfigurationTable
!= NULL
);
78 // Read the clock generator
80 SlaveAddress
.SmbusDeviceAddress
= ClockAddress
>> 1;
81 Length
= sizeof (Buffer
);
83 Status
= SmbusPpi
->Execute (
93 ASSERT_EFI_ERROR (Status
);
98 for (i
= 0; i
< sizeof (Buffer
); i
++) {
99 DEBUG((EFI_D_ERROR
, "CK505 default Clock Generator Byte %d: %x\n", i
, Buffer
[i
]));
102 for (i
= 0; i
< ConfigurationTableLength
; i
++) {
103 DEBUG((EFI_D_ERROR
, "BIOS structure Clock Generator Byte %d: %x\n", i
, ConfigurationTable
[i
]));
109 DEBUG((EFI_D_ERROR
, "Expected Clock Generator ID is %x, expecting %x\n", mSupportedClockGeneratorTable
[ClockType
].ClockId
,(Buffer
[7]&0xF)));
112 // Program clock generator
116 #if CLKGEN_CONFIG_EXTRA
117 for (j
= 0; j
< ConfigurationTableLength
; j
++) {
118 Buffer
[j
] = ConfigurationTable
[j
];
123 Status
= SmbusPpi
->Execute (
134 Status
= SmbusPpi
->Execute (
141 &ConfigurationTableLength
,
144 #endif // CLKGEN_CONFIG_EXTRA
146 ConfigurationTable
[4] = (ConfigurationTable
[4] & 0x3) | (Buffer
[4] & 0xFC);
149 Status
= SmbusPpi
->Execute (
157 &ConfigurationTable
[4]
160 ASSERT_EFI_ERROR (Status
);
163 // Dump contents after write
168 SlaveAddress
.SmbusDeviceAddress
= ClockAddress
>> 1;
169 Length
= sizeof (Buffer
);
171 Status
= SmbusPpi
->Execute (
182 for (i
= 0; i
< ConfigurationTableLength
; i
++) {
183 DEBUG((EFI_D_ERROR
, "Clock Generator Byte %d: %x\n", i
, Buffer
[i
]));
192 Configure the clock generator using the SMBUS PPI services.
194 This function performs a block write, and dumps debug information.
196 @param PeiServices General purpose services available to every PEIM.
197 @param ClockType Clock generator's model name.
198 @param ClockAddress SMBUS address of clock generator.
199 @param ConfigurationTableLength Length of configuration table.
200 @param ConfigurationTable Pointer of configuration table.
203 @retval EFI_SUCCESS Operation success.
207 ReadClockGeneratorID (
208 IN EFI_PEI_SERVICES
**PeiServices
,
209 IN EFI_PEI_SMBUS_PPI
*SmbusPpi
,
210 IN UINT8 ClockAddress
214 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress
;
215 UINT8 Buffer
[MAX_CLOCK_GENERATOR_BUFFER_LENGTH
];
217 EFI_SMBUS_DEVICE_COMMAND Command
;
220 // Read the clock generator
222 SlaveAddress
.SmbusDeviceAddress
= ClockAddress
>> 1;
223 Length
= sizeof (Buffer
);
225 Status
= SmbusPpi
->Execute (
237 // Sanity check that the requested clock type is present in our supported clocks table
239 DEBUG((EFI_D_ERROR
, "Expected Clock Generator ID is 0x%x\n", Buffer
[7]));
245 Configure the clock generator to enable free-running operation. This keeps
246 the clocks from being stopped when the system enters C3 or C4.
250 @retval EFI_SUCCESS The function completed successfully.
254 ConfigurePlatformClocks (
255 IN EFI_PEI_SERVICES
**PeiServices
,
256 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
261 // Comment it out for now
262 // Not supported by Hybrid model.
265 UINT8
*ConfigurationTable
;
267 CLOCK_GENERATOR_TYPE ClockType
= ClockGeneratorCk505
;
268 UINT8 ConfigurationTable_Desktop
[] = CLOCK_GENERATOR_SETTINGS_DESKTOP
;
269 UINT8 ConfigurationTable_Mobile
[] = CLOCK_GENERATOR_SETTINGS_MOBILE
;
270 UINT8 ConfigurationTable_Tablet
[] = CLOCK_GENERATOR_SEETINGS_TABLET
;
272 EFI_PLATFORM_INFO_HOB
*PlatformInfoHob
;
273 BOOLEAN EnableSpreadSpectrum
;
275 SYSTEM_CONFIGURATION SystemConfiguration
;
278 EFI_SMBUS_DEVICE_COMMAND Command
;
279 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress
;
282 UINT8 ClockAddress
= CLOCK_GENERATOR_ADDRESS
;
284 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*Variable
;
287 // Obtain Platform Info from HOB.
289 Status
= GetPlatformInfoHob ((CONST EFI_PEI_SERVICES
**) PeiServices
, &PlatformInfoHob
);
290 ASSERT_EFI_ERROR (Status
);
292 DEBUG((EFI_D_ERROR
, "PlatformInfo protocol is working in ConfigurePlatformClocks()...%x\n",PlatformInfoHob
->PlatformFlavor
));
297 Status
= (**PeiServices
).LocatePpi (
298 (CONST EFI_PEI_SERVICES
**) PeiServices
,
299 &gEfiPeiSmbusPpiGuid
,
304 ASSERT_EFI_ERROR (Status
);
307 SlaveAddress
.SmbusDeviceAddress
= ClockAddress
>> 1;
309 Command
= 0x87; //Control Register 7 Vendor ID Check
310 Status
= ((EFI_PEI_SMBUS_PPI
*) SmbusPpi
)->Execute (
321 if (EFI_ERROR (Status
) || ((Data
& 0x0F) != CK505_GENERATOR_ID
)) {
322 DEBUG((EFI_D_ERROR
, "Clock Generator CK505 Not Present, vendor ID on board is %x\n",(Data
& 0x0F)));
325 ClockGenID
= Data
& 0x0F;
327 EnableSpreadSpectrum
= FALSE
;
328 VariableSize
= sizeof (SYSTEM_CONFIGURATION
);
329 ZeroMem (&SystemConfiguration
, sizeof (SYSTEM_CONFIGURATION
));
331 Status
= (*PeiServices
)->LocatePpi (
332 (CONST EFI_PEI_SERVICES
**) PeiServices
,
333 &gEfiPeiReadOnlyVariable2PpiGuid
,
339 // Use normal setup default from NVRAM variable,
340 // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable.
342 VariableSize
= sizeof(SYSTEM_CONFIGURATION
);
343 Status
= Variable
->GetVariable (Variable
,
345 &gEfiSetupVariableGuid
,
348 &SystemConfiguration
);
349 if (EFI_ERROR (Status
) || VariableSize
!= sizeof(SYSTEM_CONFIGURATION
)) {
350 //The setup variable is corrupted
351 VariableSize
= sizeof(SYSTEM_CONFIGURATION
);
352 Status
= Variable
->GetVariable(Variable
,
354 &gEfiSetupVariableGuid
,
359 ASSERT_EFI_ERROR (Status
);
361 if(!EFI_ERROR (Status
)){
362 EnableSpreadSpectrum
= SystemConfiguration
.EnableClockSpreadSpec
;
366 // Perform platform-specific intialization dependent upon Board ID:
368 DEBUG((EFI_D_ERROR
, "board id is %x, platform id is %x\n",PlatformInfoHob
->BoardId
,PlatformInfoHob
->PlatformFlavor
));
371 switch (PlatformInfoHob
->BoardId
) {
372 case BOARD_ID_MINNOW2
:
373 case BOARD_ID_MINNOW2_TURBOT
:
375 switch(PlatformInfoHob
->PlatformFlavor
) {
377 ConfigurationTable
= ConfigurationTable_Tablet
;
378 Length
= sizeof (ConfigurationTable_Tablet
);
381 ConfigurationTable
= ConfigurationTable_Mobile
;
382 Length
= sizeof (ConfigurationTable_Mobile
);
386 ConfigurationTable
= ConfigurationTable_Desktop
;
387 Length
= sizeof (ConfigurationTable_Desktop
);
394 // Perform common clock initialization:
396 // Program Spread Spectrum function.
398 if (EnableSpreadSpectrum
)
400 ConfigurationTable
[mSupportedClockGeneratorTable
[ClockType
].SpreadSpectrumByteOffset
] |= mSupportedClockGeneratorTable
[ClockType
].SpreadSpectrumBitOffset
;
402 ConfigurationTable
[mSupportedClockGeneratorTable
[ClockType
].SpreadSpectrumByteOffset
] &= ~(mSupportedClockGeneratorTable
[ClockType
].SpreadSpectrumBitOffset
);
407 Status
= ConfigureClockGenerator (PeiServices
, SmbusPpi
, ClockType
, ClockAddress
, Length
, ConfigurationTable
);
408 ASSERT_EFI_ERROR (Status
);
413 static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList
[] = {
415 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
416 &gEfiPeiSmbusPpiGuid
,
417 ConfigurePlatformClocks
422 InstallPlatformClocksNotify (
423 IN CONST EFI_PEI_SERVICES
**PeiServices
428 DEBUG ((EFI_D_INFO
, "InstallPlatformClocksNotify()...\n"));
430 Status
= (*PeiServices
)->NotifyPpi(PeiServices
, &mNotifyList
[0]);
431 ASSERT_EFI_ERROR (Status
);
437 #pragma optimize( "", on )