提交 17aa02be 编写于 作者: G Greg Kroah-Hartman

Merge tag 'tag-ib-usb-typec-chrome-platform-cros-ec-typec-changes-for-5.12' of...

Merge tag 'tag-ib-usb-typec-chrome-platform-cros-ec-typec-changes-for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux into usb-next

Benson writes:

cros-ec-typec changes for usb for v5.12

Chrome OS EC Type-C driver features implemented this round:
* Registration of cable plug information
* Support for SOP' plug registration and altmodes
* Support for reporting number of altmodes supported by partners and plugs
* Send mux configuration ack to EC via a new host command
* Reporting SOP' and Partner PD revisions

* tag 'tag-ib-usb-typec-chrome-platform-cros-ec-typec-changes-for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
  platform/chrome: cros_ec_typec: Set opmode to PD on SOP connected
  platform/chrome: cros_ec_typec: Set Partner PD revision from status
  platform/chrome: cros_ec_typec: Report SOP' PD revision from status
  platform/chrome: cros_ec_typec: Send mux configuration acknowledgment to EC
  platform/chrome: cros_ec_typec: Parameterize cros_typec_cmds_supported()
  platform/chrome: cros_ec_typec: Register plug altmodes
  platform/chrome: cros_ec_typec: Register SOP' cable plug
  platform/chrome: cros_ec_typec: Set partner num_altmodes
  platform/chrome: cros_ec_typec: Store cable plug type
  platform/chrome: cros_ec_typec: Register cable
  platform/chrome: cros_ec_typec: Rename discovery struct
  platform/chrome: cros_ec_typec: Factor out PD identity parsing
  platform/chrome: cros_ec_typec: Make disc_done flag partner-only
