Commit ceeb1625 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman

usb: typec: Separate the definitions for data and power roles

USB Type-C specification v1.2 separated the power and data
roles more clearly. Dual-Role-Data term was introduced, and
the meaning of DRP was changed from "Dual-Role-Port" to
"Dual-Role-Power".

In order to allow the port drivers to describe the
capabilities of the ports more clearly according to the
newest specifications, introducing separate definitions for
the data roles.
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fde0aa6c
...@@ -282,10 +282,10 @@ typec_altmode_roles_show(struct device *dev, struct device_attribute *attr, ...@@ -282,10 +282,10 @@ typec_altmode_roles_show(struct device *dev, struct device_attribute *attr,
ssize_t ret; ssize_t ret;
switch (mode->roles) { switch (mode->roles) {
case TYPEC_PORT_DFP: case TYPEC_PORT_SRC:
ret = sprintf(buf, "source\n"); ret = sprintf(buf, "source\n");
break; break;
case TYPEC_PORT_UFP: case TYPEC_PORT_SNK:
ret = sprintf(buf, "sink\n"); ret = sprintf(buf, "sink\n");
break; break;
case TYPEC_PORT_DRP: case TYPEC_PORT_DRP:
...@@ -797,14 +797,14 @@ static const char * const typec_data_roles[] = { ...@@ -797,14 +797,14 @@ static const char * const typec_data_roles[] = {
}; };
static const char * const typec_port_types[] = { static const char * const typec_port_types[] = {
[TYPEC_PORT_DFP] = "source", [TYPEC_PORT_SRC] = "source",
[TYPEC_PORT_UFP] = "sink", [TYPEC_PORT_SNK] = "sink",
[TYPEC_PORT_DRP] = "dual", [TYPEC_PORT_DRP] = "dual",
}; };
static const char * const typec_port_types_drp[] = { static const char * const typec_port_types_drp[] = {
[TYPEC_PORT_DFP] = "dual [source] sink", [TYPEC_PORT_SRC] = "dual [source] sink",
[TYPEC_PORT_UFP] = "dual source [sink]", [TYPEC_PORT_SNK] = "dual source [sink]",
[TYPEC_PORT_DRP] = "[dual] source sink", [TYPEC_PORT_DRP] = "[dual] source sink",
}; };
...@@ -875,9 +875,7 @@ static ssize_t data_role_store(struct device *dev, ...@@ -875,9 +875,7 @@ static ssize_t data_role_store(struct device *dev,
return ret; return ret;
mutex_lock(&port->port_type_lock); mutex_lock(&port->port_type_lock);
if (port->port_type != TYPEC_PORT_DRP) { if (port->cap->data != TYPEC_PORT_DRD) {
dev_dbg(dev, "port type fixed at \"%s\"",
typec_port_types[port->port_type]);
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
goto unlock_and_ret; goto unlock_and_ret;
} }
...@@ -897,7 +895,7 @@ static ssize_t data_role_show(struct device *dev, ...@@ -897,7 +895,7 @@ static ssize_t data_role_show(struct device *dev,
{ {
struct typec_port *port = to_typec_port(dev); struct typec_port *port = to_typec_port(dev);
if (port->cap->type == TYPEC_PORT_DRP) if (port->cap->data == TYPEC_PORT_DRD)
return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ? return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ?
"[host] device" : "host [device]"); "[host] device" : "host [device]");
...@@ -1328,7 +1326,6 @@ struct typec_port *typec_register_port(struct device *parent, ...@@ -1328,7 +1326,6 @@ struct typec_port *typec_register_port(struct device *parent,
const struct typec_capability *cap) const struct typec_capability *cap)
{ {
struct typec_port *port; struct typec_port *port;
int role;
int ret; int ret;
int id; int id;
...@@ -1354,21 +1351,36 @@ struct typec_port *typec_register_port(struct device *parent, ...@@ -1354,21 +1351,36 @@ struct typec_port *typec_register_port(struct device *parent,
goto err_mux; goto err_mux;
} }
if (cap->type == TYPEC_PORT_DFP) switch (cap->type) {
role = TYPEC_SOURCE; case TYPEC_PORT_SRC:
else if (cap->type == TYPEC_PORT_UFP)
role = TYPEC_SINK;
else
role = cap->prefer_role;
if (role == TYPEC_SOURCE) {
port->data_role = TYPEC_HOST;
port->pwr_role = TYPEC_SOURCE; port->pwr_role = TYPEC_SOURCE;
port->vconn_role = TYPEC_SOURCE; port->vconn_role = TYPEC_SOURCE;
} else { break;
port->data_role = TYPEC_DEVICE; case TYPEC_PORT_SNK:
port->pwr_role = TYPEC_SINK; port->pwr_role = TYPEC_SINK;
port->vconn_role = TYPEC_SINK; port->vconn_role = TYPEC_SINK;
break;
case TYPEC_PORT_DRP:
if (cap->prefer_role != TYPEC_NO_PREFERRED_ROLE)
port->pwr_role = cap->prefer_role;
else
port->pwr_role = TYPEC_SINK;
break;
}
switch (cap->data) {
case TYPEC_PORT_DFP:
port->data_role = TYPEC_HOST;
break;
case TYPEC_PORT_UFP:
port->data_role = TYPEC_DEVICE;
break;
case TYPEC_PORT_DRD:
if (cap->prefer_role == TYPEC_SOURCE)
port->data_role = TYPEC_HOST;
else
port->data_role = TYPEC_DEVICE;
break;
} }
port->id = id; port->id = id;
......
...@@ -1219,6 +1219,7 @@ static const struct tcpc_config fusb302_tcpc_config = { ...@@ -1219,6 +1219,7 @@ static const struct tcpc_config fusb302_tcpc_config = {
.max_snk_mw = 15000, .max_snk_mw = 15000,
.operating_snk_mw = 2500, .operating_snk_mw = 2500,
.type = TYPEC_PORT_DRP, .type = TYPEC_PORT_DRP,
.data = TYPEC_PORT_DRD,
.default_role = TYPEC_SINK, .default_role = TYPEC_SINK,
.alt_modes = NULL, .alt_modes = NULL,
}; };
......
...@@ -345,7 +345,7 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port) ...@@ -345,7 +345,7 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
else if (port->tcpc->config->default_role == TYPEC_SINK) else if (port->tcpc->config->default_role == TYPEC_SINK)
return SNK_UNATTACHED; return SNK_UNATTACHED;
/* Fall through to return SRC_UNATTACHED */ /* Fall through to return SRC_UNATTACHED */
} else if (port->port_type == TYPEC_PORT_UFP) { } else if (port->port_type == TYPEC_PORT_SNK) {
return SNK_UNATTACHED; return SNK_UNATTACHED;
} }
return SRC_UNATTACHED; return SRC_UNATTACHED;
...@@ -2179,7 +2179,7 @@ static inline enum tcpm_state unattached_state(struct tcpm_port *port) ...@@ -2179,7 +2179,7 @@ static inline enum tcpm_state unattached_state(struct tcpm_port *port)
return SRC_UNATTACHED; return SRC_UNATTACHED;
else else
return SNK_UNATTACHED; return SNK_UNATTACHED;
} else if (port->port_type == TYPEC_PORT_DFP) { } else if (port->port_type == TYPEC_PORT_SRC) {
return SRC_UNATTACHED; return SRC_UNATTACHED;
} }
...@@ -3469,11 +3469,11 @@ static int tcpm_port_type_set(const struct typec_capability *cap, ...@@ -3469,11 +3469,11 @@ static int tcpm_port_type_set(const struct typec_capability *cap,
if (!port->connected) { if (!port->connected) {
tcpm_set_state(port, PORT_RESET, 0); tcpm_set_state(port, PORT_RESET, 0);
} else if (type == TYPEC_PORT_UFP) { } else if (type == TYPEC_PORT_SNK) {
if (!(port->pwr_role == TYPEC_SINK && if (!(port->pwr_role == TYPEC_SINK &&
port->data_role == TYPEC_DEVICE)) port->data_role == TYPEC_DEVICE))
tcpm_set_state(port, PORT_RESET, 0); tcpm_set_state(port, PORT_RESET, 0);
} else if (type == TYPEC_PORT_DFP) { } else if (type == TYPEC_PORT_SRC) {
if (!(port->pwr_role == TYPEC_SOURCE && if (!(port->pwr_role == TYPEC_SOURCE &&
port->data_role == TYPEC_HOST)) port->data_role == TYPEC_HOST))
tcpm_set_state(port, PORT_RESET, 0); tcpm_set_state(port, PORT_RESET, 0);
...@@ -3641,6 +3641,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) ...@@ -3641,6 +3641,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
port->typec_caps.prefer_role = tcpc->config->default_role; port->typec_caps.prefer_role = tcpc->config->default_role;
port->typec_caps.type = tcpc->config->type; port->typec_caps.type = tcpc->config->type;
port->typec_caps.data = tcpc->config->data;
port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */ port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */
port->typec_caps.pd_revision = 0x0200; /* USB-PD spec release 2.0 */ port->typec_caps.pd_revision = 0x0200; /* USB-PD spec release 2.0 */
port->typec_caps.dr_set = tcpm_dr_set; port->typec_caps.dr_set = tcpm_dr_set;
......
...@@ -393,31 +393,39 @@ static int tps6598x_probe(struct i2c_client *client) ...@@ -393,31 +393,39 @@ static int tps6598x_probe(struct i2c_client *client)
if (ret < 0) if (ret < 0)
return ret; return ret;
tps->typec_cap.revision = USB_TYPEC_REV_1_2;
tps->typec_cap.pd_revision = 0x200;
tps->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
tps->typec_cap.pr_set = tps6598x_pr_set;
tps->typec_cap.dr_set = tps6598x_dr_set;
switch (TPS_SYSCONF_PORTINFO(conf)) { switch (TPS_SYSCONF_PORTINFO(conf)) {
case TPS_PORTINFO_SINK_ACCESSORY: case TPS_PORTINFO_SINK_ACCESSORY:
case TPS_PORTINFO_SINK: case TPS_PORTINFO_SINK:
tps->typec_cap.type = TYPEC_PORT_UFP; tps->typec_cap.type = TYPEC_PORT_SNK;
tps->typec_cap.data = TYPEC_PORT_UFP;
break; break;
case TPS_PORTINFO_DRP_UFP_DRD: case TPS_PORTINFO_DRP_UFP_DRD:
case TPS_PORTINFO_DRP_DFP_DRD: case TPS_PORTINFO_DRP_DFP_DRD:
tps->typec_cap.dr_set = tps6598x_dr_set; tps->typec_cap.type = TYPEC_PORT_DRP;
/* fall through */ tps->typec_cap.data = TYPEC_PORT_DRD;
break;
case TPS_PORTINFO_DRP_UFP: case TPS_PORTINFO_DRP_UFP:
tps->typec_cap.type = TYPEC_PORT_DRP;
tps->typec_cap.data = TYPEC_PORT_UFP;
break;
case TPS_PORTINFO_DRP_DFP: case TPS_PORTINFO_DRP_DFP:
tps->typec_cap.pr_set = tps6598x_pr_set;
tps->typec_cap.type = TYPEC_PORT_DRP; tps->typec_cap.type = TYPEC_PORT_DRP;
tps->typec_cap.data = TYPEC_PORT_DFP;
break; break;
case TPS_PORTINFO_SOURCE: case TPS_PORTINFO_SOURCE:
tps->typec_cap.type = TYPEC_PORT_DFP; tps->typec_cap.type = TYPEC_PORT_SRC;
tps->typec_cap.data = TYPEC_PORT_DFP;
break; break;
default: default:
return -ENODEV; return -ENODEV;
} }
tps->typec_cap.revision = USB_TYPEC_REV_1_2;
tps->typec_cap.pd_revision = 0x200;
tps->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
tps->port = typec_register_port(&client->dev, &tps->typec_cap); tps->port = typec_register_port(&client->dev, &tps->typec_cap);
if (IS_ERR(tps->port)) if (IS_ERR(tps->port))
return PTR_ERR(tps->port); return PTR_ERR(tps->port);
......
...@@ -572,6 +572,7 @@ static struct tcpc_config wcove_typec_config = { ...@@ -572,6 +572,7 @@ static struct tcpc_config wcove_typec_config = {
.operating_snk_mw = 15000, .operating_snk_mw = 15000,
.type = TYPEC_PORT_DRP, .type = TYPEC_PORT_DRP,
.data = TYPEC_PORT_DRD,
.default_role = TYPEC_SINK, .default_role = TYPEC_SINK,
}; };
......
...@@ -592,11 +592,18 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) ...@@ -592,11 +592,18 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
return ret; return ret;
if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP) if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
cap->type = TYPEC_PORT_DRP; cap->data = TYPEC_PORT_DRD;
else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP) else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
cap->type = TYPEC_PORT_DFP; cap->data = TYPEC_PORT_DFP;
else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP) else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
cap->type = TYPEC_PORT_UFP; cap->data = TYPEC_PORT_UFP;
if (con->cap.provider && con->cap.consumer)
cap->type = TYPEC_PORT_DRP;
else if (con->cap.provider)
cap->type = TYPEC_PORT_SRC;
else if (con->cap.consumer)
cap->type = TYPEC_PORT_SNK;
cap->revision = ucsi->cap.typec_version; cap->revision = ucsi->cap.typec_version;
cap->pd_revision = ucsi->cap.pd_version; cap->pd_revision = ucsi->cap.pd_version;
......
...@@ -91,6 +91,7 @@ struct tcpc_config { ...@@ -91,6 +91,7 @@ struct tcpc_config {
unsigned int operating_snk_mw; unsigned int operating_snk_mw;
enum typec_port_type type; enum typec_port_type type;
enum typec_port_data data;
enum typec_role default_role; enum typec_role default_role;
bool try_role_hw; /* try.{src,snk} implemented in hardware */ bool try_role_hw; /* try.{src,snk} implemented in hardware */
......
...@@ -22,9 +22,15 @@ struct typec_port; ...@@ -22,9 +22,15 @@ struct typec_port;
struct fwnode_handle; struct fwnode_handle;
enum typec_port_type { enum typec_port_type {
TYPEC_PORT_SRC,
TYPEC_PORT_SNK,
TYPEC_PORT_DRP,
};
enum typec_port_data {
TYPEC_PORT_DFP, TYPEC_PORT_DFP,
TYPEC_PORT_UFP, TYPEC_PORT_UFP,
TYPEC_PORT_DRP, TYPEC_PORT_DRD,
}; };
enum typec_plug_type { enum typec_plug_type {
...@@ -186,10 +192,11 @@ struct typec_partner_desc { ...@@ -186,10 +192,11 @@ struct typec_partner_desc {
/* /*
* struct typec_capability - USB Type-C Port Capabilities * struct typec_capability - USB Type-C Port Capabilities
* @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role) * @type: Supported power role of the port
* @data: Supported data role of the port
* @revision: USB Type-C Specification release. Binary coded decimal * @revision: USB Type-C Specification release. Binary coded decimal
* @pd_revision: USB Power Delivery Specification revision if supported * @pd_revision: USB Power Delivery Specification revision if supported
* @prefer_role: Initial role preference * @prefer_role: Initial role preference (DRP ports).
* @accessory: Supported Accessory Modes * @accessory: Supported Accessory Modes
* @sw: Cable plug orientation switch * @sw: Cable plug orientation switch
* @mux: Multiplexer switch for Alternate/Accessory Modes * @mux: Multiplexer switch for Alternate/Accessory Modes
...@@ -205,6 +212,7 @@ struct typec_partner_desc { ...@@ -205,6 +212,7 @@ struct typec_partner_desc {
*/ */
struct typec_capability { struct typec_capability {
enum typec_port_type type; enum typec_port_type type;
enum typec_port_data data;
u16 revision; /* 0120H = "1.2" */ u16 revision; /* 0120H = "1.2" */
u16 pd_revision; /* 0300H = "3.0" */ u16 pd_revision; /* 0300H = "3.0" */
int prefer_role; int prefer_role;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment