Emulator support of fake GPIO input

For all GPIOs, the current values are recorded. A test can then change
the value of a GPIO input by gpio_set_level(). The changed value is
recorded and also interrupt is fired if the change fits the interrupt
flags defined in board/host/board.c.

BUG=chrome-os-partner:19235
TEST=Pass all tests
BRANCH=None

Change-Id: If8e547e5adf4a20dcb118f5fe2187293005d4ca3
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/170907
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
Vic Yang
2013-09-29 00:55:36 +08:00
committed by chrome-internal-fetch
parent 2d856c5103
commit c77575ac0d
9 changed files with 79 additions and 119 deletions

View File

@@ -4,19 +4,23 @@
*/
/* Emulator board-specific configuration */
#include "extpower.h"
#include "gpio.h"
#include "lid_switch.h"
#include "power_button.h"
#include "temp_sensor.h"
#include "util.h"
#define MOCK_GPIO(x) {#x, 0, 0, 0, 0}
#define MOCK_GPIO_INT(x, i, r) {#x, 0, 0, i, r}
const struct gpio_info gpio_list[] = {
MOCK_GPIO(EC_INT),
MOCK_GPIO(LID_OPEN),
MOCK_GPIO(POWER_BUTTON_L),
MOCK_GPIO_INT(LID_OPEN, GPIO_INT_BOTH, lid_interrupt),
MOCK_GPIO_INT(POWER_BUTTON_L, GPIO_INT_BOTH, power_button_interrupt),
MOCK_GPIO(WP),
MOCK_GPIO(ENTERING_RW),
MOCK_GPIO(AC_PRESENT),
MOCK_GPIO_INT(AC_PRESENT, GPIO_INT_BOTH, extpower_interrupt),
MOCK_GPIO(PCH_BKLTEN),
MOCK_GPIO(ENABLE_BACKLIGHT),
};

View File

@@ -5,8 +5,15 @@
/* GPIO module for emulator */
#include "console.h"
#include "common.h"
#include "gpio.h"
#include "timer.h"
#include "util.h"
static int gpio_values[GPIO_COUNT];
static int gpio_interrupt_enabled[GPIO_COUNT];
test_mockable void gpio_pre_init(void)
{
@@ -15,16 +22,42 @@ test_mockable void gpio_pre_init(void)
test_mockable int gpio_get_level(enum gpio_signal signal)
{
return gpio_values[signal];
}
static int gpio_interrupt_check(uint32_t flags, int old, int new)
{
if ((flags & (GPIO_INT_F_RISING|GPIO_INT_F_BOTH)) &&
old == 0 && new == 1)
return 1;
if ((flags & (GPIO_INT_F_FALLING|GPIO_INT_F_BOTH)) &&
old == 1 && new == 0)
return 1;
if ((flags & GPIO_INT_F_LOW) && new == 0)
return 1;
if ((flags & GPIO_INT_F_HIGH) && new == 1)
return 1;
return 0;
}
test_mockable void gpio_set_level(enum gpio_signal signal, int value)
{
/* Nothing */
const struct gpio_info *g = gpio_list + signal;
const uint32_t flags = g->flags;
const int old_value = gpio_values[signal];
gpio_values[signal] = value;
if (g->irq_handler == NULL || !gpio_interrupt_enabled[signal])
return;
if (gpio_interrupt_check(flags, old_value, value))
g->irq_handler(signal);
}
test_mockable int gpio_enable_interrupt(enum gpio_signal signal)
{
gpio_interrupt_enabled[signal] = 1;
return EC_SUCCESS;
}

View File

@@ -22,14 +22,13 @@
#include "adapter_externs.h"
/* Local state */
static int mock_ac;
static int mock_id;
static int mock_current;
static struct power_state_context ctx;
static void test_reset_mocks(void)
{
mock_ac = 0;
gpio_set_level(GPIO_AC_PRESENT, 0);
mock_id = 0;
mock_current = 0;
memset(&ctx, 0, sizeof(ctx));
@@ -37,13 +36,6 @@ static void test_reset_mocks(void)
/* Mocked functions from the rest of the EC */
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_AC_PRESENT)
return mock_ac;
return 0;
}
int adc_read_channel(enum adc_channel ch)
{
switch (ch) {
@@ -83,8 +75,7 @@ void chipset_throttle_cpu(int throttle)
static void change_ac(int val)
{
mock_ac = val;
extpower_interrupt(GPIO_AC_PRESENT);
gpio_set_level(GPIO_AC_PRESENT, val);
msleep(50);
}
@@ -183,6 +174,7 @@ static int test_turbo(void)
TEST_ASSERT(ac_turbo == 0);
test_turbo_init();
change_ac(0);
set_id(ad_id_vals[1].lo - 1);
change_ac(1);
watch_adapter_closely(&ctx);

View File

@@ -15,22 +15,11 @@
#include "timer.h"
#include "util.h"
static int mock_ac;
static int ac_hook_count;
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_AC_PRESENT)
return mock_ac;
return 0;
}
static void set_ac(int val)
{
if (val == mock_ac)
return;
mock_ac = val;
extpower_interrupt(GPIO_AC_PRESENT);
gpio_set_level(GPIO_AC_PRESENT, val);
msleep(50);
}

