mb/google/guybrush: Update bootblock power-on timings for PCIe

This configures the bootblock portion of the PCIe GPIOs in the correct
sequence to meet the power-on timings.

Setting the PCIE Reset happens in coreboot instead of in the FSP.

The Aux reset lines are anded with the PCIe RST line, so both have
to be brought up together.  On v1 of guybrush, the PCIe reset line
also resets EC communication, so it must be brought up immediately on
that version.

BUG=b:184796302, b:184598323
TEST=Verify timings between GPIO init sections.  All available modules
are present after training.

Signed-off-by: Martin Roth <martinroth@chromium.org>
Change-Id: I2d0b812b654b0cd317a2c8c1ce554e850c96be44
Reviewed-on: https://review.coreboot.org/c/coreboot/+/52868
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
This commit is contained in:
Martin Roth 2021-05-03 16:21:11 -06:00 committed by Martin Roth
parent 46bee3f48c
commit 324cea9d1b
6 changed files with 145 additions and 23 deletions

View file

@ -5,8 +5,13 @@
#include <bootblock_common.h>
#include <baseboard/variants.h>
#include <console/console.h>
#include <delay.h>
#include <device/pci_ops.h>
#include <soc/pci_devs.h>
#include <timer.h>
#define FC350_PCIE_INIT_DELAY_US (20 * USECS_PER_MSEC)
struct stopwatch pcie_init_timeout_sw;
void mb_set_up_early_espi(void)
{
@ -22,13 +27,21 @@ void mb_set_up_early_espi(void)
void bootblock_mainboard_early_init(void)
{
size_t num_gpios;
uint32_t dword;
const struct soc_amd_gpio *gpios;
size_t base_num_gpios, override_num_gpios;
const struct soc_amd_gpio *base_gpios, *override_gpios;
if (!CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK)) {
gpios = variant_early_gpio_table(&num_gpios);
program_gpios(gpios, num_gpios);
base_gpios = variant_early_gpio_table(&base_num_gpios);
override_gpios = variant_early_override_gpio_table(&override_num_gpios);
gpio_configure_pads_with_override(base_gpios, base_num_gpios,
override_gpios, override_num_gpios);
/* Set a timer to make sure there's enough delay for
* the Fibocom 350 PCIe init
*/
stopwatch_init_usecs_expire(&pcie_init_timeout_sw, FC350_PCIE_INIT_DELAY_US);
}
printk(BIOS_DEBUG, "Bootblock configure eSPI\n");
@ -51,7 +64,31 @@ void bootblock_mainboard_early_init(void)
void bootblock_mainboard_init(void)
{
/* Put FPMCU check after EC initialization */
size_t base_num_gpios, override_num_gpios;
const struct soc_amd_gpio *base_gpios, *override_gpios;
int i = 0;
/* Make sure that at least 20ms has elapsed since enabling WWAN power
* in bootblock_mainboard_early_init.
* This is only applicable if verstage is not in the PSP and the board
* is using the fibocom 350 WLAN card, so this typically will not be hit.
*/
if (!CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) && variant_has_pcie_wwan()) {
while (!stopwatch_expired(&pcie_init_timeout_sw)) {
mdelay(1);
i++;
};
if (i)
printk(BIOS_DEBUG, "Delayed %d ms for PCIe\n", i);
}
base_gpios = variant_bootblock_gpio_table(&base_num_gpios);
override_gpios = variant_bootblock_override_gpio_table(&override_num_gpios);
gpio_configure_pads_with_override(base_gpios, base_num_gpios, override_gpios,
override_num_gpios);
/* FPMCU check needs to happen after EC initialization for FW_CONFIG bits */
if (variant_has_fpmcu())
variant_fpmcu_reset();
}

View file

