| /** |
| * @file |
| * |
| * Routines to support Hotplug. |
| * |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: CIMx-NB |
| * @e sub-project: |
| * @e \$Revision:$ @e \$Date:$ |
| * |
| */ |
| /***************************************************************************** |
| * |
| * Copyright (C) 2012 Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * |
| ***************************************************************************/ |
| /*---------------------------------------------------------------------------------------- |
| * M O D U L E S U S E D |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| #include "NbPlatform.h" |
| #include "amdSbLib.h" |
| |
| #ifndef HOTPLUG_SUPPORT_DISABLED |
| |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| #define ATTN_BUTTON_PRESENT BIT0 |
| #define PWR_CONTROLLER_PRESENT BIT1 |
| #define MRL_SENSOR_PRESENT BIT2 |
| #define ATTN_INDICATOR_PRESENT BIT3 |
| #define PWR_INDICATOR_PRESENT BIT4 |
| #define HOTPLUG_SURPRISE BIT5 |
| #define HOTPLUG_CAPABLE BIT6 |
| |
| #define ATTN_BUTTON_PRESSED BIT0 |
| #define PWR_FAULT_DETECTED BIT1 |
| #define MRL_SENSOR_CHANGED BIT2 |
| #define PRESENCE_DETECT_CHANGED BIT3 |
| #define COMMAND_COMPLETED BIT4 |
| #define MRL_SENSOR_STATE BIT5 |
| #define PRESENCE_DETECT_STATE BIT6 |
| #define DL_STATE_CHANGED BIT8 |
| |
| #define PWR_CONTROLLER_CNTL BIT10 |
| #define NO_COMMAND_COMPLETED_SUPPORTED BIT18 |
| #define SERVER_HOTPLUG_CAPABILITY \ |
| (ATTN_BUTTON_PRESENT | PWR_CONTROLLER_PRESENT | ATTN_INDICATOR_PRESENT | PWR_INDICATOR_PRESENT | HOTPLUG_CAPABLE) |
| #define NATIVE_HOTPLUG_CAPABILITY \ |
| (HOTPLUG_SURPRISE | HOTPLUG_CAPABLE) |
| |
| #define SERVER_HOTPLUG 1 |
| #define NATIVE_HOTPLUG 2 |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * P R O T O T Y P E S O F L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * E X P O R T E D F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Init Ports Hotplug capability. |
| * Initialize hotplug controller init port hotplug capability |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| * @retval AGESA_SUCCESS Hotplug controller successfully initialized. |
| * @retval AGESA_FAIL Failure during initialization of hotplug controller. |
| */ |
| /*----------------------------------------------------------------------------------------*/ |
| UINT32 |
| PcieInitHotplug ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| UINT32 ServerHotplugPortMask; |
| PORT PortId; |
| PCI_ADDR ClkPciAddress; |
| NB_INFO NbInfo; |
| PCIE_CONFIG *pPcieConfig; |
| |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieInitHotplug Enter\n")); |
| pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); |
| NbInfo = LibNbGetRevisionInfo (pConfig); |
| ServerHotplugPortMask = 0; |
| ClkPciAddress = pConfig->NbPciAddress; |
| ClkPciAddress.Address.Function = 1; |
| if (NbInfo.Type == NB_SR5690) { |
| for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { |
| if (pPcieConfig->PortConfiguration[PortId].PortPresent == ON && |
| pPcieConfig->PortConfiguration[PortId].PortHotplug != OFF ) { |
| PCI_ADDR Port; |
| Port = PcieLibGetPortPciAddress (PortId, pConfig); |
| if (pPcieConfig->PortConfiguration[PortId].PortHotplug == SERVER_HOTPLUG) { |
| UINT8 HpDescriptorRegister; |
| UINT8 HpDescriptorOffset; |
| ServerHotplugPortMask |= 1 << PortId; |
| HpDescriptorOffset = (PcieLibGetStaticPortInfo (PcieLibNativePortId (PortId, pConfig), pConfig))->HotplugAddress; |
| if (HpDescriptorOffset != 0xff) { |
| ServerHotplugPortMask |= 1 << PortId; |
| HpDescriptorRegister = (PcieLibGetCoreInfo (PcieLibGetCoreId (PortId, pConfig), pConfig))->HotplugRegister; |
| //Enable CLK config |
| LibNbEnableClkConfig (pConfig); |
| //Setup descriptor |
| LibNbPciRMW ( |
| ClkPciAddress.AddressValue | HpDescriptorRegister , |
| AccessWidth32, |
| 0xffffffff, |
| ((1 << 3) | (pPcieConfig->ExtPortConfiguration[PortId].PortHotplugDevMap << 2) | pPcieConfig->ExtPortConfiguration[PortId].PortHotplugByteMap) << HpDescriptorOffset, |
| pConfig |
| ); |
| //Hide CLK config |
| LibNbDisableClkConfig (pConfig); |
| // Enable power fault |
| LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG10, AccessWidth32, (UINT32)~BIT4, BIT4, pConfig); |
| //Set up capability. Keep NO_COMMAND_COMPLETED_SUPPORTED (bit 18) to zero |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessWidth32, 0xfffbffff, SERVER_HOTPLUG_CAPABILITY, pConfig); |
| //Clear Status |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG72, AccessWidth16, 0xffffffff, 0x11F, pConfig); |
| } |
| } |
| if (pPcieConfig->PortConfiguration[PortId].PortHotplug == NATIVE_HOTPLUG) { |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessWidth32, 0xffffffff, NATIVE_HOTPLUG_CAPABILITY, pConfig); |
| } |
| } |
| } |
| } |
| return ServerHotplugPortMask; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Init Ports Hotplug capability. |
| * Initialize hotplug controller init port hotplug capability |
| * |
| * @param[in] ServerHotplugPortMask ServerHotplugPortMask |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| * @retval AGESA_SUCCESS Hotplug controller successfully initialized. |
| * @retval AGESA_FAIL Failure during initialization of hotplug controller. |
| */ |
| /*----------------------------------------------------------------------------------------*/ |
| VOID |
| PcieCheckHotplug ( |
| IN UINT32 ServerHotplugPortMask, |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| PORT PortId; |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieCheckHotplug Enter\n")); |
| //Check if Firmware loaded successfully |
| for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { |
| //Check Firmware Loaded successfully |
| if ((ServerHotplugPortMask & (1 << PortId)) != 0) { |
| UINT32 Count; |
| PCI_ADDR Port; |
| UINT16 SlotStatus; |
| |
| Count = 30; //Setup counter for 30ms |
| Port = PcieLibGetPortPciAddress (PortId, pConfig); |
| do { |
| STALL (GET_BLOCK_CONFIG_PTR (pConfig), 1000, 0); |
| LibNbPciRead (Port.AddressValue | NB_PCIP_REG72, AccessWidth16, &SlotStatus, pConfig); |
| } while ((SlotStatus & (ATTN_BUTTON_PRESSED | PWR_FAULT_DETECTED)) == 0 && --Count != 0); |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Hotplug Firmware Init PortId = %d SlotStatus = 0x%x Retry = %d\n", PortId, SlotStatus, Count)); |
| if ((SlotStatus & PWR_FAULT_DETECTED) != 0 || (SlotStatus & (PWR_FAULT_DETECTED | ATTN_BUTTON_PRESSED)) == 0) { |
| REPORT_EVENT (AGESA_ERROR, PCIE_ERROR_HOTPLUG_INIT, PortId, 0, 0, 0, pConfig); |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " ERROR!!!Hotplug Firmware Init FAIL\n")); |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessWidth32, (UINT32)~SERVER_HOTPLUG_CAPABILITY, 0x0, pConfig); |
| } else { |
| //Clear Status |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG72, AccessWidth16, 0xffffffff, 0x11F, pConfig); |
| if ((SlotStatus & PRESENCE_DETECT_CHANGED) != 0) { |
| //Power on slot |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG70, AccessWidth16, (UINT32)~PWR_CONTROLLER_CNTL, 0x0, pConfig); |
| } |
| } |
| } |
| } |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieCheckHotplug Exit\n")); |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Init Ports Hotplug capability. |
| * Initialize hotplug controller init port hotplug capability |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| * @retval AGESA_SUCCESS Hotplug controller successfully initialized. |
| * @retval AGESA_FAIL Failure during initialization of hotplug controller. |
| */ |
| /*----------------------------------------------------------------------------------------*/ |
| /* |
| AGESA_STATUS |
| PcieInitHotplug ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| AGESA_STATUS Status; |
| UINT32 ServerHotplugPortMask; |
| PORT PortId; |
| PCI_ADDR ClkPciAddress; |
| NB_INFO NbInfo; |
| PCIE_CONFIG *pPcieConfig; |
| |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieInitHotplug Enter\n")); |
| pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); |
| NbInfo = LibNbGetRevisionInfo (pConfig); |
| ServerHotplugPortMask = 0; |
| ClkPciAddress = pConfig->NbPciAddress; |
| ClkPciAddress.Address.Function = 1; |
| Status = AGESA_SUCCESS; |
| if (NbInfo.Type == NB_SR5690) { |
| for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { |
| if (pPcieConfig->PortConfiguration[PortId].PortPresent == ON && |
| pPcieConfig->PortConfiguration[PortId].PortHotplug != OFF ) { |
| PCI_ADDR Port; |
| Port = PcieLibGetPortPciAddress (PortId, pConfig); |
| if (pPcieConfig->PortConfiguration[PortId].PortHotplug == SERVER_HOTPLUG) { |
| UINT8 HpDescriptorRegister; |
| UINT8 HpDescriptorOffset; |
| ServerHotplugPortMask |= 1 << PortId; |
| HpDescriptorOffset = (PcieLibGetStaticPortInfo (PcieLibNativePortId (PortId, pConfig), pConfig))->HotplugAddress; |
| if (HpDescriptorOffset != 0xff) { |
| ServerHotplugPortMask |= 1 << PortId; |
| HpDescriptorRegister = (PcieLibGetCoreInfo (PcieLibGetCoreId (PortId, pConfig), pConfig))->HotplugRegister; |
| //Enable CLK config |
| LibNbEnableClkConfig (pConfig); |
| //Setup descriptor |
| LibNbPciRMW ( |
| ClkPciAddress.AddressValue | HpDescriptorRegister , |
| AccessWidth32, |
| 0xffffffff, |
| ((1 << 3) | (pPcieConfig->ExtPortConfiguration[PortId].PortHotplugDevMap << 2) | pPcieConfig->ExtPortConfiguration[PortId].PortHotplugByteMap) << HpDescriptorOffset, |
| pConfig |
| ); |
| //Hide CLK config |
| LibNbDisableClkConfig (pConfig); |
| // Enable power fault |
| LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG10, AccessWidth32, (UINT32)~BIT4, BIT4, pConfig); |
| //Set up capability. Keep NO_COMMAND_COMPLETED_SUPPORTED (bit 18) to zero |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessWidth32, 0xfffbffff, SERVER_HOTPLUG_CAPABILITY, pConfig); |
| //Clear Status |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG72, AccessWidth16, 0xffffffff, 0x11F, pConfig); |
| } |
| } |
| if (pPcieConfig->PortConfiguration[PortId].PortHotplug == NATIVE_HOTPLUG) { |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessWidth32, 0xffffffff, NATIVE_HOTPLUG_CAPABILITY, pConfig); |
| } |
| } |
| } |
| if (ServerHotplugPortMask != 0) { |
| UINT32 FirmwareLength; |
| FirmwareLength = sizeof (Firmware); |
| if (FirmwareLength > 0) { |
| UINT32 *pFirmware; |
| pFirmware = (UINT32*)FIX_PTR_ADDR (&Firmware[0], NULL); |
| //Load firmware |
| LibNbMcuControl (AssertReset, pConfig); |
| LibNbLoadMcuFirmwareBlock (0x200, (sizeof (Firmware) - 64), pFirmware, pConfig); |
| LibNbLoadMcuFirmwareBlock (0xFFC0, 64, &pFirmware[(sizeof (Firmware) - 64) / 4], pConfig); |
| LibNbMcuControl (DeAssertReset, pConfig); |
| } |
| } |
| //Check if Firmware loaded successfully |
| for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { |
| //Check Firmware Loaded successfully |
| if ((ServerHotplugPortMask & (1 << PortId)) != 0) { |
| UINT32 Count; |
| PCI_ADDR Port; |
| UINT16 SlotStatus; |
| |
| Count = 30; //Setup counter for 30ms |
| Port = PcieLibGetPortPciAddress (PortId, pConfig); |
| do { |
| STALL (GET_BLOCK_CONFIG_PTR (pConfig), 1000, 0); |
| LibNbPciRead (Port.AddressValue | NB_PCIP_REG72, AccessWidth16, &SlotStatus, pConfig); |
| } while ((SlotStatus & (ATTN_BUTTON_PRESSED | PWR_FAULT_DETECTED)) == 0 && --Count != 0); |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Hotplug Firmware Init PortId = %d SlotStatus = 0x%x Retry = %d\n", PortId, SlotStatus, Count)); |
| if ((SlotStatus & PWR_FAULT_DETECTED) != 0 || (SlotStatus & (PWR_FAULT_DETECTED | ATTN_BUTTON_PRESSED)) == 0) { |
| Status = AGESA_ERROR; |
| REPORT_EVENT (AGESA_ERROR, PCIE_ERROR_HOTPLUG_INIT, PortId, 0, 0, 0, pConfig); |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " ERROR!!!Hotplug Firmware Init FAIL\n", PortId)); |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessWidth32, ~SERVER_HOTPLUG_CAPABILITY, 0x0, pConfig); |
| } else { |
| //Clear Status |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG72, AccessWidth16, 0xffffffff, 0x11F, pConfig); |
| if ((SlotStatus & PRESENCE_DETECT_CHANGED) != 0) { |
| //Power on slot |
| LibNbPciRMW (Port.AddressValue | NB_PCIP_REG70, AccessWidth16, ~PWR_CONTROLLER_CNTL, 0x0, pConfig); |
| } |
| } |
| } |
| } |
| } |
| CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieInitHotplug Exit. Status[0x%x]\n", Status)); |
| return Status; |
| } |
| */ |
| #endif |