View File

@@ -29,8 +29,6 @@ static unsigned int lpc_char_cnt;
/*****************************************************************************/
/* Mock functions */
static int mock_power_button = 1;
int lid_is_open(void)
{
return 1;
@@ -41,13 +39,6 @@ void lpc_keyboard_put_char(uint8_t chr, int send_irq)
lpc_char_buf[lpc_char_cnt++] = chr;
}
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_POWER_BUTTON_L)
return mock_power_button;
return 0;
}
/*****************************************************************************/
/* Test utilities */
@@ -209,33 +200,27 @@ static int test_power_button(void)
set_scancode(1);
test_chipset_on();
mock_power_button = 0;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 0);
VERIFY_LPC_CHAR_DELAY("\xe0\x5e", 100);
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
VERIFY_LPC_CHAR_DELAY("\xe0\xde", 100);
set_scancode(2);
write_cmd_byte(read_cmd_byte() & ~I8042_XLATE);
mock_power_button = 0;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 0);
VERIFY_LPC_CHAR_DELAY("\xe0\x37", 100);
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
VERIFY_LPC_CHAR_DELAY("\xe0\xf0\x37", 100);
test_chipset_off();
mock_power_button = 0;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 0);
VERIFY_NO_CHAR();
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
VERIFY_NO_CHAR();
return EC_SUCCESS;

View File

@@ -24,7 +24,6 @@ static uint8_t lp5562_reg[LP5562_NUM_WATCH_REG];
#define LED_COLOR_YELLOW LP5562_COLOR_BLUE(0x40)
#define LED_COLOR_RED LP5562_COLOR_RED(0x80)
static int mock_ac;
static enum charging_state mock_charge_state = ST_IDLE;
static int lp5562_failed_i2c_reg = -1;
static const char * const state_names[] = POWER_STATE_NAME_TABLE;
@@ -32,16 +31,9 @@ static const char * const state_names[] = POWER_STATE_NAME_TABLE;
/*****************************************************************************/
/* Mock functions */
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_AC_PRESENT)
return mock_ac;
return 0;
}
static void set_ac(int ac)
{
mock_ac = ac;
gpio_set_level(GPIO_AC_PRESENT, ac);
ccprintf("[%T TEST AC = %d]\n", ac);
}

View File

