summaryrefslogtreecommitdiff
path: root/common/charge_manager.c
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2014-12-23 09:45:16 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-12-24 21:06:16 +0000
commit73bbc9eda8bbdfa190e3fdde16a852dd2755276c (patch)
tree6d3c853f97bf40510180272bdb378bf57bf38b05 /common/charge_manager.c
parentb9b457173ea7f194c13a2d025496c3c49cf05792 (diff)
downloadchrome-ec-73bbc9eda8bbdfa190e3fdde16a852dd2755276c.tar.gz
charge_manager: Request power swap when switching from dual-role override port
Ports should have source roles by default, and should go back to being sources once we stop charging from them. BUG=chrome-os-partner:31195 TEST=Manual on Samus. Connect Samus to dual-role port. Set override port, verify that Samus charges. Attach dedicated charger, verify that the dual-role port becomes a charge source again. Also pass unit tests. BRANCH=Samus Change-Id: Icf153117229cbf0f71d4bdeb888f73299acd5eeb Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/237452 Reviewed-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'common/charge_manager.c')
-rw-r--r--common/charge_manager.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/common/charge_manager.c b/common/charge_manager.c
index a74ba3a0d6..651cf3af5e 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -87,6 +87,21 @@ static int charge_manager_is_seeded(void)
}
/**
+ * Perform cleanup operations on an override port, when switching to a
+ * different port. This involves switching the port from sink to source,
+ * if applicable.
+ */
+static void charge_manager_cleanup_override_port(int port)
+{
+ if (port < 0 || port >= PD_PORT_COUNT)
+ return;
+
+ if (pd_get_partner_dualrole_capable(port) &&
+ pd_get_role(port) == PD_ROLE_SINK)
+ pd_request_power_swap(port);
+}
+
+/**
* Select the 'best' charge port, as defined by the supplier heirarchy and the
* ability of the port to provide power.
*/
@@ -141,10 +156,6 @@ static void charge_manager_get_best_charge_port(int *new_port,
}
}
- /* Clear override if no charge is available on override port */
- if (override_port != OVERRIDE_OFF &&
- override_port != port)
- override_port = OVERRIDE_OFF;
}
*new_port = port;
@@ -183,6 +194,16 @@ static void charge_manager_refresh(void)
available_charge[i][new_port].current = 0;
}
+ /*
+ * Clear override if it wasn't selected as the 'best' port -- it means
+ * that no charge is available on the port, or the port was rejected.
+ */
+ if (override_port >= 0 &&
+ override_port != new_port) {
+ charge_manager_cleanup_override_port(override_port);
+ override_port = OVERRIDE_OFF;
+ }
+
if (new_supplier == CHARGE_SUPPLIER_NONE) {
new_charge_current = 0;
new_charge_current_uncapped = 0;
@@ -259,8 +280,11 @@ void charge_manager_update(int supplier,
if (available_charge[supplier][port].current == 0 &&
charge->current > 0 &&
!pd_get_partner_dualrole_capable(port)) {
+ charge_manager_cleanup_override_port(override_port);
override_port = OVERRIDE_OFF;
if (delayed_override_port != OVERRIDE_OFF) {
+ charge_manager_cleanup_override_port(
+ delayed_override_port);
delayed_override_port = OVERRIDE_OFF;
hook_call_deferred(
board_charge_manager_override_timeout,
@@ -322,9 +346,13 @@ int charge_manager_set_override(int port)
int retval = EC_SUCCESS;
ASSERT(port >= OVERRIDE_DONT_CHARGE && port < PD_PORT_COUNT);
- /* Supersede any pending delayed overrides. */
+ /* Supersede any pending delayed overrides. */
if (delayed_override_port != OVERRIDE_OFF) {
+ if (delayed_override_port != port)
+ charge_manager_cleanup_override_port(
+ delayed_override_port);
+
delayed_override_port = OVERRIDE_OFF;
hook_call_deferred(
board_charge_manager_override_timeout, -1);
@@ -333,6 +361,7 @@ int charge_manager_set_override(int port)
/* Set the override port if it's a sink. */
if (port < 0 || pd_get_role(port) == PD_ROLE_SINK) {
if (override_port != port) {
+ charge_manager_cleanup_override_port(override_port);
override_port = port;
if (charge_manager_is_seeded())
hook_call_deferred(charge_manager_refresh, 0);