bc12: Add charging mode role information to callback
Update the result callback routine to also provide information about the charging mode role. This permits tests to validate plug/unplug events detected by the BC1.2 device operating in charging mode. Signed-off-by: Keith Short <keithshort@google.com>
This commit is contained in:
parent
824d021377
commit
86cb55943d
|
@ -30,7 +30,7 @@ struct pi3usb9201_config {
|
|||
struct pi3usb9201_data {
|
||||
const struct device *dev;
|
||||
struct k_work work;
|
||||
enum bc12_type partner_type;
|
||||
struct bc12_partner_state partner_state;
|
||||
struct gpio_callback gpio_cb;
|
||||
|
||||
bc12_callback_t result_cb;
|
||||
|
@ -148,22 +148,56 @@ static void pi3usb9201_notify_callback(const struct device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
static bool pi3usb9201_partner_has_changed(const struct device *dev,
|
||||
struct bc12_partner_state *state)
|
||||
{
|
||||
struct pi3usb9201_data *pi3usb9201_data = dev->data;
|
||||
|
||||
/* Always notify when clearing out partner state */
|
||||
if (!state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (state->bc12_role != pi3usb9201_data->partner_state.bc12_role) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (state->bc12_role == BC12_PORTABLE_DEVICE &&
|
||||
pi3usb9201_data->partner_state.type != state->type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (state->bc12_role == BC12_CHARGING_PORT &&
|
||||
pi3usb9201_data->partner_state.pd_partner_connected != state->pd_partner_connected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify the application about changes to the BC1.2 partner.
|
||||
*
|
||||
* @param dev BC1.2 device instance
|
||||
* @param state New partner state information. Set to NULL to indicate no
|
||||
* partner is connected.
|
||||
*/
|
||||
static void pi3usb9201_update_charging_partner(const struct device *dev,
|
||||
struct bc12_partner_state *const state)
|
||||
{
|
||||
struct pi3usb9201_data *pi3usb9201_data = dev->data;
|
||||
|
||||
if (state && state->type == pi3usb9201_data->partner_type) {
|
||||
/* No change to the charging partner */
|
||||
if (!pi3usb9201_partner_has_changed(dev, state)) {
|
||||
/* No change to the partner */
|
||||
return;
|
||||
}
|
||||
|
||||
if (state && state->type != BC12_TYPE_NONE) {
|
||||
/* Now update the current charger type */
|
||||
pi3usb9201_data->partner_type = state->type;
|
||||
if (state) {
|
||||
/* Now update callback with the new partner type. */
|
||||
pi3usb9201_data->partner_state = *state;
|
||||
pi3usb9201_notify_callback(dev, state);
|
||||
} else {
|
||||
pi3usb9201_data->partner_type = BC12_TYPE_NONE;
|
||||
pi3usb9201_data->partner_state.bc12_role = BC12_DISCONNECTED;
|
||||
pi3usb9201_notify_callback(dev, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -196,12 +230,14 @@ static int pi3usb9201_client_detect_start(const struct device *dev)
|
|||
|
||||
static void pi3usb9201_client_detect_finish(const struct device *dev, const int status)
|
||||
{
|
||||
struct bc12_partner_state new_chg;
|
||||
struct bc12_partner_state new_partner_state;
|
||||
int bit_pos;
|
||||
bool enable_usb_data;
|
||||
|
||||
new_partner_state.bc12_role = BC12_PORTABLE_DEVICE;
|
||||
|
||||
/* Set charge voltage to 5V */
|
||||
new_chg.voltage_uv = BC12_CHARGER_VOLTAGE_UV;
|
||||
new_partner_state.voltage_uv = BC12_CHARGER_VOLTAGE_UV;
|
||||
|
||||
/*
|
||||
* Find set bit position. Note that this function is only called if a
|
||||
|
@ -209,11 +245,11 @@ static void pi3usb9201_client_detect_finish(const struct device *dev, const int
|
|||
*/
|
||||
bit_pos = __builtin_ffs(status) - 1;
|
||||
|
||||
new_chg.current_ua = bc12_chg_limits[bit_pos].current_limit;
|
||||
new_chg.type = bc12_chg_limits[bit_pos].partner_type;
|
||||
new_partner_state.current_ua = bc12_chg_limits[bit_pos].current_limit;
|
||||
new_partner_state.type = bc12_chg_limits[bit_pos].partner_type;
|
||||
|
||||
LOG_DBG("client status = 0x%x, current = %d mA, type = %d",
|
||||
status, new_chg.current_ua, new_chg.type);
|
||||
status, new_partner_state.current_ua, new_partner_state.type);
|
||||
|
||||
/* bc1.2 is complete and start bit does not auto clear */
|
||||
if (pi3usb9201_bc12_detect_ctrl(dev, false) < 0) {
|
||||
|
@ -231,7 +267,7 @@ static void pi3usb9201_client_detect_finish(const struct device *dev, const int
|
|||
}
|
||||
|
||||
/* Inform charge manager of new supplier type and current limit */
|
||||
pi3usb9201_update_charging_partner(dev, &new_chg);
|
||||
pi3usb9201_update_charging_partner(dev, &new_partner_state);
|
||||
}
|
||||
|
||||
static int pi3usb9201_disconnect(const struct device *dev)
|
||||
|
@ -282,18 +318,19 @@ static int pi3usb9201_set_portable_device(const struct device *dev)
|
|||
}
|
||||
|
||||
if (pi3usb9201_client_detect_start(dev) < 0) {
|
||||
struct bc12_partner_state new_result;
|
||||
struct bc12_partner_state partner_state;
|
||||
|
||||
/*
|
||||
* VBUS is present, but starting bc1.2 detection failed
|
||||
* for some reason. Set the partner type to unknown limit
|
||||
* current to the minimum allowed for a suspended USB device.
|
||||
*/
|
||||
new_result.voltage_uv = BC12_CHARGER_VOLTAGE_UV;
|
||||
new_result.current_ua = BC12_CHARGER_MIN_CURR_UA;
|
||||
new_result.type = BC12_TYPE_UNKNOWN;
|
||||
partner_state.bc12_role = BC12_PORTABLE_DEVICE;
|
||||
partner_state.voltage_uv = BC12_CHARGER_VOLTAGE_UV;
|
||||
partner_state.current_ua = BC12_CHARGER_MIN_CURR_UA;
|
||||
partner_state.type = BC12_TYPE_UNKNOWN;
|
||||
/* Save supplier type and notify callbacks */
|
||||
pi3usb9201_update_charging_partner(dev, &new_result);
|
||||
pi3usb9201_update_charging_partner(dev, &partner_state);
|
||||
LOG_ERR("bc1.2 detection failed, using defaults");
|
||||
|
||||
return -EIO;
|
||||
|
@ -384,9 +421,9 @@ static int pi3usb9201_init(const struct device *dev)
|
|||
|
||||
/*
|
||||
* Set most recent bc1.2 detection type result to
|
||||
* BC12_TYPE_NONE for the port.
|
||||
* BC12_DISCONNECTED for the port.
|
||||
*/
|
||||
pi3usb9201_data->partner_type = BC12_TYPE_NONE;
|
||||
pi3usb9201_data->partner_state.bc12_role = BC12_DISCONNECTED;
|
||||
|
||||
rv = gpio_pin_configure_dt(&cfg->intb_gpio, GPIO_INPUT);
|
||||
if (rv < 0) {
|
||||
|
@ -417,16 +454,16 @@ static int pi3usb9201_init(const struct device *dev)
|
|||
return pi3usb9201_interrupt_enable(dev, false);
|
||||
}
|
||||
|
||||
#define PI2USB9201_DEFINE(inst) \
|
||||
static struct pi3usb9201_data pi3usb9201_data_##inst; \
|
||||
\
|
||||
static const struct pi3usb9201_config pi3usb9201_config_##inst = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
.intb_gpio = GPIO_DT_SPEC_INST_GET(inst, intb_gpios), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, pi3usb9201_init, NULL, &pi3usb9201_data_##inst, \
|
||||
&pi3usb9201_config_##inst, POST_KERNEL, \
|
||||
#define PI2USB9201_DEFINE(inst) \
|
||||
static struct pi3usb9201_data pi3usb9201_data_##inst; \
|
||||
\
|
||||
static const struct pi3usb9201_config pi3usb9201_config_##inst = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
.intb_gpio = GPIO_DT_SPEC_INST_GET(inst, intb_gpios), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, pi3usb9201_init, NULL, &pi3usb9201_data_##inst, \
|
||||
&pi3usb9201_config_##inst, POST_KERNEL, \
|
||||
CONFIG_APPLICATION_INIT_PRIORITY, &pi3usb9201_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(PI2USB9201_DEFINE)
|
||||
|
|
|
@ -65,6 +65,7 @@ extern "C" {
|
|||
enum bc12_role {
|
||||
BC12_DISCONNECTED,
|
||||
BC12_PORTABLE_DEVICE,
|
||||
BC12_CHARGING_PORT,
|
||||
};
|
||||
|
||||
/** @brief BC1.2 charging partner type. */
|
||||
|
@ -81,19 +82,34 @@ enum bc12_type {
|
|||
BC12_TYPE_PROPRIETARY,
|
||||
/** Unknown charging port, BC1.2 detection failed. */
|
||||
BC12_TYPE_UNKNOWN,
|
||||
/** Count of valid BC12 types. */
|
||||
BC12_TYPE_COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief BC1.2 detected partner state.
|
||||
*
|
||||
* @param type Charging partner type.
|
||||
* @param current_ma Current, in uA, that the charging partner provides.
|
||||
* @param voltage_mv Voltage, in uV, that the charging partner provides.
|
||||
* @param bc12_role Current role of the BC1.2 device.
|
||||
* @param type Charging partner type. Valid when bc12_role is BC12_PORTABLE_DEVICE.
|
||||
* @param current_ma Current, in uA, that the charging partner provides. Valid when bc12_role is
|
||||
* BC12_PORTABLE_DEVICE.
|
||||
* @param voltage_mv Voltage, in uV, that the charging partner provides. Valid when bc12_role is
|
||||
* BC12_PORTABLE_DEVICE.
|
||||
* @param pd_partner_connected True if a PD partner is currently connected. Valid when bc12_role is
|
||||
* BC12_CHARGING_PORT.
|
||||
*/
|
||||
struct bc12_partner_state {
|
||||
enum bc12_type type;
|
||||
int current_ua;
|
||||
int voltage_uv;
|
||||
enum bc12_role bc12_role;
|
||||
union {
|
||||
struct {
|
||||
enum bc12_type type;
|
||||
int current_ua;
|
||||
int voltage_uv;
|
||||
};
|
||||
struct {
|
||||
bool pd_partner_connected;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,8 +38,13 @@ static void bc12_test_result_cb(const struct device *dev, struct bc12_partner_st
|
|||
fixture->callback_count++;
|
||||
|
||||
if (state) {
|
||||
LOG_INF("callback: type %d, voltage %d, current %d", state->type, state->voltage_uv,
|
||||
state->current_ua);
|
||||
if (state->bc12_role == BC12_PORTABLE_DEVICE) {
|
||||
LOG_INF("charging partner: type %d, voltage %d, current %d", state->type,
|
||||
state->voltage_uv, state->current_ua);
|
||||
} else if (state->bc12_role == BC12_CHARGING_PORT) {
|
||||
LOG_INF("portable device partner: connected %d",
|
||||
state->pd_partner_connected);
|
||||
}
|
||||
fixture->partner_state = *state;
|
||||
} else {
|
||||
LOG_INF("callback: partner disconnect");
|
||||
|
@ -80,6 +85,7 @@ ZTEST_USER_F(bc12_pd_mode, test_bc12_sdp_charging_partner)
|
|||
* for SDP ports or when BC1.2 detection fails.
|
||||
*/
|
||||
zassert_equal(fixture->callback_count, 1);
|
||||
zassert_equal(fixture->partner_state.bc12_role, BC12_PORTABLE_DEVICE);
|
||||
zassert_equal(fixture->partner_state.type, BC12_TYPE_SDP);
|
||||
zassert_equal(fixture->partner_state.current_ua, 2500);
|
||||
zassert_equal(fixture->partner_state.voltage_uv, 5000 * 1000);
|
||||
|
@ -109,6 +115,7 @@ ZTEST_USER_F(bc12_pd_mode, test_bc12_cdp_charging_partner)
|
|||
k_sleep(K_MSEC(100));
|
||||
|
||||
zassert_equal(fixture->callback_count, 1);
|
||||
zassert_equal(fixture->partner_state.bc12_role, BC12_PORTABLE_DEVICE);
|
||||
zassert_equal(fixture->partner_state.type, BC12_TYPE_CDP);
|
||||
zassert_equal(fixture->partner_state.current_ua, 1500 * 1000);
|
||||
zassert_equal(fixture->partner_state.voltage_uv, 5000 * 1000);
|
||||
|
@ -139,6 +146,7 @@ ZTEST_USER_F(bc12_pd_mode, test_bc12_sdp_to_dcp_charging_partner)
|
|||
k_sleep(K_MSEC(100));
|
||||
|
||||
zassert_equal(fixture->callback_count, 1);
|
||||
zassert_equal(fixture->partner_state.bc12_role, BC12_PORTABLE_DEVICE);
|
||||
zassert_equal(fixture->partner_state.type, BC12_TYPE_SDP);
|
||||
zassert_equal(fixture->partner_state.current_ua, 2500);
|
||||
zassert_equal(fixture->partner_state.voltage_uv, 5000 * 1000);
|
||||
|
@ -154,6 +162,7 @@ ZTEST_USER_F(bc12_pd_mode, test_bc12_sdp_to_dcp_charging_partner)
|
|||
|
||||
/* The BC1.2 driver should invoke the callback once to report the new state. */
|
||||
zassert_equal(fixture->callback_count, 1);
|
||||
zassert_equal(fixture->partner_state.bc12_role, BC12_PORTABLE_DEVICE);
|
||||
zassert_equal(fixture->partner_state.type, BC12_TYPE_DCP);
|
||||
zassert_equal(fixture->partner_state.current_ua, 1500 * 1000);
|
||||
zassert_equal(fixture->partner_state.voltage_uv, 5000 * 1000);
|
||||
|
@ -165,9 +174,7 @@ static void bc12_before(void *data)
|
|||
|
||||
fixture->callback_count = 0;
|
||||
fixture->disconnect_detected = 0;
|
||||
fixture->partner_state.type = BC12_TYPE_NONE;
|
||||
fixture->partner_state.current_ua = 0;
|
||||
fixture->partner_state.voltage_uv = 0;
|
||||
memset(&fixture->partner_state, 0, sizeof(struct bc12_partner_state));
|
||||
|
||||
bc12_set_result_cb(fixture->bc12_dev, &bc12_test_result_cb, fixture);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue