From 59593b5b5c9444609b51e199bb8a57cf0c31efcc Mon Sep 17 00:00:00 2001 From: Cliff Huang Date: Tue, 11 Nov 2025 11:19:02 -0800 Subject: [PATCH] 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 Change-Id: I94a7ee2ecd8d3fd83006297ef68f97ff49e47595 Reviewed-on: https://review.coreboot.org/c/coreboot/+/90000 Reviewed-by: Pranava Y N Tested-by: build bot (Jenkins) --- src/mainboard/google/fatcat/mainboard.c | 12 +++ .../baseboard/include/baseboard/variants.h | 1 + .../google/fatcat/variants/fatcat/fw_config.c | 74 +++++++++++++++++-- .../google/fatcat/variants/fatcat/gpio.c | 11 ++- .../fatcat/variants/fatcat/overridetree.cb | 8 +- .../google/fatcat/variants/fatcat/variant.c | 8 ++ 6 files changed, 103 insertions(+), 11 deletions(-) diff --git a/src/mainboard/google/fatcat/mainboard.c b/src/mainboard/google/fatcat/mainboard.c index 1ea606a6f1..b731f1d4d5 100644 --- a/src/mainboard/google/fatcat/mainboard.c +++ b/src/mainboard/google/fatcat/mainboard.c @@ -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 */ diff --git a/src/mainboard/google/fatcat/variants/baseboard/include/baseboard/variants.h b/src/mainboard/google/fatcat/variants/baseboard/include/baseboard/variants.h index ad26ab8a67..e0f4996579 100644 --- a/src/mainboard/google/fatcat/variants/baseboard/include/baseboard/variants.h +++ b/src/mainboard/google/fatcat/variants/baseboard/include/baseboard/variants.h @@ -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); diff --git a/src/mainboard/google/fatcat/variants/fatcat/fw_config.c b/src/mainboard/google/fatcat/variants/fatcat/fw_config.c index 0344103453..25f9a339df 100644 --- a/src/mainboard/google/fatcat/variants/fatcat/fw_config.c +++ b/src/mainboard/google/fatcat/variants/fatcat/fw_config.c @@ -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); +} diff --git a/src/mainboard/google/fatcat/variants/fatcat/gpio.c b/src/mainboard/google/fatcat/variants/fatcat/gpio.c index 59dbe23680..696fb8ba4d 100644 --- a/src/mainboard/google/fatcat/variants/fatcat/gpio.c +++ b/src/mainboard/google/fatcat/variants/fatcat/gpio.c @@ -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 */ diff --git a/src/mainboard/google/fatcat/variants/fatcat/overridetree.cb b/src/mainboard/google/fatcat/variants/fatcat/overridetree.cb index db599a394b..5ad0dc63c8 100644 --- a/src/mainboard/google/fatcat/variants/fatcat/overridetree.cb +++ b/src/mainboard/google/fatcat/variants/fatcat/overridetree.cb @@ -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 diff --git a/src/mainboard/google/fatcat/variants/fatcat/variant.c b/src/mainboard/google/fatcat/variants/fatcat/variant.c index a8b5b4146d..cb42dfb3b0 100644 --- a/src/mainboard/google/fatcat/variants/fatcat/variant.c +++ b/src/mainboard/google/fatcat/variants/fatcat/variant.c @@ -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)