diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index b153ed5bffb1..7129973f19e7 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1624,71 +1624,11 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con) return NULL; } -static void ucsi_init_port(struct ucsi *ucsi, struct ucsi_connector *con) -{ - enum usb_role u_role = USB_ROLE_NONE; - int ret; - - /* Get the status */ - ret = ucsi_get_connector_status(con, false); - if (ret) { - dev_err(ucsi->dev, "con%d: failed to get status\n", con->num); - return; - } - - if (ucsi->ops->connector_status) - ucsi->ops->connector_status(con); - - switch (UCSI_CONSTAT(con, PARTNER_TYPE)) { - case UCSI_CONSTAT_PARTNER_TYPE_UFP: - case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: - u_role = USB_ROLE_HOST; - fallthrough; - case UCSI_CONSTAT_PARTNER_TYPE_CABLE: - typec_set_data_role(con->port, TYPEC_HOST); - break; - case UCSI_CONSTAT_PARTNER_TYPE_DFP: - u_role = USB_ROLE_DEVICE; - typec_set_data_role(con->port, TYPEC_DEVICE); - break; - default: - break; - } - - /* Check if there is already something connected */ - if (UCSI_CONSTAT(con, CONNECTED)) { - typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR)); - ucsi_register_partner(con); - ucsi_pwr_opmode_change(con); - ucsi_orientation(con); - ucsi_port_psy_changed(con); - if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) - ucsi_get_partner_identity(con); - if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS) - ucsi_check_cable(con); - } - - /* Only notify USB controller if partner supports USB data */ - if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB))) - u_role = USB_ROLE_NONE; - - ret = usb_role_switch_set_role(con->usb_role_sw, u_role); - if (ret) - dev_err(ucsi->dev, "con:%d: failed to set usb role:%d\n", - con->num, u_role); - - if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) { - ucsi_register_device_pdos(con); - ucsi_get_src_pdos(con); - ucsi_check_altmodes(con); - ucsi_check_connector_capability(con); - } -} - static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) { struct typec_capability *cap = &con->typec_cap; enum typec_accessory *accessory = cap->accessory; + enum usb_role u_role = USB_ROLE_NONE; u64 command; char *name; int ret; @@ -1789,6 +1729,63 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) goto out; } + /* Get the status */ + ret = ucsi_get_connector_status(con, false); + if (ret) { + dev_err(ucsi->dev, "con%d: failed to get status\n", con->num); + goto out; + } + + if (ucsi->ops->connector_status) + ucsi->ops->connector_status(con); + + switch (UCSI_CONSTAT(con, PARTNER_TYPE)) { + case UCSI_CONSTAT_PARTNER_TYPE_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: + u_role = USB_ROLE_HOST; + fallthrough; + case UCSI_CONSTAT_PARTNER_TYPE_CABLE: + typec_set_data_role(con->port, TYPEC_HOST); + break; + case UCSI_CONSTAT_PARTNER_TYPE_DFP: + u_role = USB_ROLE_DEVICE; + typec_set_data_role(con->port, TYPEC_DEVICE); + break; + default: + break; + } + + /* Check if there is already something connected */ + if (UCSI_CONSTAT(con, CONNECTED)) { + typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR)); + ucsi_register_partner(con); + ucsi_pwr_opmode_change(con); + ucsi_orientation(con); + ucsi_port_psy_changed(con); + if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) + ucsi_get_partner_identity(con); + if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS) + ucsi_check_cable(con); + } + + /* Only notify USB controller if partner supports USB data */ + if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB))) + u_role = USB_ROLE_NONE; + + ret = usb_role_switch_set_role(con->usb_role_sw, u_role); + if (ret) { + dev_err(ucsi->dev, "con:%d: failed to set usb role:%d\n", + con->num, u_role); + ret = 0; + } + + if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) { + ucsi_register_device_pdos(con); + ucsi_get_src_pdos(con); + ucsi_check_altmodes(con); + ucsi_check_connector_capability(con); + } + trace_ucsi_register_port(con->num, con); out: @@ -1906,29 +1903,17 @@ static int ucsi_init(struct ucsi *ucsi) goto err_unregister; } - /* Delay other interactions with each connector until ucsi_init_port is done */ - for (i = 0; i < ucsi->cap.num_connectors; i++) - mutex_lock(&connector[i].lock); - /* Enable all supported notifications */ ntfy = ucsi_get_supported_notifications(ucsi); command = UCSI_SET_NOTIFICATION_ENABLE | ntfy; ucsi->message_in_size = 0; ret = ucsi_send_command(ucsi, command); - if (ret < 0) { - for (i = 0; i < ucsi->cap.num_connectors; i++) - mutex_unlock(&connector[i].lock); + if (ret < 0) goto err_unregister; - } ucsi->connector = connector; ucsi->ntfy = ntfy; - for (i = 0; i < ucsi->cap.num_connectors; i++) { - ucsi_init_port(ucsi, &connector[i]); - mutex_unlock(&connector[i].lock); - } - mutex_lock(&ucsi->ppm_lock); ret = ucsi->ops->read_cci(ucsi, &cci); mutex_unlock(&ucsi->ppm_lock);