charge_manager: add option to charge from dual-role devices

Add option to charge automatically from dual-role devices. This
also changes the charge override behavior such that any new
device attached will clear the override because any new source
is a potential device we might charge from.

BUG=chrome-os-partner:44958
BRANCH=smaug
TEST=tested charge_manager unittests with
CONFIG_CHARGE_MANAGER_DRP_CHARGING both defined and undefined

Change-Id: Iac77ff0c501826d5fb5a9d50f88399ebc3955b87
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/297789
Reviewed-by: Shawn N <shawnn@chromium.org>
This commit is contained in:
Alec Berg
2015-09-06 20:29:08 -07:00
committed by chrome-bot
parent 490e8a482f
commit ebfdb59702
6 changed files with 118 additions and 26 deletions

View File

@@ -140,7 +140,7 @@ static int charge_manager_is_seeded(void)
return 1;
}
#ifndef TEST_CHARGE_MANAGER
#ifndef TEST_BUILD
/**
* Fills passed power_info structure with current info about the passed port.
*/
@@ -273,7 +273,7 @@ static void charge_manager_fill_power_info(int port,
r->meas.voltage_now = adc_read_channel(ADC_VBUS);
}
}
#endif /* TEST_CHARGE_MANAGER */
#endif /* TEST_BUILD */
#ifdef CONFIG_USB_PD_LOGGING
/**
@@ -384,6 +384,7 @@ static void charge_manager_get_best_charge_port(int *new_port,
override_port != j)
continue;
#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/*
* Don't charge from a dual-role port unless
* it is our override port.
@@ -391,6 +392,7 @@ static void charge_manager_get_best_charge_port(int *new_port,
if (dualrole_capability[j] != CAP_DEDICATED &&
override_port != j)
continue;
#endif
candidate_port_power =
POWER(available_charge[i][j]);
@@ -609,7 +611,9 @@ static void charge_manager_make_change(enum charge_manager_change_type change,
* Ignore all except for transition to non-dualrole,
* which may occur some time after we see a charge
*/
#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
if (dualrole_capability[port] != CAP_DEDICATED)
#endif
return;
/* Clear override only if a charge is present on the port */
for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
@@ -626,9 +630,13 @@ static void charge_manager_make_change(enum charge_manager_change_type change,
break;
}
/* Remove override when a dedicated charger is plugged */
if (clear_override && override_port != port &&
dualrole_capability[port] == CAP_DEDICATED) {
/* Remove override when a charger is plugged */
if (clear_override && override_port != port
#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* only remove override when it's a dedicated charger */
&& dualrole_capability[port] == CAP_DEDICATED
#endif
) {
charge_manager_cleanup_override_port(override_port);
override_port = OVERRIDE_OFF;
if (delayed_override_port != OVERRIDE_OFF) {
@@ -797,7 +805,7 @@ int charge_manager_get_active_charge_port(void)
return charge_port;
}
#ifndef TEST_CHARGE_MANAGER
#ifndef TEST_BUILD
static int hc_pd_power_info(struct host_cmd_handler_args *args)
{
const struct ec_params_usb_pd_power_info *p = args->params;
@@ -816,7 +824,7 @@ static int hc_pd_power_info(struct host_cmd_handler_args *args)
DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO,
hc_pd_power_info,
EC_VER_MASK(0));
#endif /* TEST_CHARGE_MANAGER */
#endif /* TEST_BUILD */
static int hc_charge_port_override(struct host_cmd_handler_args *args)
{

View File

@@ -262,6 +262,9 @@
/* Compile charge manager */
#undef CONFIG_CHARGE_MANAGER
/* Allow charge manager to default to charging from dual-role partners */
#undef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Handle the external power limit host command in charge manager */
#undef CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT

View File

@@ -37,13 +37,14 @@ test-list-host+=sbs_charging host_command
test-list-host+=bklight_lid bklight_passthru interrupt timer_dos button
test-list-host+=math_util sbs_charging_v2 battery_get_params_smart
test-list-host+=lightbar inductive_charging usb_pd fan charge_manager
test-list-host+=charge_ramp
test-list-host+=charge_manager_drp_charging charge_ramp
battery_get_params_smart-y=battery_get_params_smart.o
bklight_lid-y=bklight_lid.o
bklight_passthru-y=bklight_passthru.o
button-y=button.o
charge_manager-y=charge_manager.o
charge_manager_drp_charging-y=charge_manager.o
charge_ramp-y+=charge_ramp.o
console_edit-y=console_edit.o
extpwr_gpio-y=extpwr_gpio.o

View File

@@ -463,17 +463,21 @@ static int test_dual_role(void)
/* Initialize table to no charge. */
initialize_charge_table(0, 5000, 1000);
/*
* Mark P0 as dual-role and set a charge. Verify that we don't charge
* from the port.
*/
/* Mark P0 as dual-role and set a charge. */
charge_manager_update_dualrole(0, CAP_DUALROLE);
charge.current = 500;
charge.voltage = 5000;
charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Verify we do charge from dual-role port */
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 500);
#else
/* Verify we don't charge from dual-role port */
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
TEST_ASSERT(active_charge_limit == 0);
#endif
/* Mark P0 as the override port, verify that we now charge. */
charge_manager_set_override(0);
@@ -482,12 +486,17 @@ static int test_dual_role(void)
TEST_ASSERT(active_charge_limit == 500);
TEST_ASSERT(pd_get_role(0) == PD_ROLE_SINK);
/* Remove override and verify we go back to not charging */
/* Remove override and verify we go back to previous state */
charge_manager_set_override(OVERRIDE_OFF);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 500);
#else
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
TEST_ASSERT(active_charge_limit == 0);
TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE);
#endif
/* Mark P0 as the override port, verify that we again charge. */
charge_manager_set_override(0);
@@ -530,9 +539,14 @@ static int test_dual_role(void)
charge.current = 400;
charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 1, &charge);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 600);
#else
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 400);
TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE);
#endif
/*
* Verify the port is handled normally if the dual-role source is
@@ -548,8 +562,8 @@ static int test_dual_role(void)
TEST_ASSERT(active_charge_limit == 500);
/*
* Verify that we charge from the dedicated port if a dual-role
* source is also attached.
* Test one port connected to dedicated charger and one connected
* to dual-role device.
*/
charge_manager_update_dualrole(0, CAP_DUALROLE);
charge.current = 0;
@@ -559,9 +573,19 @@ static int test_dual_role(void)
charge.current = 200;
charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 1, &charge);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Verify we charge from port with higher priority */
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 500);
#else
/*
* Verify that we charge from the dedicated port if a dual-role
* source is also attached.
*/
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 200);
TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE);
#endif
return EC_SUCCESS;
}
@@ -605,19 +629,23 @@ static int test_unknown_dualrole_capability(void)
struct charge_port_info charge;
/* Initialize table to no charge. */
initialize_charge_table(0, 5000, 1000);
initialize_charge_table(0, 5000, 2000);
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
/*
* Set a charge on P0 with unknown dualrole capability,
* verify that we don't charge from the port.
*/
/* Set a charge on P0 with unknown dualrole capability, */
charge.current = 500;
charge.voltage = 5000;
charge_manager_update_dualrole(0, CAP_UNKNOWN);
charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Verify we do charge from that port */
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 500);
#else
/* Verify that we don't charge from the port. */
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
#endif
/* Toggle to dedicated and verify port becomes active. */
charge_manager_update_dualrole(0, CAP_DEDICATED);
@@ -629,14 +657,24 @@ static int test_unknown_dualrole_capability(void)
charge_manager_update_dualrole(1, CAP_DUALROLE);
charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 1, &charge);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 1000);
#else
TEST_ASSERT(active_charge_port == 0);
#endif
/* Remove charger on port 0 */
charge.current = 0;
charge_manager_update_dualrole(0, CAP_UNKNOWN);
charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 1000);
#else
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
#endif
/* Set override to charge on port 1 */
charge_manager_set_override(1);
@@ -651,26 +689,43 @@ static int test_unknown_dualrole_capability(void)
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 1);
/*
* Insert UNKNOWN capability charger on port 0, verify that override
* is still kept.
*/
/* Insert UNKNOWN capability charger on port 0 */
charge_manager_update_dualrole(0, CAP_UNKNOWN);
charge.current = 2000;
charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge);
wait_for_charge_manager_refresh();
wait_for_charge_manager_refresh();
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Verify override is removed */
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 2000);
#else
/* Verify override is still kept */
TEST_ASSERT(active_charge_port == 1);
#endif
/* Toggle to dualrole, verify that override is still kept. */
/* Toggle to dualrole */
charge_manager_update_dualrole(0, CAP_DUALROLE);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Verify no change */
TEST_ASSERT(active_charge_port == 0);
#else
/* Verify override is still kept */
TEST_ASSERT(active_charge_port == 1);
#endif
/* Toggle to dedicated, verify that override is removed. */
/* Toggle to dedicated */
charge_manager_update_dualrole(0, CAP_UNKNOWN);
wait_for_charge_manager_refresh();
#ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING
/* Verify no change */
TEST_ASSERT(active_charge_port == 0);
#else
/* Verify override is still kept */
TEST_ASSERT(active_charge_port == 1);
#endif
charge_manager_update_dualrole(0, CAP_DEDICATED);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 0);

View File

@@ -0,0 +1,17 @@
/* Copyright 2015 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 /* No test task */

View File

@@ -118,6 +118,14 @@ int bd99992gw_get_temp(uint16_t adc);
#ifdef TEST_CHARGE_MANAGER
#define CONFIG_CHARGE_MANAGER
#undef CONFIG_CHARGE_MANAGER_DRP_CHARGING
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_PORT_COUNT 2
#endif
#ifdef TEST_CHARGE_MANAGER_DRP_CHARGING
#define CONFIG_CHARGE_MANAGER
#define CONFIG_CHARGE_MANAGER_DRP_CHARGING
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_PORT_COUNT 2
#endif