summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2014-12-17 10:36:48 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-12-17 22:26:56 +0000
commit86835f7067b7ce26431ca459be3d59662736275f (patch)
tree29157fcda8227315f537cdb4168549344ba7421e
parentec12acc81f47e9b88517cd4a955414f7a1ee1cf6 (diff)
downloadchrome-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.h6
-rw-r--r--board/samus_pd/board.c16
-rw-r--r--board/samus_pd/board.h6
-rw-r--r--common/charge_manager.c77
-rw-r--r--include/charge_manager.h13
-rw-r--r--test/charge_manager.c50
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();
}