Move TPSChrome charging temperature range to battery pack

This change moves vendor specific temperature ranges to battery pack
files or board setup files. And added a host test case to verify that
does not change x86 smart battery charging state machine behavior.

BUG=chrome-os-partner:21181
BRANCH=None
TEST=manual
  build test: util/ecmakeall.sh
  hosttests: make hosttests && make runtests

Change-Id: I48e76826b5555f64b78e3c063ce5f02416c72aa2
Signed-off-by: Rong Chang <rongchang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/62978
Reviewed-by: Vic Yang <victoryang@chromium.org>
This commit is contained in:
Rong Chang
2013-07-24 08:22:48 -07:00
committed by ChromeBot
parent 7b95d397fe
commit 6c280b1b32
23 changed files with 453 additions and 203 deletions

View File

@@ -4,6 +4,7 @@
*/
/* Daisy board-specific configuration */
#include "battery_pack.h"
#include "common.h"
#include "gaia_power.h"
#include "gpio.h"
@@ -99,6 +100,16 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
GPIO_SIGNAL_NOT_IMPLEMENTED("WP_L"),
};
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
.start_charging_max_c = 45,
.charging_min_c = 5,
.charging_max_c = 60,
.discharging_min_c = 0,
.discharging_max_c = 100,
};
/* I2C ports */
const struct i2c_port_t i2c_ports[I2C_PORTS_USED] = {
{"0", 0, 100},

View File

@@ -17,6 +17,13 @@
#define CONFIG_TEMP_SENSOR
#undef CONFIG_WATCHDOG
/* Host test config */
#ifdef SMART_BATTERY_CHARGER
#define CONFIG_CHARGER
#define CONFIG_MOCK_BATTERY
#define CONFIG_CHARGER_INPUT_CURRENT 4032
#endif
/* Keyboard protocol */
#ifdef KB_8042
#define CONFIG_KEYBOARD_PROTOCOL_8042

View File

@@ -4,6 +4,7 @@
*/
/* Pit board-specific configuration */
#include "battery_pack.h"
#include "common.h"
#include "extpower.h"
#include "gaia_power.h"
@@ -80,6 +81,16 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
{"KB_OUT12", GPIO_A, (1<<13), GPIO_KB_OUTPUT, NULL},
};
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 0,
.start_charging_max_c = 45,
.charging_min_c = 0,
.charging_max_c = 60,
.discharging_min_c = 0,
.discharging_max_c = 100,
};
/* I2C ports */
const struct i2c_port_t i2c_ports[I2C_PORTS_USED] = {
{"host", I2C_PORT_HOST, 100},

View File

@@ -4,6 +4,7 @@
*/
/* Puppy board-specific configuration */
#include "battery_pack.h"
#include "common.h"
#include "extpower.h"
#include "gaia_power.h"
@@ -80,6 +81,16 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
{"KB_OUT12", GPIO_A, (1<<13), GPIO_KB_OUTPUT, NULL},
};
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
.start_charging_max_c = 45,
.charging_min_c = 5,
.charging_max_c = 60,
.discharging_min_c = 0,
.discharging_max_c = 100,
};
/* I2C ports */
const struct i2c_port_t i2c_ports[I2C_PORTS_USED] = {
{"host", I2C_PORT_HOST, 100},

View File

@@ -4,6 +4,7 @@
*/
/* Snow board-specific configuration */
#include "battery_pack.h"
#include "board_config.h"
#include "chipset.h"
#include "common.h"
@@ -93,6 +94,16 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
{"KB_OUT12", GPIO_C, (1<<7), GPIO_KB_OUTPUT, NULL},
};
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
.start_charging_max_c = 45,
.charging_min_c = 5,
.charging_max_c = 60,
.discharging_min_c = 0,
.discharging_max_c = 100,
};
/* I2C ports */
const struct i2c_port_t i2c_ports[I2C_PORTS_USED] = {
{"host", I2C_PORT_HOST, 100},

View File

@@ -5,6 +5,7 @@
/* Spring board-specific configuration */
#include "adc.h"
#include "battery_pack.h"
#include "board_config.h"
#include "chipset.h"
#include "common.h"
@@ -93,6 +94,16 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
{"ILIM", GPIO_B, (1<<4), GPIO_OUT_LOW, NULL},
};
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
.start_charging_max_c = 45,
.charging_min_c = 5,
.charging_max_c = 60,
.discharging_min_c = 0,
.discharging_max_c = 100,
};
/* ADC channels */
const struct adc_t adc_channels[ADC_CH_COUNT] = {
/*

View File

@@ -12,18 +12,21 @@
#define SB_SHIP_MODE_DATA 0x0010
/* FIXME: We need REAL values for all this stuff */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 0,
.start_charging_max_c = 45,
.charging_min_c = 0,
.charging_max_c = 45,
.discharging_min_c = -10,
.discharging_max_c = 60,
};
static const struct battery_info info = {
.voltage_max = 8400,
.voltage_normal = 7400,
.voltage_min = 6000,
/* Operational temperature range */
.temp_charge_min = CELSIUS_TO_DECI_KELVIN(0),
.temp_charge_max = CELSIUS_TO_DECI_KELVIN(45),
.temp_discharge_min = CELSIUS_TO_DECI_KELVIN(-10),
.temp_discharge_max = CELSIUS_TO_DECI_KELVIN(60),
/* Pre-charge values. */
.precharge_current = 256, /* mA */
};
@@ -37,18 +40,6 @@ const struct battery_info *battery_get_info(void)
* called "smart". Do we really want to second-guess it? For now, let's not. */
void battery_vendor_params(struct batt_params *batt)
{
#if 0
/* Limit charging voltage */
if (batt->desired_voltage > info.voltage_max)
batt->desired_voltage = info.voltage_max;
/* Don't charge if outside of allowable temperature range */
if (batt->temperature >= info.temp_charge_max ||
batt->temperature <= info.temp_charge_min) {
batt->desired_voltage = 0;
batt->desired_current = 0;
}
#endif
}
int battery_command_cut_off(struct host_cmd_handler_args *args)

