Files
OpenCellular/test/sbs_charging.c
Vic Yang 4bdfc7eb7b Add more charge state machine test
This includes:
  - Charge mode control host command
  - Low battery shutdown/hibernate

Also, speed up the test by 20x since we now need to wait for more than
30 seconds for low battery state test.

BUG=chrome-os-partner:19236
TEST=Pass the test
BRANCH=None

Change-Id: If2e91a33f3a80f58da01a6c3da128cb603101dea
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/167613
Reviewed-by: Rong Chang <rongchang@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2013-09-04 20:32:33 +00:00

237 lines
5.9 KiB
C

/* 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 "ec_commands.h"
#include "hooks.h"
#include "host_command.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;
static int is_force_discharge;
static int is_hibernated;
/* 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;
}
int board_discharge_on_ac(int enabled)
{
is_force_discharge = enabled;
return EC_SUCCESS;
}
void system_hibernate(int sec, int usec)
{
is_hibernated = 1;
}
/* 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 charge_control(enum ec_charge_control_mode mode)
{
struct ec_params_charge_control params;
params.mode = mode;
return test_send_host_command(EC_CMD_CHARGE_CONTROL, 1, &params,
sizeof(params), NULL, 0);
}
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);
sb_write(SB_TEMPERATURE, CELSIUS_TO_DECI_KELVIN(40));
/* Force idle */
ccprintf("[CHARGING TEST] AC on, force idle\n");
mock_ac_present = 1;
sb_write(SB_CURRENT, 1000);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_CHARGE);
charge_control(CHARGE_CONTROL_IDLE);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_IDLE);
charge_control(CHARGE_CONTROL_NORMAL);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_CHARGE);
/* Force discharge */
ccprintf("[CHARGING TEST] AC on, force discharge\n");
mock_ac_present = 1;
sb_write(SB_CURRENT, 1000);
charge_control(CHARGE_CONTROL_DISCHARGE);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_IDLE);
TEST_ASSERT(is_force_discharge);
charge_control(CHARGE_CONTROL_NORMAL);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_CHARGE);
TEST_ASSERT(!is_force_discharge);
return EC_SUCCESS;
}
static int test_low_battery(void)
{
ccprintf("[CHARGING TEST] Low battery with AC\n");
mock_ac_present = 1;
is_hibernated = 0;
sb_write(SB_CURRENT, 1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
mock_chipset_state = CHIPSET_STATE_SOFT_OFF;
hook_notify(HOOK_CHIPSET_SHUTDOWN);
TEST_ASSERT(!is_hibernated);
ccprintf("[CHARGING TEST] Low battery shutdown S0->S5\n");
mock_chipset_state = CHIPSET_STATE_ON;
hook_notify(HOOK_CHIPSET_PRE_INIT);
hook_notify(HOOK_CHIPSET_STARTUP);
mock_ac_present = 0;
is_hibernated = 0;
sb_write(SB_CURRENT, -1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
mock_chipset_state = CHIPSET_STATE_SOFT_OFF;
hook_notify(HOOK_CHIPSET_SHUTDOWN);
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery shutdown S5\n");
is_hibernated = 0;
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 10);
wait_charging_state();
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery AP shutdown\n");
is_shutdown = 0;
mock_chipset_state = CHIPSET_STATE_ON;
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 10);
mock_ac_present = 1;
sb_write(SB_CURRENT, 1000);
wait_charging_state();
mock_ac_present = 0;
sb_write(SB_CURRENT, -1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
usleep(32 * SECOND);
wait_charging_state();
TEST_ASSERT(is_shutdown);
return EC_SUCCESS;
}
static int test_batt_fake(void)
{
ccprintf("[CHARGING TEST] Fake battery command\n");
mock_chipset_state = CHIPSET_STATE_ON;
hook_notify(HOOK_CHIPSET_PRE_INIT);
hook_notify(HOOK_CHIPSET_STARTUP);
mock_ac_present = 0;
is_hibernated = 0;
sb_write(SB_CURRENT, -1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 30);
wait_charging_state();
UART_INJECT("battfake 2\n");
msleep(50);
mock_chipset_state = CHIPSET_STATE_SOFT_OFF;
hook_notify(HOOK_CHIPSET_SHUTDOWN);
TEST_ASSERT(is_hibernated);
return EC_SUCCESS;
}
void run_test(void)
{
test_setup();
RUN_TEST(test_charge_state);
RUN_TEST(test_low_battery);
RUN_TEST(test_batt_fake);
test_print_result();
}