blob: 25ef38f587fd64398dd352fc7ee1d313baee0370 [file] [log] [blame]
/**
* @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