From 567186a0003b37d956045b3da3c19f292d7c9d4c Mon Sep 17 00:00:00 2001 From: Kapil Porwal Date: Mon, 24 Nov 2025 13:18:05 +0530 Subject: [PATCH] mb/google/bluey: Add support for off-mode charging Implement full support for the LB_BOOT_MODE_OFFMODE_CHARGING state. This mode is detected when the system powers on due to an external charging event (cable insertion) while the system was previously fully powered off. This boot mode is critical for systems that need to maintain a light footprint to quickly start charging without performing a full boot. It combines with the existing low-battery mode to define a unified "low power boot" state. In romstage, the boot mode is detected using is_off_mode() and the EC's low battery status, and the result is saved to CBMEM. In ramstage, this mode is read to determine if heavy, resource-intensive initializations should be skipped to conserve time and power. Key changes: - In romstage.c, implement set_boot_mode() to determine the mode (NORMAL, OFFMODE_CHARGING, or LOW_BATTERY) and save it to CBMEM_ID_BOOT_MODE. - In mainboard.c, introduce get_boot_mode() and is_low_power_boot() to retrieve and check the CBMEM value. - Skip heavy ramstage initializations (mainboard_init and mainboard_needs_pcie_init) when in a low-power boot mode. - Update lb_add_boot_mode to report the mode stored in CBMEM to the coreboot table. BUG=b:439819922 TEST=Verify off-mode charging behavior on Google/Quenbi. Change-Id: I57d25deb6b2b1f9ff199cea5ca2953f10ffb4746 Signed-off-by: Kapil Porwal Reviewed-on: https://review.coreboot.org/c/coreboot/+/90176 Reviewed-by: Subrata Banik Tested-by: build bot (Jenkins) --- src/mainboard/google/bluey/mainboard.c | 51 ++++++++++++++------------ src/mainboard/google/bluey/romstage.c | 29 +++++++++++++++ 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/mainboard/google/bluey/mainboard.c b/src/mainboard/google/bluey/mainboard.c index c20d98bbf5..07b50352c6 100644 --- a/src/mainboard/google/bluey/mainboard.c +++ b/src/mainboard/google/bluey/mainboard.c @@ -2,6 +2,9 @@ #include #include +#include +#include +#include #include #include #include @@ -13,27 +16,30 @@ #include /* - * Check if the system is in low battery boot mode. - * - * This function calls the underlying EC function only once during the + * This function calls the underlying PMIC/EC function only once during the * first execution and caches the result for all subsequent calls. - * - * Return `true` if system battery is below critical threshold, `false` otherwise. */ -static inline bool is_low_battery_mode(void) +static enum boot_mode_t get_boot_mode(void) { - if (!CONFIG(EC_GOOGLE_CHROMEEC)) - return false; - - static bool low_battery_mode_cached = false; - static bool cached_low_battery_result = false; - - if (!low_battery_mode_cached) { - cached_low_battery_result = google_chromeec_is_below_critical_threshold(); - low_battery_mode_cached = true; + static bool initialized = false; + static enum boot_mode_t boot_mode = LB_BOOT_MODE_NORMAL; + if (!initialized) { + enum boot_mode_t *boot_mode_ptr = cbmem_find(CBMEM_ID_BOOT_MODE); + if (boot_mode_ptr) + boot_mode = *boot_mode_ptr; + printk(BIOS_INFO, "Boot mode is %d\n", boot_mode); + initialized = true; } + return boot_mode; +} - return cached_low_battery_result; +static bool is_low_power_boot(void) +{ + enum boot_mode_t boot_mode = get_boot_mode(); + if ((boot_mode == LB_BOOT_MODE_LOW_BATTERY) || + (boot_mode == LB_BOOT_MODE_OFFMODE_CHARGING)) + return true; + return false; } static void setup_usb(void) @@ -51,20 +57,17 @@ void lb_add_boot_mode(struct lb_header *header) mode->tag = LB_TAG_BOOT_MODE; mode->size = sizeof(*mode); - mode->boot_mode = LB_BOOT_MODE_NORMAL; + mode->boot_mode = get_boot_mode(); - if (is_low_battery_mode()) - mode->boot_mode = LB_BOOT_MODE_LOW_BATTERY; - - /* Enable charging only during low-battery mode */ - if (mode->boot_mode == LB_BOOT_MODE_LOW_BATTERY) + /* Enable charging only during off-mode or low-battery mode */ + if (is_low_power_boot()) enable_slow_battery_charging(); } bool mainboard_needs_pcie_init(void) { /* Skip PCIe initialization if boot mode is "low-battery" or "off-mode charging"*/ - if (is_low_battery_mode()) + if (is_low_power_boot()) return false; return true; @@ -83,7 +86,7 @@ static void display_startup(void) static void mainboard_init(struct device *dev) { /* Skip mainboard initialization if boot mode is "low-battery" or "off-mode charging"*/ - if (is_low_battery_mode()) + if (is_low_power_boot()) return; gpi_firmware_load(QUP_0_GSI_BASE); diff --git a/src/mainboard/google/bluey/romstage.c b/src/mainboard/google/bluey/romstage.c index b76dfba1f2..c2cbf5b7c4 100644 --- a/src/mainboard/google/bluey/romstage.c +++ b/src/mainboard/google/bluey/romstage.c @@ -2,12 +2,29 @@ #include #include "board.h" +#include +#include +#include +#include #include #include #include #include #include +static enum boot_mode_t boot_mode = LB_BOOT_MODE_NORMAL; + +static void set_boot_mode(void) +{ + if (!CONFIG(EC_GOOGLE_CHROMEEC)) + return; + + if (is_off_mode()) + boot_mode = LB_BOOT_MODE_OFFMODE_CHARGING; + else if (google_chromeec_is_below_critical_threshold()) + boot_mode = LB_BOOT_MODE_LOW_BATTERY; +} + void platform_romstage_main(void) { /* Watchdog must be checked first to avoid erasing watchdog info later. */ @@ -18,6 +35,9 @@ void platform_romstage_main(void) /* QCLib: DDR init & train */ qclib_load_and_run(); + /* Underlying PMIC registers are accessible only at this point */ + set_boot_mode(); + aop_fw_load_reset(); qclib_rerun(); @@ -31,3 +51,12 @@ void platform_romstage_main(void) if (CONFIG(MAINBOARD_HAS_FINGERPRINT_VIA_SPI)) gpio_output(GPIO_EN_FP_RAILS, 1); } + +void platform_romstage_postram(void) +{ + enum boot_mode_t *boot_mode_ptr = cbmem_add(CBMEM_ID_BOOT_MODE, sizeof(*boot_mode_ptr)); + if (boot_mode_ptr) { + *boot_mode_ptr = boot_mode; + printk(BIOS_INFO, "Boot mode is %d\n", *boot_mode_ptr); + } +}