aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>2018-03-20 08:57:05 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-03-22 08:40:10 -0400
commitceeb162500c3480b660a47d509db7955a7913271 (patch)
treef532363ff66a205bd47aa6be9e28d9604db7159e
parentfde0aa6c175a4d8aa19e82b86ae0f9278bc8563b (diff)
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: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/typec/class.c56
-rw-r--r--drivers/usb/typec/fusb302/fusb302.c1
-rw-r--r--drivers/usb/typec/tcpm.c9
-rw-r--r--drivers/usb/typec/tps6598x.c26
-rw-r--r--drivers/usb/typec/typec_wcove.c1
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c13
-rw-r--r--include/linux/usb/tcpm.h1
-rw-r--r--include/linux/usb/typec.h14
8 files changed, 80 insertions, 41 deletions
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 2620a694704f..53df10df2f9d 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -282,10 +282,10 @@ typec_altmode_roles_show(struct device *dev, struct device_attribute *attr,
282 ssize_t ret; 282 ssize_t ret;
283 283
284 switch (mode->roles) { 284 switch (mode->roles) {
285 case TYPEC_PORT_DFP: 285 case TYPEC_PORT_SRC:
286 ret = sprintf(buf, "source\n"); 286 ret = sprintf(buf, "source\n");
287 break; 287 break;
288 case TYPEC_PORT_UFP: 288 case TYPEC_PORT_SNK:
289 ret = sprintf(buf, "sink\n"); 289 ret = sprintf(buf, "sink\n");
290 break; 290 break;
291 case TYPEC_PORT_DRP: 291 case TYPEC_PORT_DRP:
@@ -797,14 +797,14 @@ static const char * const typec_data_roles[] = {
797}; 797};
798 798
799static const char * const typec_port_types[] = { 799static const char * const typec_port_types[] = {
800 [TYPEC_PORT_DFP] = "source", 800 [TYPEC_PORT_SRC] = "source",
801 [TYPEC_PORT_UFP] = "sink", 801 [TYPEC_PORT_SNK] = "sink",
802 [TYPEC_PORT_DRP] = "dual", 802 [TYPEC_PORT_DRP] = "dual",
803}; 803};
804 804
805static const char * const typec_port_types_drp[] = { 805static const char * const typec_port_types_drp[] = {
806 [TYPEC_PORT_DFP] = "dual [source] sink", 806 [TYPEC_PORT_SRC] = "dual [source] sink",
807 [TYPEC_PORT_UFP] = "dual source [sink]", 807 [TYPEC_PORT_SNK] = "dual source [sink]",
808 [TYPEC_PORT_DRP] = "[dual] source sink", 808 [TYPEC_PORT_DRP] = "[dual] source sink",
809}; 809};
810 810
@@ -875,9 +875,7 @@ static ssize_t data_role_store(struct device *dev,
875 return ret; 875 return ret;
876 876
877 mutex_lock(&port->port_type_lock); 877 mutex_lock(&port->port_type_lock);
878 if (port->port_type != TYPEC_PORT_DRP) { 878 if (port->cap->data != TYPEC_PORT_DRD) {
879 dev_dbg(dev, "port type fixed at \"%s\"",
880 typec_port_types[port->port_type]);
881 ret = -EOPNOTSUPP; 879 ret = -EOPNOTSUPP;
882 goto unlock_and_ret; 880 goto unlock_and_ret;
883 } 881 }
@@ -897,7 +895,7 @@ static ssize_t data_role_show(struct device *dev,
897{ 895{
898 struct typec_port *port = to_typec_port(dev); 896 struct typec_port *port = to_typec_port(dev);
899 897
900 if (port->cap->type == TYPEC_PORT_DRP) 898 if (port->cap->data == TYPEC_PORT_DRD)
901 return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ? 899 return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ?
902 "[host] device" : "host [device]"); 900 "[host] device" : "host [device]");
903 901
@@ -1328,7 +1326,6 @@ struct typec_port *typec_register_port(struct device *parent,
1328 const struct typec_capability *cap) 1326 const struct typec_capability *cap)
1329{ 1327{
1330 struct typec_port *port; 1328 struct typec_port *port;
1331 int role;
1332 int ret; 1329 int ret;
1333 int id; 1330 int id;
1334 1331
@@ -1354,21 +1351,36 @@ struct typec_port *typec_register_port(struct device *parent,
1354 goto err_mux; 1351 goto err_mux;
1355 } 1352 }
1356 1353
1357 if (cap->type == TYPEC_PORT_DFP) 1354 switch (cap->type) {
1358 role = TYPEC_SOURCE; 1355 case TYPEC_PORT_SRC:
1359 else if (cap->type == TYPEC_PORT_UFP)
1360 role = TYPEC_SINK;
1361 else
1362 role = cap->prefer_role;
1363
1364 if (role == TYPEC_SOURCE) {
1365 port->data_role = TYPEC_HOST;
1366 port->pwr_role = TYPEC_SOURCE; 1356 port->pwr_role = TYPEC_SOURCE;
1367 port->vconn_role = TYPEC_SOURCE; 1357 port->vconn_role = TYPEC_SOURCE;
1368 } else { 1358 break;
1369 port->data_role = TYPEC_DEVICE; 1359 case TYPEC_PORT_SNK:
1370 port->pwr_role = TYPEC_SINK; 1360 port->pwr_role = TYPEC_SINK;
1371 port->vconn_role = TYPEC_SINK; 1361 port->vconn_role = TYPEC_SINK;
1362 break;
1363 case TYPEC_PORT_DRP:
1364 if (cap->prefer_role != TYPEC_NO_PREFERRED_ROLE)
1365 port->pwr_role = cap->prefer_role;
1366 else
1367 port->pwr_role = TYPEC_SINK;
1368 break;
1369 }
1370
1371 switch (cap->data) {
1372 case TYPEC_PORT_DFP:
1373 port->data_role = TYPEC_HOST;
1374 break;
1375 case TYPEC_PORT_UFP:
1376 port->data_role = TYPEC_DEVICE;
1377 break;
1378 case TYPEC_PORT_DRD:
1379 if (cap->prefer_role == TYPEC_SOURCE)
1380 port->data_role = TYPEC_HOST;
1381 else
1382 port->data_role = TYPEC_DEVICE;
1383 break;
1372 } 1384 }
1373 1385
1374 port->id = id; 1386 port->id = id;
diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c
index 06794c06330f..82bf7c0ed53c 100644
--- a/drivers/usb/typec/fusb302/fusb302.c
+++ b/drivers/usb/typec/fusb302/fusb302.c
@@ -1219,6 +1219,7 @@ static const struct tcpc_config fusb302_tcpc_config = {
1219 .max_snk_mw = 15000, 1219 .max_snk_mw = 15000,
1220 .operating_snk_mw = 2500, 1220 .operating_snk_mw = 2500,
1221 .type = TYPEC_PORT_DRP, 1221 .type = TYPEC_PORT_DRP,
1222 .data = TYPEC_PORT_DRD,
1222 .default_role = TYPEC_SINK, 1223 .default_role = TYPEC_SINK,
1223 .alt_modes = NULL, 1224 .alt_modes = NULL,
1224}; 1225};
diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index 4c0fc5493d58..62e710bb6367 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -345,7 +345,7 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
345 else if (port->tcpc->config->default_role == TYPEC_SINK) 345 else if (port->tcpc->config->default_role == TYPEC_SINK)
346 return SNK_UNATTACHED; 346 return SNK_UNATTACHED;
347 /* Fall through to return SRC_UNATTACHED */ 347 /* Fall through to return SRC_UNATTACHED */
348 } else if (port->port_type == TYPEC_PORT_UFP) { 348 } else if (port->port_type == TYPEC_PORT_SNK) {
349 return SNK_UNATTACHED; 349 return SNK_UNATTACHED;
350 } 350 }
351 return SRC_UNATTACHED; 351 return SRC_UNATTACHED;
@@ -2179,7 +2179,7 @@ static inline enum tcpm_state unattached_state(struct tcpm_port *port)
2179 return SRC_UNATTACHED; 2179 return SRC_UNATTACHED;
2180 else 2180 else
2181 return SNK_UNATTACHED; 2181 return SNK_UNATTACHED;
2182 } else if (port->port_type == TYPEC_PORT_DFP) { 2182 } else if (port->port_type == TYPEC_PORT_SRC) {
2183 return SRC_UNATTACHED; 2183 return SRC_UNATTACHED;
2184 } 2184 }
2185 2185
@@ -3469,11 +3469,11 @@ static int tcpm_port_type_set(const struct typec_capability *cap,
3469 3469
3470 if (!port->connected) { 3470 if (!port->connected) {
3471 tcpm_set_state(port, PORT_RESET, 0); 3471 tcpm_set_state(port, PORT_RESET, 0);
3472 } else if (type == TYPEC_PORT_UFP) { 3472 } else if (type == TYPEC_PORT_SNK) {
3473 if (!(port->pwr_role == TYPEC_SINK && 3473 if (!(port->pwr_role == TYPEC_SINK &&
3474 port->data_role == TYPEC_DEVICE)) 3474 port->data_role == TYPEC_DEVICE))
3475 tcpm_set_state(port, PORT_RESET, 0); 3475 tcpm_set_state(port, PORT_RESET, 0);
3476 } else if (type == TYPEC_PORT_DFP) { 3476 } else if (type == TYPEC_PORT_SRC) {
3477 if (!(port->pwr_role == TYPEC_SOURCE && 3477 if (!(port->pwr_role == TYPEC_SOURCE &&
3478 port->data_role == TYPEC_HOST)) 3478 port->data_role == TYPEC_HOST))
3479 tcpm_set_state(port, PORT_RESET, 0); 3479 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 3641
3642 port->typec_caps.prefer_role = tcpc->config->default_role; 3642 port->typec_caps.prefer_role = tcpc->config->default_role;
3643 port->typec_caps.type = tcpc->config->type; 3643 port->typec_caps.type = tcpc->config->type;
3644 port->typec_caps.data = tcpc->config->data;
3644 port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */ 3645 port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */
3645 port->typec_caps.pd_revision = 0x0200; /* USB-PD spec release 2.0 */ 3646 port->typec_caps.pd_revision = 0x0200; /* USB-PD spec release 2.0 */
3646 port->typec_caps.dr_set = tcpm_dr_set; 3647 port->typec_caps.dr_set = tcpm_dr_set;
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 37a15c14a6c6..8b8406867c02 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -393,31 +393,39 @@ static int tps6598x_probe(struct i2c_client *client)
393 if (ret < 0) 393 if (ret < 0)
394 return ret; 394 return ret;
395 395
396 tps->typec_cap.revision = USB_TYPEC_REV_1_2;
397 tps->typec_cap.pd_revision = 0x200;
398 tps->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
399 tps->typec_cap.pr_set = tps6598x_pr_set;
400 tps->typec_cap.dr_set = tps6598x_dr_set;
401
396 switch (TPS_SYSCONF_PORTINFO(conf)) { 402 switch (TPS_SYSCONF_PORTINFO(conf)) {
397 case TPS_PORTINFO_SINK_ACCESSORY: 403 case TPS_PORTINFO_SINK_ACCESSORY:
398 case TPS_PORTINFO_SINK: 404 case TPS_PORTINFO_SINK:
399 tps->typec_cap.type = TYPEC_PORT_UFP; 405 tps->typec_cap.type = TYPEC_PORT_SNK;
406 tps->typec_cap.data = TYPEC_PORT_UFP;
400 break; 407 break;
401 case TPS_PORTINFO_DRP_UFP_DRD: 408 case TPS_PORTINFO_DRP_UFP_DRD:
402 case TPS_PORTINFO_DRP_DFP_DRD: 409 case TPS_PORTINFO_DRP_DFP_DRD:
403 tps->typec_cap.dr_set = tps6598x_dr_set; 410 tps->typec_cap.type = TYPEC_PORT_DRP;
404 /* fall through */ 411 tps->typec_cap.data = TYPEC_PORT_DRD;
412 break;
405 case TPS_PORTINFO_DRP_UFP: 413 case TPS_PORTINFO_DRP_UFP:
414 tps->typec_cap.type = TYPEC_PORT_DRP;
415 tps->typec_cap.data = TYPEC_PORT_UFP;
416 break;
406 case TPS_PORTINFO_DRP_DFP: 417 case TPS_PORTINFO_DRP_DFP:
407 tps->typec_cap.pr_set = tps6598x_pr_set;
408 tps->typec_cap.type = TYPEC_PORT_DRP; 418 tps->typec_cap.type = TYPEC_PORT_DRP;
419 tps->typec_cap.data = TYPEC_PORT_DFP;
409 break; 420 break;
410 case TPS_PORTINFO_SOURCE: 421 case TPS_PORTINFO_SOURCE:
411 tps->typec_cap.type = TYPEC_PORT_DFP; 422 tps->typec_cap.type = TYPEC_PORT_SRC;
423 tps->typec_cap.data = TYPEC_PORT_DFP;
412 break; 424 break;
413 default: 425 default:
414 return -ENODEV; 426 return -ENODEV;
415 } 427 }
416 428
417 tps->typec_cap.revision = USB_TYPEC_REV_1_2;
418 tps->typec_cap.pd_revision = 0x200;
419 tps->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
420
421 tps->port = typec_register_port(&client->dev, &tps->typec_cap); 429 tps->port = typec_register_port(&client->dev, &tps->typec_cap);
422 if (IS_ERR(tps->port)) 430 if (IS_ERR(tps->port))
423 return PTR_ERR(tps->port); 431 return PTR_ERR(tps->port);
diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c
index 2e990e0d917d..19cca7f1b2c5 100644
--- a/drivers/usb/typec/typec_wcove.c
+++ b/drivers/usb/typec/typec_wcove.c
@@ -572,6 +572,7 @@ static struct tcpc_config wcove_typec_config = {
572 .operating_snk_mw = 15000, 572 .operating_snk_mw = 15000,
573 573
574 .type = TYPEC_PORT_DRP, 574 .type = TYPEC_PORT_DRP,
575 .data = TYPEC_PORT_DRD,
575 .default_role = TYPEC_SINK, 576 .default_role = TYPEC_SINK,
576}; 577};
577 578
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 69d544cfcd45..bf0977fbd100 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -592,11 +592,18 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
592 return ret; 592 return ret;
593 593
594 if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP) 594 if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
595 cap->type = TYPEC_PORT_DRP; 595 cap->data = TYPEC_PORT_DRD;
596 else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP) 596 else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
597 cap->type = TYPEC_PORT_DFP; 597 cap->data = TYPEC_PORT_DFP;
598 else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP) 598 else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
599 cap->type = TYPEC_PORT_UFP; 599 cap->data = TYPEC_PORT_UFP;
600
601 if (con->cap.provider && con->cap.consumer)
602 cap->type = TYPEC_PORT_DRP;
603 else if (con->cap.provider)
604 cap->type = TYPEC_PORT_SRC;
605 else if (con->cap.consumer)
606 cap->type = TYPEC_PORT_SNK;
600 607
601 cap->revision = ucsi->cap.typec_version; 608 cap->revision = ucsi->cap.typec_version;
602 cap->pd_revision = ucsi->cap.pd_version; 609 cap->pd_revision = ucsi->cap.pd_version;
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index ca1c0b57f03f..5a5e1d8c5b65 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -91,6 +91,7 @@ struct tcpc_config {
91 unsigned int operating_snk_mw; 91 unsigned int operating_snk_mw;
92 92
93 enum typec_port_type type; 93 enum typec_port_type type;
94 enum typec_port_data data;
94 enum typec_role default_role; 95 enum typec_role default_role;
95 bool try_role_hw; /* try.{src,snk} implemented in hardware */ 96 bool try_role_hw; /* try.{src,snk} implemented in hardware */
96 97
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 2408e5c2ed91..672b39bb0adc 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -22,9 +22,15 @@ struct typec_port;
22struct fwnode_handle; 22struct fwnode_handle;
23 23
24enum typec_port_type { 24enum typec_port_type {
25 TYPEC_PORT_SRC,
26 TYPEC_PORT_SNK,
27 TYPEC_PORT_DRP,
28};
29
30enum typec_port_data {
25 TYPEC_PORT_DFP, 31 TYPEC_PORT_DFP,
26 TYPEC_PORT_UFP, 32 TYPEC_PORT_UFP,
27 TYPEC_PORT_DRP, 33 TYPEC_PORT_DRD,
28}; 34};
29 35
30enum typec_plug_type { 36enum typec_plug_type {
@@ -186,10 +192,11 @@ struct typec_partner_desc {
186 192
187/* 193/*
188 * struct typec_capability - USB Type-C Port Capabilities 194 * struct typec_capability - USB Type-C Port Capabilities
189 * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role) 195 * @type: Supported power role of the port
196 * @data: Supported data role of the port
190 * @revision: USB Type-C Specification release. Binary coded decimal 197 * @revision: USB Type-C Specification release. Binary coded decimal
191 * @pd_revision: USB Power Delivery Specification revision if supported 198 * @pd_revision: USB Power Delivery Specification revision if supported
192 * @prefer_role: Initial role preference 199 * @prefer_role: Initial role preference (DRP ports).
193 * @accessory: Supported Accessory Modes 200 * @accessory: Supported Accessory Modes
194 * @sw: Cable plug orientation switch 201 * @sw: Cable plug orientation switch
195 * @mux: Multiplexer switch for Alternate/Accessory Modes 202 * @mux: Multiplexer switch for Alternate/Accessory Modes
@@ -205,6 +212,7 @@ struct typec_partner_desc {
205 */ 212 */
206struct typec_capability { 213struct typec_capability {
207 enum typec_port_type type; 214 enum typec_port_type type;
215 enum typec_port_data data;
208 u16 revision; /* 0120H = "1.2" */ 216 u16 revision; /* 0120H = "1.2" */
209 u16 pd_revision; /* 0300H = "3.0" */ 217 u16 pd_revision; /* 0300H = "3.0" */
210 int prefer_role; 218 int prefer_role;