AGESA_STATUS GfxInitSsid ( IN GFX_PLATFORM_CONFIG *Gfx ) { AGESA_STATUS Status; UINT32 TempData; PCI_ADDR IgpuAddress; PCI_ADDR HdaudioAddress; Status = AGESA_SUCCESS; TempData = 0; IgpuAddress = Gfx->GfxPciAddress; HdaudioAddress = Gfx->GfxPciAddress; HdaudioAddress.Address.Function = 1; // Set SSID for internal GPU if (UserOptions.CfgGnbIGPUSSID != 0) { GnbLibPciRMW ((IgpuAddress.AddressValue | 0x4C), AccessS3SaveWidth32, 0, UserOptions.CfgGnbIGPUSSID, GnbLibGetHeader (Gfx)); } else { GnbLibPciRead (IgpuAddress.AddressValue, AccessS3SaveWidth32, &TempData, GnbLibGetHeader (Gfx)); GnbLibPciRMW ((IgpuAddress.AddressValue | 0x4C), AccessS3SaveWidth32, 0, TempData, GnbLibGetHeader (Gfx)); } // Set SSID for internal HD Audio if (UserOptions.CfgGnbHDAudioSSID != 0) { GnbLibPciRMW ((HdaudioAddress.AddressValue | 0x4C), AccessS3SaveWidth32, 0, UserOptions.CfgGnbHDAudioSSID, GnbLibGetHeader (Gfx)); } else { GnbLibPciRead (HdaudioAddress.AddressValue, AccessS3SaveWidth32, &TempData, GnbLibGetHeader (Gfx)); GnbLibPciRMW ((HdaudioAddress.AddressValue | 0x4C), AccessS3SaveWidth32, 0, TempData, GnbLibGetHeader (Gfx)); } return Status; }
/** * Create IVRS entry * * * @param[in] Type Block type * @param[in] Ivhd IVHD header pointer * @param[in] StdHeader Standard configuration header * */ VOID GnbCreateIvhdHeaderTN ( IN IVRS_BLOCK_TYPE Type, OUT IVRS_IVHD_ENTRY *Ivhd, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Value; Ivhd->Type = (UINT8) Type; Ivhd->Flags = IVHD_FLAG_COHERENT | IVHD_FLAG_IOTLBSUP | IVHD_FLAG_ISOC | IVHD_FLAG_RESPASSPW | IVHD_FLAG_PASSPW | IVHD_FLAG_PPRSUB | IVHD_FLAG_PREFSUP; Ivhd->Length = sizeof (IVRS_IVHD_ENTRY); Ivhd->DeviceId = 0x2; Ivhd->CapabilityOffset = GnbLibFindPciCapability (MAKE_SBDFO (0, 0, 0, 2, 0), IOMMU_CAP_ID, StdHeader); Ivhd->PciSegment = 0; GnbLibPciRead (MAKE_SBDFO (0, 0, 0, 2, Ivhd->CapabilityOffset + 0x4), AccessWidth32, &Ivhd->BaseAddress, StdHeader); GnbLibPciRead (MAKE_SBDFO (0, 0, 0, 2, Ivhd->CapabilityOffset + 0x8), AccessWidth32, (UINT8 *) &Ivhd->BaseAddress + 4, StdHeader); Ivhd->BaseAddress = Ivhd->BaseAddress & 0xfffffffffffffffe; ASSERT (Ivhd->BaseAddress != 0x0); GnbLibPciRead (MAKE_SBDFO (0, 0, 0, 2, Ivhd->CapabilityOffset + 0x10), AccessWidth32, &Value, StdHeader); Ivhd->IommuInfo = (UINT16) (Value & 0x1f) | (0x13 << IVHD_INFO_UNITID_OFFSET); Ivhd->IommuEfr = (0 << IVHD_EFR_XTSUP_OFFSET) | (0 << IVHD_EFR_NXSUP_OFFSET) | (1 << IVHD_EFR_GTSUP_OFFSET) | (0 << IVHD_EFR_GLXSUP_OFFSET) | (1 << IVHD_EFR_IASUP_OFFSET) | (0 << IVHD_EFR_GASUP_OFFSET) | (0 << IVHD_EFR_HESUP_OFFSET) | (0x8 << IVHD_EFR_PASMAX_OFFSET) | (0 << IVHD_EFR_MSINUMPPR_OFFSET) | (4 << IVHD_EFR_PNCOUNTERS_OFFSET) | (2 << IVHD_EFR_PNBANKS_OFFSET); }
VOID GfxFillNbPStateVid ( IN OUT ATOM_INTEGRATED_SYSTEM_INFO_V6 *IntegratedInfoTable, IN GFX_PLATFORM_CONFIG *Gfx ) { D18F3xDC_STRUCT D18F3xDC; D18F6x90_STRUCT D18F6x90; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3xDC_ADDRESS), AccessWidth32, &D18F3xDC.Value, GnbLibGetHeader (Gfx) ); IntegratedInfoTable->usNBP0Voltage = (USHORT) D18F3xDC.Field.NbPs0Vid; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 6, D18F6x90_ADDRESS), AccessWidth32, &D18F6x90.Value, GnbLibGetHeader (Gfx) ); IntegratedInfoTable->usNBP1Voltage = (USHORT) D18F6x90.Field.NbPs1Vid; IntegratedInfoTable->ulMinimumNClk = GfxLibCalculateClk ( (UINT8) (((D18F6x90.Field.NbPs1NclkDiv != 0) && (D18F6x90.Field.NbPs1NclkDiv < D18F3xDC.Field.NbPs0NclkDiv)) ? D18F6x90.Field.NbPs1NclkDiv : D18F3xDC.Field.NbPs0NclkDiv), IntegratedInfoTable->ulDentistVCOFreq ); }
SCAN_STATUS GfxScanPcieDevice ( IN PCI_ADDR Device, IN OUT GNB_PCI_SCAN_DATA *ScanData ) { UINT8 ClassCode; UINT32 VendorId; IDS_HDT_CONSOLE (GFX_MISC, " Evaluate device [%d:%d:%d]\n", Device.Address.Bus, Device.Address.Device, Device.Address.Function ); if (GnbLibPciIsBridgeDevice (Device.AddressValue, ScanData->StdHeader)) { UINT32 SaveBusConfiguration; UINT32 Value; if (Device.Address.Bus == 0) { ((GFX_SCAN_DATA *) ScanData)->BaseBridge = Device; } GnbLibPciRead (Device.AddressValue | 0x18, AccessWidth32, &SaveBusConfiguration, ScanData->StdHeader); Value = (((0xFF << 8) | ((GFX_SCAN_DATA *) ScanData)->BusNumber) << 8) | Device.Address.Bus; GnbLibPciWrite (Device.AddressValue | 0x18, AccessWidth32, &Value, ScanData->StdHeader); ((GFX_SCAN_DATA *) ScanData)->BusNumber++; GnbLibPciScanSecondaryBus (Device, ScanData); ((GFX_SCAN_DATA *) ScanData)->BusNumber--; GnbLibPciWrite (Device.AddressValue | 0x18, AccessWidth32, &SaveBusConfiguration, ScanData->StdHeader); return 0; } GnbLibPciRead (Device.AddressValue | 0x0b, AccessWidth8, &ClassCode, ScanData->StdHeader); if (ClassCode == 3) { IDS_HDT_CONSOLE (GFX_MISC, " Found GFX Card\n" ); GnbLibPciRead (Device.AddressValue | 0x00, AccessWidth32, &VendorId, ScanData->StdHeader); if (!GnbLibPciIsPcieDevice (Device.AddressValue, ScanData->StdHeader)) { IDS_HDT_CONSOLE (GFX_MISC, " GFX Card is PCI device\n" ); ((GFX_SCAN_DATA *) ScanData)->GfxCardInfo->PciGfxCardBitmap |= (1 << ((GFX_SCAN_DATA *) ScanData)->BaseBridge.Address.Device); return 0; } if ((UINT16) VendorId == 0x1002) { IDS_HDT_CONSOLE (GFX_MISC, " GFX Card is AMD PCIe device\n" ); ((GFX_SCAN_DATA *) ScanData)->GfxCardInfo->AmdPcieGfxCardBitmap |= (1 << ((GFX_SCAN_DATA *) ScanData)->BaseBridge.Address.Device); } ((GFX_SCAN_DATA *) ScanData)->GfxCardInfo->PcieGfxCardBitmap |= (1 << ((GFX_SCAN_DATA *) ScanData)->BaseBridge.Address.Device); } return 0; }
/** * Read CPU (DCT) indirect registers * * * * @param[in] Address PCI address of DCT register * @param[in] IndirectAddress Offset of DCT register * @param[out] Value Pointer to value * @param[in] Config Pointer to standard header */ VOID GnbLibCpuPciIndirectRead ( IN UINT32 Address, IN UINT32 IndirectAddress, OUT UINT32 *Value, IN VOID *Config ) { UINT32 OffsetRegisterValue; GnbLibPciWrite (Address, AccessWidth32, &IndirectAddress, Config); do { GnbLibPciRead (Address , AccessWidth32, &OffsetRegisterValue, Config); } while ((OffsetRegisterValue & BIT31) == 0); GnbLibPciRead (Address + 4, AccessWidth32, Value, Config); }
VOID PcieAcsCapabilityPortEnableV4 ( IN PCIe_ENGINE_CONFIG *Engine, IN PCIe_PLATFORM_CONFIG *Pcie ) { DxF0x2A4_STRUCT DxF0x2A4; IDS_HDT_CONSOLE (GNB_TRACE, "PcieAcsCapabilityPortEnableV4 Enter\n"); //Step 3, Check each individual ACS sub-capability in each port configure space, if the individual capability is implemented, then go to step 4 to enable it GnbLibPciRead ( Engine->Type.Port.Address.AddressValue | DxF0x2A4_ADDRESS, AccessWidth32, &DxF0x2A4.Value, GnbLibGetHeader (Pcie) ); DxF0x2A4.Field.Bitfield_16_16 = DxF0x2A4.Field.Bitfield_0_0; DxF0x2A4.Field.Bitfield_17_17 = DxF0x2A4.Field.Bitfield_1_1; //Step 4, Enable each individual ACS sub-items in each port configure space GnbLibPciWrite ( Engine->Type.Port.Address.AddressValue | DxF0x2A4_ADDRESS, AccessS3SaveWidth32, &DxF0x2A4.Value, GnbLibGetHeader (Pcie) ); IDS_HDT_CONSOLE (GNB_TRACE, "PcieAcsCapabilityPortEnableV4 Exit\n"); }
/*----------------------------------------------------------------------------------------*/ BOOLEAN IsPcieCommClk ( IN PCI_ADDR Device, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 PcieCapPtr; UINT32 Value; PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, StdHeader); if (PcieCapPtr == 0) { return FALSE; } GnbLibPciRead ( Device.AddressValue | (PcieCapPtr + PCIE_LINK_CTRL_REGISTER), AccessWidth32, &Value, StdHeader ); if ((Value & BIT28) != 0) { return TRUE; } return FALSE; }
/** * Get max non 0 VID index * * * @param[in] StdHeader Standard configuration header * @retval NBVDD VID index */ UINT8 GfxLibMaxVidIndex ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 MaxVid; UINT8 MaxVidIndex; UINT8 SclkVidArray[4]; UINTN Index; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &SclkVidArray[0], StdHeader ); MaxVidIndex = 0; MaxVid = 0xff; for (Index = 0; Index < 4; Index++) { if (SclkVidArray[Index] != 0 && SclkVidArray[Index] < MaxVid) { MaxVid = SclkVidArray[Index]; MaxVidIndex = (UINT8) Index; } } return MaxVidIndex; }
AGESA_STATUS GnbCreateIvrsEntryTN ( IN GNB_HANDLE *GnbHandle, IN IVRS_BLOCK_TYPE Type, IN VOID *Ivrs, IN AMD_CONFIG_PARAMS *StdHeader ) { IVRS_IVHD_ENTRY *Ivhd; UINT8 IommuCapabilityOffset; UINT32 Value; IDS_HDT_CONSOLE (GNB_TRACE, "GnbFmCreateIvrsEntry Entry\n"); if (Type == IvrsIvhdBlock || Type == IvrsIvhdrBlock) { // Update IVINFO IommuCapabilityOffset = GnbLibFindPciCapability (MAKE_SBDFO (0, 0, 0, 2, 0), IOMMU_CAP_ID, StdHeader); GnbLibPciRead (MAKE_SBDFO (0, 0, 0, 2, IommuCapabilityOffset + 0x10), AccessWidth32, &Value, StdHeader); ((IOMMU_IVRS_HEADER *) Ivrs)->IvInfo = Value & (IVINFO_HTATSRESV_MASK | IVINFO_VASIZE_MASK | IVINFO_GASIZE_MASK | IVINFO_PASIZE_MASK); // Address of IVHD entry Ivhd = (IVRS_IVHD_ENTRY*) ((UINT8 *)Ivrs + ((IOMMU_IVRS_HEADER *) Ivrs)->TableLength); GnbCreateIvhdHeaderTN (Type, Ivhd, StdHeader); if (Type == IvrsIvhdBlock) { GnbCreateIvhdTN (Ivhd, StdHeader); } else { GnbCreateIvhdrTN (Ivhd, StdHeader); } ((IOMMU_IVRS_HEADER *) Ivrs)->TableLength = ((IOMMU_IVRS_HEADER *) Ivrs)->TableLength + Ivhd->Length; } IDS_HDT_CONSOLE (GNB_TRACE, "GnbFmCreateIvrsEntry Exit\n"); return AGESA_SUCCESS; }
/*----------------------------------------------------------------------------------------*/ STATIC BOOLEAN PcieClkPmCheckDeviceCapability ( IN PCI_ADDR Device, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 MaxFunc; UINT8 CurrentFunc; UINT8 PcieCapPtr; UINT32 Value; MaxFunc = GnbLibPciIsMultiFunctionDevice (Device.AddressValue, StdHeader) ? 7 : 0; for (CurrentFunc = 0; CurrentFunc <= MaxFunc; CurrentFunc++) { Device.Address.Function = CurrentFunc; if (GnbLibPciIsDevicePresent (Device.AddressValue, StdHeader)) { PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, StdHeader); if (PcieCapPtr == 0) { return FALSE; } GnbLibPciRead ( Device.AddressValue | (PcieCapPtr + PCIE_LINK_CAP_REGISTER), AccessWidth32, &Value, StdHeader ); if ((Value & BIT18) == 0) { return FALSE; } } } return TRUE; }
/** * Check if link fail because device does not support Gen X * * * @param[in] CurrentEngine Pointer to engine config descriptor * @param[in] Pcie Pointer to global PCIe configuration * */ VOID STATIC PcieTrainingCheckVcoNegotiation ( IN PCIe_ENGINE_CONFIG *CurrentEngine, IN PCIe_PLATFORM_CONFIG *Pcie ) { UINT32 TimeStamp; DxFxx128_STRUCT DxFxx128; TimeStamp = PcieTimerGetTimeStamp (Pcie); GnbLibPciRead (CurrentEngine->Type.Port.Address.AddressValue | DxFxx128_ADDRESS, AccessWidth32, &DxFxx128, GnbLibGetHeader (Pcie)); if (DxFxx128.Field.VcNegotiationPending == 0) { UINT16 NumberOfPhyLane; NumberOfPhyLane = PcieConfigGetNumberOfPhyLane (CurrentEngine); if (Pcie->GfxCardWorkaround == GfxWorkaroundEnable && NumberOfPhyLane >= 8) { // Limit exposure of workaround to x8 and x16 port. PcieTrainingSetPortStateV2 (CurrentEngine, LinkStateGfxWorkaround, TRUE, Pcie); } else { PcieTrainingSetPortStateV2 (CurrentEngine, LinkStateTrainingSuccess, FALSE, Pcie); } return; } if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= 1000 * 1000) { PcieTrainingSetPortStateV2 (CurrentEngine, LinkStateRetrain, FALSE, Pcie); } }
/*----------------------------------------------------------------------------------------*/ VOID PcieRetrain ( IN PCI_ADDR Function, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 PcieCapPtr; UINT32 Value; PcieCapPtr = GnbLibFindPciCapability (Function.AddressValue, PCIE_CAP_ID, StdHeader); Value = BIT27; if (PcieCapPtr != 0) { GnbLibPciRMW ( Function.AddressValue | (PcieCapPtr + PCIE_LINK_CTRL_REGISTER), AccessS3SaveWidth32, ~(UINT32) (BIT5), BIT5, StdHeader ); IDS_HDT_CONSOLE (GNB_TRACE, " PcieRetrain link on Device = %d:%d:%d\n", Function.Address.Bus, Function.Address.Device, Function.Address.Function); do { GnbLibPciRead ( Function.AddressValue | (PcieCapPtr + PCIE_LINK_CTRL_REGISTER), AccessS3SaveWidth32, &Value, StdHeader); } while ((Value & BIT27) != 0); } }
/** * Create IVHD entry * * * @param[in] Ivhd IVHD header pointer * @param[in] StdHeader Standard configuration header * */ VOID SbCreateIvhdEntries ( OUT IVRS_IVHD_ENTRY *Ivhd, IN AMD_CONFIG_PARAMS *StdHeader ) { PCI_ADDR Start; PCI_ADDR End; PCI_ADDR PciAddress; UINT32 Value; IDS_HDT_CONSOLE (GNB_TRACE, "SbCreateIvhdEntries Entry\n"); PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x14, 4, 0); // P2P alias entry GnbLibPciRead (PciAddress.AddressValue | 0x18, AccessWidth32, &Value, StdHeader); Start.AddressValue = MAKE_SBDFO (0, (Value >> 8) & 0xff, 0, 0, 0); End.AddressValue = MAKE_SBDFO (0, (Value >> 16) & 0xff, 0x1f, 0x7, 0); GnbIvhdAddDeviceAliasRangeEntry (Start, End, PciAddress, 0, Ivhd, StdHeader); PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x14, 0, 0); // HPET GnbIvhdAddSpecialDeviceEntry (IvhdSpecialDeviceHpet, PciAddress, 0, 0, Ivhd, StdHeader); // APIC GnbIvhdAddSpecialDeviceEntry ( IvhdSpecialDeviceIoapic, PciAddress, GnbLiGetIoapicId (SbGetSbIoApicBaseAddress (StdHeader), StdHeader), 0xD7, Ivhd, StdHeader ); IDS_HDT_CONSOLE (GNB_TRACE, "SbCreateIvhdEntries Exit\n"); }
AGESA_STATUS GfxEnableGmmAccessV5 ( IN OUT GFX_PLATFORM_CONFIG *Gfx ) { UINT32 Value; GNB_HANDLE *GnbHandle; GnbHandle = GnbGetHandle (GnbLibGetHeader (Gfx)); ASSERT (GnbHandle != NULL); // GmmBase should be 0 before enable. ASSERT (GnbHandle->GmmBase == 0); if (!GnbLibPciIsDevicePresent (Gfx->GfxPciAddress.AddressValue, GnbLibGetHeader (Gfx))) { IDS_ERROR_TRAP; return AGESA_ERROR; } // Check if base address for GMM allocated by reading D1F0x24 Graphics Memory Mapped Base Address Gfx->GmmBase = 0; GnbLibPciRead (Gfx->GfxPciAddress.AddressValue | 0x24, AccessWidth32, &Value, GnbLibGetHeader (Gfx)); Gfx->GmmBase |= (Value & 0xfffffff0); if (Gfx->GmmBase == 0) { IDS_ERROR_TRAP; return AGESA_ERROR; } // Check if base address for FB allocated GnbLibPciRead (Gfx->GfxPciAddress.AddressValue | 0x10, AccessWidth32, &Value, GnbLibGetHeader (Gfx)); if ((Value & 0xfffffff0) == 0) { IDS_ERROR_TRAP; return AGESA_ERROR; } //Push CPU MMIO pci config to S3 script GnbLibS3SaveConfigSpace (MAKE_SBDFO (0, 0, 0x18, 1, 0), 0xBC, 0x80, AccessS3SaveWidth32, GnbLibGetHeader (Gfx)); // Turn on memory decoding on GFX to enable access to GMM register space GnbLibPciRMW (Gfx->GfxPciAddress.AddressValue | 0x4, AccessWidth32, 0xffffffff, BIT1 | BIT2, GnbLibGetHeader (Gfx)); //Push iGPU pci config to S3 script GnbLibS3SaveConfigSpace (Gfx->GfxPciAddress.AddressValue, 0x24, 0x10, AccessS3SaveWidth32, GnbLibGetHeader (Gfx)); GnbLibS3SaveConfigSpace (Gfx->GfxPciAddress.AddressValue, 0x04, 0x04, AccessS3SaveWidth16, GnbLibGetHeader (Gfx)); GnbHandle->GmmBase = Gfx->GmmBase; return AGESA_SUCCESS; }
UINT32 PcieSiliconRegisterRead ( IN PCIe_SILICON_CONFIG *Silicon, IN UINT32 Address, IN PCIe_PLATFORM_CONFIG *Pcie ) { UINT32 Value; GnbLibPciWrite (Silicon->Address.AddressValue | 0xE0, AccessWidth32, &Address, GnbLibGetHeader (Pcie)); GnbLibPciRead (Silicon->Address.AddressValue | 0xE4, AccessWidth32, &Value, GnbLibGetHeader (Pcie)); return Value; }
AGESA_STATUS GfxEnableGmmAccess ( IN OUT GFX_PLATFORM_CONFIG *Gfx ) { UINT32 Value; if (!GnbLibPciIsDevicePresent (Gfx->GfxPciAddress.AddressValue, GnbLibGetHeader (Gfx))) { IDS_ERROR_TRAP; return AGESA_ERROR; } // Check if base address for GMM allocated GnbLibPciRead (Gfx->GfxPciAddress.AddressValue | 0x18, AccessWidth32, &Gfx->GmmBase, GnbLibGetHeader (Gfx)); if (Gfx->GmmBase == 0) { IDS_ERROR_TRAP; return AGESA_ERROR; } // Check if base address for FB allocated GnbLibPciRead (Gfx->GfxPciAddress.AddressValue | 0x10, AccessWidth32, &Value, GnbLibGetHeader (Gfx)); if ((Value & 0xfffffff0) == 0) { IDS_ERROR_TRAP; return AGESA_ERROR; } //Push CPU MMIO pci config to S3 script GnbLibS3SaveConfigSpace (MAKE_SBDFO (0, 0, 0x18, 1, 0), 0xBC, 0x80, AccessS3SaveWidth32, GnbLibGetHeader (Gfx)); // Turn on memory decoding on APC to enable access to GMM register space if (Gfx->GfxControllerMode == GfxControllerLegacyBridgeMode) { GnbLibPciRMW (MAKE_SBDFO (0, 0, 1, 0, 0x4), AccessWidth32, 0xffffffff, BIT1 | BIT2, GnbLibGetHeader (Gfx)); //Push APC pci config to S3 script GnbLibS3SaveConfigSpace (MAKE_SBDFO (0, 0, 1, 0, 0), 0x2C, 0x18, AccessS3SaveWidth32, GnbLibGetHeader (Gfx)); GnbLibS3SaveConfigSpace (MAKE_SBDFO (0, 0, 1, 0, 0), 0x4, 0x4, AccessS3SaveWidth16, GnbLibGetHeader (Gfx)); } // Turn on memory decoding on GFX to enable access to GMM register space GnbLibPciRMW (Gfx->GfxPciAddress.AddressValue | 0x4, AccessWidth32, 0xffffffff, BIT1 | BIT2, GnbLibGetHeader (Gfx)); //Push iGPU pci config to S3 script GnbLibS3SaveConfigSpace (Gfx->GfxPciAddress.AddressValue, 0x24, 0x10, AccessS3SaveWidth32, GnbLibGetHeader (Gfx)); GnbLibS3SaveConfigSpace (Gfx->GfxPciAddress.AddressValue, 0x04, 0x04, AccessS3SaveWidth16, GnbLibGetHeader (Gfx)); return AGESA_SUCCESS; }
/** * Check a PCIE device to see if it supports phantom functions * * @param[in] Device Device pci address * @param[in] StdHeader Standard configuration header * @return TRUE Current device supports phantom functions */ STATIC BOOLEAN GnbCheckPhantomFuncSupport ( IN PCI_ADDR Device, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 PcieCapPtr; UINT32 Value; Value = 0; PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, StdHeader); if (PcieCapPtr != 0) { GnbLibPciRead (Device.AddressValue | (PcieCapPtr + 4), AccessWidth32, &Value, StdHeader); } return ((Value & (BIT3 | BIT4)) != 0) ? TRUE : FALSE; }
/** * Get disable DLL shutdown in self-refresh mode. * * * @param[in] Channel DCT controller index * @param[in] StdHeader Standard configuration header * @retval DisDllShutdownSR */ UINT32 GfxLibGetDisDllShutdownSR ( IN UINT8 Channel, IN AMD_CONFIG_PARAMS *StdHeader ) { D18F2x90_STRUCT D18F2x090; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 2, (Channel == 0) ? D18F2x90_ADDRESS : D18F2x190_ADDRESS), AccessWidth32, &D18F2x090.Value, StdHeader ); return D18F2x090.Field.DisDllShutdownSR; }
VOID GfxFillHtcData ( IN OUT ATOM_INTEGRATED_SYSTEM_INFO_V6 *IntegratedInfoTable, IN GFX_PLATFORM_CONFIG *Gfx ) { D18F3x64_STRUCT D18F3x64; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x64_ADDRESS), AccessWidth32, &D18F3x64.Value, GnbLibGetHeader (Gfx) ); IntegratedInfoTable->ucHtcTmpLmt = (UCHAR) (D18F3x64.Field.HtcTmpLmt / 2 + 52); IntegratedInfoTable->ucHtcHystLmt = (UCHAR) (D18F3x64.Field.HtcHystLmt / 2); }
/** * Request boot up voltage * * * * @param[in] LinkCap Global GEN capability * @param[in] Pcie Pointer to PCIe configuration data area */ VOID PcieFmSetBootUpVoltage ( IN PCIE_LINK_SPEED_CAP LinkCap, IN PCIe_PLATFORM_CONFIG *Pcie ) { FCRxFE00_70A2_STRUCT FCRxFE00_70A2; D18F3x15C_STRUCT D18F3x15C; UINT8 TargetVidIndex; UINT32 Temp; IDS_HDT_CONSOLE (GNB_TRACE, "PcieFmSetBootUpVoltage Enter\n"); ASSERT (LinkCap <= PcieGen2); GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &D18F3x15C.Value, GnbLibGetHeader (Pcie) ); Temp = D18F3x15C.Value; if (LinkCap > PcieGen1) { FCRxFE00_70A2.Value = NbSmuReadEfuse (FCRxFE00_70A2_ADDRESS, GnbLibGetHeader (Pcie)); TargetVidIndex = (UINT8) FCRxFE00_70A2.Field.PcieGen2Vid; } else { TargetVidIndex = PcieSiliconGetGen1VoltageIndex (GnbLibGetHeader (Pcie)); } IDS_HDT_CONSOLE (PCIE_MISC, " Set Voltage for Gen %d, Vid Index %d\n", LinkCap, TargetVidIndex); if (TargetVidIndex == 3) { D18F3x15C.Field.SclkVidLevel2 = D18F3x15C.Field.SclkVidLevel3; GnbLibPciWrite ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &D18F3x15C.Value, GnbLibGetHeader (Pcie) ); PcieSiliconRequestVoltage (2, GnbLibGetHeader (Pcie)); } GnbLibPciWrite ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &Temp, GnbLibGetHeader (Pcie) ); PcieSiliconRequestVoltage (TargetVidIndex, GnbLibGetHeader (Pcie)); IDS_HDT_CONSOLE (GNB_TRACE, "PcieFmSetBootUpVoltage Exit\n"); }
AGESA_STATUS PcieFmAlibBuildAcpiTable ( IN VOID *AlibSsdtPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS AgesaStatus; D18F4x15C_STRUCT D18F4x15C; PP_FUSE_ARRAY *PpFuseArray; UINT32 AmlObjName; VOID *AmlObjPtr; IDS_HDT_CONSOLE (GNB_TRACE, "PcieFmAlibBuildAcpiTable Enter\n"); AgesaStatus = AGESA_SUCCESS; // Set voltage configuration PpFuseArray = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader); ASSERT (PpFuseArray != NULL); if (PpFuseArray != NULL) { GnbLibPciRead ( MAKE_SBDFO (0, 0, 0x18, 0x4, D18F4x15C_ADDRESS), AccessWidth32, &D18F4x15C.Value, StdHeader ); if (D18F4x15C.Field.BoostSrc != 0 || PpFuseArray->GpuBoostCap != 0) { // AmlObjName = 'B0DA'; AmlObjName = Int32FromChar ('A', 'D', '0', 'B'); AmlObjPtr = GnbLibFind (AlibSsdtPtr, ((ACPI_TABLE_HEADER*) &AlibSsdt[0])->TableLength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { *(UINT8*)((UINT8*) AmlObjPtr + 5) = 1; } else { AgesaStatus = AGESA_FATAL; } } } else { AgesaStatus = AGESA_FATAL; } IDS_HDT_CONSOLE (GNB_TRACE, "PcieFmAlibBuildAcpiTable Exit[0x%x]\n", AgesaStatus); return AgesaStatus; }
PCIE_ASPM_TYPE excel950_fun1 ( IN PCI_ADDR Device, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 PcieCapPtr; UINT32 Value; PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, StdHeader); if (PcieCapPtr == 0) { return 0; } GnbLibPciRead ( Device.AddressValue | (PcieCapPtr + PCIE_LINK_CAP_REGISTER), AccessWidth32, &Value, StdHeader ); return (Value >> 10) & 3; }
UINT32 GfxLibGetMainPllFreq ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 MainPllFreq; D18F3xD4_STRUCT D18F3xD4; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3xD4_ADDRESS), AccessWidth32, &D18F3xD4.Value, StdHeader ); if (D18F3xD4.Field.MainPllOpFreqIdEn == 1) { MainPllFreq = 100 * (D18F3xD4.Field.MainPllOpFreqId + 0x10); } else { MainPllFreq = 1600; } return MainPllFreq; }
/** * Get Gen1 voltage Index * * * * * @param[in] StdHeader Standard configuration header */ UINT8 PcieSiliconGetGen1VoltageIndex ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 Index; UINT8 Gen1VidIndex; UINT8 SclkVidArray[4]; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, 0x15c ), AccessWidth32, &SclkVidArray[0], StdHeader ); Gen1VidIndex = 0; for (Index = 0; Index < 4; Index++) { if (SclkVidArray[Index] > SclkVidArray[Gen1VidIndex]) { Gen1VidIndex = Index; } } return Gen1VidIndex; }
AGESA_STATUS GfxInitSview ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; AGESA_STATUS AgesaStatus; GFX_PLATFORM_CONFIG *Gfx; UINT32 OriginalCmdReg; IDS_HDT_CONSOLE (GNB_TRACE, "GfxInitSview Enter\n"); AgesaStatus = AGESA_SUCCESS; Status = GfxLocateConfigData (StdHeader, &Gfx); AGESA_STATUS_UPDATE (Status, AgesaStatus); if (Status == AGESA_SUCCESS) { if (GfxLibIsControllerPresent (StdHeader)) { if (!GfxFmIsVbiosPosted (Gfx)) { GFX_VBIOS_IMAGE_INFO VbiosImageInfo; LibAmdMemCopy (&VbiosImageInfo.StdHeader, StdHeader, sizeof (AMD_CONFIG_PARAMS), StdHeader); VbiosImageInfo.ImagePtr = NULL; VbiosImageInfo.GfxPciAddress = Gfx->GfxPciAddress; VbiosImageInfo.Flags = GFX_VBIOS_IMAGE_FLAG_SPECIAL_POST; GnbLibPciRead (Gfx->GfxPciAddress.AddressValue | 0x4, AccessS3SaveWidth8, &OriginalCmdReg, StdHeader); GnbLibPciRMW (Gfx->GfxPciAddress.AddressValue | 0x4, AccessS3SaveWidth8, 0xff, BIT1 | BIT2 | BIT0, StdHeader); Status = AgesaGetVbiosImage (0, &VbiosImageInfo); if (Status == AGESA_SUCCESS && VbiosImageInfo.ImagePtr != NULL) { GfxLibCopyMemToFb (VbiosImageInfo.ImagePtr, 0, (*((UINT8*) VbiosImageInfo.ImagePtr + 2)) << 9, Gfx); } else { GfxFmDisableController (StdHeader); AgesaStatus = AGESA_ERROR; } GnbLibPciRMW (Gfx->GfxPciAddress.AddressValue | 0x4, AccessS3SaveWidth8, 0x00, OriginalCmdReg, StdHeader); } } } IDS_HDT_CONSOLE (GNB_TRACE, "GfxInitSview Exit [0x%x]\n", AgesaStatus); return AgesaStatus; }
/** * Create IVHD entry * * * @param[in] Ivhd IVHD header pointer * @param[in] StdHeader Standard configuration header * */ VOID SbCreateIvhdEntries ( OUT IVRS_IVHD_ENTRY *Ivhd, IN AMD_CONFIG_PARAMS *StdHeader ) { PCI_ADDR Start; PCI_ADDR End; PCI_ADDR PciAddress; UINT32 Value; AMD_LATE_PARAMS *LateParamsPtr; IDS_HDT_CONSOLE (GNB_TRACE, "SbCreateIvhdEntries Entry\n"); LateParamsPtr = (AMD_LATE_PARAMS *) StdHeader; PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x14, 4, 0); // P2P alias entry GnbLibPciRead (PciAddress.AddressValue | 0x18, AccessWidth32, &Value, StdHeader); Start.AddressValue = MAKE_SBDFO (0, (Value >> 8) & 0xff, 0, 0, 0); End.AddressValue = MAKE_SBDFO (0, (Value >> 16) & 0xff, 0x1f, 0x7, 0); GnbIvhdAddDeviceAliasRangeEntry (Start, End, PciAddress, 0, Ivhd, StdHeader); PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x14, 0, 0); // HPET GnbIvhdAddSpecialDeviceEntry (IvhdSpecialDeviceHpet, PciAddress, 0, 0, Ivhd, StdHeader); // APIC if (LateParamsPtr->GnbLateConfiguration.FchIoapicId != 0xff) { GnbIvhdAddSpecialDeviceEntry ( IvhdSpecialDeviceIoapic, PciAddress, LateParamsPtr->GnbLateConfiguration.FchIoapicId, 0xD7, Ivhd, StdHeader ); } IDS_HDT_CONSOLE (GNB_TRACE, "SbCreateIvhdEntries Exit\n"); }
VOID STATIC PcieMidPortInitCallbackKV ( IN PCIe_ENGINE_CONFIG *Engine, IN OUT VOID *Buffer, IN PCIe_PLATFORM_CONFIG *Pcie ) { DxFxx68_STRUCT DxFxx68; D0F0xE4_PIF_0012_STRUCT D0F0xE4_PIF_0012; PCIe_SUBLINK_INFO *SublinkInfo; PCIe_WRAPPER_INFO *WrapperInfo; PCIe_WRAPPER_CONFIG *Wrapper; CPU_LOGICAL_ID LogicalId; UINT8 Count; UINT8 Nibble; PciePortProgramRegisterTable (PortInitMidTableKV.Table, PortInitMidTableKV.Length, Engine, TRUE, Pcie); if (PcieConfigCheckPortStatus (Engine, INIT_STATUS_PCIE_TRAINING_SUCCESS) || Engine->Type.Port.PortData.LinkHotplug != HotplugDisabled) { PcieEnableSlotPowerLimitV5 (Engine, Pcie); if (GnbFmCheckIommuPresent ((GNB_HANDLE*) PcieConfigGetParentSilicon (Engine), GnbLibGetHeader (Pcie))) { PcieInitPortForIommuV4 (Engine, Pcie); } // After GFX link is trained up and before ASPM is enabled, AGESA needs to check link width, // if it equals to x16, then apply the following change to GFX port: // Per port register 0xA1 - PCIE LC TRAINING CONTROL, bit16 - LC_EXTEND_WAIT_FOR_SKP = 1 GnbLibPciRead ( Engine->Type.Port.Address.AddressValue | DxFxx68_ADDRESS, AccessWidth32, &DxFxx68, GnbLibGetHeader (Pcie) ); if (DxFxx68.Field.NegotiatedLinkWidth == 16) { PciePortRegisterRMW ( Engine, DxFxxE4_xA1_ADDRESS, DxFxxE4_xA1_LcExtendWaitForSkp_MASK, (1 << DxFxxE4_xA1_LcExtendWaitForSkp_OFFSET), TRUE, Pcie ); } } Wrapper = PcieConfigGetParentWrapper (Engine); SublinkInfo = &(((PCIe_INFO_BUFFER *)Buffer)->SublinkInfo[MIN (Engine->EngineData.StartLane, Engine->EngineData.EndLane) / 4]); WrapperInfo = &(((PCIe_INFO_BUFFER *)Buffer)->WrapperInfo[Wrapper->WrapId]); GetLogicalIdOfCurrentCore (&LogicalId, (AMD_CONFIG_PARAMS *)Pcie->StdHeader); // Check if this CPU is KV A0 // UBTS468566 if ((LogicalId.Revision & AMD_F15_KV_A0) != 0) { Count = SublinkInfo->GppPortCount; IDS_HDT_CONSOLE (GNB_TRACE, "x1x2 PortCount = %02x\n", Count); if (Count == 2) { // If number of GPP ports under the same sublink is 2, Delay L1 Exit (prolong minimum time spent in L1) PciePortRegisterRMW ( Engine, DxFxxE4_xA0_ADDRESS, DxFxxE4_xA0_LcDelayCount_MASK | DxFxxE4_xA0_LcDelayL1Exit_MASK, (0 << DxFxxE4_xA0_LcDelayCount_OFFSET) | (1 << DxFxxE4_xA0_LcDelayL1Exit_OFFSET), TRUE, Pcie ); } else if (Count > 2) { // If number of GPP ports > 2 if (SublinkInfo->MaxGenCapability > Gen1) { // If at least 1 GPP is Gen2 capable, Disable PLL Power down feature Wrapper = PcieConfigGetParentWrapper (Engine); Nibble = (UINT8) ((MIN (Engine->EngineData.StartLane, Engine->EngineData.EndLane) % 8) / 4); // Only PSD and PPD can have x1/x2 links, so we assume that PIF number is always 0 D0F0xE4_PIF_0012.Value = PcieRegisterRead ( Wrapper, PIF_SPACE (Wrapper->WrapId, 0, D0F0xE4_PIF_0012_ADDRESS + Nibble), Pcie ); D0F0xE4_PIF_0012.Field.PllPowerStateInOff = PifPowerStateL0; D0F0xE4_PIF_0012.Field.PllPowerStateInTxs2 = PifPowerStateL0; PcieRegisterWrite ( Wrapper, PIF_SPACE (Wrapper->WrapId, 0, D0F0xE4_PIF_0012_ADDRESS + Nibble), D0F0xE4_PIF_0012.Value, TRUE, Pcie ); } else { // All ports are only Gen1 PciePortRegisterRMW ( Engine, DxFxxE4_xC0_ADDRESS, DxFxxE4_xC0_StrapMedyTSxCount_MASK, 0x2 << DxFxxE4_xC0_StrapMedyTSxCount_OFFSET, TRUE, Pcie ); } } } PcieRegisterRMW ( Wrapper, WRAP_SPACE (Wrapper->WrapId, D0F0xE4_WRAP_0802_ADDRESS + (0x100 * Engine->Type.Port.PortId)), D0F0xE4_WRAP_0802_StrapBifL1ExitLatency_MASK, (WrapperInfo->L1ExitLatencyValue << D0F0xE4_WRAP_0802_StrapBifL1ExitLatency_OFFSET), TRUE, Pcie ); if (WrapperInfo->DisableL1OnWrapper == TRUE) { Engine->Type.Port.PortData.LinkAspm &= ~(AspmL1); } PcieEnableAspm (Engine, Pcie); }
/** * Set current link speed * * * @param[in] LinkSpeedCapability Link Speed Capability * @param[in] Engine Pointer to engine configuration descriptor * @param[in] Pcie Pointer to global PCIe configuration * */ VOID PcieSetLinkSpeedCapV4 ( IN PCIE_LINK_SPEED_CAP LinkSpeedCapability, IN PCIe_ENGINE_CONFIG *Engine, IN PCIe_PLATFORM_CONFIG *Pcie ) { DxF0xE4_xA4_STRUCT DxF0xE4_xA4; DxF0xE4_xC0_STRUCT DxF0xE4_xC0; DxF0x88_STRUCT DxF0x88; GnbLibPciRead ( Engine->Type.Port.Address.AddressValue | DxF0x88_ADDRESS, AccessWidth32, &DxF0x88.Value, GnbLibGetHeader (Pcie) ); DxF0xE4_xA4.Value = PciePortRegisterRead ( Engine, DxF0xE4_xA4_ADDRESS, Pcie ); DxF0xE4_xC0.Value = PciePortRegisterRead ( Engine, DxF0xE4_xC0_ADDRESS, Pcie ); switch (LinkSpeedCapability) { case PcieGen3: DxF0xE4_xA4.Field.LcGen2EnStrap = 0x1; DxF0xE4_xA4.Field.LcGen3EnStrap = 0x1; DxF0xE4_xA4.Field.LcMultUpstreamAutoSpdChngEn = 0x1; DxF0x88.Field.TargetLinkSpeed = 0x3; DxF0x88.Field.HwAutonomousSpeedDisable = 0x0; PciePortRegisterRMW ( Engine, DxF0xE4_xA2_ADDRESS, DxF0xE4_xA2_LcDynLanesPwrState_MASK, (2 << DxF0xE4_xA2_LcDynLanesPwrState_OFFSET), FALSE, Pcie ); break; case PcieGen2: DxF0xE4_xA4.Field.LcGen2EnStrap = 0x1; DxF0xE4_xA4.Field.LcMultUpstreamAutoSpdChngEn = 0x1; DxF0x88.Field.TargetLinkSpeed = 0x2; DxF0x88.Field.HwAutonomousSpeedDisable = 0x0; break; case PcieGen1: DxF0xE4_xA4.Field.LcGen2EnStrap = 0x0; DxF0xE4_xA4.Field.LcMultUpstreamAutoSpdChngEn = 0x0; DxF0x88.Field.TargetLinkSpeed = 0x1; DxF0x88.Field.HwAutonomousSpeedDisable = 0x1; PcieRegisterWriteField ( PcieConfigGetParentWrapper (Engine), WRAP_SPACE (PcieConfigGetParentWrapper (Engine)->WrapId, D0F0xE4_WRAP_0803_ADDRESS + 0x100 * Engine->Type.Port.PortId), D0F0xE4_WRAP_0803_StrapBifDeemphasisSel_OFFSET, D0F0xE4_WRAP_0803_StrapBifDeemphasisSel_WIDTH, 0, FALSE, Pcie ); break; default: ASSERT (FALSE); break; } if ((Pcie->PsppPolicy == PsppDisabled) || (PcieConfigIsSbPcieEngine (Engine))) { DxF0xE4_xC0.Field.StrapAutoRcSpeedNegotiationDis = 0x0; } else { DxF0xE4_xC0.Field.StrapAutoRcSpeedNegotiationDis = 0x1; } PciePortRegisterWrite ( Engine, DxF0xE4_xA4_ADDRESS, DxF0xE4_xA4.Value, FALSE, Pcie ); PciePortRegisterWrite ( Engine, DxF0xE4_xC0_ADDRESS, DxF0xE4_xC0.Value, FALSE, Pcie ); GnbLibPciWrite ( Engine->Type.Port.Address.AddressValue | DxF0x88_ADDRESS, AccessWidth32, &DxF0x88.Value, GnbLibGetHeader (Pcie) ); }
AGESA_STATUS PcieAlibBuildAcpiTable ( IN AMD_CONFIG_PARAMS *StdHeader, OUT VOID **AlibSsdtPtr ) { AGESA_STATUS Status; UINT32 AmlObjName; PCIe_PLATFORM_CONFIG *Pcie; PP_FUSE_ARRAY *PpFuseArray; VOID *AlibSsdtBuffer; VOID *AmlObjPtr; UINT8 SclkVidArray[4]; UINT8 BootUpVid; UINT8 BootUpVidIndex; UINT8 Gen1VidIndex; UINTN Index; UINTN AlibSsdtlength; Status = AGESA_SUCCESS; AlibSsdtlength = ((ACPI_TABLE_HEADER*) &AlibSsdt[0])->TableLength; if (*AlibSsdtPtr == NULL) { AlibSsdtBuffer = GnbAllocateHeapBuffer ( AMD_ACPI_ALIB_BUFFER_HANDLE, AlibSsdtlength, StdHeader ); ASSERT (AlibSsdtBuffer != NULL); if (AlibSsdtBuffer == NULL) { return AGESA_ERROR; } *AlibSsdtPtr = AlibSsdtBuffer; } else { AlibSsdtBuffer = *AlibSsdtPtr; } // Copy template to buffer LibAmdMemCopy (AlibSsdtBuffer, &AlibSsdt[0], AlibSsdtlength, StdHeader); // Set PCI MMIO configuration // AmlObjName = '10DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '1'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); if (AmlObjPtr != NULL) { UINT64 MsrReg; LibAmdMsrRead (MSR_MMIO_Cfg_Base, &MsrReg, StdHeader); if ((MsrReg & BIT0) != 0 && (MsrReg & 0xFFFFFFFF00000000) == 0) { *(UINT32*)((UINT8*)AmlObjPtr + 5) = (UINT32)(MsrReg & 0xFFFFF00000); } else { Status = AGESA_ERROR; } } else { Status = AGESA_ERROR; } // Set voltage configuration PpFuseArray = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader); if (PpFuseArray != NULL) { // AmlObjName = '30DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '3'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { *(UINT8*)((UINT8*)AmlObjPtr + 5) = PpFuseArray->PcieGen2Vid; } else { Status = AGESA_ERROR; } } else { Status = AGESA_ERROR; } GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &SclkVidArray[0], StdHeader ); Gen1VidIndex = 0; BootUpVidIndex = 0; BootUpVid = 0xff; for (Index = 0; Index < 4; Index++) { if (SclkVidArray[Index] > SclkVidArray[Gen1VidIndex]) { Gen1VidIndex = (UINT8) Index; } if (SclkVidArray[Index] != 0 && SclkVidArray[Index] < BootUpVid) { BootUpVid = SclkVidArray[Index]; BootUpVidIndex = (UINT8) Index; } } // AmlObjName = '40DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '4'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { *(UINT8*)((UINT8*)AmlObjPtr + 5) = Gen1VidIndex; } else { Status = AGESA_ERROR; } // AmlObjName = '50DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '5'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { *(UINT8*)((UINT8*)AmlObjPtr + 5) = BootUpVidIndex; } else { Status = AGESA_ERROR; } // Set PCIe configuration if (PcieLocateConfigurationData (StdHeader, &Pcie) == AGESA_SUCCESS) { // AmlObjName = '20DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '2'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { *(UINT8*)((UINT8*)AmlObjPtr + 5) = Pcie->PsppPolicy; } else { Status = AGESA_ERROR; } // AmlObjName = '60DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '6'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { PcieConfigRunProcForAllEngines ( DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE, PcieAlibSetPortMaxSpeedCallback, (UINT8*)((UINT8*)AmlObjPtr + 7), Pcie ); } else { Status = AGESA_ERROR; } // AmlObjName = '80DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '8'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { PcieConfigRunProcForAllEngines ( DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE, PcieAlibSetPortOverrideSpeedCallback, (UINT8*)((UINT8*)AmlObjPtr + 7), Pcie ); } else { Status = AGESA_ERROR; } // AmlObjName = '70DA'; AmlObjName = Int32FromChar ('A', 'D', '0', '7'); AmlObjPtr = GnbLibFind (AlibSsdtBuffer, AlibSsdtlength, (UINT8*) &AmlObjName, sizeof (AmlObjName)); ASSERT (AmlObjPtr != NULL); if (AmlObjPtr != NULL) { PcieConfigRunProcForAllEngines ( DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE, PcieAlibSetPortInfoCallback, (UINT8*)((UINT8*)AmlObjPtr + 4), Pcie ); } else { Status = AGESA_ERROR; } } else { ASSERT (FALSE); Status = AGESA_ERROR; } if (Status == AGESA_SUCCESS) { Status = PcieFmAlibBuildAcpiTable (AlibSsdtBuffer, StdHeader); } if (Status != AGESA_SUCCESS) { //Shrink table length to size of the header ((ACPI_TABLE_HEADER*) AlibSsdtBuffer)->TableLength = sizeof (ACPI_TABLE_HEADER); } ChecksumAcpiTable ((ACPI_TABLE_HEADER*) AlibSsdtBuffer, StdHeader); return Status; }
/** * Family specific fuse table patch * Is's correct behavior if we would have 4 states, it would be * PP_FUSE_ARRAY->LclkDpmDid[0] - Goes to State 5 * PP_FUSE_ARRAY->LclkDpmDid[1] - Goes to State 6 * PP_FUSE_ARRAY->LclkDpmDid[2] - Goes to State 7 * If we would have 4 states it would be * PP_FUSE_ARRAY->LclkDpmDid[0] - Goes to State 4 * PP_FUSE_ARRAY->LclkDpmDid[1] - Goes to State 5 * PP_FUSE_ARRAY->LclkDpmDid[2] - Goes to State 6 * PP_FUSE_ARRAY->LclkDpmDid[3] - Goes to State 7 * * @param[in] PpFuseArray Pointer to PP_FUSE_ARRAY * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS */ VOID NbFmFuseAdjustFuseTablePatch ( IN OUT PP_FUSE_ARRAY *PpFuseArray, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 LclkDpmMode; UINT8 SwSatateIndex; UINT8 MaxSclkIndex; UINT8 DpmStateIndex; UINT8 CurrentSclkDpmDid; CPU_LOGICAL_ID LogicalId; D18F3x15C_STRUCT D18F3x15C; LclkDpmMode = GnbBuildOptions.LclkDpmEn ? LclkDpmRcActivity : LclkDpmDisabled; GetLogicalIdOfCurrentCore (&LogicalId, StdHeader); if ((LogicalId.Revision & (AMD_F12_LN_A0 | AMD_F12_LN_A1)) != 0) { LclkDpmMode = LclkDpmDisabled; } IDS_OPTION_HOOK (IDS_GNB_LCLK_DPM_EN, &LclkDpmMode, StdHeader); // Read Sclk VID GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &D18F3x15C.Value, StdHeader ); PpFuseArray->SclkVid[0] = (UINT8) (D18F3x15C.Field.SclkVidLevel0); PpFuseArray->SclkVid[1] = (UINT8) (D18F3x15C.Field.SclkVidLevel1); PpFuseArray->SclkVid[2] = (UINT8) (D18F3x15C.Field.SclkVidLevel2); PpFuseArray->SclkVid[3] = (UINT8) (D18F3x15C.Field.SclkVidLevel3); //For all CPU rev LclkDpmValid[3] = 0 PpFuseArray->LclkDpmValid[3] = 0; PpFuseArray->LclkDpmVid[3] = 0; PpFuseArray->LclkDpmDid[3] = 0; // For LCLKDPM set LclkDpmVid[0] = 0, no matter if LCLK DMP enable or disable. PpFuseArray->LclkDpmVid[0] = 0; if (LclkDpmMode != LclkDpmRcActivity) { //If LCLK DPM disable (LclkDpmMode != LclkDpmRcActivity) // - LclkDpmDid[1,2] = LclkDpmDid [0], LclkDpmVid[1,2] = LclkDpmVid[0] // - Execute LCLK DPM init PpFuseArray->LclkDpmVid[1] = PpFuseArray->LclkDpmVid[0]; PpFuseArray->LclkDpmVid[2] = PpFuseArray->LclkDpmVid[0]; PpFuseArray->LclkDpmDid[1] = PpFuseArray->LclkDpmDid[0]; PpFuseArray->LclkDpmDid[2] = PpFuseArray->LclkDpmDid[0]; IDS_HDT_CONSOLE (NB_MISC, " F12 LCLK DPM Mode Disable -- use DPM0 fusing\n"); } else { // If LCLK DPM enabled // - use fused values for LclkDpmDid[0,1,2] and appropriate voltage // - Execute LCLK DPM init PpFuseArray->LclkDpmVid[2] = PpFuseArray->PcieGen2Vid; if (GfxLibIsControllerPresent (StdHeader)) { //VID index = VID index associated with highest SCLK DPM state in the Powerplay state where Label_Performance=1 // This would ignore the UVD case (where Label_Performance would be 0). for (SwSatateIndex = 0 ; SwSatateIndex < PP_FUSE_MAX_NUM_SW_STATE; SwSatateIndex++) { if (PpFuseArray->PolicyLabel[SwSatateIndex] == POLICY_LABEL_PERFORMANCE) { break; } } MaxSclkIndex = 0; CurrentSclkDpmDid = 0xff; ASSERT (PpFuseArray->SclkDpmValid[SwSatateIndex] != 0); for (DpmStateIndex = 0; DpmStateIndex < PP_FUSE_MAX_NUM_DPM_STATE; DpmStateIndex++) { if ((PpFuseArray->SclkDpmValid[SwSatateIndex] & (1 << DpmStateIndex)) != 0) { if (PpFuseArray->SclkDpmDid[DpmStateIndex] < CurrentSclkDpmDid) { CurrentSclkDpmDid = PpFuseArray->SclkDpmDid[DpmStateIndex]; MaxSclkIndex = DpmStateIndex; } } } PpFuseArray->LclkDpmVid[1] = PpFuseArray->SclkDpmVid[MaxSclkIndex]; } else { PpFuseArray->LclkDpmVid[1] = PpFuseArray->LclkDpmVid[0]; PpFuseArray->LclkDpmDid[1] = PpFuseArray->LclkDpmDid[0]; } // - use fused values for LclkDpmDid[0,1,2] and appropriate voltage //Keep using actual fusing IDS_HDT_CONSOLE (NB_MISC, " LCLK DPM use actual fusing.\n"); } //Patch SclkThermDid to 200Mhz if not fused if (PpFuseArray->SclkThermDid == 0) { PpFuseArray->SclkThermDid = GfxLibCalculateDid (200 * 100, GfxLibGetMainPllFreq (StdHeader) * 100); } }