@ -6,7 +6,7 @@
#include <soc/gpio.h>
#include <types.h>
/* TODO: test if this really works */
/* All PCIe Resets are handled in coreboot */
static const fsp_dxio_descriptor guybrush_czn_dxio_descriptors[] = {
{ /* WLAN */
.engine_type = PCIE_ENGINE,
@ -18,7 +18,6 @@ static const fsp_dxio_descriptor guybrush_czn_dxio_descriptors[] = {
.link_aspm = ASPM_L1,
.turn_off_unused_lanes = true,
.clk_req = CLK_REQ0,
.gpio_group_id = GPIO_29,
.port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122}
},
{ /* SD */
@ -31,7 +30,6 @@ static const fsp_dxio_descriptor guybrush_czn_dxio_descriptors[] = {
.link_aspm = ASPM_L1,
.turn_off_unused_lanes = true,
.clk_req = CLK_REQ1,
.gpio_group_id = GPIO_70,
.port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122}
},
{ /* WWAN */
@ -44,7 +42,6 @@ static const fsp_dxio_descriptor guybrush_czn_dxio_descriptors[] = {
.link_aspm = ASPM_L1,
.turn_off_unused_lanes = true,
.clk_req = CLK_REQ2,
.gpio_group_id = GPIO_18,
.port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122}
},
{ /* NVME */
@ -57,7 +54,6 @@ static const fsp_dxio_descriptor guybrush_czn_dxio_descriptors[] = {
.link_aspm = ASPM_L1,
.turn_off_unused_lanes = true,
.clk_req = CLK_REQ3,
.gpio_group_id = GPIO_40,
.port_params = {PP_PSPP_AC, 0x133, PP_PSPP_DC, 0x122}
},
{ /* TODO: remove this temporay workaround */

View file

@ -7,6 +7,7 @@
#include <soc/gpio.h>
/* GPIO configuration in ramstage*/
/* Please make sure that *ALL* GPIOs are configured in this table */
static const struct soc_amd_gpio base_gpio_table[] = {
/* PWR_BTN_L */
PAD_NF(GPIO_0, PWR_BTN_L, PULL_NONE),
@ -40,7 +41,7 @@ static const struct soc_amd_gpio base_gpio_table[] = {
/* SOC_SAR_INT_L */
PAD_SCI(GPIO_17, PULL_NONE, EDGE_LOW),
/* WWAN_AUX_RESET_L */
PAD_GPO(GPIO_18, LOW),
PAD_GPO(GPIO_18, HIGH),
/* I2C3_SCL */
PAD_NF(GPIO_19, I2C3_SCL, PULL_NONE),
/* I2C3_SDA */
@ -55,12 +56,11 @@ static const struct soc_amd_gpio base_gpio_table[] = {
PAD_GPO(GPIO_24, HIGH),
/* GPIO_25: Not available */
/* PCIE_RST0_L */
/* TODO: change back to PCIE_RST_L when we figure out why PCIE_RST doesn't go high. */
PAD_GPO(GPIO_26, HIGH),
PAD_NFO(GPIO_26, PCIE_RST_L, HIGH),
/* PCIE_RST1_L */
PAD_NF(GPIO_27, PCIE_RST1_L, PULL_NONE),
/* GPIO_28: Not available */
/* WLAN_AUX_RESET */
/* WLAN_AUX_RESET (Active HIGH)*/
PAD_GPO(GPIO_29, LOW),
/* ESPI_CS_L */
PAD_NF(GPIO_30, ESPI_CS_L, PULL_NONE),
@ -167,22 +167,32 @@ static const struct soc_amd_gpio base_gpio_table[] = {
/* Early GPIO configuration */
static const struct soc_amd_gpio early_gpio_table[] = {
/* WWAN_AUX_RESET_L */
PAD_GPO(GPIO_18, LOW),
/* WLAN_AUX_RESET (ACTIVE HIGH) */
PAD_GPO(GPIO_29, HIGH),
/* SSD_AUX_RESET_L */
PAD_GPO(GPIO_40, LOW),
/* SD_AUX_RESET_L */
PAD_GPO(GPIO_69, LOW),
/* Guybrush BID>1: Unused TP27; BID==1: SD_AUX_RESET_L */
PAD_NC(GPIO_70),
/* PCIE_RST0_L */
PAD_NFO(GPIO_26, PCIE_RST_L, HIGH),
/* Power on WLAN & WWAN */
/* EN_PP3300_WLAN */
PAD_GPO(GPIO_6, HIGH),
/* EN_PWR_WWAN_X */
PAD_GPO(GPIO_8, HIGH),
/* WWAN_DISABLE */
PAD_GPO(GPIO_85, LOW),
/* WLAN_DISABLE */
PAD_GPO(GPIO_130, LOW),
/* Enable ESPI, GSC Interrupt & I2C Communication */
/* GSC_SOC_INT_L */
PAD_INT(GPIO_3, PULL_NONE, EDGE_LOW, STATUS_DELIVERY),
/* I2C3_SCL */
PAD_NF(GPIO_19, I2C3_SCL, PULL_NONE),
/* I2C3_SDA */
PAD_NF(GPIO_20, I2C3_SDA, PULL_NONE),
/* PCIE_RST0_L */
PAD_GPO(GPIO_26, HIGH),
/* ESPI_CS_L */
PAD_NF(GPIO_30, ESPI_CS_L, PULL_NONE),
/* ESPI_SOC_CLK */
@ -197,17 +207,58 @@ static const struct soc_amd_gpio early_gpio_table[] = {
PAD_NF(GPIO_107, SPI2_HOLD_L_ESPI2_D3, PULL_NONE),
/* ESPI_ALERT_L */
PAD_NF(GPIO_108, ESPI_ALERT_D1, PULL_NONE),
/* Enable UART 0 */
/* UART0_RXD */
PAD_NF(GPIO_141, UART0_RXD, PULL_NONE),
/* UART0_TXD */
PAD_NF(GPIO_143, UART0_TXD, PULL_NONE),
};
/* Power-on timing requirements:
* Fibocom 350-GL:
* FCP0# goes high (GPIO 6) to Reset# high (GPIO 24): 20ms min
* FCP0# goes high (GPIO 6) to PERST# high (GPIO 26): 100ms min
* PERST# high (GPIO 26) to PCIE Training (FSP-M): 23ms min
*
* Realtek RTL8852AE:
* Power (3.3 V) valid to PERST# high (GPIO_26): 50ms min
*
* Qualcomm WCN6856:
* Power (3.3 V) valid to PERST# high (GPIO_26): 50ms min
*
* RTS5250S / RTS5227S / RTS5261S
* Power (3.3 V) valid to PERST# high (GPIO_69/70): 1ms min
*
* PCIe spec:
* Power (3.3 V) valid to PERST# high (GPIO_26): 50ms min (SUGGESTED)
*
* NVME adapters planned for Guybrush:
* No power on timings specified - Assumed to require PCIe Spec suggested
* guidelines. Testing seems to bear out this assumption.
*/
static const struct soc_amd_gpio bootblock_gpio_table[] = {
/* Enable WWAN & WLAN */
/* WWAN_RST_L */
PAD_GPO(GPIO_24, HIGH),
/* WWAN_DISABLE */
PAD_GPO(GPIO_85, LOW),
/* WLAN_DISABLE */
PAD_GPO(GPIO_130, LOW),
};
/* GPIO configuration for sleep */
static const struct soc_amd_gpio sleep_gpio_table[] = {
/* TODO: Fill sleep gpio configuration */
};
const struct soc_amd_gpio *__weak variant_bootblock_gpio_table(size_t *size)
{
*size = ARRAY_SIZE(bootblock_gpio_table);
return bootblock_gpio_table;
}
const struct soc_amd_gpio *__weak variant_base_gpio_table(size_t *size)
{
*size = ARRAY_SIZE(base_gpio_table);
@ -219,6 +270,18 @@ const struct soc_amd_gpio *__weak variant_override_gpio_table(size_t *size)
return NULL;
}
const struct soc_amd_gpio * __weak variant_early_override_gpio_table(size_t *size)
{
*size = 0;
return NULL;
}
const struct soc_amd_gpio * __weak variant_bootblock_override_gpio_table(size_t *size)
{
*size = 0;
return NULL;
}
const struct soc_amd_gpio *__weak variant_early_gpio_table(size_t *size)
{
*size = ARRAY_SIZE(early_gpio_table);

View file

@ -19,14 +19,19 @@
*/
const struct soc_amd_gpio *variant_base_gpio_table(size_t *size);
/*
* This function allows variant to override any GPIOs that are different than the base GPIO
* configuration provided by variant_base_gpio_table().
* These functions allow variants to override any GPIOs that are different than the base GPIO
* configuration provided without having to replace the entire file.
*/
const struct soc_amd_gpio *variant_override_gpio_table(size_t *size);
const struct soc_amd_gpio *variant_early_override_gpio_table(size_t *size);
const struct soc_amd_gpio *variant_bootblock_override_gpio_table(size_t *size);
/* This function provides early GPIO init in bootblock or psp. */
/* This function provides early GPIO init in early bootblock or psp. */
const struct soc_amd_gpio *variant_early_gpio_table(size_t *size);
/* This function provides GPIO settings at the end of bootblock. */
const struct soc_amd_gpio *variant_bootblock_gpio_table(size_t *size);
/* This function provides GPIO settings before entering sleep. */
const struct soc_amd_gpio *variant_sleep_gpio_table(size_t *size);

View file

@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
bootblock-y += gpio.c
ramstage-y += gpio.c
subdirs-y += ./memory

View file

@ -18,6 +18,13 @@ static const struct soc_amd_gpio bid1_gpio_table[] = {
PAD_GPI(GPIO_74, PULL_NONE),
};
/* This table is used by guybrush variant with board version < 2. */
/* Use AUX Reset lines instead of PCIE_RST for Board Version 1 */
static const struct soc_amd_gpio bid1_early_gpio_table[] = {
/* SD_AUX_RESET_L */
PAD_GPO(GPIO_70, HIGH),
};
const struct soc_amd_gpio *variant_override_gpio_table(size_t *size)
{
uint32_t board_version = board_id();
@ -30,3 +37,16 @@ const struct soc_amd_gpio *variant_override_gpio_table(size_t *size)
return NULL;
}
const struct soc_amd_gpio *variant_early_override_gpio_table(size_t *size)
{
uint32_t board_version = board_id();
*size = 0;
if (board_version < 2) {
*size = ARRAY_SIZE(bid1_early_gpio_table);
return bid1_early_gpio_table;
}
return NULL;
}