mb/google/fatcat: Add x1 slot power sequence and support AICs with PRSNT2#

Address x1 slot enumeration issues for certain add in cards (AICs)
during boot. This change implements proper power sequencing and adds
support for AICs that use PRSNT2# signaling instead of ClkReq#. The
x1 slot power rail (X1_PCIE_SLOT_PWR_EN via GPP_A8) is pull-high by
design, with GPP_A08 PAD defaulting to GPI configuration. This enables
slot power during early boot phases. PERST# (GPP_D19) is logically
ANDed with PLTRST#, ensuring PLTRST# de-assertion occurs only after x1
slot power stabilization, maintaining proper PCIe timing automatically.

For scenarios requiring power-off at boot, the following sequence
ensures compliance with PCIe link training timing requirements:

Step 1 (romstage): ClkReq PAD off; PERST# asserted; power off
Step 2 (ramstage at BS_PRE_DEVICE exit): Power on; ClkReq PAD on (if
       used)
Step 3 (ramstage at BS_DEV_INIT_CHIPS entry): PERST# de-asserted

The CBI fw_config SD field has been redefined to accommodate different
AIC types:
- SD_BAYHUB: For AICs supporting ClkReq# signaling
- SD_GENSYS: For AICs using only PRSNT2# signaling

BUG=None
TEST=Boot Fatcat board with AIC cards configured via CBI fw_config SD
field (SD_BAYHUB or SD_GENSYS). Confirm PCIe device enumeration
appears correctly in boot log. For instance:
[SPEW ]  do_pci_scan_bridge for PCI: 00:00:1c.0
[DEBUG]  PCI: pci_scan_bus for segment group 00 bus ae
[DEBUG]  PCI: 00:ae:00.0 [1217/9860] enabled

The device should be seen from lspci command, such as:
ae:00.0 Class 0805: Device 1217:9860 (rev 01)

Signed-off-by: Cliff Huang <cliff.huang@intel.com>
Change-Id: I94a7ee2ecd8d3fd83006297ef68f97ff49e47595
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90000
Reviewed-by: Pranava Y N <pranavayn@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Cliff Huang 2025-11-11 11:19:02 -08:00 committed by Jérémy Compostella
commit 59593b5b5c
6 changed files with 103 additions and 11 deletions

View file

