diff options
Diffstat (limited to 'baseboard/grunt/battery.c')
-rw-r--r-- | baseboard/grunt/battery.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/baseboard/grunt/battery.c b/baseboard/grunt/battery.c new file mode 100644 index 0000000000..8c9755daac --- /dev/null +++ b/baseboard/grunt/battery.c @@ -0,0 +1,126 @@ +/* Copyright 2018 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_smart.h" +#include "console.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "timer.h" + +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) + +/* Shutdown mode parameter to write to manufacturer access register */ +#define SB_SHUTDOWN_DATA 0x0010 + +static enum battery_present batt_pres_prev = BP_NOT_SURE; + +/* Battery may delay reporting battery present */ +static int battery_report_present = 1; + +static const struct battery_info info = { + .voltage_max = 13200, /* mV */ + .voltage_normal = 11550, + .voltage_min = 9000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 50, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 75, +}; + +const struct battery_info *battery_get_info(void) +{ + return &info; +} + +int board_cut_off_battery(void) +{ + int rv; + /* Ship mode command must be sent twice to take effect */ + rv = sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); + if (rv != EC_SUCCESS) + return rv; + return sb_write(SB_MANUFACTURER_ACCESS, SB_SHUTDOWN_DATA); +} + +enum battery_present battery_hw_present(void) +{ + /* The GPIO is low when the battery is physically present */ + return gpio_get_level(GPIO_EC_BATT_PRES_ODL) ? BP_NO : BP_YES; +} + +static int battery_init(void) +{ + int batt_status; + + return battery_status(&batt_status) ? 0 : + !!(batt_status & STATUS_INITIALIZED); +} + +/* Allow booting now that the battery has woke up */ +static void battery_now_present(void) +{ + CPRINTS("battery will now report present"); + battery_report_present = 1; +} +DECLARE_DEFERRED(battery_now_present); + +static int battery_check_disconnect(void) +{ + /* TODO(ecgh): Read the status of charge/discharge FETs */ + return BATTERY_NOT_DISCONNECTED; +} + +enum battery_present battery_is_present(void) +{ + enum battery_present batt_pres; + static int battery_report_present_timer_started; + + /* Get the physical hardware status */ + batt_pres = battery_hw_present(); + + /* + * Make sure battery status is implemented, I2C transactions are + * success & the battery status is Initialized to find out if it + * is a working battery and it is not in the cut-off mode. + */ + if (batt_pres == BP_YES && batt_pres_prev != batt_pres && + (battery_is_cut_off() != BATTERY_CUTOFF_STATE_NORMAL || + battery_check_disconnect() != BATTERY_NOT_DISCONNECTED || + battery_init() == 0)) { + battery_report_present = 0; + /* + * When this path is taken, the _timer_started flag must be + * reset so the 'else if' path will be entered and the + * battery_report_present flag can be set by the deferred + * call. This handles the case of the battery being disconected + * and reconnected while running or if battery_init() returns an + * error due to a failed sb_read. + */ + battery_report_present_timer_started = 0; + } else if (batt_pres == BP_YES && batt_pres_prev == BP_NO && + !battery_report_present_timer_started) { + /* + * Wait 1/2 second before reporting present if it was + * previously reported as not present + */ + battery_report_present_timer_started = 1; + battery_report_present = 0; + hook_call_deferred(&battery_now_present_data, 500 * MSEC); + } + + if (!battery_report_present) + batt_pres = BP_NO; + + batt_pres_prev = batt_pres; + + return batt_pres; +} |