@@ -7,6 +7,7 @@
#include "common.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "lid_switch.h"
@@ -14,16 +15,8 @@
#include "timer.h"
#include "util.h"
static int mock_lid;
static int lid_hook_count;
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_LID_OPEN)
return mock_lid;
return 0;
}
static void lid_change_hook(void)
{
lid_hook_count++;
@@ -39,14 +32,12 @@ int lid_memmap_state(void)
static int test_hook(void)
{
/* Close lid for testing */
mock_lid = 0;
lid_interrupt(GPIO_LID_OPEN);
gpio_set_level(GPIO_LID_OPEN, 0);
msleep(100);
lid_hook_count = 0;
host_clear_events(0xffffffff);
mock_lid = 1;
lid_interrupt(GPIO_LID_OPEN);
gpio_set_level(GPIO_LID_OPEN, 1);
msleep(50);
TEST_ASSERT(lid_hook_count == 1);
TEST_ASSERT(lid_is_open());
@@ -54,8 +45,7 @@ static int test_hook(void)
TEST_ASSERT(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN));
mock_lid = 0;
lid_interrupt(GPIO_LID_OPEN);
gpio_set_level(GPIO_LID_OPEN, 0);
msleep(50);
TEST_ASSERT(lid_hook_count == 2);
TEST_ASSERT(!lid_is_open());
@@ -69,14 +59,12 @@ static int test_hook(void)
static int test_debounce(void)
{
/* Close lid for testing */
mock_lid = 0;
lid_interrupt(GPIO_LID_OPEN);
gpio_set_level(GPIO_LID_OPEN, 0);
msleep(100);
lid_hook_count = 0;
host_clear_events(0xffffffff);
mock_lid = 1;
lid_interrupt(GPIO_LID_OPEN);
gpio_set_level(GPIO_LID_OPEN, 1);
msleep(20);
TEST_ASSERT(lid_hook_count == 0);
TEST_ASSERT(!lid_is_open());
@@ -84,8 +72,7 @@ static int test_debounce(void)
TEST_ASSERT(!(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)));
mock_lid = 0;
lid_interrupt(GPIO_LID_OPEN);
gpio_set_level(GPIO_LID_OPEN, 0);
msleep(50);
TEST_ASSERT(lid_hook_count == 0);
TEST_ASSERT(!lid_is_open());

View File

@@ -7,6 +7,7 @@
#include "common.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "power_button.h"
@@ -14,20 +15,11 @@
#include "timer.h"
#include "util.h"
static int mock_power_button = 1;
static int mock_lid = 1;
static int pb_hook_count;
int gpio_get_level(enum gpio_signal signal)
{
if (signal == GPIO_POWER_BUTTON_L)
return mock_power_button;
return 0;
}
int lid_is_open(void)
{
return mock_lid;
return 1;
}
static void pb_change_hook(void)
@@ -45,14 +37,12 @@ int pb_memmap_state(void)
static int test_hook(void)
{
/* Release power button for testing */
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
msleep(100);
pb_hook_count = 0;
host_clear_events(0xffffffff);
mock_power_button = 0;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 0);
msleep(50);
TEST_ASSERT(pb_hook_count == 1);
TEST_ASSERT(power_button_is_pressed());
@@ -61,8 +51,7 @@ static int test_hook(void)
EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON));
host_clear_events(0xffffffff);
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
msleep(50);
TEST_ASSERT(pb_hook_count == 2);
TEST_ASSERT(!power_button_is_pressed());
@@ -76,14 +65,12 @@ static int test_hook(void)
static int test_debounce(void)
{
/* Release power button for testing */
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
msleep(100);
pb_hook_count = 0;
host_clear_events(0xffffffff);
mock_power_button = 0;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 0);
msleep(20);
TEST_ASSERT(pb_hook_count == 0);
TEST_ASSERT(!power_button_is_pressed());
@@ -91,8 +78,7 @@ static int test_debounce(void)
TEST_ASSERT(!(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)));
mock_power_button = 1;
power_button_interrupt(GPIO_POWER_BUTTON_L);
gpio_set_level(GPIO_POWER_BUTTON_L, 1);
msleep(50);
TEST_ASSERT(pb_hook_count == 0);
TEST_ASSERT(!power_button_is_pressed());