@ -62,6 +62,18 @@ static void mainboard_early(void *unused)
BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_EXIT, mainboard_early, NULL);
void __weak fw_config_post_gpio_configure(void)
{
/* default implementation does nothing */
}
static void mainboard_pre_dev_init_chips(void *unused)
{
fw_config_post_gpio_configure();
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_ENTRY, mainboard_pre_dev_init_chips, NULL);
void __weak baseboard_devtree_update(void)
{
/* Override dev tree settings per baseboard */

View file

@ -19,6 +19,7 @@ const struct pad_config *variant_early_gpio_table(size_t *num);
const struct pad_config *variant_romstage_gpio_table(size_t *num);
void fw_config_configure_pre_mem_gpio(void);
void fw_config_gpio_padbased_override(struct pad_config *padbased_table);
void fw_config_post_gpio_configure(void);
const struct mb_cfg *variant_memory_params(void);
void variant_get_spd_info(struct mem_spd *spd_info);

View file

@ -168,20 +168,70 @@ static const struct pad_config audio_disable_pads[] = {
PAD_NC(GPP_D17, NONE),
};
/*
* NOTE: The PCIe slot power PADs are pulled high by default on Fatcat. Since
* these PADs default to GPI configuration, slot power is enabled during early
* boot. Also, PERST# PADs are logically ANDed with PLTRST#. This ensures that
* PLTRST# de-assertion at the slot occurs after PCIe slot power stabilization,
* maintaining proper PCIe power-on sequences.
*
* If slot power must be disabled at boot, PERST# de-assertion must occur after
* power restoration and satisfy PCIe link training timing requirements.
* Additionally, the slot power PADs are recommended to be reworked to pull low
* to avoid a power glitch. The suggested power sequence is:
*
* Step 1 (romstage): ClkReq PAD off; PERST# asserted; power off
* Step 2 (ramstage at BS_PRE_DEVICE exit): Power on; ClkReq PAD on (if used)
* Step 3 (ramstage at BS_DEV_INIT_CHIPS entry): PERST# de-asserted
*/
/* x1 slot power sequence: 1. no clkreq; PERST=asserted; power=off */
static const struct pad_config pre_mem_x1slot_pads[] = {
/* GPP_C11: CLKREQ2_X1_GEN4_DT_CEM_SLOT_N */
PAD_CFG_GPI(GPP_C11, NONE, DEEP),
/* GPP_D19: X1_DT_PCIE_RST_N */
PAD_CFG_GPO(GPP_D19, 0, PLTRST),
/* GPP_A08: X1_PCIE_SLOT_PWR_EN */
PAD_CFG_GPO(GPP_A08, 0, PLTRST),
};
/* x1 slot CBI + x1 slot power sequence: 2. power=on */
static const struct pad_config x1slot_pads[] = {
/* GPP_A08: X1_PCIE_SLOT_PWR_EN */
PAD_CFG_GPO(GPP_A08, 1, PLTRST),
/* GPP_D19: X1_DT_PCIE_RST_N */
PAD_CFG_GPO(GPP_D19, 1, PLTRST),
PAD_CFG_GPO(GPP_D19, 0, PLTRST),
/* GPP_B25: X1_SLOT_WAKE_N */
PAD_CFG_GPI_SCI_LOW(GPP_B25, NONE, DEEP, LEVEL),
};
/*
* x1 slot power sequence: 3. PERST# = de-assert;
*/
static const struct pad_config post_x1slot_pads[] = {
/* GPP_D19: X1_DT_PCIE_RST_N */
PAD_CFG_GPO(GPP_D19, 1, PLTRST),
};
static const struct pad_config x1slot_clkreq_pads[] = {
/* x1 slot power sequence: 3a. Clkreq = enable for AIC with clkreq support */
/* GPP_C11: CLKREQ2_X1_GEN4_DT_CEM_SLOT_N */
PAD_CFG_NF(GPP_C11, NONE, DEEP, NF1),
};
static const struct pad_config x1slot_prsnt_pads[] = {
/* x1 slot power sequence: 3b. clkreq = GPI or NC for AIC using PRSNT2# */
/* GPP_C11: for PRSNT2_X1_GEN4_DT_CEM_SLOT_N */
PAD_CFG_GPI(GPP_C11, NONE, DEEP),
};
static const struct pad_config x1slot_disable_pads[] = {
/* GPP_A08: X1_PCIE_SLOT_PWR_EN */
PAD_CFG_GPO(GPP_A08, 0, PLTRST),
PAD_CFG_GPO(GPP_A08, 1, PLTRST),
/* GPP_D19: X1_DT_PCIE_RST_N */
PAD_NC(GPP_D19, NONE),
/* GPP_C11: CLKREQ2_X1_GEN4_DT_CEM_SLOT_N */
PAD_NC(GPP_C11, NONE),
/* GPP_B25: X1_SLOT_WAKE_N */
PAD_NC(GPP_B25, NONE)
};
@ -579,6 +629,9 @@ void fw_config_configure_pre_mem_gpio(void)
GPIO_CONFIGURE_PADS(pre_mem_gen5_ssd_pwr_pads);
}
if (!fw_config_probe(FW_CONFIG(SD, SD_NONE)))
GPIO_CONFIGURE_PADS(pre_mem_x1slot_pads);
/*
* NOTE: We place WWAN sequence 2 here. According to the WWAN FIBOCOM
* FM350-GL datasheet, the minimum time requirement (Tpr: time between 3.3V
@ -661,10 +714,15 @@ void fw_config_gpio_padbased_override(struct pad_config *padbased_table)
GPIO_PADBASED_OVERRIDE(padbased_table, wwan_disable_pads);
}
if (fw_config_probe(FW_CONFIG(SD, SD_NONE)))
GPIO_PADBASED_OVERRIDE(padbased_table, x1slot_disable_pads);
else
if (fw_config_probe(FW_CONFIG(SD, SD_GENSYS))) {
GPIO_PADBASED_OVERRIDE(padbased_table, x1slot_pads);
GPIO_PADBASED_OVERRIDE(padbased_table, x1slot_prsnt_pads);
} else if (fw_config_probe(FW_CONFIG(SD, SD_BAYHUB))) {
GPIO_PADBASED_OVERRIDE(padbased_table, x1slot_pads);
GPIO_PADBASED_OVERRIDE(padbased_table, x1slot_clkreq_pads);
} else {
GPIO_PADBASED_OVERRIDE(padbased_table, x1slot_disable_pads);
}
if (fw_config_probe(FW_CONFIG(TOUCHPAD, TOUCHPAD_LPSS_I2C))) {
GPIO_PADBASED_OVERRIDE(padbased_table, touchpad_lpss_i2c_enable_pads);
@ -727,3 +785,9 @@ void fw_config_gpio_padbased_override(struct pad_config *padbased_table)
GPIO_PADBASED_OVERRIDE(padbased_table, fp_disable_pads);
}
}
void fw_config_post_gpio_configure(void)
{
if (!fw_config_probe(FW_CONFIG(SD, SD_NONE)))
GPIO_CONFIGURE_PADS(post_x1slot_pads);
}

View file

@ -28,6 +28,8 @@ static const struct pad_config gpio_table[] = {
/* GPP_A06: ESPI_RST_EC_R_N */
/* GPP_A06 : GPP_A06 ==> ESPI_RST_HDR configured on reset, do not touch */
/* GPP_A08: X1_PCIE_SLOT_PWR_EN */
/* NOTE: x1 slot power will be updated according to SD fw_config */
/* GPP_A09: M.2_WWAN_FCP_OFF_N */
PAD_CFG_GPO(GPP_A09, 1, PLTRST),
/* GPP_A10: M.2_WWAN_DISABLE_N */
@ -81,7 +83,8 @@ static const struct pad_config gpio_table[] = {
PAD_CFG_GPO(GPP_B21, 0, DEEP),
/* GPP_B24: ESPI_ALERT0_EC_R_N */
PAD_NC(GPP_B24, NONE),
/* GPP_B25: X1_SLOT_WAKE_N */
/* NOTE: x1 slot wake will be overridden according to SD fw_config */
/* GPP_C00: GPP_C0_SMBCLK */
PAD_CFG_NF(GPP_C00, NONE, DEEP, NF1),
/* GPP_C01: GPP_C1_SMBDATA */
@ -101,7 +104,7 @@ static const struct pad_config gpio_table[] = {
/* GPP_C10: CLKREQ1_X4_GEN5_M2_SSD_N */
PAD_CFG_NF(GPP_C10, NONE, DEEP, NF1),
/* GPP_C11: CLKREQ2_X1_GEN4_DT_CEM_SLOT_N */
PAD_CFG_NF(GPP_C11, NONE, DEEP, NF1),
/* NOTE: x1 slot clkreq will be overridden according to SD fw_config */
/* GPP_C12: CLKREQ3_X1_GEN1_GBE_LAN_N */
PAD_CFG_NF(GPP_C12, NONE, DEEP, NF1),
/* GPP_C13: CLKREQ4_X1_GEN4_M2_WLAN_N */
@ -159,6 +162,8 @@ static const struct pad_config gpio_table[] = {
PAD_CFG_NF(GPP_D17, NONE, DEEP, NF1),
/* GPP_D18: CLKREQ6_X4_GEN4_M2_SSD_N */
PAD_CFG_NF(GPP_D18, NONE, DEEP, NF1),
/* GPP_D19: X1_DT_PCIE_RST_N */
/* NOTE: X1 PERST will follow power sequence according to SD fw_config */
/* GPP_D20: CSE_EARLY_SW */
PAD_CFG_GPI_SCI_HIGH(GPP_D20, NONE, DEEP, LEVEL),
/* GPP_D21: NC */
@ -363,8 +368,6 @@ static const struct pad_config early_gpio_table[] = {
/* Pad configuration in romstage */
static const struct pad_config romstage_gpio_table[] = {
/* GPP_A08: X1_PCIE_SLOT_PWR_EN */
PAD_CFG_GPO(GPP_A08, 0, PLTRST),
/* GPP_C00: GPP_C0_SMBCLK */
PAD_CFG_NF(GPP_C00, NONE, DEEP, NF1),
/* GPP_C01: GPP_C1_SMBDATA */

View file

@ -36,8 +36,8 @@ fw_config
end
field SD 13 14
option SD_NONE 0
option SD_GENSYS 1
option SD_BAYHUB 2
option SD_GENSYS 1 # use pin B17 as PRSNT2#
option SD_BAYHUB 2 # use pin B17 as ClkReq#
end
field STORAGE 15 16
option STORAGE_UNKNOWN 0
@ -602,6 +602,10 @@ chip soc/intel/pantherlake
register "pcie_rp[PCIE_RP(3)]" = "{
.clk_src = 2,
.clk_req = 2,
/*
* NOTE: The clock usage flag is changed to
* PCIE_RP_CLK_REQ_UNUSED in variant.c when PRSNT#2 is used.
*/
.flags = PCIE_RP_CLK_REQ_DETECT | PCIE_RP_LTR | PCIE_RP_AER,
}"
chip soc/intel/common/block/pcie/rtd3

View file

@ -75,6 +75,14 @@ void variant_update_soc_chip_config(struct soc_intel_pantherlake_config *config)
*/
config->thc_mode[0] = THC_HID_I2C_MODE;
}
/* x1 Slot */
if (fw_config_probe(FW_CONFIG(SD, SD_GENSYS))) {
uint8_t flags = config->pcie_rp[PCIE_RP(3)].flags;
flags &= ~(PCIE_RP_CLK_REQ_DETECT | PCIE_RP_CLK_REQ_UNUSED);
flags |= PCIE_RP_CLK_SRC_UNUSED;
config->pcie_rp[PCIE_RP(3)].flags = flags;
}
}
void variant_update_soc_memory_init_params(FSPM_UPD *memupd)