コード例 #1
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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);

	return EC_SUCCESS;
}
コード例 #2
0
ファイル: usb_charger.c プロジェクト: coreboot/chrome-ec
static void usb_charger_init(void)
{
	int i;
	struct charge_port_info charge_none;

	/* Initialize all charge suppliers to 0 */
	charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
	charge_none.current = 0;
	for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
		charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
					     i,
					     &charge_none);

#ifndef CONFIG_USB_PD_VBUS_DETECT_TCPC
		/*
		 * Initialize VBUS supplier based on whether VBUS is present.
		 * For CONFIG_USB_PD_VBUS_DETECT_TCPC, usb_charger_vbus_change()
		 * will be called directly from TCPC alert.
		 */
		update_vbus_supplier(i, pd_snk_is_vbus_provided(i));
#endif
	}
}
コード例 #3
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #4
0
ファイル: usb_charger.c プロジェクト: fourier49/BIZ_EC
static void usb_charger_init(void)
{
	int i;
	struct charge_port_info charge_none;

	/* Initialize all pericom charge suppliers to 0 */
	charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
	charge_none.current = 0;
	for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
		charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
					     i,
					     &charge_none);
		charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
					     i,
					     &charge_none);

#ifndef CONFIG_USB_PD_TCPM_VBUS
		/* Initialize VBUS supplier based on whether VBUS is present */
		update_vbus_supplier(i, pd_snk_is_vbus_provided(i));
