diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2014-12-17 10:36:48 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-12-17 22:26:56 +0000 |
commit | 86835f7067b7ce26431ca459be3d59662736275f (patch) | |
tree | 29157fcda8227315f537cdb4168549344ba7421e | |
parent | ec12acc81f47e9b88517cd4a955414f7a1ee1cf6 (diff) | |
download | chrome-ec-86835f7067b7ce26431ca459be3d59662736275f.tar.gz |
charge_manager: Allow board to reject a selected charge port
Modify board_set_active_charge_port to return status indicating whether
the selected charge port was rejected. If rejected, zero out its
available charge and attempt to select a different charge port.
Also, reduce the length of related console prints.
BUG=chrome-os-partner:34677
TEST=Manual on Samus. Plug C-to-Arec into port 1, verify that charge
manager does not select port 1 as active and charging icon is not seen
in OS.
BRANCH=Samus.
Change-Id: I56e3337f90c04b93ef7cc9873af6ee0f4b1ffc7d
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/236361
Reviewed-by: Alec Berg <alecaberg@chromium.org>
-rw-r--r-- | board/host/board.h | 6 | ||||
-rw-r--r-- | board/samus_pd/board.c | 16 | ||||
-rw-r--r-- | board/samus_pd/board.h | 6 | ||||
-rw-r--r-- | common/charge_manager.c | 77 | ||||
-rw-r--r-- | include/charge_manager.h | 13 | ||||
-rw-r--r-- | test/charge_manager.c | 50 |
6 files changed, 126 insertions, 42 deletions
diff --git a/board/host/board.h b/board/host/board.h index 0ae8e0c452..d33a4a56dc 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -56,10 +56,4 @@ enum charge_supplier { /* supplier_priority table defined in board.c */ extern const int supplier_priority[]; -/* Set the active charge port. */ -void board_set_active_charge_port(int charge_port); - -/* Set the charge current limit. */ -void board_set_charge_limit(int charge_ma); - #endif /* __BOARD_H */ diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c index 96070fa0cf..c9432e3efd 100644 --- a/board/samus_pd/board.c +++ b/board/samus_pd/board.c @@ -485,18 +485,24 @@ static void pd_send_ec_int(void) * Set active charge port -- only one port can be active at a time. * * @param charge_port Charge port to enable. + * + * Returns EC_SUCCESS if charge port is accepted and made active, + * EC_ERROR_* otherwise. */ -void board_set_active_charge_port(int charge_port) +int board_set_active_charge_port(int charge_port) { if (charge_port >= 0 && charge_port < PD_PORT_COUNT && pd_get_role(charge_port) != PD_ROLE_SINK) { - CPRINTS("Port %d is not a sink, skipping enable", charge_port); - charge_port = CHARGE_PORT_NONE; + CPRINTS("Skip enable p%d", charge_port); + return EC_ERROR_INVAL; } + pd_status.active_charge_port = charge_port; gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, !(charge_port == 0)); gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, !(charge_port == 1)); - CPRINTS("Set active charge port %d", charge_port); + + CPRINTS("New chg p%d", charge_port); + return EC_SUCCESS; } /** @@ -517,7 +523,7 @@ void board_set_charge_limit(int charge_ma) pd_status.curr_lim_ma = charge_ma; pd_send_ec_int(); - CPRINTS("Set ilim duty %d", pwm_duty); + CPRINTS("New ilim %d", charge_ma); } /* Send host event up to AP */ diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h index 931876df27..05233d3b09 100644 --- a/board/samus_pd/board.h +++ b/board/samus_pd/board.h @@ -123,12 +123,6 @@ void board_update_battery_soc(int soc); /* Get the last received battery level. */ int board_get_battery_soc(void); -/* Set the active charge port. */ -void board_set_active_charge_port(int charge_port); - -/* Set the charge current limit. */ -void board_set_charge_limit(int charge_ma); - /* Send host event to AP */ void pd_send_host_event(int mask); diff --git a/common/charge_manager.c b/common/charge_manager.c index b2ef55a796..364681abe9 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -87,17 +87,15 @@ static int charge_manager_is_seeded(void) } /** - * Charge manager refresh -- responsible for selecting the active charge port - * and charge power. Called as a deferred task. + * Select the 'best' charge port, as defined by the supplier heirarchy and the + * ability of the port to provide power. */ -static void charge_manager_refresh(void) +static void charge_manager_get_best_charge_port(int *new_port, + int *new_supplier) { - int new_supplier = CHARGE_SUPPLIER_NONE; - int new_port = CHARGE_PORT_NONE; - int new_charge_current, new_charge_current_uncapped; - int new_charge_voltage, i, j; - int updated_new_port = CHARGE_PORT_NONE; - int updated_old_port = CHARGE_PORT_NONE; + int supplier = CHARGE_SUPPLIER_NONE; + int port = CHARGE_PORT_NONE; + int i, j; /* Skip port selection on OVERRIDE_DONT_CHARGE. */ if (override_port != OVERRIDE_DONT_CHARGE) { @@ -115,7 +113,7 @@ static void charge_manager_refresh(void) * charge on another override port. */ if (override_port != OVERRIDE_OFF && - override_port == new_port && + override_port == port && override_port != j) continue; @@ -129,27 +127,62 @@ static void charge_manager_refresh(void) if (available_charge[i][j].current > 0 && available_charge[i][j].voltage > 0 && - (new_supplier == CHARGE_SUPPLIER_NONE || + (supplier == CHARGE_SUPPLIER_NONE || supplier_priority[i] < - supplier_priority[new_supplier] || + supplier_priority[supplier] || (j == override_port && - new_port != override_port) || + port != override_port) || (supplier_priority[i] == - supplier_priority[new_supplier] && + supplier_priority[supplier] && POWER(available_charge[i][j]) > - POWER(available_charge[new_supplier] - [new_port])))) { - new_supplier = i; - new_port = j; + POWER(available_charge[supplier][port])))) { + supplier = i; + port = j; } } /* Clear override if no charge is available on override port */ if (override_port != OVERRIDE_OFF && - override_port != new_port) + override_port != port) override_port = OVERRIDE_OFF; } + *new_port = port; + *new_supplier = supplier; +} + +/** + * Charge manager refresh -- responsible for selecting the active charge port + * and charge power. Called as a deferred task. + */ +static void charge_manager_refresh(void) +{ + int new_supplier, new_port; + int new_charge_current, new_charge_current_uncapped; + int new_charge_voltage, i; + int updated_new_port = CHARGE_PORT_NONE; + int updated_old_port = CHARGE_PORT_NONE; + + /* Hunt for an acceptable charge port */ + while (1) { + charge_manager_get_best_charge_port(&new_port, &new_supplier); + + /* If the port changed, attempt to switch to it */ + if (new_port == charge_port || + board_set_active_charge_port(new_port) == EC_SUCCESS) + break; + + /* 'Dont charge' request must be accepted */ + ASSERT(new_port != CHARGE_PORT_NONE); + + /* + * Zero the available charge on the rejected port so that + * it is no longer chosen. + */ + for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) + available_charge[i][new_port].current = 0; + } + if (new_supplier == CHARGE_SUPPLIER_NONE) { new_charge_current = 0; new_charge_current_uncapped = 0; @@ -170,11 +203,9 @@ static void charge_manager_refresh(void) /* Change the charge limit + charge port if modified. */ if (new_port != charge_port || new_charge_current != charge_current) { - CPRINTS("New charge limit: supplier %d port %d current %d " - "voltage %d", new_supplier, new_port, - new_charge_current, new_charge_voltage); board_set_charge_limit(new_charge_current); - board_set_active_charge_port(new_port); + CPRINTS("CL: p%d s%d i%d v%d", new_supplier, new_port, + new_charge_current, new_charge_voltage); } /* diff --git a/include/charge_manager.h b/include/charge_manager.h index 9cd0abeefb..d1ee472a50 100644 --- a/include/charge_manager.h +++ b/include/charge_manager.h @@ -35,7 +35,18 @@ int charge_manager_set_override(int port); /* Returns the current active charge port, as determined by charge manager */ int charge_manager_get_active_charge_port(void); -/* Board-level callback, called on delayed override timeout */ +/* Board-level callback functions */ + +/* + * Set the active charge port. Returns EC_SUCCESS if the charge port is + * accepted, returns ec_error_list status otherwise. + */ +int board_set_active_charge_port(int charge_port); + +/* Set the charge current limit. */ +void board_set_charge_limit(int charge_ma); + +/* Called on delayed override timeout */ void board_charge_manager_override_timeout(void); #endif /* __CHARGE_MANAGER_H */ diff --git a/test/charge_manager.c b/test/charge_manager.c index ead8a6d9e0..fc184bebea 100644 --- a/test/charge_manager.c +++ b/test/charge_manager.c @@ -32,6 +32,7 @@ BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT); static unsigned int active_charge_limit = CHARGE_SUPPLIER_NONE; static unsigned int active_charge_port = CHARGE_PORT_NONE; +static unsigned int charge_port_to_reject = CHARGE_PORT_NONE; static int new_power_request[PD_PORT_COUNT]; static int dual_role_capable[PD_PORT_COUNT]; static int power_role[PD_PORT_COUNT]; @@ -47,9 +48,20 @@ void board_set_charge_limit(int charge_ma) active_charge_limit = charge_ma; } -void board_set_active_charge_port(int charge_port) +/* Sets a charge port that will be rejected as the active port. */ +static void set_charge_port_to_reject(int port) { + charge_port_to_reject = port; +} + +int board_set_active_charge_port(int charge_port) +{ + if (charge_port != CHARGE_PORT_NONE && + charge_port == charge_port_to_reject) + return EC_ERROR_INVAL; + active_charge_port = charge_port; + return EC_SUCCESS; } void board_charge_manager_override_timeout(void) @@ -112,6 +124,7 @@ static void initialize_charge_table(int current, int voltage, int ceil) struct charge_port_info charge; charge_manager_set_override(OVERRIDE_OFF); + set_charge_port_to_reject(CHARGE_PORT_NONE); charge.current = current; charge.voltage = voltage; @@ -487,6 +500,40 @@ static int test_dual_role(void) return EC_SUCCESS; } +static int test_rejected_port(void) +{ + struct charge_port_info charge; + + /* Initialize table to no charge. */ + initialize_charge_table(0, 5000, 1000); + TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); + + /* Set a charge on P0. */ + charge.current = 500; + charge.voltage = 5000; + charge_manager_update(CHARGE_SUPPLIER_TEST2, 0, &charge); + wait_for_charge_manager_refresh(); + TEST_ASSERT(active_charge_port == 0); + TEST_ASSERT(active_charge_limit == 500); + + /* Set P0 as rejected, and verify that it doesn't become active. */ + set_charge_port_to_reject(1); + charge.current = 1000; + charge_manager_update(CHARGE_SUPPLIER_TEST1, 1, &charge); + wait_for_charge_manager_refresh(); + TEST_ASSERT(active_charge_port == 0); + TEST_ASSERT(active_charge_limit == 500); + + /* Don't reject P0, and verify it can become active. */ + set_charge_port_to_reject(CHARGE_PORT_NONE); + charge_manager_update(CHARGE_SUPPLIER_TEST1, 1, &charge); + wait_for_charge_manager_refresh(); + TEST_ASSERT(active_charge_port == 1); + TEST_ASSERT(active_charge_limit == 1000); + + return EC_SUCCESS; +} + void run_test(void) { test_reset(); @@ -497,6 +544,7 @@ void run_test(void) RUN_TEST(test_new_power_request); RUN_TEST(test_override); RUN_TEST(test_dual_role); + RUN_TEST(test_rejected_port); test_print_result(); } |