mb/pcengines/apu2: add reset logic for PCIe slots
PC Engines apu2 had many problems with PCIe cards detection. The cards were inconsistently detected when booted from G3, S5 or after a reboot. AGESA can reset PCIe slots using GPIO via callback. Use it to reset the slots that support using GPIO as reset signal. Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com> Change-Id: I8ff7db6ff85cce45b84729be905e6c895a24f6f2 Reviewed-on: https://review.coreboot.org/c/coreboot/+/39703 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
d07ac8ee13
commit
c04871a398
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AGESA.h>
|
#include <AGESA.h>
|
||||||
|
#include <amdblocks/acpimmio.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <spd_bin.h>
|
#include <spd_bin.h>
|
||||||
#include <northbridge/amd/agesa/BiosCallOuts.h>
|
#include <northbridge/amd/agesa/BiosCallOuts.h>
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
#include "hudson.h"
|
#include "hudson.h"
|
||||||
|
|
||||||
static AGESA_STATUS board_ReadSpd_from_cbfs(UINT32 Func, UINTN Data, VOID *ConfigPtr);
|
static AGESA_STATUS board_ReadSpd_from_cbfs(UINT32 Func, UINTN Data, VOID *ConfigPtr);
|
||||||
|
static AGESA_STATUS board_GnbPciExSlotReset(UINT32 Func, UINTN Data, VOID *ConfigPtr);
|
||||||
|
|
||||||
const BIOS_CALLOUT_STRUCT BiosCallouts[] =
|
const BIOS_CALLOUT_STRUCT BiosCallouts[] =
|
||||||
{
|
{
|
||||||
|
@ -32,6 +34,7 @@ const BIOS_CALLOUT_STRUCT BiosCallouts[] =
|
||||||
{AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
|
{AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
|
||||||
{AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp },
|
{AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp },
|
||||||
{AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
|
{AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
|
||||||
|
{AGESA_GNB_PCIE_SLOT_RESET, board_GnbPciExSlotReset },
|
||||||
{AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopSuccess },
|
{AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopSuccess },
|
||||||
{AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopSuccess }
|
{AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopSuccess }
|
||||||
};
|
};
|
||||||
|
@ -139,3 +142,71 @@ static AGESA_STATUS board_ReadSpd_from_cbfs(UINT32 Func, UINTN Data, VOID *Confi
|
||||||
|
|
||||||
return AGESA_SUCCESS;
|
return AGESA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PCIE slot reset control */
|
||||||
|
static AGESA_STATUS board_GnbPciExSlotReset(UINT32 Func, UINTN Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
AGESA_STATUS Status;
|
||||||
|
PCIe_SLOT_RESET_INFO *ResetInfo;
|
||||||
|
uint32_t GpioData;
|
||||||
|
uint8_t GpioValue;
|
||||||
|
|
||||||
|
ResetInfo = ConfigPtr;
|
||||||
|
Status = AGESA_UNSUPPORTED;
|
||||||
|
|
||||||
|
switch (ResetInfo->ResetId) {
|
||||||
|
/*
|
||||||
|
* ResetID 1 = PCIE_RST# affects all PCIe slots on all boards except
|
||||||
|
* apu2. ResetID 1 does not need any GPIO.
|
||||||
|
*/
|
||||||
|
case 1:
|
||||||
|
Status = AGESA_SUCCESS;
|
||||||
|
break;
|
||||||
|
case 51: /* GPIO51 resets mPCIe1 slot on apu2 */
|
||||||
|
switch (ResetInfo->ResetControl) {
|
||||||
|
case AssertSlotReset:
|
||||||
|
GpioData = gpio1_read32(0x8);
|
||||||
|
printk(BIOS_DEBUG, "%s: ResetID %u assert %08x\n",
|
||||||
|
__func__, ResetInfo->ResetId, GpioData);
|
||||||
|
GpioValue = gpio1_read8(0xa);
|
||||||
|
GpioValue &= ~BIT6;
|
||||||
|
gpio1_write8(0xa, GpioValue);
|
||||||
|
Status = AGESA_SUCCESS;
|
||||||
|
break;
|
||||||
|
case DeassertSlotReset:
|
||||||
|
GpioData = gpio1_read32(0x8);
|
||||||
|
printk(BIOS_DEBUG, "%s: ResetID %u deassert %08x\n",
|
||||||
|
__func__, ResetInfo->ResetId, GpioData);
|
||||||
|
GpioValue = gpio1_read8(0xa);
|
||||||
|
GpioValue |= BIT6;
|
||||||
|
gpio1_write8(0xa, GpioValue);
|
||||||
|
Status = AGESA_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 55: /* GPIO51 resets mPCIe2 slot on apu2 */
|
||||||
|
switch (ResetInfo->ResetControl) {
|
||||||
|
case AssertSlotReset:
|
||||||
|
GpioData = gpio1_read32(0xc);
|
||||||
|
printk(BIOS_DEBUG, "%s: ResetID %u assert %08x\n",
|
||||||
|
__func__, ResetInfo->ResetId, GpioData);
|
||||||
|
GpioValue = gpio1_read8(0xe);
|
||||||
|
GpioValue &= ~BIT6;
|
||||||
|
gpio1_write8(0xa, GpioValue);
|
||||||
|
Status = AGESA_SUCCESS;
|
||||||
|
break;
|
||||||
|
case DeassertSlotReset:
|
||||||
|
GpioData = gpio1_read32(0xc);
|
||||||
|
printk(BIOS_DEBUG, "%s: ResetID %u deassert %08x\n",
|
||||||
|
__func__, ResetInfo->ResetId, GpioData);
|
||||||
|
GpioValue = gpio1_read8(0xe);
|
||||||
|
GpioValue |= BIT6;
|
||||||
|
gpio1_write8(0xa, GpioValue);
|
||||||
|
Status = AGESA_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,15 @@
|
||||||
#include <AGESA.h>
|
#include <AGESA.h>
|
||||||
#include <northbridge/amd/agesa/state_machine.h>
|
#include <northbridge/amd/agesa/state_machine.h>
|
||||||
|
|
||||||
|
#define PCIE_NIC_RESET_ID 1
|
||||||
|
|
||||||
|
#if CONFIG(BOARD_PCENGINES_APU2)
|
||||||
|
#define PCIE_GFX_RESET_ID 55
|
||||||
|
#define PCIE_PORT3_RESET_ID 51
|
||||||
|
#else
|
||||||
|
#define PCIE_GFX_RESET_ID PCIE_NIC_RESET_ID
|
||||||
|
#define PCIE_PORT3_RESET_ID PCIE_NIC_RESET_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
||||||
{
|
{
|
||||||
|
@ -24,7 +33,7 @@ static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
||||||
HotplugDisabled,
|
HotplugDisabled,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
AspmDisabled, 0x01, 0)
|
AspmDisabled, PCIE_PORT3_RESET_ID, 0)
|
||||||
},
|
},
|
||||||
/* Initialize Port descriptor (PCIe port, Lanes 1, PCI Device Number 2, ...) */
|
/* Initialize Port descriptor (PCIe port, Lanes 1, PCI Device Number 2, ...) */
|
||||||
{
|
{
|
||||||
|
@ -34,7 +43,7 @@ static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
||||||
HotplugDisabled,
|
HotplugDisabled,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
AspmDisabled, 0x02, 0)
|
AspmDisabled, PCIE_NIC_RESET_ID, 0)
|
||||||
},
|
},
|
||||||
/* Initialize Port descriptor (PCIe port, Lanes 2, PCI Device Number 2, ...) */
|
/* Initialize Port descriptor (PCIe port, Lanes 2, PCI Device Number 2, ...) */
|
||||||
{
|
{
|
||||||
|
@ -44,7 +53,7 @@ static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
||||||
HotplugDisabled,
|
HotplugDisabled,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
AspmDisabled, 0x03, 0)
|
AspmDisabled, PCIE_NIC_RESET_ID, 0)
|
||||||
},
|
},
|
||||||
/* Initialize Port descriptor (PCIe port, Lanes 3, PCI Device Number 2, ...) */
|
/* Initialize Port descriptor (PCIe port, Lanes 3, PCI Device Number 2, ...) */
|
||||||
{
|
{
|
||||||
|
@ -54,7 +63,7 @@ static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
||||||
HotplugDisabled,
|
HotplugDisabled,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
AspmDisabled, 0x04, 0)
|
AspmDisabled, PCIE_NIC_RESET_ID, 0)
|
||||||
},
|
},
|
||||||
/* Initialize Port descriptor (PCIe port, Lanes 4-7, PCI Device Number 4, ...) */
|
/* Initialize Port descriptor (PCIe port, Lanes 4-7, PCI Device Number 4, ...) */
|
||||||
{
|
{
|
||||||
|
@ -64,7 +73,7 @@ static const PCIe_PORT_DESCRIPTOR PortList[] = {
|
||||||
HotplugDisabled,
|
HotplugDisabled,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
PcieGenMaxSupported,
|
PcieGenMaxSupported,
|
||||||
AspmDisabled, 0x05, 0)
|
AspmDisabled, PCIE_GFX_RESET_ID, 0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,15 @@ void board_BeforeAgesa(struct sysinfo *cb)
|
||||||
|
|
||||||
/* Release GPIO32/33 for other uses. */
|
/* Release GPIO32/33 for other uses. */
|
||||||
pm_write8(0xea, 1);
|
pm_write8(0xea, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assert resets on the PCIe slots, since AGESA calls deassert callout
|
||||||
|
* only. Only apu2 uses GPIOs to reset PCIe slots.
|
||||||
|
*/
|
||||||
|
if (CONFIG(BOARD_PCENGINES_APU2)) {
|
||||||
|
gpio1_write8(0xa, gpio1_read8(0xa) & ~(1 << 6));
|
||||||
|
gpio1_write8(0xe, gpio1_read8(0xe) & ~(1 << 6));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void early_lpc_init(void)
|
static void early_lpc_init(void)
|
||||||
|
|
Loading…
Reference in New Issue