#endif
	}
}
コード例 #5
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #6
0
ファイル: board.c プロジェクト: fishbaoz/chrome-ec
static void update_vbus_supplier(int vbus_level)
{
	struct charge_port_info charge;

	charge.voltage = USB_CHARGER_VOLTAGE_MV;
	charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
	charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge);
}
コード例 #7
0
ファイル: usb_pd_policy.c プロジェクト: coreboot/chrome-ec
void typec_set_input_current_limit(int port, uint32_t max_ma,
				   uint32_t supply_voltage)
{
	struct charge_port_info charge;
	charge.current = max_ma;
	charge.voltage = supply_voltage;
	charge_manager_update_charge(CHARGE_SUPPLIER_TYPEC, port, &charge);
}
コード例 #8
0
ファイル: usb_pd_policy.c プロジェクト: coreboot/chrome-ec
void pd_set_input_current_limit(int port, uint32_t max_ma,
				uint32_t supply_voltage)
{
#ifdef CONFIG_CHARGE_MANAGER
	struct charge_port_info charge;
	charge.current = max_ma;
	charge.voltage = supply_voltage;
	charge_manager_update_charge(CHARGE_SUPPLIER_PD, port, &charge);
#endif
}
コード例 #9
0
ファイル: usb_pd_policy.c プロジェクト: fishbaoz/chrome-ec
void typec_set_input_current_limit(int port, uint32_t max_ma,
				   uint32_t supply_voltage)
{
	struct charge_port_info charge;
	charge.current = max_ma;
	charge.voltage = supply_voltage;
	charge_manager_update_charge(CHARGE_SUPPLIER_TYPEC, port, &charge);

	/* notify host of power info change */
	pd_send_host_event(PD_EVENT_POWER_CHANGE);
}
コード例 #10
0
void typec_set_input_current_limit(int port, uint32_t max_ma,
				   uint32_t supply_voltage)
{
#ifdef CONFIG_CHARGE_MANAGER
	struct charge_port_info charge;
	charge.current = max_ma;
	charge.voltage = supply_voltage;
	charge_manager_update_charge(CHARGE_SUPPLIER_TYPEC, port, &charge);
#endif

	/* notify host of power info change */
}
コード例 #11
0
ファイル: board.c プロジェクト: fishbaoz/chrome-ec
static void reset_charge(int port)
{
	struct charge_port_info charge_none;

	charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
	charge_none.current = 0;
	charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
				     port,
				     &charge_none);
	charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
				     port,
				     &charge_none);
	charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
				     port,
				     &charge_none);
	charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
				     port,
				     &charge_none);
	charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
				     port,
				     &charge_none);
}
コード例 #12
0
ファイル: usb_pd_policy.c プロジェクト: littlebabay/chrome-ec
void pd_set_input_current_limit(int port, uint32_t max_ma,
				uint32_t supply_voltage)
{
#ifdef CONFIG_CHARGE_MANAGER
	struct charge_port_info charge;

	charge.current = max_ma;
	charge.voltage = supply_voltage;
	charge_manager_update_charge(CHARGE_SUPPLIER_PD, port, &charge);
#endif
	/* notify host of power info change */
	pd_send_host_event(PD_EVENT_POWER_CHANGE);
}
コード例 #13
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #14
0
ファイル: usb_charger.c プロジェクト: coreboot/chrome-ec
static void update_vbus_supplier(int port, int vbus_level)
{
	struct charge_port_info charge;

	/*
	 * If VBUS is low, or VBUS is high and we are not outputting VBUS
	 * ourselves, then update the VBUS supplier.
	 */
	if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) {
		charge.voltage = USB_CHARGER_VOLTAGE_MV;
		charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
		charge_manager_update_charge(CHARGE_SUPPLIER_VBUS,
					     port,
					     &charge);
	}
}
コード例 #15
0
ファイル: board.c プロジェクト: fourier49/BZ_DEV_EC
/* Initialize board. */
static void board_init(void)
{
	int i, bc12_status;
	struct charge_port_info charge_none, charge_vbus;
	struct charge_port_info *charge_sel;

	/* Enable rev1 testing GPIOs */
	gpio_set_level(GPIO_SYSTEM_POWER_H, 1);
	/* Enable PD MCU interrupt */
	gpio_enable_interrupt(GPIO_PD_MCU_INT);
	/* Enable VBUS interrupt */
	gpio_enable_interrupt(GPIO_VBUS_WAKE_L);

	charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
	charge_none.current = 0;
	charge_vbus.voltage = USB_CHARGER_VOLTAGE_MV;
	charge_vbus.current = USB_CHARGER_MIN_CURR_MA;
	for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
		/* Initialize all pericom charge suppliers to 0 */
		charge_manager_update_charge(
				CHARGE_SUPPLIER_PROPRIETARY,
				i,
				&charge_none);
		charge_manager_update_charge(
				CHARGE_SUPPLIER_BC12_CDP,
				i,
				&charge_none);
		charge_manager_update_charge(
				CHARGE_SUPPLIER_BC12_DCP,
				i,
				&charge_none);
		charge_manager_update_charge(
				CHARGE_SUPPLIER_BC12_SDP,
				i,
				&charge_none);
		charge_manager_update_charge(
				CHARGE_SUPPLIER_OTHER,
				i,
				&charge_none);

		/* Initialize VBUS supplier based on VBUS */
		/* TODO(crbug.com/498974): Don't do i2c from hook_init. */
		bc12_status = pi3usb9281_get_charger_status(i);
		charge_sel = PI3USB9281_CHG_STATUS_ANY(bc12_status) ?
				&charge_vbus : &charge_none;
		charge_manager_update_charge(
				CHARGE_SUPPLIER_VBUS,
				i,
				charge_sel);
	}
}
コード例 #16
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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();
}
コード例 #17
0
ファイル: board.c プロジェクト: fishbaoz/chrome-ec
static void usb_charger_bc12_detect(void)
{
	int type;
	struct charge_port_info charge;

	type = charger_detect_get_device_type();
	if (gpio_get_level(GPIO_AC_PRESENT) && type) {
		charge.voltage = USB_CHARGER_VOLTAGE_MV;
		if (type == CHARGE_SUPPLIER_BC12_CDP)
			charge.current = 1500;
		else
			charge.current = 500;

		charge_manager_update_charge(type, 0, &charge);
	} else
		reset_charge(0);


	/* notify host of power info change */
	pd_send_host_event(PD_EVENT_POWER_CHANGE);
}
コード例 #18
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #19
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #20
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #21
0
ファイル: charge_manager.c プロジェクト: coreboot/chrome-ec
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;
}
コード例 #22
0
ファイル: usb_charger.c プロジェクト: fourier49/BIZ_EC
static void usb_charger_bc12_detect(int port)
{
	int device_type, charger_status;
	struct charge_port_info charge;
	int type;

	charge.voltage = USB_CHARGER_VOLTAGE_MV;

	/* Read interrupt register to clear on chip */
	pi3usb9281_get_interrupts(port);

	if (usb_charger_port_is_sourcing_vbus(port)) {
		/* If we're sourcing VBUS then we're not charging */
		device_type = charger_status = 0;
	} else {
		/* Set device type */
		device_type = pi3usb9281_get_device_type(port);
		charger_status = pi3usb9281_get_charger_status(port);
	}

	/* Debounce pin plug order if we detect a charger */
	if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
		msleep(USB_CHG_DEBOUNCE_DELAY_MS);

		/* next operation might trigger a detach interrupt */
		pi3usb9281_disable_interrupts(port);
		/* Ensure D+/D- are open before resetting */
		pi3usb9281_set_switch_manual(port, 1);
		pi3usb9281_set_pins(port, 0);
		/* Let D+/D- relax to their idle state */
		msleep(40);

		/*
		 * Trigger chip reset to refresh detection registers.
		 * WARNING: This reset is acceptable for samus_pd,
		 * but may not be acceptable for devices that have
		 * an OTG / device mode, as we may be interrupting
		 * the connection.
		 */
		pi3usb9281_reset(port);
		/*
		 * Restore data switch settings - switches return to
		 * closed on reset until restored.
		 */
		usb_charger_set_switches(port, USB_SWITCH_RESTORE);
		/* Clear possible disconnect interrupt */
		pi3usb9281_get_interrupts(port);
		/* Mask attach interrupt */
		pi3usb9281_set_interrupt_mask(port,
					      0xff &
					      ~PI3USB9281_INT_ATTACH);
		/* Re-enable interrupts */
		pi3usb9281_enable_interrupts(port);
		msleep(USB_CHG_RESET_DELAY_MS);

		/* Clear possible attach interrupt */
		pi3usb9281_get_interrupts(port);
		/* Re-enable attach interrupt */
		pi3usb9281_set_interrupt_mask(port, 0xff);

		/* Re-read ID registers */
		device_type = pi3usb9281_get_device_type(port);
		charger_status = pi3usb9281_get_charger_status(port);
	}

	/* Attachment: decode + update available charge */
	if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
		if (PI3USB9281_CHG_STATUS_ANY(charger_status))
			type = CHARGE_SUPPLIER_PROPRIETARY;
		else if (device_type & PI3USB9281_TYPE_CDP)
			type = CHARGE_SUPPLIER_BC12_CDP;
		else if (device_type & PI3USB9281_TYPE_DCP)
			type = CHARGE_SUPPLIER_BC12_DCP;
		else if (device_type & PI3USB9281_TYPE_SDP)
			type = CHARGE_SUPPLIER_BC12_SDP;
		else
			type = CHARGE_SUPPLIER_OTHER;

		charge.current = pi3usb9281_get_ilim(device_type,
						     charger_status);
		charge_manager_update_charge(type, port, &charge);
	} else { /* Detachment: update available charge to 0 */
		charge.current = 0;
		charge_manager_update_charge(
					CHARGE_SUPPLIER_PROPRIETARY,
					port,
					&charge);
		charge_manager_update_charge(
					CHARGE_SUPPLIER_BC12_CDP,
					port,
					&charge);
		charge_manager_update_charge(
					CHARGE_SUPPLIER_BC12_DCP,
					port,
					&charge);
		charge_manager_update_charge(
					CHARGE_SUPPLIER_BC12_SDP,
					port,
					&charge);
		charge_manager_update_charge(
					CHARGE_SUPPLIER_OTHER,
					port,
					&charge);
	}

	/* notify host of power info change */
	pd_send_host_event(PD_EVENT_POWER_CHANGE);
}