/* Copyright 2014 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. * * Test charge manager module. */ #include "battery.h" #include "charge_manager.h" #include "common.h" #include "ec_commands.h" #include "test_util.h" #include "timer.h" #include "usb_pd.h" #include "util.h" #define CHARGE_MANAGER_SLEEP_MS 50 /* Charge supplier priority: lower number indicates higher priority. */ const int supplier_priority[] = { [CHARGE_SUPPLIER_TEST1] = 0, [CHARGE_SUPPLIER_TEST2] = 1, [CHARGE_SUPPLIER_TEST3] = 1, [CHARGE_SUPPLIER_TEST4] = 1, [CHARGE_SUPPLIER_TEST5] = 3, [CHARGE_SUPPLIER_TEST6] = 3, [CHARGE_SUPPLIER_TEST7] = 5, [CHARGE_SUPPLIER_TEST8] = 6, [CHARGE_SUPPLIER_TEST9] = 6, }; BUILD_ASSERT((int)CHARGE_SUPPLIER_COUNT == (int)CHARGE_SUPPLIER_TEST_COUNT); 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[CONFIG_USB_PD_PORT_COUNT]; static int power_role[CONFIG_USB_PD_PORT_COUNT]; /* Callback functions called by CM on state change */ void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma, int charge_mv) { active_charge_limit = charge_ma; } /* 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) { } void pd_set_new_power_request(int port) { new_power_request[port] = 1; } enum battery_present battery_is_present(void) { return BP_YES; } static void clear_new_power_requests(void) { int i; for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; ++i) new_power_request[i] = 0; } static void pd_set_role(int port, int role) { power_role[port] = role; } int pd_get_role(int port) { return power_role[port]; } void pd_request_power_swap(int port) { if (power_role[port] == PD_ROLE_SINK) power_role[port] = PD_ROLE_SOURCE; else power_role[port] = PD_ROLE_SINK; } static void wait_for_charge_manager_refresh(void) { msleep(CHARGE_MANAGER_SLEEP_MS); } static void initialize_charge_table(int current, int voltage, int ceil) { int i, j; 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; for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; ++i) { for (j = 0; j < CEIL_REQUESTOR_COUNT; ++j) charge_manager_set_ceil(i, j, ceil); charge_manager_update_dualrole(i, CAP_DEDICATED); pd_set_role(i, PD_ROLE_SINK); for (j = 0; j < CHARGE_SUPPLIER_COUNT; ++j) charge_manager_update_charge(j, i, &charge); } wait_for_charge_manager_refresh(); } static int test_initialization(void) { int i, j; struct charge_port_info charge; /* * No charge port should be selected until all ports + suppliers * have reported in with an initial charge. */ TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); charge.current = 1000; charge.voltage = 5000; /* Initialize all supplier/port pairs, except for the last one */ for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) for (j = 0; j < CONFIG_USB_PD_PORT_COUNT; ++j) { if (i == 0) charge_manager_update_dualrole(j, CAP_DEDICATED); if (i == CHARGE_SUPPLIER_COUNT - 1 && j == CONFIG_USB_PD_PORT_COUNT - 1) break; charge_manager_update_charge(i, j, &charge); } /* Verify no active charge port, since all pairs haven't updated */ wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); /* Update last pair and verify a charge port has been selected */ charge_manager_update_charge(CHARGE_SUPPLIER_COUNT-1, CONFIG_USB_PD_PORT_COUNT-1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port != CHARGE_PORT_NONE); return EC_SUCCESS; } static int test_safe_mode(void) { int port = 0; struct charge_port_info charge; /* Initialize table to no charge */ initialize_charge_table(0, 5000, 5000); /* * Set a 2A non-dedicated charger on port 0 and verify that * it is selected, due to safe mode. */ charge_manager_update_dualrole(port, CAP_DUALROLE); charge.current = 2000; charge.voltage = 5000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, port, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == port); TEST_ASSERT(active_charge_limit == 2000); /* Verify ceil is ignored, due to safe mode. */ charge_manager_set_ceil(port, 0, 500); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_limit == 2000); /* * Leave safe mode and verify normal port selection rules go * into effect. */ charge_manager_leave_safe_mode(); wait_for_charge_manager_refresh(); #ifdef CONFIG_CHARGE_MANAGER_DRP_CHARGING TEST_ASSERT(active_charge_port == port); TEST_ASSERT(active_charge_limit == 500); #else TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); #endif /* For subsequent tests, safe mode is exited. */ return EC_SUCCESS; } static int test_priority(void) { struct charge_port_info charge; /* Initialize table to no charge */ initialize_charge_table(0, 5000, 5000); TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); /* * Set a 1A charge via a high-priority supplier and a 2A charge via * a low-priority supplier, and verify the HP supplier is chosen. */ charge.current = 2000; charge.voltage = 5000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 0, &charge); charge.current = 1000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 1000); /* * Set a higher charge on a LP supplier and verify we still use the * lower charge. */ charge.current = 1500; charge_manager_update_charge(CHARGE_SUPPLIER_TEST7, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 1000); /* * Zero our HP charge and verify fallback to next highest priority, * which happens to be a different port. */ charge.current = 0; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 2000); /* Add a charge at equal priority and verify highest charge selected */ charge.current = 2500; charge_manager_update_charge(CHARGE_SUPPLIER_TEST5, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 2500); charge.current = 3000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 3000); /* * Add a charge at equal priority and equal power, verify that the * active port doesn't change since the first plugged port is * selected as the tiebreaker. */ charge.current = 3000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 3000); return EC_SUCCESS; } static int test_charge_ceil(void) { int port; struct charge_port_info charge; /* Initialize table to 1A @ 5V, and verify port + limit */ initialize_charge_table(1000, 5000, 1000); TEST_ASSERT(active_charge_port != CHARGE_PORT_NONE); TEST_ASSERT(active_charge_limit == 1000); /* Set a 500mA ceiling, verify port is unchanged */ port = active_charge_port; charge_manager_set_ceil(port, 0, 500); wait_for_charge_manager_refresh(); TEST_ASSERT(port == active_charge_port); TEST_ASSERT(active_charge_limit == 500); /* Raise the ceiling to 2A, verify limit goes back to 1A */ charge_manager_set_ceil(port, 0, 2000); wait_for_charge_manager_refresh(); TEST_ASSERT(port == active_charge_port); TEST_ASSERT(active_charge_limit == 1000); /* Verify that ceiling is ignored in determining active charge port */ charge.current = 2000; charge.voltage = 5000; charge_manager_update_charge(0, 0, &charge); charge.current = 2500; charge_manager_update_charge(0, 1, &charge); charge_manager_set_ceil(1, 0, 750); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 750); /* Set a secondary lower ceiling and verify it takes effect */ charge_manager_set_ceil(1, 1, 500); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 500); /* Raise the secondary ceiling and verify the primary takes effect */ charge_manager_set_ceil(1, 1, 800); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 750); /* Remove the primary celing and verify the secondary takes effect */ charge_manager_set_ceil(1, 0, CHARGE_CEIL_NONE); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 800); /* Remove all ceilings */ charge_manager_set_ceil(1, 1, CHARGE_CEIL_NONE); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 2500); /* Verify forced ceil takes effect immediately */ charge_manager_force_ceil(1, 500); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 500); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 500); return EC_SUCCESS; } static int test_new_power_request(void) { struct charge_port_info charge; /* Initialize table to no charge */ initialize_charge_table(0, 5000, 5000); /* Clear power requests, and verify they are zero'd */ clear_new_power_requests(); wait_for_charge_manager_refresh(); TEST_ASSERT(new_power_request[0] == 0); TEST_ASSERT(new_power_request[1] == 0); /* Charge from port 1 and verify NPR on port 1 only */ charge.current = 1000; charge.voltage = 5000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(new_power_request[0] == 0); TEST_ASSERT(new_power_request[1] == 1); clear_new_power_requests(); /* Reduce port 1 through ceil and verify no NPR */ charge_manager_set_ceil(1, 0, 500); wait_for_charge_manager_refresh(); TEST_ASSERT(new_power_request[0] == 0); TEST_ASSERT(new_power_request[1] == 0); clear_new_power_requests(); /* Change port 1 voltage and verify NPR on port 1 */ charge.voltage = 4000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(new_power_request[0] == 0); TEST_ASSERT(new_power_request[1] == 1); clear_new_power_requests(); /* Add low-priority source and verify no NPRs */ charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(new_power_request[0] == 0); TEST_ASSERT(new_power_request[1] == 0); clear_new_power_requests(); /* * Add higher-priority source and verify NPR on both ports, * since we're switching charge ports. */ charge_manager_update_charge(CHARGE_SUPPLIER_TEST1, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(new_power_request[0] == 1); TEST_ASSERT(new_power_request[1] == 1); clear_new_power_requests(); return EC_SUCCESS; } static int test_override(void) { struct charge_port_info charge; /* Initialize table to no charge */ initialize_charge_table(0, 5000, 1000); /* * Set a low-priority supplier on p0 and high-priority on p1, then * verify that p1 is selected. */ charge.current = 500; charge.voltage = 5000; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); charge_manager_update_charge(CHARGE_SUPPLIER_TEST1, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 500); /* Set override to p0 and verify p0 is selected */ charge_manager_set_override(0); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); /* Remove override and verify p1 is again selected */ charge_manager_set_override(OVERRIDE_OFF); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); /* * Set override again to p0, but set p0 charge to 0, and verify p1 * is again selected. */ charge.current = 0; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); charge_manager_set_override(0); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); /* Set non-zero charge on port 0 and verify override was auto-removed */ charge.current = 250; charge_manager_update_charge(CHARGE_SUPPLIER_TEST5, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); /* * Verify current limit is still selected according to supplier * priority on the override port. */ charge.current = 300; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); charge_manager_set_override(0); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 300); charge.current = 100; charge_manager_update_charge(CHARGE_SUPPLIER_TEST1, 0, &charge); charge_manager_set_override(0); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 100); /* * Verify that a don't charge override request on a dual-role * port causes a swap to source. */ pd_set_role(0, PD_ROLE_SINK); charge_manager_update_dualrole(0, CAP_DUALROLE); charge_manager_set_override(OVERRIDE_DONT_CHARGE); wait_for_charge_manager_refresh(); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE); /* * Verify that an override request to a dual-role source port * causes a role swap to sink. */ charge_manager_set_override(0); wait_for_charge_manager_refresh(); charge.current = 200; charge_manager_update_charge(CHARGE_SUPPLIER_TEST1, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 200); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SINK); /* Set override to "don't charge", then verify we're not charging */ charge_manager_set_override(OVERRIDE_DONT_CHARGE); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); TEST_ASSERT(active_charge_limit == 0); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE); /* Update a charge supplier, verify that we still aren't charging */ charge.current = 200; charge_manager_update_charge(CHARGE_SUPPLIER_TEST1, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); TEST_ASSERT(active_charge_limit == 0); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE); /* Turn override off, verify that we go back to the correct charge */ charge_manager_set_override(OVERRIDE_OFF); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 500); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE); return EC_SUCCESS; } static int test_dual_role(void) { struct charge_port_info charge; /* Initialize table to no charge. */ initialize_charge_table(0, 5000, 1000); /* 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); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 500); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SINK); /* 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); charge.current = 550; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 550); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SINK); /* * Insert a dual-role charger into P1 and set the override. Verify * that the override correctly changes. */ charge_manager_update_dualrole(1, CAP_DUALROLE); charge_manager_set_override(1); charge.current = 500; charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 1, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 500); TEST_ASSERT(pd_get_role(1) == PD_ROLE_SINK); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SOURCE); /* Set override back to P0 and verify switch */ charge_manager_set_override(0); charge.current = 600; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 600); TEST_ASSERT(pd_get_role(0) == PD_ROLE_SINK); TEST_ASSERT(pd_get_role(1) == PD_ROLE_SOURCE); /* Insert a dedicated charger and verify override is removed */ charge.current = 0; charge_manager_update_charge(CHARGE_SUPPLIER_TEST6, 1, &charge); wait_for_charge_manager_refresh(); charge_manager_update_dualrole(1, CAP_DEDICATED); 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 * unplugged and replaced with a dedicated source. */ charge_manager_update_dualrole(0, CAP_DEDICATED); charge.current = 0; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); charge.current = 500; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); TEST_ASSERT(active_charge_limit == 500); /* * Test one port connected to dedicated charger and one connected * to dual-role device. */ charge_manager_update_dualrole(0, CAP_DUALROLE); charge.current = 0; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); charge.current = 500; charge_manager_update_charge(CHARGE_SUPPLIER_TEST2, 0, &charge); 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; } 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(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(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(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; } static int test_unknown_dualrole_capability(void) { struct charge_port_info charge; /* Initialize table to no charge. */ initialize_charge_table(0, 5000, 2000); TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE); /* 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); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 0); /* Add dualrole charger in port 1 */ charge.current = 1000; 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); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); /* * Toggle port 0 to dedicated, verify that override is still kept * because there's no charge on the port. */ charge_manager_update_dualrole(0, CAP_DEDICATED); wait_for_charge_manager_refresh(); TEST_ASSERT(active_charge_port == 1); /* 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 */ 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 */ 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); return EC_SUCCESS; } void run_test(void) { test_reset(); RUN_TEST(test_initialization); RUN_TEST(test_safe_mode); RUN_TEST(test_priority); RUN_TEST(test_charge_ceil); RUN_TEST(test_new_power_request); RUN_TEST(test_override); RUN_TEST(test_dual_role); RUN_TEST(test_rejected_port); RUN_TEST(test_unknown_dualrole_capability); test_print_result(); }