View File

@@ -47,6 +47,20 @@ static const int const current_limit[TEMP_RANGE_MAX][VOLT_RANGE_MAX] = {
{ 800, 1600, 800},
};
const struct battery_temperature_ranges bat_temp_ranges = {
/*
* Operational temperature range
* 0 <= T_charge <= 50 deg C
* -20 <= T_discharge <= 60 deg C
*/
.start_charging_min_c = 0,
.start_charging_max_c = 50,
.charging_min_c = 0,
.charging_max_c = 50,
.discharging_min_c = -20,
.discharging_max_c = 60,
};
static const struct battery_info info = {
/*
* Design voltage
@@ -58,16 +72,6 @@ static const struct battery_info info = {
.voltage_normal = 7400,
.voltage_min = 6000,
/*
* Operational temperature range
* 0 <= T_charge <= 50 deg C
* -20 <= T_discharge <= 60 deg C
*/
.temp_charge_min = CELSIUS_TO_DECI_KELVIN(0),
.temp_charge_max = CELSIUS_TO_DECI_KELVIN(50),
.temp_discharge_min = CELSIUS_TO_DECI_KELVIN(-20),
.temp_discharge_max = CELSIUS_TO_DECI_KELVIN(60),
/* Pre-charge current: I <= 0.01C */
.precharge_current = 64, /* mA */
};
@@ -87,26 +91,27 @@ void battery_vendor_params(struct batt_params *batt)
{
int *desired_current = &batt->desired_current;
int temp_range, volt_range;
int bat_temp_c = DECI_KELVIN_TO_CELSIUS(batt->temperature);
/* Limit charging voltage */
if (batt->desired_voltage > info.voltage_max)
batt->desired_voltage = info.voltage_max;
/* Don't charge if outside of allowable temperature range */
if (batt->temperature >= info.temp_charge_max ||
batt->temperature <= info.temp_charge_min) {
if (bat_temp_c >= bat_temp_ranges.charging_max_c ||
bat_temp_c < bat_temp_ranges.charging_min_c) {
batt->desired_voltage = 0;
batt->desired_current = 0;
return;
}
if (batt->temperature <= CELSIUS_TO_DECI_KELVIN(10))
if (bat_temp_c <= 10)
temp_range = TEMP_RANGE_10;
else if (batt->temperature <= CELSIUS_TO_DECI_KELVIN(23))
else if (bat_temp_c <= 23)
temp_range = TEMP_RANGE_23;
else if (batt->temperature <= CELSIUS_TO_DECI_KELVIN(35))
else if (bat_temp_c <= 35)
temp_range = TEMP_RANGE_35;
else if (batt->temperature <= CELSIUS_TO_DECI_KELVIN(45))
else if (bat_temp_c <= 45)
temp_range = TEMP_RANGE_45;
else
temp_range = TEMP_RANGE_50;

View File

@@ -14,22 +14,21 @@
#define SB_SHIP_MODE_DATA 0xc574
/* Values for 54Wh 3UPF656790-1-T1001 battery */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 0,
.start_charging_max_c = 60,
.charging_min_c = 0,
.charging_max_c = 60,
.discharging_min_c = 0,
.discharging_max_c = 50,
};
static const struct battery_info info = {
.voltage_max = 12600,
.voltage_normal = 11100, /* Average of max & min */
.voltage_min = 9000,
/*
* Operational temperature range
* 0 <= T_charge <= 60 deg C
* 0 <= T_discharge <= 50 deg C
*/
.temp_charge_min = CELSIUS_TO_DECI_KELVIN(0),
.temp_charge_max = CELSIUS_TO_DECI_KELVIN(60),
.temp_discharge_min = CELSIUS_TO_DECI_KELVIN(0),
.temp_discharge_max = CELSIUS_TO_DECI_KELVIN(50),
/* Pre-charge values. */
.precharge_current = 256, /* mA */
};
@@ -43,18 +42,6 @@ const struct battery_info *battery_get_info(void)
* called "smart". Do we really want to second-guess it? For now, let's not. */
void battery_vendor_params(struct batt_params *batt)
{
#if 0
/* Limit charging voltage */
if (batt->desired_voltage > info.voltage_max)
batt->desired_voltage = info.voltage_max;
/* Don't charge if outside of allowable temperature range */
if (batt->temperature >= info.temp_charge_max ||
batt->temperature <= info.temp_charge_min) {
batt->desired_voltage = 0;
batt->desired_current = 0;
}
#endif
}
int battery_command_cut_off(struct host_cmd_handler_args *args)

View File

@@ -9,22 +9,21 @@
#include "gpio.h"
/* FIXME: We need REAL values for all this stuff */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 0,
.start_charging_max_c = 50,
.charging_min_c = 0,
.charging_max_c = 50,
.discharging_min_c = -20,
.discharging_max_c = 60,
};
static const struct battery_info info = {
.voltage_max = 16800,
.voltage_normal = 14800,
.voltage_min = 10800,
/*
* Operational temperature range
* 0 <= T_charge <= 50 deg C
* -20 <= T_discharge <= 60 deg C
*/
.temp_charge_min = CELSIUS_TO_DECI_KELVIN(0),
.temp_charge_max = CELSIUS_TO_DECI_KELVIN(50),
.temp_discharge_min = CELSIUS_TO_DECI_KELVIN(-20),
.temp_discharge_max = CELSIUS_TO_DECI_KELVIN(60),
/* Pre-charge values. */
.precharge_current = 256, /* mA */
};
@@ -38,18 +37,6 @@ const struct battery_info *battery_get_info(void)
* called "smart". Do we really want to second-guess it? For now, let's not. */
void battery_vendor_params(struct batt_params *batt)
{
#if 0
/* Limit charging voltage */
if (batt->desired_voltage > info.voltage_max)
batt->desired_voltage = info.voltage_max;
/* Don't charge if outside of allowable temperature range */
if (batt->temperature >= info.temp_charge_max ||
batt->temperature <= info.temp_charge_min) {
batt->desired_voltage = 0;
batt->desired_current = 0;
}
#endif
}
/**

View File

@@ -46,6 +46,7 @@ common-$(CONFIG_LED_PEPPY)+=led_peppy.o
common-$(CONFIG_LED_SLIPPY)+=led_slippy.o
common-$(CONFIG_LID_SWITCH)+=lid_switch.o
common-$(CONFIG_LPC)+=port80.o
common-$(CONFIG_MOCK_BATTERY)+=mock_smart_battery_stub.o mock_charger.o
common-$(CONFIG_ONEWIRE_LED)+=onewire_led.o
common-$(CONFIG_POWER_BUTTON)+=power_button.o
common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o

View File

@@ -34,6 +34,13 @@
/* Timeout after AP battery shutdown warning before we kill the AP */
#define LOW_BATTERY_SHUTDOWN_TIMEOUT_US (30 * SECOND)
#ifndef TASK_ID_CHARGER
#define TASK_ID_CHARGER TASK_ID_INVALID
#endif
#ifndef TASK_ID_SWITCH
#define TASK_ID_SWITCH TASK_ID_INVALID
#endif
static const char * const state_name[] = POWER_STATE_NAME_TABLE;
static int state_machine_force_idle = 0;
@@ -483,6 +490,7 @@ static enum power_state state_charge(struct power_state_context *ctx)
static enum power_state state_discharge(struct power_state_context *ctx)
{
struct batt_params *batt = &ctx->curr.batt;
int8_t bat_temp_c = DECI_KELVIN_TO_CELSIUS(batt->temperature);
if (ctx->curr.ac)
return PWR_STATE_REINIT;
@@ -490,8 +498,8 @@ static enum power_state state_discharge(struct power_state_context *ctx)
return PWR_STATE_ERROR;
/* Handle overtemp in discharging state by powering off host */
if ((batt->temperature > ctx->battery->temp_discharge_max ||
batt->temperature < ctx->battery->temp_discharge_min) &&
if ((bat_temp_c >= bat_temp_ranges.discharging_max_c ||
bat_temp_c < bat_temp_ranges.discharging_min_c) &&
chipset_in_state(CHIPSET_STATE_ON)) {
CPRINTF("[%T charge force shutdown due to battery temp]\n");
chipset_force_shutdown();

View File

@@ -78,7 +78,6 @@ int charger_set_current(int current)
return EC_SUCCESS;
}
int charger_get_voltage(int *voltage)
{
*voltage = mock_voltage;
@@ -94,6 +93,48 @@ int charger_set_voltage(int voltage)
}
int charger_get_option(int *option)
{
return EC_SUCCESS;
}
int charger_set_option(int option)
{
return EC_SUCCESS;
}
int charger_manufacturer_id(int *id)
{
return EC_SUCCESS;
}
int charger_device_id(int *id)
{
return EC_SUCCESS;
}
int charger_get_input_current(int *input_current)
{
return EC_SUCCESS;
}
int charger_set_input_current(int input_current)
{
return EC_SUCCESS;
}
int charger_closest_current(int current)
{
return current;
}
int charger_post_init(void)
{
mock_current = CONFIG_CHARGER_INPUT_CURRENT;

View File

@@ -1,105 +1,124 @@
/* Copyright (c) 2013 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.
*
* Smart battery driver.
*/
#include "battery_pack.h"
#include "common.h"
#include "console.h"
#include "smart_battery.h"
#include "smart_battery_stub.h"
#include "uart.h"
#include "util.h"
static int mock_temperature = 2981;
static int mock_desire_voltage = 7000;
static int mock_desire_current = 3000;
static int mock_voltage = 6000;
static int mock_current = 3000;
static uint16_t mock_smart_battery[SB_MANUFACTURER_DATA + 1];
int sb_read(int cmd, int *param)
{
switch (cmd)
{
case SB_TEMPERATURE:
*param = mock_temperature;
break;
case SB_VOLTAGE:
*param = mock_voltage;
break;
case SB_CURRENT:
*param = mock_current;
break;
case SB_RELATIVE_STATE_OF_CHARGE:
case SB_ABSOLUTE_STATE_OF_CHARGE:
*param = 70; /* 70% charged */
break;
case SB_REMAINING_CAPACITY:
*param = 7000; /* 7000 mAh */
break;
case SB_FULL_CHARGE_CAPACITY:
case SB_DESIGN_CAPACITY:
*param = 10000; /* 10000 mAh */
break;
case SB_AVERAGE_TIME_TO_EMPTY:
case SB_RUN_TIME_TO_EMPTY:
*param = 60; /* 60 min to empty */
break;
case SB_AVERAGE_TIME_TO_FULL:
*param = 30; /* 30 min to full */
break;
case SB_CHARGING_CURRENT:
*param = mock_desire_current;
break;
case SB_CHARGING_VOLTAGE:
*param = mock_desire_voltage;
break;
case SB_CYCLE_COUNT:
*param = 10;
break;
case SB_DESIGN_VOLTAGE:
*param = 7400; /* 7.4 V */
break;
case SB_SERIAL_NUMBER:
*param = 112233;
break;
default:
*param = 0;
break;
}
if (cmd >= ARRAY_SIZE(mock_smart_battery))
return EC_ERROR_UNIMPLEMENTED;
if (cmd < 0 || param == NULL)
return EC_ERROR_INVAL;
*param = mock_smart_battery[cmd];
return EC_SUCCESS;
}
int sb_write(int cmd, int param)
{
uart_printf("sb_write: cmd = %d, param = %d\n", cmd, param);
if (cmd >= ARRAY_SIZE(mock_smart_battery))
return EC_ERROR_UNIMPLEMENTED;
if (cmd < 0)
return EC_ERROR_INVAL;
mock_smart_battery[cmd] = param;
return EC_SUCCESS;
}
static int command_sb_mock(int argc, char **argv)
int battery_manufacturer_name(char *manufacturer_name, int buf_size)
{
char *e;
int v;
if (argc < 3)
return EC_ERROR_PARAM_COUNT;
v = strtoi(argv[2], &e, 0);
if (*e)
return EC_ERROR_PARAM2;
if (!strcasecmp(argv[1], "temperature"))
mock_temperature = v;
else if (!strcasecmp(argv[1], "desire_voltage"))
mock_desire_voltage = v;
else if (!strcasecmp(argv[1], "desire_current"))
mock_desire_current = v;
else if (!strcasecmp(argv[1], "voltage"))
mock_voltage = v;
else if (!strcasecmp(argv[1], "current"))
mock_current = v;
else
return EC_ERROR_PARAM1;
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(sbmock, command_sb_mock,
"name value",
"Mock smart battery attribute",
NULL);
int battery_device_name(char *device_name, int buf_size)
{
return EC_SUCCESS;
}
int battery_device_chemistry(char *device_chemistry, int buf_size)
{
return EC_SUCCESS;
}
int battery_current(int *current)
{
int rv, d;
rv = sb_read(SB_CURRENT, &d);
if (rv)
return rv;
*current = (int16_t)d;
return EC_SUCCESS;
}
int battery_average_current(int *current)
{
int rv, d;
rv = sb_read(SB_AVERAGE_CURRENT, &d);
if (rv)
return rv;
*current = (int16_t)d;
return EC_SUCCESS;
}
int battery_time_at_rate(int rate, int *minutes)
{
return EC_SUCCESS;
}
int battery_manufacturer_date(int *year, int *month, int *day)
{
return EC_SUCCESS;
}
/* Fake battery */
const struct battery_temperature_ranges bat_temp_ranges = {
/*
* Operational temperature range
* 0 <= T_charge <= 50 deg C
* -20 <= T_discharge <= 60 deg C
*/
.start_charging_min_c = 0,
.start_charging_max_c = 50,
.charging_min_c = 0,
.charging_max_c = 50,
.discharging_min_c = -20,
.discharging_max_c = 60,
};
static const struct battery_info bat_info = {
/*
* Design voltage
* max = 8.4V
* normal = 7.4V
* min = 6.0V
*/
.voltage_max = 8400,
.voltage_normal = 7400,
.voltage_min = 6000,
/* Pre-charge current: I <= 0.01C */
.precharge_current = 64, /* mA */
};
const struct battery_info *battery_get_info(void)
{
return &bat_info;
}
void battery_vendor_params(struct batt_params *batt)
{
}

View File

@@ -5,6 +5,7 @@
* TI TPS65090 PMU charging task.
*/
#include "battery_pack.h"
#include "clock.h"
#include "chipset.h"
#include "common.h"
@@ -58,31 +59,30 @@ static void enable_charging(int enable)
gpio_set_level(GPIO_CHARGER_EN, enable);
}
/*
* TODO(rongchang): move battery vendor specific functions to battery pack
* module
*/
static int battery_temperature_celsius(int t)
static int battery_temperature_celsius(int deci_k)
{
return (t - 2731) / 10;
return (deci_k - 2731) / 10;
}
static int battery_start_charging_range(int t)
static int battery_start_charging_range(int deci_k)
{
t = battery_temperature_celsius(t);
return (t >= 5 && t < 45);
int8_t temp_c = battery_temperature_celsius(deci_k);
return (temp_c >= bat_temp_ranges.start_charging_min_c &&
temp_c < bat_temp_ranges.start_charging_max_c);
}
static int battery_charging_range(int t)
static int battery_charging_range(int deci_k)
{
t = battery_temperature_celsius(t);
return (t >= 5 && t < 60);
int8_t temp_c = battery_temperature_celsius(deci_k);
return (temp_c >= bat_temp_ranges.charging_min_c &&
temp_c < bat_temp_ranges.charging_max_c);
}
static int battery_discharging_range(int t)
static int battery_discharging_range(int deci_k)
{
t = battery_temperature_celsius(t);
return (t >= 0 && t < 100);
int8_t temp_c = battery_temperature_celsius(deci_k);
return (temp_c >= bat_temp_ranges.discharging_min_c &&
temp_c < bat_temp_ranges.discharging_max_c);
}
/*

View File

@@ -106,6 +106,27 @@ int battery_manufacturer_date(int *year, int *month, int *day)
return EC_SUCCESS;
}
/* Read manufacturer name */
int battery_manufacturer_name(char *manufacturer_name, int buf_size)
{
return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR,
SB_MANUFACTURER_NAME, manufacturer_name, buf_size);
}
/* Read device name */
int battery_device_name(char *device_name, int buf_size)
{
return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR,
SB_DEVICE_NAME, device_name, buf_size);
}
/* Read battery type/chemistry */
int battery_device_chemistry(char *device_chemistry, int buf_size)
{
return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR,
SB_DEVICE_CHEMISTRY, device_chemistry, buf_size);
}
/*****************************************************************************/
/* Console commands */

