Skip to content

Commit

Permalink
Save battery thresholds at second-to-last sector
Browse files Browse the repository at this point in the history
Make battery thresholds persistent by saving them in flash space. This
allows configuring them after EC reset (system powered-off, unplugged)
but before any system firmware or OS policy can be applied.

Signed-off-by: Tim Crawford <[email protected]>
  • Loading branch information
crawfxrd committed Nov 26, 2024
1 parent c9bbd9b commit 85da2d2
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/board/system76/common/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ void acpi_write(uint8_t addr, uint8_t data) {

case 0xBD:
battery_set_end_threshold(data);
(void)battery_save_thresholds();
break;

#if HAVE_LED_AIRPLANE_N
Expand Down
48 changes: 48 additions & 0 deletions src/board/system76/common/battery.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only

#include <board/battery.h>
#include <board/flash.h>
#include <board/gpio.h>
#include <board/smbus.h>
#include <common/debug.h>
Expand All @@ -13,6 +14,18 @@ uint16_t battery_charger_input_current = CHARGER_INPUT_CURRENT;
#define BATTERY_START_DEFAULT 0
#define BATTERY_END_DEFAULT 100

// Flash address to save charging thresholds to
static const uint32_t BAT_CFG_ADDR = CONFIG_EC_FLASH_SIZE - (2 * 1024);
static const uint16_t BAT_CFG_MAGIC = 0x4254;

struct battery_config {
uint16_t magic;
uint8_t start_threshold;
uint8_t end_threshold;
};

static struct battery_config __xdata bat_cfg = { { 0 } };

// Represents a battery percentage level, below which charging will begin.
// Valid values are [0, 100]
// A value of 0 turns off the start threshold control.
Expand Down Expand Up @@ -112,3 +125,38 @@ void battery_reset(void) {
battery_start_threshold = BATTERY_START_THRESHOLD;
battery_end_threshold = BATTERY_END_THRESHOLD;
}

// Read the charge thresholds from flash. Falls back to defaults if not found.
bool battery_load_thresholds(void) {
bool loaded = true;

flash_read(BAT_CFG_ADDR, (uint8_t *)&bat_cfg, sizeof(bat_cfg));

if (bat_cfg.magic != BAT_CFG_MAGIC) {
bat_cfg.magic = BAT_CFG_MAGIC;
bat_cfg.start_threshold = BATTERY_START_THRESHOLD;
bat_cfg.end_threshold = BATTERY_END_THRESHOLD;
loaded = false;
}

(void)battery_set_start_threshold(bat_cfg.start_threshold);
(void)battery_set_end_threshold(bat_cfg.end_threshold);

return loaded;
}

// Write the charge thresholds to flash.
bool battery_save_thresholds(void) {
if ((bat_cfg.start_threshold == battery_start_threshold) &&
(bat_cfg.end_threshold == battery_end_threshold)) {
return true;
}

bat_cfg.start_threshold = battery_start_threshold;
bat_cfg.end_threshold = battery_end_threshold;

flash_erase(BAT_CFG_ADDR);
flash_write(BAT_CFG_ADDR, (uint8_t *)&bat_cfg, sizeof(bat_cfg));

return flash_read_u16(BAT_CFG_ADDR) == BAT_CFG_MAGIC;
}
3 changes: 3 additions & 0 deletions src/board/system76/common/include/board/battery.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ bool battery_set_start_threshold(uint8_t value);
uint8_t battery_get_end_threshold(void);
bool battery_set_end_threshold(uint8_t value);

bool battery_load_thresholds(void);
bool battery_save_thresholds(void);

int16_t battery_charger_configure(void);
void battery_event(void);
void battery_reset(void);
Expand Down
1 change: 1 addition & 0 deletions src/board/system76/common/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ void init(void) {
// Must happen last
power_init();
board_init();
(void)battery_load_thresholds();
}

void main(void) {
Expand Down

0 comments on commit 85da2d2

Please sign in to comment.