From a1d126aa4ee49b300dcfa6efcfd17b703b244e01 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Mon, 27 Jan 2020 14:49:00 -0800 Subject: [PATCH] ucsi: Add usage of USB role switch functionality This change adds usage of USB role switch framework to notify USB role to start USB host/device stack to USB driver. Change-Id: I9778e0e3d2db2aaccf2f19c6dfd2482dad6acbfc Signed-off-by: Mayank Rana --- drivers/usb/typec/ucsi/ucsi.c | 32 ++++++++++++++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 4fc50abccbe1..6b7470719654 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -473,15 +473,19 @@ static void ucsi_unregister_partner(struct ucsi_connector *con) static void ucsi_partner_change(struct ucsi_connector *con) { int ret; + struct ucsi *ucsi = con->ucsi; + enum usb_role u_role = USB_ROLE_NONE; if (!con->partner) return; switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: + u_role = USB_ROLE_HOST; 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: @@ -492,6 +496,11 @@ static void ucsi_partner_change(struct ucsi_connector *con) if (!completion_done(&con->complete)) complete(&con->complete); + ret = usb_role_switch_set_role(ucsi->usb_role_sw, u_role); + if (ret) + dev_err(ucsi->dev, "%s(): failed to set role(%d):%d\n", + __func__, u_role, ret); + /* Can't rely on Partner Flags field. Always checking the alt modes. */ ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); if (ret) @@ -510,6 +519,7 @@ static void ucsi_handle_connector_change(struct work_struct *work) enum typec_role role; u64 command; int ret; + enum usb_role u_role = USB_ROLE_NONE; mutex_lock(&con->lock); @@ -540,9 +550,11 @@ static void ucsi_handle_connector_change(struct work_struct *work) switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: + u_role = USB_ROLE_HOST; 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: @@ -553,6 +565,11 @@ static void ucsi_handle_connector_change(struct work_struct *work) ucsi_register_partner(con); else ucsi_unregister_partner(con); + + ret = usb_role_switch_set_role(ucsi->usb_role_sw, u_role); + if (ret) + dev_err(ucsi->dev, "%s(): failed to set role(%d):%d\n", + __func__, u_role, ret); } if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) { @@ -776,6 +793,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) enum typec_accessory *accessory = cap->accessory; u64 command; int ret; + enum usb_role role = USB_ROLE_NONE; INIT_WORK(&con->work, ucsi_handle_connector_change); init_completion(&con->complete); @@ -840,9 +858,11 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: + role = USB_ROLE_HOST; typec_set_data_role(con->port, TYPEC_HOST); break; case UCSI_CONSTAT_PARTNER_TYPE_DFP: + role = USB_ROLE_DEVICE; typec_set_data_role(con->port, TYPEC_DEVICE); break; default: @@ -857,6 +877,11 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) ucsi_register_partner(con); } + ret = usb_role_switch_set_role(ucsi->usb_role_sw, role); + if (ret) + dev_err(ucsi->dev, "%s(): failed to set role(%d):%d\n", + __func__, role, ret); + if (con->partner) { ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); if (ret) @@ -920,6 +945,13 @@ int ucsi_init(struct ucsi *ucsi) goto err_reset; } + ucsi->usb_role_sw = fwnode_usb_role_switch_get(dev_fwnode(ucsi->dev)); + if (IS_ERR_OR_NULL(ucsi->usb_role_sw)) { + dev_err(ucsi->dev, "%s(): Unable to find usb role switch\n", + __func__); + ucsi->usb_role_sw = NULL; + } + /* Register all connectors */ for (i = 0; i < ucsi->cap.num_connectors; i++) { ret = ucsi_register_port(ucsi, i); diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index cf3f48428bce..b391496072e4 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -7,6 +7,7 @@ #include #include #include +#include /* -------------------------------------------------------------------------- */ @@ -277,6 +278,8 @@ struct ucsi { #define EVENT_PENDING 0 #define COMMAND_PENDING 1 #define ACK_PENDING 2 + + struct usb_role_switch *usb_role_sw; }; #define UCSI_MAX_SVID 5