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 <sean@starlabs.systems>
Change-Id: I3d518c35c26f3d3ee1dd72b4a35861d19cdb85ab
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90973
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Sean Rhodes 2026-01-28 12:10:00 +00:00
commit 0306eb0723
4 changed files with 100 additions and 0 deletions

View file

@ -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"

View file

@ -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

View file

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _STARLABS_CMN_NVME_SEQ_H_
#define _STARLABS_CMN_NVME_SEQ_H_
#include <stddef.h>
#include <soc/gpio.h>
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_ */

View file

@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <commonlib/bsd/compiler.h>
#include <common/nvme_seq.h>
#include <intelblocks/gpio.h>
#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);