/** * GPP hot plug handler * * * @param[in] pConfig Southbridge configuration structure pointer. * @param[in] HpPort The hot plug port number. * */ static VOID sbGppHotPlugSmiProcess ( IN AMDSBCFG* pConfig, IN UINT32 HpPort ) { UINT8 FailedPort; // First restore GPP pads if needed if (pConfig->GppDynamicPowerSaving && pConfig->AlinkPhyPllPowerDown && pConfig->GppPhyPllPowerDown) { rwAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29), ~(UINT32) (1 << (12 + HpPort)), 0); rwAlink (RC_INDXC_REG65, ~(UINT32) (0x101 << HpPort), 0); SbStall (1000); } FailedPort = (UINT8) (1 << HpPort); if (pConfig->GppGen2 && pConfig->GppGen2Strap) { if (GppPortPollingLtssm (pConfig, FailedPort, TRUE)) { sbGppForceGen1 (pConfig, FailedPort); FailedPort = GppPortPollingLtssm (pConfig, FailedPort, FALSE); } } else { sbGppForceGen1 (pConfig, FailedPort); FailedPort = GppPortPollingLtssm (pConfig, FailedPort, FALSE); } }
/** * sbGppTogglePcieReset - Toggle PCIE_RST2# * * * @param[in] pConfig * */ VOID sbGppTogglePcieReset ( IN AMDSBCFG* pConfig ) { if (pConfig->GppToggleReset) { SbResetPcie (SbBlock, AssertReset); SbStall (500); SbResetPcie (SbBlock, DeassertReset); } }
/** * azaliaInitAfterPciEnum - Config HD Audio after PCI emulation * * * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID azaliaInitAfterPciEnum ( IN AMDSBCFG* pConfig ) { UINT8 Data; UINT8 i; UINT8 dbEnableAzalia; UINT8 dbPinRouting; UINT8 dbChannelNum; UINT8 dbTempVariable; UINT16 dwTempVariable; UINT32 ddBAR0; UINT32 ddTempVariable; dbEnableAzalia = 0; dbChannelNum = 0; dbTempVariable = 0; dwTempVariable = 0; ddBAR0 = 0; ddTempVariable = 0; if ( pConfig->AzaliaController == 1 ) { return; } if ( pConfig->AzaliaController != 1 ) { RWPCI ((AZALIA_BUS_DEV_FUN << 16) + SB_AZ_REG04, AccWidthUint8 | S3_SAVE, ~BIT1, BIT1); if ( pConfig->BuildParameters.AzaliaSsid != NULL ) { RWPCI ((AZALIA_BUS_DEV_FUN << 16) + SB_AZ_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.AzaliaSsid); } ReadPCI ((AZALIA_BUS_DEV_FUN << 16) + SB_AZ_REG10, AccWidthUint32, &ddBAR0); if ( ddBAR0 != 0 ) { if ( ddBAR0 != 0xFFFFFFFF ) { ddBAR0 &= ~(0x03FFF); dbEnableAzalia = 1; } } } if ( dbEnableAzalia ) { // Get SDIN Configuration if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin0 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x01); } if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin1 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x01); } if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin2 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x01); } if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin3 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x01); } // INT#A Azalia resource Data = 0x93; // Azalia APIC index WriteIO (SB_IOMAP_REGC00, AccWidthUint8, &Data); Data = 0x10; // IRQ16 (INTA#) WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &Data); i = 11; do { ReadMEM ( ddBAR0 + SB_AZ_BAR_REG08, AccWidthUint8 | S3_SAVE, &dbTempVariable); dbTempVariable |= BIT0; WriteMEM (ddBAR0 + SB_AZ_BAR_REG08, AccWidthUint8 | S3_SAVE, &dbTempVariable); SbStall (1000); ReadMEM (ddBAR0 + SB_AZ_BAR_REG08, AccWidthUint8 | S3_SAVE, &dbTempVariable); i--; } while ((! (dbTempVariable & BIT0)) && (i > 0) ); if ( i == 0 ) { return; } SbStall (1000); ReadMEM ( ddBAR0 + SB_AZ_BAR_REG0E, AccWidthUint16, &dwTempVariable); if ( dwTempVariable & 0x0F ) { //atleast one azalia codec found // ?? E0 is not real register what we expect. we have change to GPIO/and program GPIO Mux //ReadMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGE0, AccWidthUint8, &dbPinRouting); dbPinRouting = pConfig->AZALIACONFIG.AzaliaSdinPin; do { if ( ( ! (dbPinRouting & BIT0) ) && (dbPinRouting & BIT1) ) { // dbChannelNum = 3; configureAzaliaPinCmd (pConfig, ddBAR0, dbChannelNum); } dbPinRouting >>= 2; dbChannelNum++; } while ( dbChannelNum != 4 ); } else { //No Azalia codec found if ( pConfig->AzaliaController != 2 ) {
/** * CheckGppLinkStatus - loop polling the link status for each GPP port * * * Return: ToggleStatus[3:0] = Port bitmap for those need to clear De-emphasis * * @param[in] pConfig Southbridge configuration structure pointer. * */ UINT8 CheckGppLinkStatus ( IN AMDSBCFG* pConfig ) { UINT32 retryCounter; UINT32 portId; UINT32 abIndex; UINT32 Data32; UINT8 portScanMap; UINT8 portScanMap2; UINT8 ToggleStatus; UINT16 i; SBGPPPORTCONFIG *portCfg; portScanMap = 0; retryCounter = MAX_TRAINING_RETRY; ToggleStatus = 0; // Obtain a list of ports to be checked for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) { portCfg = &pConfig->PORTCONFIG[portId].PortCfg; if ( portCfg->PortPresent == TRUE && portCfg->PortDetected == FALSE ) { portScanMap |= 1 << portId; } } portScanMap2 = portScanMap; // // After training is enabled, Check LCSTATE for each port, if LCSTATE<= 4, then keep // polling for up to 40ms. If LCSTATE still <= 4, then assume the port to be empty. // i = 400; while ( --i && portScanMap2) { for (portId = 0; portId < MAX_GPP_PORTS; portId++) { portCfg = &pConfig->PORTCONFIG[portId].PortCfg; if (((portCfg->PortHotPlug == FALSE) || ((portCfg->PortHotPlug == TRUE) && (pConfig->S3Resume == FALSE)) ) && (portScanMap2 & (1 << portId))) { // // Get port link state (reading LC_CURRENT_STATE of PCIEIND_P) // abIndex = SB_RCINDXP_REGA5 | (UINT32) (RCINDXP << 29) | (portId << 24); Data32 = readAlink (abIndex) & 0x3F; if ((UINT8) (Data32) > 4) { portScanMap2 &= ~(1 << portId); // This port is not empty break; } SbStall (100); // Delay 100us } } } portScanMap &= ~portScanMap2; // Mark remaining ports as empty while ( --retryCounter && portScanMap ) { for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) { portCfg = &pConfig->PORTCONFIG[portId].PortCfg; if (( portCfg->PortHotPlug == TRUE ) && ( pConfig->S3Resume )) { continue; } if ( portCfg->PortPresent == TRUE && portCfg->PortDetected == FALSE ) { // // Get port link state (reading LC_CURRENT_STATE of PCIEIND_P) // SbStall (1000); // Delay 400us abIndex = SB_RCINDXP_REGA5 | (UINT32) (RCINDXP << 29) | (portId << 24); Data32 = readAlink (abIndex) & 0x3F3F3F3F; if ( (UINT8) (Data32) == 0x10 ) { portCfg->PortDetected = TRUE; portScanMap &= ~(1 << portId); } else { for (i = 0; i < 4; i++) { // // Compliance mode (0x7), downgrade from Gen2 to Gen1 (*A12) // if ((UINT8) (Data32) == 0x29 || (UINT8) (Data32) == 0x2A || (UINT8) (Data32) == 0x7 ) { ToggleStatus |= (1 << portId); // A11 only: need to toggle GPP reset portScanMap &= ~(1 << portId); } Data32 >>= 8; } } } } }
/** * GPP early programming and link training. On exit all populated EPs should be fully operational. * * * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sbPcieGppEarlyInit ( IN AMDSBCFG* pConfig ) { UINT8 TogglePort; UINT8 portNum; UINT32 reg32Value; UINT8 retryCount; UINT8 cimGppMemWrImprove; UINT8 cimGppLaneReversal; UINT8 cimAlinkPhyPllPowerDown; cimGppMemWrImprove = pConfig->GppMemWrImprove; cimGppLaneReversal = (UINT8) pConfig->GppLaneReversal; cimAlinkPhyPllPowerDown = (UINT8) pConfig->AlinkPhyPllPowerDown; #if SB_CIMx_PARAMETER == 0 cimGppMemWrImprove = cimGppMemWrImproveDefault; cimGppLaneReversal = cimGppLaneReversalDefault; cimAlinkPhyPllPowerDown = cimAlinkPhyPllPowerDownDefault; #endif // // Configure NB-SB link PCIE PHY PLL power down for L1 // if ( cimAlinkPhyPllPowerDown == TRUE ) { UINT32 abValue; // Set PCIE_P_CNTL in Alink PCIEIND space writeAlink (SB_AX_INDXC_REG30 | (UINT32) (AXINDC << 29), 0x40); abValue = readAlink (SB_AX_DATAC_REG34 | (UINT32) (AXINDC << 29)); abValue |= BIT12 + BIT3 + BIT0; abValue &= ~(BIT9 + BIT4); writeAlink (SB_AX_DATAC_REG34 | (UINT32) (AXINDC << 29), abValue); rwAlink (SB_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), ~BIT8, (BIT8)); } // // Set ABCFG 0x031C[0] = 1 enable the lane reversal support. // reg32Value = readAlink (SB_ABCFG_REG31C | (UINT32) (ABCFG << 29)); if ( cimGppLaneReversal ) { writeAlink (SB_ABCFG_REG31C | (UINT32) (ABCFG << 29), reg32Value | BIT0); } else { writeAlink (SB_ABCFG_REG31C | (UINT32) (ABCFG << 29), reg32Value | 0x00); } // // Set abcfg:0x90[20] = 1 to enable GPP bridge multi-function // reg32Value = readAlink (SB_ABCFG_REG90 | (UINT32) (ABCFG << 29)); writeAlink (SB_ABCFG_REG90 | (UINT32) (ABCFG << 29), reg32Value | BIT20); // // Initialize and configure GPP // if (pConfig->GppFunctionEnable) { // PreInit - Enable GPP link training PreInitGppLink (pConfig); // // GPP Upstream Memory Write Arbitration Enhancement ABCFG 0x54[26] = 1 // GPP Memory Write Max Payload Improvement RCINDC_Reg 0x10[12:10] = 0x4 // if ( cimGppMemWrImprove == TRUE ) { rwAlink (SB_ABCFG_REG54 | (UINT32) (ABCFG << 29), ~BIT26, (BIT26)); rwAlink (SB_RCINDXC_REG10 | (UINT32) (RCINDXC << 29), ~(BIT12 + BIT11 + BIT10), (BIT12)); } if ( pConfig->S3Resume ) { for ( portNum = 0; portNum < MAX_GPP_PORTS; portNum++ ) { reg32Value = readAlink ((SB_ABCFG_REG340 + portNum * 4) | (UINT32) (ABCFG << 29)); writeAlink ((SB_ABCFG_REG340 + portNum * 4) | (UINT32) (ABCFG << 29), reg32Value & ~BIT21); } } // // a) Loop polling regA5 -> LcState (timeout ~100ms); // b) if (LcState[5:0] == 0x10), training successful, go to g); // c) if any of (LcState[13:8], [21:16], [29:24]) == 0x29 or 0x2A: // d) Clear De-emphasis bit for relevant ports; // e) Toggle GPP reset signal (via OEM callback); // f) go back to a); // g) exit; // for (retryCount = 0; retryCount < MAX_GPP_RESETS; retryCount++) { // Polling each GPP port for link status TogglePort = CheckGppLinkStatus (pConfig); if (TogglePort == 0) { break; } else { // Check failure port and clear STRAP_BIF_DE_EMPHASIS_SEL_x_GPP bit (abcfg:0x34[0, 4, 8, C][21]=0) for ( portNum = 0; portNum < MAX_GPP_PORTS; portNum++ ) { if (TogglePort & (1 << portNum)) { reg32Value = readAlink ((SB_ABCFG_REG340 + portNum * 4) | (UINT32) (ABCFG << 29)); writeAlink ((SB_ABCFG_REG340 + portNum * 4) | (UINT32) (ABCFG << 29), reg32Value & ~BIT21); } sbGppForceGen1 (portNum); } // Toggle GPP reset (Note this affects all SB800 GPP ports) CallBackToOEM (CB_SBGPP_RESET_ASSERT, (UINT32)TogglePort, pConfig); SbStall (500); CallBackToOEM (CB_SBGPP_RESET_DEASSERT, (UINT32)TogglePort, pConfig); } }; // Misc operations after link training AfterGppLinkInit (pConfig); } else { // RPR 5.11 Power Saving With GPP Disable // ABCFG 0xC0[8] = 0x0 // ABCFG 0xC0[15:12] = 0xF // Enable "Power Saving Feature for A-Link Express Lanes" // Enable "Power Saving Feature for GPP Lanes" // ABCFG 0x90[19] = 1 // ABCFG 0x90[6] = 1 // RCINDC_Reg 0x65 [27:0] = 0xFFFFFFF // ABCFG 0xC0[7:4] = 0x0 rwAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29), ~BIT8, (BIT4 + BIT5 + BIT6 + BIT7)); rwAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, (BIT12 + BIT13 + BIT14 + BIT15)); rwAlink (SB_AX_INDXC_REG40, ~(BIT9 + BIT4), (BIT0 + BIT3 + BIT12)); rwAlink (RC_INDXC_REG40, ~(BIT9 + BIT4), (BIT0 + BIT3 + BIT12)); rwAlink ((SB_ABCFG_REG90 | (UINT32) (ABCFG << 29)), 0xFFFFFFFF, (BIT6 + BIT19)); rwAlink (RC_INDXC_REG65, 0xFFFFFFFF, 0x0fffffff); rwAlink ((SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29)), ~(BIT4 + BIT5 + BIT6 + BIT7), 0); } sbGppDisableUnusedPadMap ( pConfig ); }
/** * azaliaInitAfterPciEnum - Config HD Audio after PCI emulation * * * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID azaliaInitAfterPciEnum ( IN AMDSBCFG* pConfig ) { UINT8 Data; UINT8 i; UINT8 dbEnableAzalia; UINT8 dbPinRouting; UINT8 dbChannelNum; UINT8 dbTempVariable; UINT16 dwTempVariable; UINT32 ddBAR0; UINT32 ddTempVariable; dbEnableAzalia = 0; dbChannelNum = 0; dbTempVariable = 0; dwTempVariable = 0; ddBAR0 = 0; ddTempVariable = 0; if ( pConfig->AzaliaController == 1 ) { return; } if ( pConfig->AzaliaController != 1 ) { RWPCI ((AZALIA_BUS_DEV_FUN << 16) + SB_AZ_REG04, AccWidthUint8 | S3_SAVE, ~BIT1, BIT1); if ( pConfig->BuildParameters.AzaliaSsid != NULL ) { RWPCI ((AZALIA_BUS_DEV_FUN << 16) + SB_AZ_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.AzaliaSsid); } ReadPCI ((AZALIA_BUS_DEV_FUN << 16) + SB_AZ_REG10, AccWidthUint32, &ddBAR0); if ( ddBAR0 != 0 ) { if ( ddBAR0 != 0xFFFFFFFF ) { ddBAR0 &= ~(0x03FFF); dbEnableAzalia = 1; TRACE ((DMSG_SB_TRACE, "CIMxSB - Enabling Azalia controller (BAR setup is ok) \n")); } } } if ( dbEnableAzalia ) { pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin0 = 0x03 & (pConfig->AZALIACONFIG.AzaliaSdinPin >> 0); pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin1 = 0x03 & (pConfig->AZALIACONFIG.AzaliaSdinPin >> 2); pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin2 = 0x03 & (pConfig->AZALIACONFIG.AzaliaSdinPin >> 4); pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin3 = 0x03 & (pConfig->AZALIACONFIG.AzaliaSdinPin >> 6); // Get SDIN Configuration if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin0 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG167, AccWidthUint8, 0, 0x01); } if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin1 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG168, AccWidthUint8, 0, 0x01); } if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin2 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG169, AccWidthUint8, 0, 0x01); } if ( pConfig->AZALIACONFIG.AzaliaConfig.AzaliaSdin3 == 2 ) { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x3E); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x00); } else { RWMEM (ACPI_MMIO_BASE + GPIO_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x0); RWMEM (ACPI_MMIO_BASE + IOMUX_BASE + SB_GPIO_REG170, AccWidthUint8, 0, 0x01); } // INT#A Azalia resource Data = 0x93; // Azalia APIC index WriteIO (SB_IOMAP_REGC00, AccWidthUint8, &Data); Data = 0x10; // IRQ16 (INTA#) WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &Data); i = 11; do { ReadMEM ( ddBAR0 + SB_AZ_BAR_REG08, AccWidthUint8 | S3_SAVE, &dbTempVariable); dbTempVariable |= BIT0; WriteMEM (ddBAR0 + SB_AZ_BAR_REG08, AccWidthUint8 | S3_SAVE, &dbTempVariable); SbStall (1000); ReadMEM (ddBAR0 + SB_AZ_BAR_REG08, AccWidthUint8 | S3_SAVE, &dbTempVariable); i--; } while ((! (dbTempVariable & BIT0)) && (i > 0) ); if ( i == 0 ) { TRACE ((DMSG_SB_TRACE, "CIMxSB - Problem in resetting Azalia controller\n")); return; } SbStall (1000); ReadMEM ( ddBAR0 + SB_AZ_BAR_REG0E, AccWidthUint16, &dwTempVariable); if ( dwTempVariable & 0x0F ) { TRACE ((DMSG_SB_TRACE, "CIMxSB - At least One Azalia CODEC found \n")); //atleast one azalia codec found dbPinRouting = pConfig->AZALIACONFIG.AzaliaSdinPin; do { if ( ( ! (dbPinRouting & BIT0) ) && (dbPinRouting & BIT1) ) { configureAzaliaPinCmd (pConfig, ddBAR0, dbChannelNum); } dbPinRouting >>= 2; dbChannelNum++; } while ( dbChannelNum != 4 ); } else {