mb/google/bluey: Implement off-mode charging applet
Add launch_charger_applet() to handle the system state when booting in off-mode charging or low-power modes with a charger present. Key features: 1. Monitoring: Periodically checks battery current (I-current) via SPMI/PMIC registers. 2. Event Handling: Detects and clears EC power button and lid events. If a manual power-on event is detected, the system triggers a full board reset to ensure a clean boot to the OS (preventing firmware state conflicts like ADSP-lite vs ADSP). 3. Shutdown: If the charger is removed, it signals the EC via off-mode heartbeat and initiates an AP power-off. BUG=b:439819922 BRANCH=None TEST=Verified that the device enters the charging loop when plugged in while off, and transitions to a full boot when the power button is pressed. Change-Id: I152f71eac89f5b522ea7b286517724e213c31e9a Signed-off-by: Subrata Banik <subratabanik@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/91485 Reviewed-by: Kapil Porwal <kapilporwal@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
a1dd5f05b0
commit
12710eafff
3 changed files with 100 additions and 12 deletions
|
|
@ -35,6 +35,9 @@
|
|||
#define GPIO_PANEL_POWER_ON GPIO(70)
|
||||
#define GPIO_PANEL_HPD GPIO(119)
|
||||
|
||||
/* Charging GPIOs */
|
||||
#define GPIO_PARALLEL_CHARGING_CFG GPIO(71)
|
||||
|
||||
/* SD card specific GPIOs. Only for SD-enabled devices. */
|
||||
#if CONFIG(MAINBOARD_HAS_SD_CONTROLLER)
|
||||
#define GPIO_SD_CD_L GPIO(71)
|
||||
|
|
@ -56,5 +59,6 @@ void configure_parallel_charging(void);
|
|||
void configure_parallel_charging_late(void);
|
||||
void enable_slow_battery_charging(void);
|
||||
void disable_slow_battery_charging(void);
|
||||
void launch_charger_applet(void);
|
||||
|
||||
#endif /* MAINBOARD_GOOGLE_BLUEY_BOARD_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#include <delay.h>
|
||||
#include <ec/google/chromeec/ec.h>
|
||||
#include <reset.h>
|
||||
#include <soc/pmic.h>
|
||||
#include <soc/qcom_spmi.h>
|
||||
#include <types.h>
|
||||
|
|
@ -16,16 +20,14 @@
|
|||
#define SMB2_CHGR_CHRG_EN_CMD ((SMB2_SLAVE_ID << 16) | SCHG_CHGR_CHARGING_ENABLE_CMD)
|
||||
#define SMB1_SCHG_TYPE_C_TYPE_C_DEBUG_ACCESS_SNK_CFG \
|
||||
((SMB1_SLAVE_ID << 16) | SCHG_TYPE_C_TYPE_C_DEBUG_ACCESS_SNK_CFG)
|
||||
#define SCHG_CHGR_CHARGING_FCC 0x260A
|
||||
#define SMB1_CHGR_CHARGING_FCC ((SMB1_SLAVE_ID << 16) | SCHG_CHGR_CHARGING_FCC)
|
||||
#define SMB2_CHGR_CHARGING_FCC ((SMB2_SLAVE_ID << 16) | SCHG_CHGR_CHARGING_FCC)
|
||||
|
||||
#define FCC_1A_STEP_50MA 0x14
|
||||
#define FCC_DISABLE 0x8c
|
||||
#define EN_DEBUG_ACCESS_SNK 0x1B
|
||||
|
||||
enum charging_status {
|
||||
CHRG_DISABLE,
|
||||
CHRG_ENABLE,
|
||||
};
|
||||
|
||||
#define PMC8380F_SLAVE_ID 0x05
|
||||
#define GPIO07_MODE_CTL 0x8E40
|
||||
#define GPIO07_DIG_OUT_SOURCE_CTL 0x8E44
|
||||
|
|
@ -38,7 +40,87 @@ enum charging_status {
|
|||
#define OUTPUT_INVERT 0x80
|
||||
#define PERPH_EN 0x80
|
||||
|
||||
#define GPIO_PARALLEL_CHARGING_CFG GPIO(71)
|
||||
#define DELAY_CHARGING_APPLET_MS 2000 /* 2sec */
|
||||
|
||||
enum charging_status {
|
||||
CHRG_DISABLE,
|
||||
CHRG_ENABLE,
|
||||
};
|
||||
|
||||
static int get_battery_icurr_ma(void)
|
||||
{
|
||||
/* Read battery i-current value */
|
||||
int icurr = spmi_read8(SMB1_CHGR_CHARGING_FCC);
|
||||
if (icurr <= 0)
|
||||
icurr = spmi_read8(SMB2_CHGR_CHARGING_FCC);
|
||||
if (icurr < 0)
|
||||
icurr = 0;
|
||||
|
||||
icurr *= 50;
|
||||
return icurr;
|
||||
}
|
||||
|
||||
static void clear_ec_manual_poweron_event(void)
|
||||
{
|
||||
const uint64_t manual_pwron_event_mask =
|
||||
(EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN));
|
||||
google_chromeec_clear_events_b(manual_pwron_event_mask);
|
||||
}
|
||||
|
||||
static int detect_ec_manual_poweron_event(void)
|
||||
{
|
||||
const uint64_t manual_pwron_event_mask =
|
||||
(EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON) |
|
||||
EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN));
|
||||
uint64_t events = google_chromeec_get_events_b();
|
||||
|
||||
if (!!(events & manual_pwron_event_mask))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void launch_charger_applet(void)
|
||||
{
|
||||
if (!CONFIG(EC_GOOGLE_CHROMEEC))
|
||||
return;
|
||||
|
||||
printk(BIOS_INFO, "Inside %s. Initiating charging\n", __func__);
|
||||
|
||||
/* clear any pending power button press and lid open event */
|
||||
clear_ec_manual_poweron_event();
|
||||
|
||||
do {
|
||||
/* Add static delay before reading the charging applet pre-requisites */
|
||||
mdelay(DELAY_CHARGING_APPLET_MS);
|
||||
|
||||
/*
|
||||
* Issue a shutdown if not charging.
|
||||
*/
|
||||
if (!get_battery_icurr_ma()) {
|
||||
printk(BIOS_INFO, "Issuing power-off due to change in charging state.\n");
|
||||
google_chromeec_offmode_heartbeat();
|
||||
google_chromeec_ap_poweroff();
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit the charging loop in the event of lid open or power
|
||||
* button press.
|
||||
*
|
||||
* Reset the device to ensure a fresh boot to OS.
|
||||
* This is required to avoid any kind of tear-down due to ADSP-lite
|
||||
* being loaded and need some clean up before loading ADSP firmware by
|
||||
* linux kernel.
|
||||
*/
|
||||
if (detect_ec_manual_poweron_event()) {
|
||||
printk(BIOS_INFO, "Exiting charging applet to boot to OS\n");
|
||||
do_board_reset();
|
||||
}
|
||||
|
||||
/* TODO: add Tsense support and issue a shutdown in the event of temperature trip */
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable PMC8380F GPIO07 & GPIO09 for parallel charging.
|
||||
|
|
|
|||
|
|
@ -121,12 +121,6 @@ void lb_add_boot_mode(struct lb_header *header)
|
|||
mode->tag = LB_TAG_BOOT_MODE;
|
||||
mode->size = sizeof(*mode);
|
||||
mode->boot_mode = get_boot_mode();
|
||||
|
||||
configure_parallel_charging_late();
|
||||
|
||||
/* Enable charging only during off-mode or low-battery mode with charger present */
|
||||
if (is_low_power_boot_with_charger())
|
||||
enable_slow_battery_charging();
|
||||
}
|
||||
|
||||
bool mainboard_needs_pcie_init(void)
|
||||
|
|
@ -177,14 +171,22 @@ static void mainboard_init(struct device *dev)
|
|||
if (get_boot_mode() == LB_BOOT_MODE_LOW_BATTERY)
|
||||
trigger_critical_battery_shutdown();
|
||||
|
||||
configure_parallel_charging_late();
|
||||
|
||||
/* Skip mainboard initialization if boot mode is "low-battery" or "off-mode charging" */
|
||||
if (is_low_power_boot_with_charger()) {
|
||||
/* TODO: enable fast charging */
|
||||
enable_slow_battery_charging();
|
||||
|
||||
/* Disable the lightbar for Low-Battery or Off-Mode charging sequences.
|
||||
* This maintains visual consistency between the built-in display
|
||||
* indicators and the external lightbar.
|
||||
*/
|
||||
if (CONFIG(EC_GOOGLE_CHROMEEC))
|
||||
google_chromeec_lightbar_off();
|
||||
|
||||
/* Boot to charging applet */
|
||||
launch_charger_applet();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue