From c04871a398ca945b42fde0867572094c38f6f92c Mon Sep 17 00:00:00 2001 From: Michał Żygowski Date: Fri, 20 Mar 2020 16:14:36 +0100 Subject: mb/pcengines/apu2: add reset logic for PCIe slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Change-Id: I8ff7db6ff85cce45b84729be905e6c895a24f6f2 Reviewed-on: https://review.coreboot.org/c/coreboot/+/39703 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/mainboard/pcengines/apu2/BiosCallOuts.c | 71 +++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'src/mainboard/pcengines/apu2/BiosCallOuts.c') diff --git a/src/mainboard/pcengines/apu2/BiosCallOuts.c b/src/mainboard/pcengines/apu2/BiosCallOuts.c index d6f8d84300..69af3f9db3 100644 --- a/src/mainboard/pcengines/apu2/BiosCallOuts.c +++ b/src/mainboard/pcengines/apu2/BiosCallOuts.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include "hudson.h" 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[] = { @@ -32,6 +34,7 @@ const BIOS_CALLOUT_STRUCT BiosCallouts[] = {AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported }, {AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp }, {AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData }, + {AGESA_GNB_PCIE_SLOT_RESET, board_GnbPciExSlotReset }, {AGESA_HOOKBEFORE_DQS_TRAINING, 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; } + +/* 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; +} -- cgit v1.2.3