View File

@@ -10,6 +10,7 @@
#include "chipset.h"
#include "common.h"
#include "ec_commands.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "smart_battery.h"
@@ -20,20 +21,11 @@
#define WAIT_CHARGER_TASK 500
#define BATTERY_DETACH_DELAY 35000
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;
@@ -72,7 +64,7 @@ static void test_setup(void)
/* Discharging at 100mAh */
sb_write(SB_CURRENT, -100);
/* Unplug AC */
mock_ac_present = 0;
gpio_set_level(GPIO_AC_PRESENT, 0);
}
static int wait_charging_state(void)
@@ -100,7 +92,7 @@ static int test_charge_state(void)
state = wait_charging_state();
/* Plug AC, charging at 1000mAh */
ccprintf("[CHARGING TEST] AC on\n");
mock_ac_present = 1;
gpio_set_level(GPIO_AC_PRESENT, 1);
sb_write(SB_CURRENT, 1000);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_CHARGE);
@@ -121,14 +113,14 @@ static int test_charge_state(void)
/* Unplug AC, discharging at 1000mAh */
ccprintf("[CHARGING TEST] AC off\n");
mock_ac_present = 0;
gpio_set_level(GPIO_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;
gpio_set_level(GPIO_AC_PRESENT, 0);
sb_write(SB_CURRENT, -1000);
state = wait_charging_state();
@@ -141,7 +133,7 @@ static int test_charge_state(void)
/* Force idle */
ccprintf("[CHARGING TEST] AC on, force idle\n");
mock_ac_present = 1;
gpio_set_level(GPIO_AC_PRESENT, 1);
sb_write(SB_CURRENT, 1000);
state = wait_charging_state();
TEST_ASSERT(state == PWR_STATE_CHARGE);
@@ -154,7 +146,7 @@ static int test_charge_state(void)
/* Force discharge */
ccprintf("[CHARGING TEST] AC on, force discharge\n");
mock_ac_present = 1;
gpio_set_level(GPIO_AC_PRESENT, 1);
sb_write(SB_CURRENT, 1000);
charge_control(CHARGE_CONTROL_DISCHARGE);
state = wait_charging_state();
@@ -171,7 +163,7 @@ static int test_charge_state(void)
static int test_low_battery(void)
{
ccprintf("[CHARGING TEST] Low battery with AC\n");
mock_ac_present = 1;
gpio_set_level(GPIO_AC_PRESENT, 1);
is_hibernated = 0;
sb_write(SB_CURRENT, 1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
@@ -184,7 +176,7 @@ static int test_low_battery(void)
mock_chipset_state = CHIPSET_STATE_ON;
hook_notify(HOOK_CHIPSET_PRE_INIT);
hook_notify(HOOK_CHIPSET_STARTUP);
mock_ac_present = 0;
gpio_set_level(GPIO_AC_PRESENT, 0);
is_hibernated = 0;
sb_write(SB_CURRENT, -1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
@@ -205,10 +197,10 @@ static int test_low_battery(void)
is_shutdown = 0;
mock_chipset_state = CHIPSET_STATE_ON;
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 10);
mock_ac_present = 1;
gpio_set_level(GPIO_AC_PRESENT, 1);
sb_write(SB_CURRENT, 1000);
wait_charging_state();
mock_ac_present = 0;
gpio_set_level(GPIO_AC_PRESENT, 0);
sb_write(SB_CURRENT, -1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
@@ -225,7 +217,7 @@ static int test_batt_fake(void)
mock_chipset_state = CHIPSET_STATE_ON;
hook_notify(HOOK_CHIPSET_PRE_INIT);
hook_notify(HOOK_CHIPSET_STARTUP);
mock_ac_present = 0;
gpio_set_level(GPIO_AC_PRESENT, 0);
is_hibernated = 0;
sb_write(SB_CURRENT, -1000);
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 30);