summaryrefslogtreecommitdiff
path: root/common/charge_manager.c
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2014-11-05 14:38:38 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-11-13 03:14:21 +0000
commit4340685cf9ab9335256d63a8a551faa85af4f892 (patch)
treef5594acdc2359c52bd3d039d0e3cc879ad0b093f /common/charge_manager.c
parentcf48a3640c271663fc1c4156b16f4a25264944d9 (diff)
downloadchrome-ec-4340685cf9ab9335256d63a8a551faa85af4f892.tar.gz
charge_manager: Add charge port override functionality
Allow a charge port to be selected as the override port, which means it will always be selected as the charge port, if any charge supplier is available. BUG=chrome-os-partner:32003 TEST=Attach PD charger and BC1.2 charger. Verify that active charge port switches to BC1.2 after running `chargeoverride [port]` from console. Also, pass unit tests. BRANCH=Samus Change-Id: Ia1b48ca89641842d51be7eed3b92d36d3eedc9ef Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/227730 Reviewed-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'common/charge_manager.c')
-rw-r--r--common/charge_manager.c98
1 files changed, 77 insertions, 21 deletions
diff --git a/common/charge_manager.c b/common/charge_manager.c
index 6926da4121..6b66d88a81 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -27,6 +27,7 @@ static int charge_ceil[PD_PORT_COUNT];
static int charge_port = CHARGE_PORT_NONE;
static int charge_current = CHARGE_CURRENT_UNINITIALIZED;
static int charge_supplier = CHARGE_SUPPLIER_NONE;
+static int override_port = OVERRIDE_OFF;
/**
* Initialize available charge. Run before board init, so board init can
@@ -83,29 +84,45 @@ static void charge_manager_refresh(void)
int new_port = CHARGE_PORT_NONE;
int new_charge_current, new_charge_voltage, i, j, old_port;
- /*
- * Charge supplier selection logic:
- * 1. Prefer higher priority supply.
- * 2. Prefer higher power over lower in case priority is tied.
- * available_charge can be changed at any time by other tasks,
- * so make no assumptions about its consistency.
- */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
- for (j = 0; j < PD_PORT_COUNT; ++j)
- if (available_charge[i][j].current > 0 &&
- available_charge[i][j].voltage > 0 &&
- (new_supplier == CHARGE_SUPPLIER_NONE ||
- supplier_priority[i] <
- supplier_priority[new_supplier] ||
- (supplier_priority[i] ==
- supplier_priority[new_supplier] &&
- POWER(available_charge[i][j]) >
- POWER(available_charge[new_supplier]
- [new_port])))) {
- new_supplier = i;
- new_port = j;
+ /* Skip port selection on OVERRIDE_DONT_CHARGE. */
+ if (override_port != OVERRIDE_DONT_CHARGE) {
+ /*
+ * Charge supplier selection logic:
+ * 1. Prefer higher priority supply.
+ * 2. Prefer higher power over lower in case priority is tied.
+ * available_charge can be changed at any time by other tasks,
+ * so make no assumptions about its consistency.
+ */
+ for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
+ for (j = 0; j < PD_PORT_COUNT; ++j) {
+ if (override_port != OVERRIDE_OFF &&
+ override_port == new_port &&
+ override_port != j)
+ continue;
+
+ if (available_charge[i][j].current > 0 &&
+ available_charge[i][j].voltage > 0 &&
+ (new_supplier == CHARGE_SUPPLIER_NONE ||
+ supplier_priority[i] <
+ supplier_priority[new_supplier] ||
+ (j == override_port &&
+ new_port != override_port) ||
+ (supplier_priority[i] ==
+ supplier_priority[new_supplier] &&
+ POWER(available_charge[i][j]) >
+ POWER(available_charge[new_supplier]
+ [new_port])))) {
+ new_supplier = i;
+ new_port = j;
+ }
}
+ /* Clear override if no charge is available on override port */
+ if (override_port != OVERRIDE_OFF &&
+ override_port != new_port)
+ override_port = OVERRIDE_OFF;
+ }
+
if (new_supplier == CHARGE_SUPPLIER_NONE)
new_charge_current = new_charge_voltage = 0;
else {
@@ -189,6 +206,25 @@ void charge_manager_set_ceil(int port, int ceil)
}
}
+/**
+ * Select an 'override port', a port which is always the preferred charge port.
+ *
+ * @param port Charge port to select as override, or
+ * OVERRIDE_OFF to select no override port,
+ * or OVERRIDE_DONT_CHARGE to specifc that no
+ * charge port should be selected.
+ */
+void charge_manager_set_override(int port)
+{
+ ASSERT(port >= OVERRIDE_DONT_CHARGE && port < PD_PORT_COUNT);
+
+ if (override_port != port) {
+ override_port = port;
+ if (charge_manager_is_seeded())
+ hook_call_deferred(charge_manager_refresh, 0);
+ }
+}
+
int charge_manager_get_active_charge_port(void)
{
return charge_port;
@@ -291,3 +327,23 @@ DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO,
hc_pd_power_info,
EC_VER_MASK(0));
#endif /* TEST_CHARGE_MANAGER */
+
+static int command_charge_override(int argc, char **argv)
+{
+ int port = OVERRIDE_OFF;
+ char *e;
+
+ if (argc >= 2) {
+ port = strtoi(argv[1], &e, 0);
+ if (*e || port < OVERRIDE_DONT_CHARGE || port >= PD_PORT_COUNT)
+ return EC_ERROR_PARAM1;
+ }
+
+ charge_manager_set_override(port);
+ ccprintf("Set override: %d\n", port);
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(chargeoverride, command_charge_override,
+ "[port | -1 | -2]",
+ "Force charging from a given port (-1 = off, -2 = disable charging)",
+ NULL);