From 0306eb07234858ce1d6be9b4a1ac58a7d44b582d Mon Sep 17 00:00:00 2001 From: Sean Rhodes Date: Wed, 28 Jan 2026 12:10:00 +0000 Subject: [PATCH] mb/starlabs/common: add NVMe power sequencing helper Add a shared helper (behind Kconfig) that owns the ramstage bootstate ordering for the Star Labs NVMe/M.2 slot power sequence (PWREN, PERST#, CLKREQ#). Boards/variants provide pad configs for stage 2 and stage 3 either by implementing the `variant_nvme_power_sequence_*()` helpers or by providing pad tables via `variant_nvme_power_sequence_pads()` and `variant_nvme_power_sequence_post_pads()`. Signed-off-by: Sean Rhodes Change-Id: I3d518c35c26f3d3ee1dd72b4a35861d19cdb85ab Reviewed-on: https://review.coreboot.org/c/coreboot/+/90973 Reviewed-by: Matt DeVillier Tested-by: build bot (Jenkins) --- src/mainboard/starlabs/common/Kconfig | 21 +++++++ src/mainboard/starlabs/common/Makefile.mk | 2 + .../starlabs/common/include/common/nvme_seq.h | 15 +++++ src/mainboard/starlabs/common/nvme_seq.c | 62 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 src/mainboard/starlabs/common/include/common/nvme_seq.h create mode 100644 src/mainboard/starlabs/common/nvme_seq.c diff --git a/src/mainboard/starlabs/common/Kconfig b/src/mainboard/starlabs/common/Kconfig index 8a670142c0..5501d43efe 100644 --- a/src/mainboard/starlabs/common/Kconfig +++ b/src/mainboard/starlabs/common/Kconfig @@ -13,6 +13,27 @@ config BOOTMEDIA_SMM_BWP_RUNTIME_OPTION config DRIVERS_EFI_FW_INFO def_bool y +config STARLABS_NVME_POWER_SEQUENCE + bool "Enable NVMe/M.2 slot power sequence" + depends on SOC_INTEL_COMMON_BLOCK_GPIO + default n + help + Enable Fatcat-style 3-stage NVMe/M.2 slot sequencing using PWREN, PERST# + and CLKREQ# pads. + + The sequencing is: + 1) pre-mem: PERST# asserted; PWREN=0; CLKREQ# disabled + 2) BS_PRE_DEVICE exit: PERST# still asserted; PWREN=1; CLKREQ# native + 3) BS_DEV_INIT_CHIPS entry: PERST# deasserted + + Boards selecting this option must provide their own pad configs and + implement stage 1 (pre-mem) in their early pad configuration. + + For stage 2 and stage 3, boards must either implement the + `variant_nvme_power_sequence_*()` helpers or provide pad tables via + `variant_nvme_power_sequence_pads()` and + `variant_nvme_power_sequence_post_pads()`. + config MB_COMMON_DIR string default "starlabs/common" diff --git a/src/mainboard/starlabs/common/Makefile.mk b/src/mainboard/starlabs/common/Makefile.mk index b12b7610d3..6887c47a7d 100644 --- a/src/mainboard/starlabs/common/Makefile.mk +++ b/src/mainboard/starlabs/common/Makefile.mk @@ -6,6 +6,8 @@ subdirs-$(CONFIG_VENDOR_STARLABS) += powercap subdirs-$(CONFIG_VENDOR_STARLABS) += pin_mux subdirs-$(CONFIG_VENDOR_STARLABS) += smbios +ramstage-$(CONFIG_STARLABS_NVME_POWER_SEQUENCE) += nvme_seq.c + CPPFLAGS_common += -I$(src)/mainboard/starlabs/common/include ramstage-$(CONFIG_STARLABS_ACPI_EFI_OPTION_SMI) += gnvs.c diff --git a/src/mainboard/starlabs/common/include/common/nvme_seq.h b/src/mainboard/starlabs/common/include/common/nvme_seq.h new file mode 100644 index 0000000000..fcd1838045 --- /dev/null +++ b/src/mainboard/starlabs/common/include/common/nvme_seq.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _STARLABS_CMN_NVME_SEQ_H_ +#define _STARLABS_CMN_NVME_SEQ_H_ + +#include +#include + +const struct pad_config *variant_nvme_power_sequence_pads(size_t *num); +const struct pad_config *variant_nvme_power_sequence_post_pads(size_t *num); + +void variant_nvme_power_sequence_configure(void); +void variant_nvme_power_sequence_post_gpio_configure(void); + +#endif /* _STARLABS_CMN_NVME_SEQ_H_ */ diff --git a/src/mainboard/starlabs/common/nvme_seq.c b/src/mainboard/starlabs/common/nvme_seq.c new file mode 100644 index 0000000000..5fef80865a --- /dev/null +++ b/src/mainboard/starlabs/common/nvme_seq.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +#if ENV_RAMSTAGE +const __weak struct pad_config *variant_nvme_power_sequence_pads(size_t *num) +{ + *num = 0; + return NULL; +} + +const __weak struct pad_config *variant_nvme_power_sequence_post_pads(size_t *num) +{ + *num = 0; + return NULL; +} + +__weak void variant_nvme_power_sequence_configure(void) +{ + size_t num; + const struct pad_config *pads = variant_nvme_power_sequence_pads(&num); + + if (pads && num) + gpio_configure_pads(pads, num); +} + +__weak void variant_nvme_power_sequence_post_gpio_configure(void) +{ + size_t num; + const struct pad_config *pads = variant_nvme_power_sequence_post_pads(&num); + + if (pads && num) + gpio_configure_pads(pads, num); +} +#endif + +/* + * Star Labs NVMe/M.2 slot power sequence glue. + * + * Boards/variants provide the actual pad configs (PWREN, PERST#, CLKREQ#). + * + * This file only owns the ramstage ordering so the staged overrides happen + * before PCIe enumeration/link training. + */ + +static void starlabs_nvme_power_sequence_step2(void *unused) +{ + /* Stage 2: power on + enable CLKREQ#, keep PERST# asserted. */ + variant_nvme_power_sequence_configure(); +} + +static void starlabs_nvme_power_sequence_step3(void *unused) +{ + /* Stage 3: deassert PERST# after GPIO configuration, before device init. */ + variant_nvme_power_sequence_post_gpio_configure(); +} + +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_EXIT, starlabs_nvme_power_sequence_step2, NULL); +BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_ENTRY, starlabs_nvme_power_sequence_step3, NULL);