...@@ -44,8 +44,13 @@ struct cros_typec_port { ...@@ -44,8 +44,13 @@ struct cros_typec_port {
/* Initial capabilities for the port. */ /* Initial capabilities for the port. */
struct typec_capability caps; struct typec_capability caps;
struct typec_partner *partner; struct typec_partner *partner;
struct typec_cable *cable;
/* SOP' plug. */
struct typec_plug *plug;
/* Port partner PD identity info. */ /* Port partner PD identity info. */
struct usb_pd_identity p_identity; struct usb_pd_identity p_identity;
/* Port cable PD identity info. */
struct usb_pd_identity c_identity;
struct typec_switch *ori_sw; struct typec_switch *ori_sw;
struct typec_mux *mux; struct typec_mux *mux;
struct usb_role_switch *role_sw; struct usb_role_switch *role_sw;
...@@ -57,10 +62,12 @@ struct cros_typec_port { ...@@ -57,10 +62,12 @@ struct cros_typec_port {
/* Port alt modes. */ /* Port alt modes. */
struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX]; struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
/* Flag indicating that PD discovery data parsing is completed. */ /* Flag indicating that PD partner discovery data parsing is completed. */
bool disc_done; bool sop_disc_done;
struct ec_response_typec_discovery *sop_disc; bool sop_prime_disc_done;
struct ec_response_typec_discovery *disc_data;
struct list_head partner_mode_list; struct list_head partner_mode_list;
struct list_head plug_mode_list;
}; };
/* Platform-specific data for the Chrome OS EC Type C controller. */ /* Platform-specific data for the Chrome OS EC Type C controller. */
...@@ -74,6 +81,7 @@ struct cros_typec_data { ...@@ -74,6 +81,7 @@ struct cros_typec_data {
struct notifier_block nb; struct notifier_block nb;
struct work_struct port_work; struct work_struct port_work;
bool typec_cmd_supported; bool typec_cmd_supported;
bool needs_mux_ack;
}; };
static int cros_typec_parse_port_props(struct typec_capability *cap, static int cros_typec_parse_port_props(struct typec_capability *cap,
...@@ -180,12 +188,15 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num, ...@@ -180,12 +188,15 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
return ret; return ret;
} }
static void cros_typec_unregister_altmodes(struct cros_typec_data *typec, int port_num) static void cros_typec_unregister_altmodes(struct cros_typec_data *typec, int port_num,
bool is_partner)
{ {
struct cros_typec_port *port = typec->ports[port_num]; struct cros_typec_port *port = typec->ports[port_num];
struct cros_typec_altmode_node *node, *tmp; struct cros_typec_altmode_node *node, *tmp;
struct list_head *head;
list_for_each_entry_safe(node, tmp, &port->partner_mode_list, list) { head = is_partner ? &port->partner_mode_list : &port->plug_mode_list;
list_for_each_entry_safe(node, tmp, head, list) {
list_del(&node->list); list_del(&node->list);
typec_unregister_altmode(node->amode); typec_unregister_altmode(node->amode);
devm_kfree(typec->dev, node); devm_kfree(typec->dev, node);
...@@ -197,7 +208,7 @@ static void cros_typec_remove_partner(struct cros_typec_data *typec, ...@@ -197,7 +208,7 @@ static void cros_typec_remove_partner(struct cros_typec_data *typec,
{ {
struct cros_typec_port *port = typec->ports[port_num]; struct cros_typec_port *port = typec->ports[port_num];
cros_typec_unregister_altmodes(typec, port_num); cros_typec_unregister_altmodes(typec, port_num, true);
port->state.alt = NULL; port->state.alt = NULL;
port->state.mode = TYPEC_STATE_USB; port->state.mode = TYPEC_STATE_USB;
...@@ -210,7 +221,22 @@ static void cros_typec_remove_partner(struct cros_typec_data *typec, ...@@ -210,7 +221,22 @@ static void cros_typec_remove_partner(struct cros_typec_data *typec,
typec_unregister_partner(port->partner); typec_unregister_partner(port->partner);
port->partner = NULL; port->partner = NULL;
memset(&port->p_identity, 0, sizeof(port->p_identity)); memset(&port->p_identity, 0, sizeof(port->p_identity));
port->disc_done = false; port->sop_disc_done = false;
}
static void cros_typec_remove_cable(struct cros_typec_data *typec,
int port_num)
{
struct cros_typec_port *port = typec->ports[port_num];
cros_typec_unregister_altmodes(typec, port_num, false);
typec_unregister_plug(port->plug);
port->plug = NULL;
typec_unregister_cable(port->cable);
port->cable = NULL;
memset(&port->c_identity, 0, sizeof(port->c_identity));
port->sop_prime_disc_done = false;
} }
static void cros_unregister_ports(struct cros_typec_data *typec) static void cros_unregister_ports(struct cros_typec_data *typec)
...@@ -224,6 +250,9 @@ static void cros_unregister_ports(struct cros_typec_data *typec) ...@@ -224,6 +250,9 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
if (typec->ports[i]->partner) if (typec->ports[i]->partner)
cros_typec_remove_partner(typec, i); cros_typec_remove_partner(typec, i);
if (typec->ports[i]->cable)
cros_typec_remove_cable(typec, i);
usb_role_switch_put(typec->ports[i]->role_sw); usb_role_switch_put(typec->ports[i]->role_sw);
typec_switch_put(typec->ports[i]->ori_sw); typec_switch_put(typec->ports[i]->ori_sw);
typec_mux_put(typec->ports[i]->mux); typec_mux_put(typec->ports[i]->mux);
...@@ -323,13 +352,14 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) ...@@ -323,13 +352,14 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
cros_typec_register_port_altmodes(typec, port_num); cros_typec_register_port_altmodes(typec, port_num);
cros_port->sop_disc = devm_kzalloc(dev, EC_PROTO2_MAX_RESPONSE_SIZE, GFP_KERNEL); cros_port->disc_data = devm_kzalloc(dev, EC_PROTO2_MAX_RESPONSE_SIZE, GFP_KERNEL);
if (!cros_port->sop_disc) { if (!cros_port->disc_data) {
ret = -ENOMEM; ret = -ENOMEM;
goto unregister_ports; goto unregister_ports;
} }
INIT_LIST_HEAD(&cros_port->partner_mode_list); INIT_LIST_HEAD(&cros_port->partner_mode_list);
INIT_LIST_HEAD(&cros_port->plug_mode_list);
} }
return 0; return 0;
...@@ -502,6 +532,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ...@@ -502,6 +532,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
struct ec_response_usb_pd_control_v2 *pd_ctrl) struct ec_response_usb_pd_control_v2 *pd_ctrl)
{ {
struct cros_typec_port *port = typec->ports[port_num]; struct cros_typec_port *port = typec->ports[port_num];
struct ec_params_usb_pd_mux_ack mux_ack;
enum typec_orientation orientation; enum typec_orientation orientation;
int ret; int ret;
...@@ -541,6 +572,18 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ...@@ -541,6 +572,18 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
mux_flags); mux_flags);
} }
if (!typec->needs_mux_ack)
return ret;
/* Sending Acknowledgment to EC */
mux_ack.port = port_num;
if (cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_ACK, &mux_ack,
sizeof(mux_ack), NULL, 0) < 0)
dev_warn(typec->dev,
"Failed to send Mux ACK to EC for port: %d\n",
port_num);
return ret; return ret;
} }
...@@ -598,6 +641,9 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec, ...@@ -598,6 +641,9 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
if (!typec->ports[port_num]->partner) if (!typec->ports[port_num]->partner)
return; return;
cros_typec_remove_partner(typec, port_num); cros_typec_remove_partner(typec, port_num);
if (typec->ports[port_num]->cable)
cros_typec_remove_cable(typec, port_num);
} }
} }
...@@ -612,13 +658,18 @@ static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num, ...@@ -612,13 +658,18 @@ static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
sizeof(req), resp, sizeof(*resp)); sizeof(req), resp, sizeof(*resp));
} }
static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_num) /*
* Helper function to register partner/plug altmodes.
*/
static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_num,
bool is_partner)
{ {
struct cros_typec_port *port = typec->ports[port_num]; struct cros_typec_port *port = typec->ports[port_num];
struct ec_response_typec_discovery *sop_disc = port->sop_disc; struct ec_response_typec_discovery *sop_disc = port->disc_data;
struct cros_typec_altmode_node *node; struct cros_typec_altmode_node *node;
struct typec_altmode_desc desc; struct typec_altmode_desc desc;
struct typec_altmode *amode; struct typec_altmode *amode;
int num_altmodes = 0;
int ret = 0; int ret = 0;
int i, j; int i, j;
...@@ -629,7 +680,11 @@ static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_ ...@@ -629,7 +680,11 @@ static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_
desc.mode = j; desc.mode = j;
desc.vdo = sop_disc->svids[i].mode_vdo[j]; desc.vdo = sop_disc->svids[i].mode_vdo[j];
amode = typec_partner_register_altmode(port->partner, &desc); if (is_partner)
amode = typec_partner_register_altmode(port->partner, &desc);
else
amode = typec_plug_register_altmode(port->plug, &desc);
if (IS_ERR(amode)) { if (IS_ERR(amode)) {
ret = PTR_ERR(amode); ret = PTR_ERR(amode);
goto err_cleanup; goto err_cleanup;
...@@ -644,27 +699,140 @@ static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_ ...@@ -644,27 +699,140 @@ static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_
} }
node->amode = amode; node->amode = amode;
list_add_tail(&node->list, &port->partner_mode_list);
if (is_partner)
list_add_tail(&node->list, &port->partner_mode_list);
else
list_add_tail(&node->list, &port->plug_mode_list);
num_altmodes++;
} }
} }
if (is_partner)
ret = typec_partner_set_num_altmodes(port->partner, num_altmodes);
else
ret = typec_plug_set_num_altmodes(port->plug, num_altmodes);
if (ret < 0) {
dev_err(typec->dev, "Unable to set %s num_altmodes for port: %d\n",
is_partner ? "partner" : "plug", port_num);
goto err_cleanup;
}
return 0; return 0;
err_cleanup: err_cleanup:
cros_typec_unregister_altmodes(typec, port_num); cros_typec_unregister_altmodes(typec, port_num, is_partner);
return ret; return ret;
} }
static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_num) /*
* Parse the PD identity data from the EC PD discovery responses and copy that to the supplied
* PD identity struct.
*/
static void cros_typec_parse_pd_identity(struct usb_pd_identity *id,
struct ec_response_typec_discovery *disc)
{
int i;
/* First, update the PD identity VDOs for the partner. */
if (disc->identity_count > 0)
id->id_header = disc->discovery_vdo[0];
if (disc->identity_count > 1)
id->cert_stat = disc->discovery_vdo[1];
if (disc->identity_count > 2)
id->product = disc->discovery_vdo[2];
/* Copy the remaining identity VDOs till a maximum of 6. */
for (i = 3; i < disc->identity_count && i < VDO_MAX_OBJECTS; i++)
id->vdo[i - 3] = disc->discovery_vdo[i];
}
static int cros_typec_handle_sop_prime_disc(struct cros_typec_data *typec, int port_num, u16 pd_revision)
{ {
struct cros_typec_port *port = typec->ports[port_num]; struct cros_typec_port *port = typec->ports[port_num];
struct ec_response_typec_discovery *sop_disc = port->sop_disc; struct ec_response_typec_discovery *disc = port->disc_data;
struct typec_cable_desc c_desc = {};
struct typec_plug_desc p_desc;
struct ec_params_typec_discovery req = {
.port = port_num,
.partner_type = TYPEC_PARTNER_SOP_PRIME,
};
u32 cable_plug_type;
int ret = 0;
memset(disc, 0, EC_PROTO2_MAX_RESPONSE_SIZE);
ret = cros_typec_ec_command(typec, 0, EC_CMD_TYPEC_DISCOVERY, &req, sizeof(req),
disc, EC_PROTO2_MAX_RESPONSE_SIZE);
if (ret < 0) {
dev_err(typec->dev, "Failed to get SOP' discovery data for port: %d\n", port_num);
goto sop_prime_disc_exit;
}
/* Parse the PD identity data, even if only 0s were returned. */
cros_typec_parse_pd_identity(&port->c_identity, disc);
if (disc->identity_count != 0) {
cable_plug_type = VDO_TYPEC_CABLE_TYPE(port->c_identity.vdo[0]);
switch (cable_plug_type) {
case CABLE_ATYPE:
c_desc.type = USB_PLUG_TYPE_A;
break;
case CABLE_BTYPE:
c_desc.type = USB_PLUG_TYPE_B;
break;
case CABLE_CTYPE:
c_desc.type = USB_PLUG_TYPE_C;
break;
case CABLE_CAPTIVE:
c_desc.type = USB_PLUG_CAPTIVE;
break;
default:
c_desc.type = USB_PLUG_NONE;
}
c_desc.active = PD_IDH_PTYPE(port->c_identity.id_header) == IDH_PTYPE_ACABLE;
}
c_desc.identity = &port->c_identity;
c_desc.pd_revision = pd_revision;
port->cable = typec_register_cable(port->port, &c_desc);
if (IS_ERR(port->cable)) {
ret = PTR_ERR(port->cable);
port->cable = NULL;
goto sop_prime_disc_exit;
}
p_desc.index = TYPEC_PLUG_SOP_P;
port->plug = typec_register_plug(port->cable, &p_desc);
if (IS_ERR(port->plug)) {
ret = PTR_ERR(port->plug);
port->plug = NULL;
goto sop_prime_disc_exit;
}
ret = cros_typec_register_altmodes(typec, port_num, false);
if (ret < 0) {
dev_err(typec->dev, "Failed to register plug altmodes, port: %d\n", port_num);
goto sop_prime_disc_exit;
}
return 0;
sop_prime_disc_exit:
cros_typec_remove_cable(typec, port_num);
return ret;
}
static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_num, u16 pd_revision)
{
struct cros_typec_port *port = typec->ports[port_num];
struct ec_response_typec_discovery *sop_disc = port->disc_data;
struct ec_params_typec_discovery req = { struct ec_params_typec_discovery req = {
.port = port_num, .port = port_num,
.partner_type = TYPEC_PARTNER_SOP, .partner_type = TYPEC_PARTNER_SOP,
}; };
int ret = 0; int ret = 0;
int i;
if (!port->partner) { if (!port->partner) {
dev_err(typec->dev, dev_err(typec->dev,
...@@ -674,6 +842,12 @@ static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_nu ...@@ -674,6 +842,12 @@ static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_nu
goto disc_exit; goto disc_exit;
} }
ret = typec_partner_set_pd_revision(port->partner, pd_revision);
if (ret < 0) {
dev_err(typec->dev, "Failed to update partner PD revision, port: %d\n", port_num);
goto disc_exit;
}
memset(sop_disc, 0, EC_PROTO2_MAX_RESPONSE_SIZE); memset(sop_disc, 0, EC_PROTO2_MAX_RESPONSE_SIZE);
ret = cros_typec_ec_command(typec, 0, EC_CMD_TYPEC_DISCOVERY, &req, sizeof(req), ret = cros_typec_ec_command(typec, 0, EC_CMD_TYPEC_DISCOVERY, &req, sizeof(req),
sop_disc, EC_PROTO2_MAX_RESPONSE_SIZE); sop_disc, EC_PROTO2_MAX_RESPONSE_SIZE);
...@@ -682,17 +856,7 @@ static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_nu ...@@ -682,17 +856,7 @@ static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_nu
goto disc_exit; goto disc_exit;
} }
/* First, update the PD identity VDOs for the partner. */ cros_typec_parse_pd_identity(&port->p_identity, sop_disc);
if (sop_disc->identity_count > 0)
port->p_identity.id_header = sop_disc->discovery_vdo[0];
if (sop_disc->identity_count > 1)
port->p_identity.cert_stat = sop_disc->discovery_vdo[1];
if (sop_disc->identity_count > 2)
port->p_identity.product = sop_disc->discovery_vdo[2];
/* Copy the remaining identity VDOs till a maximum of 6. */
for (i = 3; i < sop_disc->identity_count && i < VDO_MAX_OBJECTS; i++)
port->p_identity.vdo[i - 3] = sop_disc->discovery_vdo[i];
ret = typec_partner_set_identity(port->partner); ret = typec_partner_set_identity(port->partner);
if (ret < 0) { if (ret < 0) {
...@@ -700,7 +864,7 @@ static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_nu ...@@ -700,7 +864,7 @@ static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_nu
goto disc_exit; goto disc_exit;
} }
ret = cros_typec_register_altmodes(typec, port_num); ret = cros_typec_register_altmodes(typec, port_num, true);
if (ret < 0) { if (ret < 0) {
dev_err(typec->dev, "Failed to register partner altmodes, port: %d\n", port_num); dev_err(typec->dev, "Failed to register partner altmodes, port: %d\n", port_num);
goto disc_exit; goto disc_exit;
...@@ -725,18 +889,33 @@ static void cros_typec_handle_status(struct cros_typec_data *typec, int port_num ...@@ -725,18 +889,33 @@ static void cros_typec_handle_status(struct cros_typec_data *typec, int port_num
return; return;
} }
if (typec->ports[port_num]->disc_done)
return;
/* Handle any events appropriately. */ /* Handle any events appropriately. */
if (resp.events & PD_STATUS_EVENT_SOP_DISC_DONE) { if (resp.events & PD_STATUS_EVENT_SOP_DISC_DONE && !typec->ports[port_num]->sop_disc_done) {
ret = cros_typec_handle_sop_disc(typec, port_num); u16 sop_revision;
if (ret < 0) {
/* Convert BCD to the format preferred by the TypeC framework */
sop_revision = (le16_to_cpu(resp.sop_revision) & 0xff00) >> 4;
ret = cros_typec_handle_sop_disc(typec, port_num, sop_revision);
if (ret < 0)
dev_err(typec->dev, "Couldn't parse SOP Disc data, port: %d\n", port_num); dev_err(typec->dev, "Couldn't parse SOP Disc data, port: %d\n", port_num);
return; else
} typec->ports[port_num]->sop_disc_done = true;
typec->ports[port_num]->disc_done = true; if (resp.sop_connected)
typec_set_pwr_opmode(typec->ports[port_num]->port, TYPEC_PWR_MODE_PD);
}
if (resp.events & PD_STATUS_EVENT_SOP_PRIME_DISC_DONE &&
!typec->ports[port_num]->sop_prime_disc_done) {
u16 sop_prime_revision;
/* Convert BCD to the format preferred by the TypeC framework */
sop_prime_revision = (le16_to_cpu(resp.sop_prime_revision) & 0xff00) >> 4;
ret = cros_typec_handle_sop_prime_disc(typec, port_num, sop_prime_revision);
if (ret < 0)
dev_err(typec->dev, "Couldn't parse SOP' Disc data, port: %d\n", port_num);
else
typec->ports[port_num]->sop_prime_disc_done = true;
} }
} }
...@@ -827,8 +1006,8 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec) ...@@ -827,8 +1006,8 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
return 0; return 0;
} }
/* Check the EC feature flags to see if TYPEC_* commands are supported. */ /* Check the EC feature flags to see if TYPEC_* features are supported. */
static int cros_typec_cmds_supported(struct cros_typec_data *typec) static int cros_typec_feature_supported(struct cros_typec_data *typec, enum ec_feature_code feature)
{ {
struct ec_response_get_features resp = {}; struct ec_response_get_features resp = {};
int ret; int ret;
...@@ -837,11 +1016,12 @@ static int cros_typec_cmds_supported(struct cros_typec_data *typec) ...@@ -837,11 +1016,12 @@ static int cros_typec_cmds_supported(struct cros_typec_data *typec)
&resp, sizeof(resp)); &resp, sizeof(resp));
if (ret < 0) { if (ret < 0) {
dev_warn(typec->dev, dev_warn(typec->dev,
"Failed to get features, assuming typec commands unsupported.\n"); "Failed to get features, assuming typec feature=%d unsupported.\n",
feature);
return 0; return 0;
} }
return resp.flags[EC_FEATURE_TYPEC_CMD / 32] & EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_CMD); return resp.flags[feature / 32] & EC_FEATURE_MASK_1(feature);
} }
static void cros_typec_port_work(struct work_struct *work) static void cros_typec_port_work(struct work_struct *work)
...@@ -903,7 +1083,10 @@ static int cros_typec_probe(struct platform_device *pdev) ...@@ -903,7 +1083,10 @@ static int cros_typec_probe(struct platform_device *pdev)
return ret; return ret;
} }
typec->typec_cmd_supported = !!cros_typec_cmds_supported(typec); typec->typec_cmd_supported = !!cros_typec_feature_supported(typec,
EC_FEATURE_TYPEC_CMD);
typec->needs_mux_ack = !!cros_typec_feature_supported(typec,
EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK);
ret = cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_PORTS, NULL, 0, ret = cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_PORTS, NULL, 0,
&resp, sizeof(resp)); &resp, sizeof(resp));
......
...@@ -1286,6 +1286,16 @@ enum ec_feature_code { ...@@ -1286,6 +1286,16 @@ enum ec_feature_code {
EC_FEATURE_ISH = 40, EC_FEATURE_ISH = 40,
/* New TCPMv2 TYPEC_ prefaced commands supported */ /* New TCPMv2 TYPEC_ prefaced commands supported */
EC_FEATURE_TYPEC_CMD = 41, EC_FEATURE_TYPEC_CMD = 41,
/*
* The EC will wait for direction from the AP to enter Type-C alternate
* modes or USB4.
*/
EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY = 42,
/*
* The EC will wait for an acknowledge from the AP after setting the
* mux.
*/
EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK = 43,
}; };
#define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32) #define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32)
...@@ -6054,6 +6064,13 @@ struct ec_params_charger_control { ...@@ -6054,6 +6064,13 @@ struct ec_params_charger_control {
uint8_t allow_charging; uint8_t allow_charging;
} __ec_align_size1; } __ec_align_size1;
/* Get ACK from the USB-C SS muxes */
#define EC_CMD_USB_PD_MUX_ACK 0x0603
struct ec_params_usb_pd_mux_ack {
uint8_t port; /* USB-C port number */
} __ec_align1;
/*****************************************************************************/ /*****************************************************************************/
/* /*
* Reserve a range of host commands for board-specific, experimental, or * Reserve a range of host commands for board-specific, experimental, or
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册