View File

@@ -10,6 +10,7 @@
#include "common.h"
#define CELSIUS_TO_DECI_KELVIN(temp_c) ((temp_c) * 10 + 2731)
#define DECI_KELVIN_TO_CELSIUS(temp_dk) ((temp_dk - 2731) / 10)
/* Battery parameters */
struct batt_params {
@@ -21,17 +22,23 @@ struct batt_params {
int desired_current; /* Charging current desired by battery (mA) */
};
/* Working temperature ranges in degrees C */
struct battery_temperature_ranges {
int8_t start_charging_min_c;
int8_t start_charging_max_c;
int8_t charging_min_c;
int8_t charging_max_c;
int8_t discharging_min_c;
int8_t discharging_max_c;
};
extern const struct battery_temperature_ranges bat_temp_ranges;
/* Battery constants */
struct battery_info {
/* Design voltage in mV */
int voltage_max;
int voltage_normal;
int voltage_min;
/* Working temperature range in 0.1 K increments */
int temp_charge_min;
int temp_charge_max;
int temp_discharge_min;
int temp_discharge_max;
/* Pre-charge current in mA */
int precharge_current;
};

View File

@@ -149,7 +149,7 @@ int charge_get_percent(void);
/**
* Return non-zero if discharging and battery so low we should shut down.
*/
#ifdef HAS_TASK_CHARGER
#ifdef CONFIG_CHARGER
int charge_want_shutdown(void);
#else
static inline int charge_want_shutdown(void) { return 0; }

View File

@@ -213,26 +213,13 @@ static inline int battery_serial_number(int *serial)
{ return sb_read(SB_SERIAL_NUMBER, serial); }
/* Read manufacturer name */
static inline int battery_manufacturer_name(char *manufacturer_name,
int buf_size)
{
return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR,
SB_MANUFACTURER_NAME, manufacturer_name, buf_size);
}
int battery_manufacturer_name(char *manufacturer_name, int buf_size);
/* Read device name */
static inline int battery_device_name(char *device_name, int buf_size)
{
return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR,
SB_DEVICE_NAME, device_name, buf_size);
}
int battery_device_name(char *device_name, int buf_size);
/* Read battery type/chemistry */
static inline int battery_device_chemistry(char *device_chemistry, int buf_size)
{
return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR,
SB_DEVICE_CHEMISTRY, device_chemistry, buf_size);
}
int battery_device_chemistry(char *device_chemistry, int buf_size);
/* Read battery discharging current
* unit: mA

View File

@@ -31,6 +31,7 @@ test-list-$(BOARD_bolt)=
# Emulator tests
test-list-host=mutex pingpong utils kb_scan kb_mkbp lid_sw power_button hooks
test-list-host+=thermal flash queue kb_8042 extpwr_gpio console_edit system
test-list-host+=sbs_charging
console_edit-y=console_edit.o
extpwr_gpio-y=extpwr_gpio.o
@@ -46,6 +47,7 @@ pingpong-y=pingpong.o
power_button-y=power_button.o
powerdemo-y=powerdemo.o
queue-y=queue.o
sbs_charging-y=sbs_charging.o
stress-y=stress.o
system-y=system.o
thermal-y=thermal.o

112
test/sbs_charging.c Normal file
View File

@@ -0,0 +1,112 @@
/* Copyright (c) 2013 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.
*
* Test lid switch.
*/
#include "battery_pack.h"
#include "charge_state.h"
#include "chipset.h"
#include "common.h"
#include "smart_battery.h"
#include "task.h"
#include "test_util.h"
#include "util.h"
#define WAIT_CHARGER_TASK 500
static int mock_ac_present = 1;
static int mock_chipset_state = CHIPSET_STATE_ON;
static int is_shutdown;
/* Mock GPIOs */
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_AC_PRESENT)
return mock_ac_present;
return 0;
}
void chipset_force_shutdown(void)
{
is_shutdown = 1;
}
int chipset_in_state(int state_mask)
{
return state_mask & mock_chipset_state;
}
/* Setup init condition */
static void test_setup(void)
{
const struct battery_info *bat_info = battery_get_info();
/* 50% of charge */
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 50);
sb_write(SB_ABSOLUTE_STATE_OF_CHARGE, 50);
/* 25 degree Celsius */
sb_write(SB_TEMPERATURE, 250 + 2731);
/* Normal voltage */
sb_write(SB_VOLTAGE, bat_info->voltage_normal);
sb_write(SB_CHARGING_VOLTAGE, bat_info->voltage_max);
sb_write(SB_CHARGING_CURRENT, 4000);
/* Discharging at 100mAh */
sb_write(SB_CURRENT, -100);
/* Unplug AC */
mock_ac_present = 0;
}
static int wait_charging_state(void)
{
enum power_state state;
task_wake(TASK_ID_CHARGER);
msleep(WAIT_CHARGER_TASK);
state = charge_get_state();
ccprintf("[CHARGING TEST] state = %d\n", state);
return state;
}
static int test_charge_state(void)
{
enum power_state state;
state = wait_charging_state();
/* Plug AC, charging at 1000mAh */
ccprintf("[CHARGING TEST] AC on\n");
mock_ac_present = 1;
sb_write(SB_CURRENT, 1000);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_CHARGE);
/* Unplug AC, discharging at 1000mAh */
ccprintf("[CHARGING TEST] AC off\n");
mock_ac_present = 0;
sb_write(SB_CURRENT, -1000);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_DISCHARGE);
/* Discharging overtemp */
ccprintf("[CHARGING TEST] AC off, batt temp = 90 C\n");
mock_ac_present = 0;
sb_write(SB_CURRENT, -1000);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_DISCHARGE);
sb_write(SB_TEMPERATURE, CELSIUS_TO_DECI_KELVIN(90));
state = wait_charging_state();
TEST_ASSERT(is_shutdown);
TEST_ASSERT(state == PWR_STATE_DISCHARGE);
return EC_SUCCESS;
}
void run_test(void)
{
test_setup();
RUN_TEST(test_charge_state);
test_print_result();
}

View File

@@ -0,0 +1,19 @@
/* Copyright (c) 2013 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.
*/
/**
* List of enabled tasks in the priority order
*
* The first one has the lowest priority.
*
* For each task, use the macro TASK_TEST(n, r, d, s) where :
* 'n' in the name of the task
* 'r' in the main routine of the task
* 'd' in an opaque parameter passed to the routine at startup
* 's' is the stack size in bytes; must be a multiple of 8
*/
#define CONFIG_TEST_TASK_LIST \
TASK_TEST(CHARGER, charger_task, NULL, TASK_STACK_SIZE) \
TASK_TEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE)

View File

@@ -7,3 +7,4 @@
#
CFLAGS-kb_8042=-DKB_8042
CFLAGS-sbs_charging=-DSMART_BATTERY_CHARGER