]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c
Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / MultiPlatformLib / BoardClkGens / BoardClkGens.c
diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c
new file mode 100644 (file)
index 0000000..1fc7312
--- /dev/null
@@ -0,0 +1,426 @@
+/** @file\r
+  Clock generator setting for multiplatform.\r
+\r
+  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+                                                                                   \r\r
+  This program and the accompanying materials are licensed and made available under\r\r
+  the terms and conditions of the BSD License that accompanies this distribution.  \r\r
+  The full text of the license may be found at                                     \r\r
+  http://opensource.org/licenses/bsd-license.php.                                  \r\r
+                                                                                   \r\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            \r\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    \r\r
+                                                                                   \r\r
+\r
+**/\r
+\r
+#include <BoardClkGens.h>\r
+#include <Guid/SetupVariable.h>\r
+#include <Ppi/ReadOnlyVariable2.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#ifndef __GNUC__\r
+#pragma optimize( "", off )\r
+#endif\r
+\r
+#define CLKGEN_EN 1\r
+#define EFI_DEBUG 1\r
+\r
+CLOCK_GENERATOR_DETAILS   mSupportedClockGeneratorTable[] =\r
+{\r
+  { ClockGeneratorCk410, CK410_GENERATOR_ID , CK410_GENERATOR_SPREAD_SPECTRUM_BYTE, CK410_GENERATOR_SPREAD_SPECTRUM_BIT },\r
+  { ClockGeneratorCk505, CK505_GENERATOR_ID , CK505_GENERATOR_SPREAD_SPECTRUM_BYTE, CK505_GENERATOR_SPREAD_SPECTRUM_BIT }\r
+};\r
+\r
+/**\r
+  Configure the clock generator using the SMBUS PPI services.\r
+\r
+  This function performs a block write, and dumps debug information.\r
+\r
+  @param  PeiServices                General purpose services available to every PEIM.\r
+  @param  ClockType                  Clock generator's model name.\r
+  @param  ClockAddress               SMBUS address of clock generator.\r
+  @param  ConfigurationTableLength   Length of configuration table.\r
+  @param  ConfigurationTable         Pointer of configuration table.\r
+\r
+  @retval EFI_SUCCESS - Operation success.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigureClockGenerator (\r
+  IN     EFI_PEI_SERVICES              **PeiServices,\r
+  IN     EFI_PEI_SMBUS_PPI                 *SmbusPpi,\r
+  IN     CLOCK_GENERATOR_TYPE          ClockType,\r
+  IN     UINT8                         ClockAddress,\r
+  IN     UINTN                         ConfigurationTableLength,\r
+  IN OUT UINT8                         *ConfigurationTable\r
+  )\r
+{\r
+\r
+  EFI_STATUS                    Status;\r
+  EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;\r
+  UINT8                         Buffer[MAX_CLOCK_GENERATOR_BUFFER_LENGTH];\r
+  UINTN                         Length;\r
+  EFI_SMBUS_DEVICE_COMMAND      Command;\r
+#if CLKGEN_CONFIG_EXTRA\r
+  UINT8                         j;\r
+#endif\r
+\r
+  //\r
+  // Verify input arguments\r
+  //\r
+  ASSERT_EFI_ERROR (ConfigurationTableLength >= 6);\r
+  ASSERT_EFI_ERROR (ConfigurationTableLength <= MAX_CLOCK_GENERATOR_BUFFER_LENGTH);\r
+  ASSERT_EFI_ERROR (ClockType < ClockGeneratorMax);\r
+  ASSERT_EFI_ERROR (ConfigurationTable != NULL);\r
+\r
+  //\r
+  // Read the clock generator\r
+  //\r
+  SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
+  Length = sizeof (Buffer);\r
+  Command = 0;\r
+  Status = SmbusPpi->Execute (\r
+    PeiServices,\r
+    SmbusPpi,\r
+    SlaveAddress,\r
+    Command,\r
+    EfiSmbusReadBlock,\r
+    FALSE,\r
+    &Length,\r
+    Buffer\r
+    );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+#ifdef EFI_DEBUG\r
+  {\r
+    UINT8 i;\r
+    for (i = 0; i < sizeof (Buffer); i++) {\r
+      DEBUG((EFI_D_ERROR, "CK505 default Clock Generator Byte %d: %x\n", i, Buffer[i]));\r
+    }\r
+#if CLKGEN_EN\r
+    for (i = 0; i < ConfigurationTableLength; i++) {\r
+      DEBUG((EFI_D_ERROR, "BIOS structure Clock Generator Byte %d: %x\n", i, ConfigurationTable[i]));\r
+    }\r
+#endif\r
+  }\r
+#endif\r
+\r
+  DEBUG((EFI_D_ERROR, "Expected Clock Generator ID is %x, expecting %x\n", mSupportedClockGeneratorTable[ClockType].ClockId,(Buffer[7]&0xF)));\r
+\r
+  //\r
+  // Program clock generator\r
+  //\r
+  Command = 0;\r
+#if CLKGEN_EN\r
+#if CLKGEN_CONFIG_EXTRA\r
+  for (j = 0; j < ConfigurationTableLength; j++) {\r
+    Buffer[j] = ConfigurationTable[j];\r
+  }\r
+\r
+  Buffer[30] = 0x00;\r
+\r
+  Status = SmbusPpi->Execute (\r
+    PeiServices,\r
+    SmbusPpi,\r
+    SlaveAddress,\r
+    Command,\r
+    EfiSmbusWriteBlock,\r
+    FALSE,\r
+    &Length,\r
+    Buffer\r
+    );\r
+#else\r
+  Status = SmbusPpi->Execute (\r
+    PeiServices,\r
+    SmbusPpi,\r
+    SlaveAddress,\r
+    Command,\r
+    EfiSmbusWriteBlock,\r
+    FALSE,\r
+    &ConfigurationTableLength,\r
+    ConfigurationTable\r
+    );\r
+#endif // CLKGEN_CONFIG_EXTRA\r
+#else\r
+    ConfigurationTable[4] = (ConfigurationTable[4] & 0x3) | (Buffer[4] & 0xFC);\r
+    Command = 4;\r
+    Length = 1;\r
+  Status = SmbusPpi->Execute (\r
+    PeiServices,\r
+    SmbusPpi,\r
+    SlaveAddress,\r
+    Command,\r
+    EfiSmbusWriteBlock,\r
+    FALSE,\r
+    &Length,\r
+    &ConfigurationTable[4]\r
+    );\r
+#endif //CLKGEN_EN\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Dump contents after write\r
+  //\r
+  #ifdef EFI_DEBUG\r
+    {\r
+      UINT8   i;\r
+    SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
+    Length = sizeof (Buffer);\r
+      Command = 0;\r
+      Status =  SmbusPpi->Execute (\r
+        PeiServices,\r
+        SmbusPpi,\r
+        SlaveAddress,\r
+        Command,\r
+        EfiSmbusReadBlock,\r
+        FALSE,\r
+        &Length,\r
+        Buffer\r
+        );\r
+\r
+      for (i = 0; i < ConfigurationTableLength; i++) {\r
+        DEBUG((EFI_D_ERROR, "Clock Generator Byte %d: %x\n", i, Buffer[i]));\r
+      }\r
+    }\r
+    #endif\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Configure the clock generator using the SMBUS PPI services.\r
+\r
+  This function performs a block write, and dumps debug information.\r
+\r
+  @param  PeiServices                General purpose services available to every PEIM.\r
+  @param  ClockType                  Clock generator's model name.\r
+  @param  ClockAddress               SMBUS address of clock generator.\r
+  @param  ConfigurationTableLength   Length of configuration table.\r
+  @param  ConfigurationTable         Pointer of configuration table.\r
+\r
+\r
+  @retval  EFI_SUCCESS  Operation success.\r
+\r
+**/\r
+UINT8\r
+ReadClockGeneratorID (\r
+  IN     EFI_PEI_SERVICES              **PeiServices,\r
+  IN     EFI_PEI_SMBUS_PPI                 *SmbusPpi,\r
+  IN     UINT8                         ClockAddress\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;\r
+  UINT8                         Buffer[MAX_CLOCK_GENERATOR_BUFFER_LENGTH];\r
+  UINTN                         Length;\r
+  EFI_SMBUS_DEVICE_COMMAND      Command;\r
+\r
+  //\r
+  // Read the clock generator\r
+  //\r
+  SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
+  Length = sizeof (Buffer);\r
+  Command = 0;\r
+  Status = SmbusPpi->Execute (\r
+    PeiServices,\r
+    SmbusPpi,\r
+    SlaveAddress,\r
+    Command,\r
+    EfiSmbusReadBlock,\r
+    FALSE,\r
+    &Length,\r
+    Buffer\r
+    );\r
+\r
+  //\r
+  // Sanity check that the requested clock type is present in our supported clocks table\r
+  //\r
+  DEBUG((EFI_D_ERROR, "Expected Clock Generator ID is 0x%x\n", Buffer[7]));\r
+\r
+  return (Buffer[7]);\r
+}\r
+\r
+/**\r
+  Configure the clock generator to enable free-running operation.  This keeps\r
+  the clocks from being stopped when the system enters C3 or C4.\r
+\r
+  @param None\r
+\r
+  @retval EFI_SUCCESS    The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigurePlatformClocks (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,\r
+  IN VOID                       *SmbusPpi\r
+  )\r
+{\r
+  //\r
+  // Comment it out for now\r
+  // Not supported by Hybrid model.\r
+  //\r
+  EFI_STATUS                    Status;\r
+  UINT8                         *ConfigurationTable;\r
+\r
+  CLOCK_GENERATOR_TYPE          ClockType = ClockGeneratorCk505;\r
+  UINT8                         ConfigurationTable_Desktop[] = CLOCK_GENERATOR_SETTINGS_DESKTOP;\r
+  UINT8                         ConfigurationTable_Mobile[] = CLOCK_GENERATOR_SETTINGS_MOBILE;\r
+  UINT8                         ConfigurationTable_Tablet[] = CLOCK_GENERATOR_SEETINGS_TABLET;\r
+\r
+  EFI_PLATFORM_INFO_HOB         *PlatformInfoHob;\r
+  BOOLEAN                       EnableSpreadSpectrum;\r
+  UINT8                         ClockGenID=0;\r
+  SYSTEM_CONFIGURATION          SystemConfiguration;\r
+\r
+  UINTN                         Length;\r
+  EFI_SMBUS_DEVICE_COMMAND      Command;\r
+  EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;\r
+  UINT8                         Data;\r
+\r
+  UINT8                         ClockAddress = CLOCK_GENERATOR_ADDRESS;\r
+  UINTN                         VariableSize;\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI   *Variable;\r
+\r
+  //\r
+  // Obtain Platform Info from HOB.\r
+  //\r
+  Status = GetPlatformInfoHob ((CONST EFI_PEI_SERVICES **) PeiServices, &PlatformInfoHob);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DEBUG((EFI_D_ERROR, "PlatformInfo protocol is working in ConfigurePlatformClocks()...%x\n",PlatformInfoHob->PlatformFlavor));\r
+\r
+  //\r
+  // Locate SMBUS PPI\r
+  //\r
+  Status = (**PeiServices).LocatePpi (\r
+                             (CONST EFI_PEI_SERVICES **) PeiServices,\r
+                             &gEfiPeiSmbusPpiGuid,\r
+                             0,\r
+                             NULL,\r
+                             &SmbusPpi\r
+                             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Data  = 0;\r
+  SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1;\r
+  Length = 1;\r
+  Command = 0x87;   //Control Register 7 Vendor ID Check\r
+  Status = ((EFI_PEI_SMBUS_PPI *) SmbusPpi)->Execute (\r
+                                               PeiServices,\r
+                                               SmbusPpi,\r
+                                               SlaveAddress,\r
+                                               Command,\r
+                                               EfiSmbusReadByte,\r
+                                               FALSE,\r
+                                               &Length,\r
+                                               &Data\r
+                                               );\r
+\r
+  if (EFI_ERROR (Status) || ((Data & 0x0F) != CK505_GENERATOR_ID)) {\r
+      DEBUG((EFI_D_ERROR, "Clock Generator CK505 Not Present, vendor ID on board is %x\n",(Data & 0x0F)));\r
+      return EFI_SUCCESS;\r
+}\r
+  ClockGenID = Data & 0x0F;\r
+\r
+  EnableSpreadSpectrum = FALSE;\r
+  VariableSize = sizeof (SYSTEM_CONFIGURATION);\r
+  ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION));\r
+\r
+  Status = (*PeiServices)->LocatePpi (\r
+                             (CONST EFI_PEI_SERVICES **) PeiServices,\r
+                             &gEfiPeiReadOnlyVariable2PpiGuid,\r
+                             0,\r
+                             NULL,\r
+                             (VOID **) &Variable\r
+                             );\r
+  //\r
+  // Use normal setup default from NVRAM variable,\r
+  // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable.\r
+  //\r
+  VariableSize = sizeof(SYSTEM_CONFIGURATION);\r
+  Status = Variable->GetVariable (Variable,\r
+                                   L"Setup",\r
+                                   &gEfiSetupVariableGuid,\r
+                                   NULL,\r
+                                   &VariableSize,\r
+                                   &SystemConfiguration);\r
+\r
+  if(!EFI_ERROR (Status)){\r
+    EnableSpreadSpectrum = SystemConfiguration.EnableClockSpreadSpec;\r
+  }\r
+\r
+  //\r
+  // Perform platform-specific intialization dependent upon Board ID:\r
+  //\r
+  DEBUG((EFI_D_ERROR, "board id is %x, platform id is %x\n",PlatformInfoHob->BoardId,PlatformInfoHob->PlatformFlavor));\r
+\r
+\r
+  switch (PlatformInfoHob->BoardId) {\r
+    case BOARD_ID_MINNOW2:\r
+    default:\r
+      switch(PlatformInfoHob->PlatformFlavor) {\r
+      case FlavorTablet:\r
+        ConfigurationTable = ConfigurationTable_Tablet;\r
+        Length = sizeof (ConfigurationTable_Tablet);\r
+        break;\r
+      case FlavorMobile:\r
+        ConfigurationTable = ConfigurationTable_Mobile;\r
+        Length = sizeof (ConfigurationTable_Mobile);\r
+        break;\r
+      case FlavorDesktop:\r
+      default:\r
+        ConfigurationTable = ConfigurationTable_Desktop;\r
+        Length = sizeof (ConfigurationTable_Desktop);\r
+        break;\r
+      }\r
+    break;\r
+    }\r
+\r
+  //\r
+  // Perform common clock initialization:\r
+  //\r
+  // Program Spread Spectrum function.\r
+  //\r
+  if (EnableSpreadSpectrum)\r
+  {\r
+    ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] |= mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset;\r
+  } else {\r
+    ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] &= ~(mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset);\r
+  }\r
+\r
+\r
+#if CLKGEN_EN\r
+  Status = ConfigureClockGenerator (PeiServices, SmbusPpi, ClockType, ClockAddress, Length, ConfigurationTable);\r
+  ASSERT_EFI_ERROR (Status);\r
+#endif // CLKGEN_EN\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+static EFI_PEI_NOTIFY_DESCRIPTOR    mNotifyList[] = {\r
+  {\r
+    EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+    &gEfiPeiSmbusPpiGuid,\r
+    ConfigurePlatformClocks\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+InstallPlatformClocksNotify (\r
+  IN CONST EFI_PEI_SERVICES           **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+\r
+  DEBUG ((EFI_D_INFO, "InstallPlatformClocksNotify()...\n"));\r
+\r
+  Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]);\r
+  ASSERT_EFI_ERROR (Status);\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+#ifndef __GNUC__\r
+#pragma optimize( "", on )\r
+#endif\r