linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/11 v3] staging: typec: tcpm: set port type callback
@ 2017-08-28 17:23 Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 02/11 v3] staging: typec: tcpm: Check for port type for Try.SRC/Try.SNK Badhri Jagan Sridharan
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

The port type callback call enquires the tcpc_dev if
the requested port type is supported. If supported, then
performs a tcpm reset if required after setting the tcpm
internal port_type variable.

Check against the tcpm port_type instead of checking
against caps.type as port_type reflects the current
configuration.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since v1:
- Corrected  tag

Changelog since v2:
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 52 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index a911cad41a59..6c045ac9c42a 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -197,6 +197,7 @@ struct tcpm_port {
 
 	bool attached;
 	bool connected;
+	enum typec_port_type port_type;
 	bool vbus_present;
 	bool vbus_never_low;
 	bool vbus_source;
@@ -334,7 +335,7 @@ struct pd_rx_event {
 
 static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
 {
-	if (port->typec_caps.type == TYPEC_PORT_DRP) {
+	if (port->port_type == TYPEC_PORT_DRP) {
 		if (port->try_role == TYPEC_SINK)
 			return SNK_UNATTACHED;
 		else if (port->try_role == TYPEC_SOURCE)
@@ -342,7 +343,7 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
 		else if (port->tcpc->config->default_role == TYPEC_SINK)
 			return SNK_UNATTACHED;
 		/* Fall through to return SRC_UNATTACHED */
-	} else if (port->typec_caps.type == TYPEC_PORT_UFP) {
+	} else if (port->port_type == TYPEC_PORT_UFP) {
 		return SNK_UNATTACHED;
 	}
 	return SRC_UNATTACHED;
@@ -1458,7 +1459,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 		tcpm_set_state(port, SOFT_RESET, 0);
 		break;
 	case PD_CTRL_DR_SWAP:
-		if (port->typec_caps.type != TYPEC_PORT_DRP) {
+		if (port->port_type != TYPEC_PORT_DRP) {
 			tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
 			break;
 		}
@@ -1478,7 +1479,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 		}
 		break;
 	case PD_CTRL_PR_SWAP:
-		if (port->typec_caps.type != TYPEC_PORT_DRP) {
+		if (port->port_type != TYPEC_PORT_DRP) {
 			tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
 			break;
 		}
@@ -1853,7 +1854,7 @@ static bool tcpm_start_drp_toggling(struct tcpm_port *port)
 	int ret;
 
 	if (port->tcpc->start_drp_toggling &&
-	    port->typec_caps.type == TYPEC_PORT_DRP) {
+	    port->port_type == TYPEC_PORT_DRP) {
 		tcpm_log_force(port, "Start DRP toggling");
 		ret = port->tcpc->start_drp_toggling(port->tcpc,
 						     tcpm_rp_cc(port));
@@ -2163,7 +2164,7 @@ static void run_state_machine(struct tcpm_port *port)
 			break;
 		}
 		tcpm_set_cc(port, tcpm_rp_cc(port));
-		if (port->typec_caps.type == TYPEC_PORT_DRP)
+		if (port->port_type == TYPEC_PORT_DRP)
 			tcpm_set_state(port, SNK_UNATTACHED, PD_T_DRP_SNK);
 		break;
 	case SRC_ATTACH_WAIT:
@@ -2320,7 +2321,7 @@ static void run_state_machine(struct tcpm_port *port)
 			break;
 		}
 		tcpm_set_cc(port, TYPEC_CC_RD);
-		if (port->typec_caps.type == TYPEC_PORT_DRP)
+		if (port->port_type == TYPEC_PORT_DRP)
 			tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC);
 		break;
 	case SNK_ATTACH_WAIT:
@@ -2411,7 +2412,7 @@ static void run_state_machine(struct tcpm_port *port)
 		 * see USB power delivery specification, section 8.3.3.6.1.5.1).
 		 */
 		tcpm_set_state(port, hard_reset_state(port),
-			       port->typec_caps.type == TYPEC_PORT_DRP ?
+			       port->port_type == TYPEC_PORT_DRP ?
 					PD_T_DB_DETECT : PD_T_NO_RESPONSE);
 		break;
 	case SNK_DISCOVERY_DEBOUNCE:
@@ -3167,7 +3168,7 @@ static int tcpm_dr_set(const struct typec_capability *cap,
 	mutex_lock(&port->swap_lock);
 	mutex_lock(&port->lock);
 
-	if (port->typec_caps.type != TYPEC_PORT_DRP) {
+	if (port->port_type != TYPEC_PORT_DRP) {
 		ret = -EINVAL;
 		goto port_unlock;
 	}
@@ -3235,7 +3236,7 @@ static int tcpm_pr_set(const struct typec_capability *cap,
 	mutex_lock(&port->swap_lock);
 	mutex_lock(&port->lock);
 
-	if (port->typec_caps.type != TYPEC_PORT_DRP) {
+	if (port->port_type != TYPEC_PORT_DRP) {
 		ret = -EINVAL;
 		goto port_unlock;
 	}
@@ -3357,6 +3358,34 @@ static void tcpm_init(struct tcpm_port *port)
 	tcpm_set_state(port, PORT_RESET, 0);
 }
 
+static int tcpm_port_type_set(const struct typec_capability *cap,
+			      enum typec_port_type type)
+{
+	struct tcpm_port *port = typec_cap_to_tcpm(cap);
+
+	mutex_lock(&port->lock);
+	if (type == port->port_type)
+		goto port_unlock;
+
+	port->port_type = type;
+
+	if (!port->connected) {
+		tcpm_set_state(port, PORT_RESET, 0);
+	} else if (type == TYPEC_PORT_UFP) {
+		if (!(port->pwr_role == TYPEC_SINK &&
+		      port->data_role == TYPEC_DEVICE))
+			tcpm_set_state(port, PORT_RESET, 0);
+	} else if (type == TYPEC_PORT_DFP) {
+		if (!(port->pwr_role == TYPEC_SOURCE &&
+		      port->data_role == TYPEC_HOST))
+			tcpm_set_state(port, PORT_RESET, 0);
+	}
+
+port_unlock:
+	mutex_unlock(&port->lock);
+	return 0;
+}
+
 void tcpm_tcpc_reset(struct tcpm_port *port)
 {
 	mutex_lock(&port->lock);
@@ -3504,9 +3533,10 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
 	port->typec_caps.pr_set = tcpm_pr_set;
 	port->typec_caps.vconn_set = tcpm_vconn_set;
 	port->typec_caps.try_role = tcpm_try_role;
+	port->typec_caps.port_type_set = tcpm_port_type_set;
 
 	port->partner_desc.identity = &port->partner_ident;
-
+	port->port_type = tcpc->config->type;
 	/*
 	 * TODO:
 	 *  - alt_modes, set_alt_mode
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/11 v3] staging: typec: tcpm: Check for port type for Try.SRC/Try.SNK
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 03/11 v3] staging: typec: tcpm: Prevent TCPM from looping in SRC_TRYWAIT Badhri Jagan Sridharan
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

Enable Try.SRC or Try.SNK only when port_type is
DRP. Try.SRC or Try.SNK state machines are not
valid for SRC only or SNK only ports.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since v1:
- Corrected  tag

Changelog since v2:
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 6c045ac9c42a..1219e3bc13ef 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -328,10 +328,12 @@ struct pd_rx_event {
 	 (tcpm_cc_is_audio((port)->cc2) && tcpm_cc_is_open((port)->cc1)))
 
 #define tcpm_try_snk(port) \
-	((port)->try_snk_count == 0 && (port)->try_role == TYPEC_SINK)
+	((port)->try_snk_count == 0 && (port)->try_role == TYPEC_SINK && \
+	(port)->port_type == TYPEC_PORT_DRP)
 
 #define tcpm_try_src(port) \
-	((port)->try_src_count == 0 && (port)->try_role == TYPEC_SOURCE)
+	((port)->try_src_count == 0 && (port)->try_role == TYPEC_SOURCE && \
+	(port)->port_type == TYPEC_PORT_DRP)
 
 static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
 {
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/11 v3] staging: typec: tcpm: Prevent TCPM from looping in SRC_TRYWAIT
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 02/11 v3] staging: typec: tcpm: Check for port type for Try.SRC/Try.SNK Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 04/11 v3] staging: usb: tcpm: usb: type-c: tcpm: Check for Rp for tPDDebounce Badhri Jagan Sridharan
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

According to the spec the following is the condition
for exiting TryWait.SRC:

"The port shall transition to Attached.SRC when V BUS is at vSafe0V
and the SRC.Rd state is detected on exactly one of the CC pins for at
least tCCDebounce. The port shall transition to Unattached.SNK after
tDRPTry if neither of the CC1 or CC2 pins are in the SRC.Rd state"

TCPM at present keeps re-entering the SRC_TRYWAIT and keeps restarting
tDRPTry if the CC presents Rp and disconnects within tCCDebounce.

For example:
[  447.164308] pending state change SRC_TRYWAIT -> SRC_ATTACHED @ 200 ms
[  447.164386] CC1: 2 -> 0, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, disconnected]
[  447.164406] state change SRC_TRYWAIT -> SRC_TRYWAIT
[  447.164573] cc:=3
[  447.191408] pending state change SRC_TRYWAIT -> SRC_TRYWAIT_UNATTACHED @ 100 ms
[  447.191478] CC1: 0 -> 0, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, disconnected]
[  447.207261] CC1: 0 -> 2, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, connected]
[  447.207306] state change SRC_TRYWAIT -> SRC_TRYWAIT
[  447.207485] cc:=3
[  447.237283] pending state change SRC_TRYWAIT -> SRC_ATTACHED @ 200 ms
[  447.237357] CC1: 2 -> 0, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, disconnected]
[  447.237379] state change SRC_TRYWAIT -> SRC_TRYWAIT
[  447.237532] cc:=3
[  447.263219] pending state change SRC_TRYWAIT -> SRC_TRYWAIT_UNATTACHED @ 100 ms
[  447.263289] CC1: 0 -> 0, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, disconnected]
[  447.280926] CC1: 0 -> 2, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, connected]
[  447.280970] state change SRC_TRYWAIT -> SRC_TRYWAIT
[  447.281158] cc:=3
[  447.307767] pending state change SRC_TRYWAIT -> SRC_ATTACHED @ 200 ms
[  447.307838] CC1: 2 -> 0, CC2: 0 -> 0 [state SRC_TRYWAIT, polarity 0, disconnected]
[  447.307858] state change SRC_TRYWAIT -> SRC_TRYWAIT

In TCPM, tDRPTry is set tp 100ms (min 75ms and max 150ms)
and tCCdebounce is set to 200ms (min 100ms and max 200ms).
To overcome the issue, record the time at which the port
enters TryWait.SRC(SRC_TRYWAIT) and re-enter SRC_TRYWAIT
only when CC keeps debouncing within tDRPTry.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since v1:
- Corrected  tag

Changelog since v2:
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 45 ++++++++++++++++++++++++++++----------------
 1 file changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 1219e3bc13ef..d45ffa8f2cfd 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -17,6 +17,7 @@
 #include <linux/completion.h>
 #include <linux/debugfs.h>
 #include <linux/device.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -105,6 +106,7 @@
 	S(SNK_TRY),				\
 	S(SNK_TRY_WAIT),			\
 	S(SRC_TRYWAIT),				\
+	S(SRC_TRYWAIT_DEBOUNCE),		\
 	S(SRC_TRYWAIT_UNATTACHED),		\
 						\
 	S(SRC_TRY),				\
@@ -284,6 +286,9 @@ struct tcpm_port {
 	struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX];
 	struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX];
 
+	/* Deadline in jiffies to exit src_try_wait state */
+	unsigned long max_wait;
+
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *dentry;
 	struct mutex logbuffer_lock;	/* log buffer access lock */
@@ -2204,6 +2209,7 @@ static void run_state_machine(struct tcpm_port *port)
 		if (!tcpm_port_is_sink(port)) {
 			tcpm_set_state(port, SRC_TRYWAIT,
 				       PD_T_PD_DEBOUNCE);
+			port->max_wait = 0;
 			break;
 		}
 		/* No vbus, cc state is sink or open */
@@ -2211,11 +2217,22 @@ static void run_state_machine(struct tcpm_port *port)
 		break;
 	case SRC_TRYWAIT:
 		tcpm_set_cc(port, tcpm_rp_cc(port));
-		if (!port->vbus_present && tcpm_port_is_source(port))
-			tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
-		else
+		if (port->max_wait == 0) {
+			port->max_wait = jiffies +
+					 msecs_to_jiffies(PD_T_DRP_TRY);
 			tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED,
 				       PD_T_DRP_TRY);
+		} else {
+			if (time_is_after_jiffies(port->max_wait))
+				tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED,
+					       jiffies_to_msecs(port->max_wait -
+								jiffies));
+			else
+				tcpm_set_state(port, SNK_UNATTACHED, 0);
+		}
+		break;
+	case SRC_TRYWAIT_DEBOUNCE:
+		tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
 		break;
 	case SRC_TRYWAIT_UNATTACHED:
 		tcpm_set_state(port, SNK_UNATTACHED, 0);
@@ -2898,11 +2915,10 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 	case SRC_TRYWAIT:
 		/* Hand over to state machine if needed */
 		if (!port->vbus_present && tcpm_port_is_source(port))
-			new_state = SRC_ATTACHED;
-		else
-			new_state = SRC_TRYWAIT_UNATTACHED;
-
-		if (new_state != port->delayed_state)
+			tcpm_set_state(port, SRC_TRYWAIT_DEBOUNCE, 0);
+		break;
+	case SRC_TRYWAIT_DEBOUNCE:
+		if (port->vbus_present || !tcpm_port_is_source(port))
 			tcpm_set_state(port, SRC_TRYWAIT, 0);
 		break;
 	case SNK_TRY_WAIT:
@@ -2990,9 +3006,10 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 		/* Do nothing, waiting for timeout */
 		break;
 	case SRC_TRYWAIT:
-		/* Hand over to state machine if needed */
-		if (port->delayed_state != SRC_TRYWAIT_UNATTACHED)
-			tcpm_set_state(port, SRC_TRYWAIT, 0);
+		/* Do nothing, Waiting for Rd to be detected */
+		break;
+	case SRC_TRYWAIT_DEBOUNCE:
+		tcpm_set_state(port, SRC_TRYWAIT, 0);
 		break;
 	case SNK_TRY_WAIT:
 		if (tcpm_port_is_sink(port)) {
@@ -3039,11 +3056,7 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
 	case SRC_TRYWAIT:
 		/* Hand over to state machine if needed */
 		if (tcpm_port_is_source(port))
-			new_state = SRC_ATTACHED;
-		else
-			new_state = SRC_TRYWAIT_UNATTACHED;
-		if (new_state != port->delayed_state)
-			tcpm_set_state(port, SRC_TRYWAIT, 0);
+			tcpm_set_state(port, SRC_TRYWAIT_DEBOUNCE, 0);
 		break;
 	case SNK_TRY_WAIT:
 		if (!tcpm_port_is_sink(port))
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/11 v3] staging: usb: tcpm: usb: type-c: tcpm: Check for Rp for tPDDebounce
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 02/11 v3] staging: typec: tcpm: Check for port type for Try.SRC/Try.SNK Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 03/11 v3] staging: typec: tcpm: Prevent TCPM from looping in SRC_TRYWAIT Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 05/11 v3] staging: typec: tcpm: Follow Try.SRC exit requirements Badhri Jagan Sridharan
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

According the spec, the following is the conditions for exiting Try.SNK
state:
"The port shall wait for tDRPTry and only then begin monitoring the CC1 and
CC2 pins for the SNK.Rp state. The port shall then transition to
Attached.SNK when the SNK.Rp state is detected on exactly one of the CC1
or CC2 pins for at least tPDDebounce and V BUS is detected. Alternatively,
the port shall transition to TryWait.SRC if SNK.Rp state is not detected
for tPDDebounce."

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since v1:
- Corrected  tag

Changelog since v2:
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 68 ++++++++++++++++----------------------------
 1 file changed, 24 insertions(+), 44 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index d45ffa8f2cfd..7eed04698ebe 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -105,6 +105,8 @@
 						\
 	S(SNK_TRY),				\
 	S(SNK_TRY_WAIT),			\
+	S(SNK_TRY_WAIT_DEBOUNCE),               \
+	S(SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS),    \
 	S(SRC_TRYWAIT),				\
 	S(SRC_TRYWAIT_DEBOUNCE),		\
 	S(SRC_TRYWAIT_UNATTACHED),		\
@@ -2202,18 +2204,24 @@ static void run_state_machine(struct tcpm_port *port)
 		tcpm_set_state(port, SNK_TRY_WAIT, PD_T_DRP_TRY);
 		break;
 	case SNK_TRY_WAIT:
+		if (tcpm_port_is_sink(port)) {
+			tcpm_set_state(port, SNK_TRY_WAIT_DEBOUNCE, 0);
+		} else {
+			tcpm_set_state(port, SRC_TRYWAIT, 0);
+			port->max_wait = 0;
+		}
+		break;
+	case SNK_TRY_WAIT_DEBOUNCE:
+		tcpm_set_state(port, SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS,
+			       PD_T_PD_DEBOUNCE);
+		break;
+	case SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS:
 		if (port->vbus_present && tcpm_port_is_sink(port)) {
 			tcpm_set_state(port, SNK_ATTACHED, 0);
-			break;
-		}
-		if (!tcpm_port_is_sink(port)) {
-			tcpm_set_state(port, SRC_TRYWAIT,
-				       PD_T_PD_DEBOUNCE);
+		} else {
+			tcpm_set_state(port, SRC_TRYWAIT, 0);
 			port->max_wait = 0;
-			break;
 		}
-		/* No vbus, cc state is sink or open */
-		tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED, PD_T_DRP_TRYWAIT);
 		break;
 	case SRC_TRYWAIT:
 		tcpm_set_cc(port, tcpm_rp_cc(port));
@@ -2921,20 +2929,12 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 		if (port->vbus_present || !tcpm_port_is_source(port))
 			tcpm_set_state(port, SRC_TRYWAIT, 0);
 		break;
-	case SNK_TRY_WAIT:
-		if (port->vbus_present && tcpm_port_is_sink(port)) {
-			tcpm_set_state(port, SNK_ATTACHED, 0);
-			break;
+	case SNK_TRY_WAIT_DEBOUNCE:
+		if (!tcpm_port_is_sink(port)) {
+			port->max_wait = 0;
+			tcpm_set_state(port, SRC_TRYWAIT, 0);
 		}
-		if (!tcpm_port_is_sink(port))
-			new_state = SRC_TRYWAIT;
-		else
-			new_state = SRC_TRYWAIT_UNATTACHED;
-
-		if (new_state != port->delayed_state)
-			tcpm_set_state(port, SNK_TRY_WAIT, 0);
 		break;
-
 	case SRC_TRY:
 		if (tcpm_port_is_source(port))
 			tcpm_set_state(port, SRC_TRY_DEBOUNCE, 0);
@@ -2974,8 +2974,6 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 
 static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 {
-	enum tcpm_state new_state;
-
 	tcpm_log_force(port, "VBUS on");
 	port->vbus_present = true;
 	switch (port->state) {
@@ -3011,18 +3009,8 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 	case SRC_TRYWAIT_DEBOUNCE:
 		tcpm_set_state(port, SRC_TRYWAIT, 0);
 		break;
-	case SNK_TRY_WAIT:
-		if (tcpm_port_is_sink(port)) {
-			tcpm_set_state(port, SNK_ATTACHED, 0);
-			break;
-		}
-		if (!tcpm_port_is_sink(port))
-			new_state = SRC_TRYWAIT;
-		else
-			new_state = SRC_TRYWAIT_UNATTACHED;
-
-		if (new_state != port->delayed_state)
-			tcpm_set_state(port, SNK_TRY_WAIT, 0);
+	case SNK_TRY_WAIT_DEBOUNCE:
+		/* Do nothing, waiting for PD_DEBOUNCE to do be done */
 		break;
 	case SNK_TRYWAIT:
 		tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0);
@@ -3035,8 +3023,6 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 
 static void _tcpm_pd_vbus_off(struct tcpm_port *port)
 {
-	enum tcpm_state new_state;
-
 	tcpm_log_force(port, "VBUS off");
 	port->vbus_present = false;
 	port->vbus_never_low = false;
@@ -3058,14 +3044,8 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
 		if (tcpm_port_is_source(port))
 			tcpm_set_state(port, SRC_TRYWAIT_DEBOUNCE, 0);
 		break;
-	case SNK_TRY_WAIT:
-		if (!tcpm_port_is_sink(port))
-			new_state = SRC_TRYWAIT;
-		else
-			new_state = SRC_TRYWAIT_UNATTACHED;
-
-		if (new_state != port->delayed_state)
-			tcpm_set_state(port, SNK_TRY_WAIT, 0);
+	case SNK_TRY_WAIT_DEBOUNCE:
+		/* Do nothing, waiting for PD_DEBOUNCE to do be done */
 		break;
 	case SNK_TRYWAIT_VBUS:
 		tcpm_set_state(port, SNK_TRYWAIT, 0);
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/11 v3] staging: typec: tcpm: Follow Try.SRC exit requirements
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (2 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 04/11 v3] staging: usb: tcpm: usb: type-c: tcpm: Check for Rp for tPDDebounce Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 06/11 v3] staging: typec: tcpm: Comply with TryWait.SNK State Badhri Jagan Sridharan
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

According to spec:
" 4.5.2.2.9.2 Exiting from Try.SRC State:
The port shall transition to Attached.SRC when the SRC.Rd
state is detected on exactly one of the CC1 or CC2 pins for
at least tPDDebounce. The port shall transition to
TryWait.SNK after tDRPTry and the SRC.Rd state has not been
detected."

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since v1:
- Corrected  tag

Changelog since v2:
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 7eed04698ebe..fc179bdea7e4 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -112,6 +112,7 @@
 	S(SRC_TRYWAIT_UNATTACHED),		\
 						\
 	S(SRC_TRY),				\
+	S(SRC_TRY_WAIT),                        \
 	S(SRC_TRY_DEBOUNCE),			\
 	S(SNK_TRYWAIT),				\
 	S(SNK_TRYWAIT_DEBOUNCE),		\
@@ -2158,6 +2159,7 @@ static void run_state_machine(struct tcpm_port *port)
 {
 	int ret;
 	enum typec_pwr_opmode opmode;
+	unsigned int msecs;
 
 	port->enter_state = port->state;
 	switch (port->state) {
@@ -2379,7 +2381,22 @@ static void run_state_machine(struct tcpm_port *port)
 	case SRC_TRY:
 		port->try_src_count++;
 		tcpm_set_cc(port, tcpm_rp_cc(port));
-		tcpm_set_state(port, SNK_TRYWAIT, PD_T_DRP_TRY);
+		port->max_wait = 0;
+		tcpm_set_state(port, SRC_TRY_WAIT, 0);
+		break;
+	case SRC_TRY_WAIT:
+		if (port->max_wait == 0) {
+			port->max_wait = jiffies +
+					 msecs_to_jiffies(PD_T_DRP_TRY);
+			msecs = PD_T_DRP_TRY;
+		} else {
+			if (time_is_after_jiffies(port->max_wait))
+				msecs = jiffies_to_msecs(port->max_wait -
+							 jiffies);
+			else
+				msecs = 0;
+		}
+		tcpm_set_state(port, SNK_TRYWAIT, msecs);
 		break;
 	case SRC_TRY_DEBOUNCE:
 		tcpm_set_state(port, SRC_ATTACHED, PD_T_PD_DEBOUNCE);
@@ -2935,12 +2952,12 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 			tcpm_set_state(port, SRC_TRYWAIT, 0);
 		}
 		break;
-	case SRC_TRY:
+	case SRC_TRY_WAIT:
 		if (tcpm_port_is_source(port))
 			tcpm_set_state(port, SRC_TRY_DEBOUNCE, 0);
 		break;
 	case SRC_TRY_DEBOUNCE:
-		tcpm_set_state(port, SRC_TRY, 0);
+		tcpm_set_state(port, SRC_TRY_WAIT, 0);
 		break;
 	case SNK_TRYWAIT_DEBOUNCE:
 		if (port->vbus_present) {
@@ -3015,7 +3032,10 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 	case SNK_TRYWAIT:
 		tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0);
 		break;
-
+	case SRC_TRY_WAIT:
+	case SRC_TRY_DEBOUNCE:
+		/* Do nothing, waiting for sink detection */
+		break;
 	default:
 		break;
 	}
@@ -3069,7 +3089,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
 	case PORT_RESET_WAIT_OFF:
 		tcpm_set_state(port, tcpm_default_state(port), 0);
 		break;
-
+	case SRC_TRY_WAIT:
+	case SRC_TRY_DEBOUNCE:
+		/* Do nothing, waiting for sink detection */
+		break;
 	default:
 		if (port->pwr_role == TYPEC_SINK &&
 		    port->attached)
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/11 v3] staging: typec: tcpm: Comply with TryWait.SNK State
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (3 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 05/11 v3] staging: typec: tcpm: Follow Try.SRC exit requirements Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 07/11 v3] staging: typec: tcpm: Consider port_type while determining unattached_state Badhri Jagan Sridharan
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

According to the spec:
"4.5.2.2.10.2 Exiting from TryWait.SNK State
The port shall transition to Attached.SNK after tCCDebounce if or when VBUS
is detected. Note the Source may initiate USB PD communications which will
cause brief periods of the SNK.Open state on both the CC1 and CC2 pins,
but this event will not exceed tPDDebounce. The port shall transition to
Unattached.SNK when the state of both of the CC1 and CC2 pins is SNK.Open
for at least tPDDebounce."

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since v1:
- Corrected  tag

Changelog since v2:
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 58 +++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index fc179bdea7e4..0ae33330a5c7 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -2403,26 +2403,24 @@ static void run_state_machine(struct tcpm_port *port)
 		break;
 	case SNK_TRYWAIT:
 		tcpm_set_cc(port, TYPEC_CC_RD);
-		tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, PD_T_CC_DEBOUNCE);
+		tcpm_set_state(port, SNK_TRYWAIT_VBUS, PD_T_CC_DEBOUNCE);
 		break;
-	case SNK_TRYWAIT_DEBOUNCE:
-		if (port->vbus_present) {
+	case SNK_TRYWAIT_VBUS:
+		/*
+		 * TCPM stays in this state indefinitely until VBUS
+		 * is detected as long as Rp is not detected for
+		 * more than a time period of tPDDebounce.
+		 */
+		if (port->vbus_present && tcpm_port_is_sink(port)) {
 			tcpm_set_state(port, SNK_ATTACHED, 0);
 			break;
 		}
-		if (tcpm_port_is_disconnected(port)) {
-			tcpm_set_state(port, SNK_UNATTACHED,
-				       PD_T_PD_DEBOUNCE);
-			break;
-		}
-		if (tcpm_port_is_source(port))
-			tcpm_set_state(port, SRC_ATTACHED, 0);
-		/* XXX Are we supposed to stay in this state ? */
+		if (!tcpm_port_is_sink(port))
+			tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0);
 		break;
-	case SNK_TRYWAIT_VBUS:
-		tcpm_set_state(port, SNK_ATTACHED, PD_T_CC_DEBOUNCE);
+	case SNK_TRYWAIT_DEBOUNCE:
+		tcpm_set_state(port, SNK_UNATTACHED, PD_T_PD_DEBOUNCE);
 		break;
-
 	case SNK_ATTACHED:
 		ret = tcpm_snk_attach(port);
 		if (ret < 0)
@@ -2960,19 +2958,16 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 		tcpm_set_state(port, SRC_TRY_WAIT, 0);
 		break;
 	case SNK_TRYWAIT_DEBOUNCE:
-		if (port->vbus_present) {
-			tcpm_set_state(port, SNK_ATTACHED, 0);
-			break;
-		}
-		if (tcpm_port_is_source(port)) {
-			tcpm_set_state(port, SRC_ATTACHED, 0);
-			break;
-		}
-		if (tcpm_port_is_disconnected(port) &&
-		    port->delayed_state != SNK_UNATTACHED)
+		if (tcpm_port_is_sink(port))
+			tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0);
+		break;
+	case SNK_TRYWAIT_VBUS:
+		if (!tcpm_port_is_sink(port))
 			tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0);
 		break;
-
+	case SNK_TRYWAIT:
+		/* Do nothing, waiting for tCCDebounce */
+		break;
 	case PR_SWAP_SNK_SRC_SINK_OFF:
 	case PR_SWAP_SRC_SNK_TRANSITION_OFF:
 	case PR_SWAP_SRC_SNK_SOURCE_OFF:
@@ -3030,7 +3025,14 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
 		/* Do nothing, waiting for PD_DEBOUNCE to do be done */
 		break;
 	case SNK_TRYWAIT:
-		tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0);
+		/* Do nothing, waiting for tCCDebounce */
+		break;
+	case SNK_TRYWAIT_VBUS:
+		if (tcpm_port_is_sink(port))
+			tcpm_set_state(port, SNK_ATTACHED, 0);
+		break;
+	case SNK_TRYWAIT_DEBOUNCE:
+		/* Do nothing, waiting for Rp */
 		break;
 	case SRC_TRY_WAIT:
 	case SRC_TRY_DEBOUNCE:
@@ -3067,10 +3069,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
 	case SNK_TRY_WAIT_DEBOUNCE:
 		/* Do nothing, waiting for PD_DEBOUNCE to do be done */
 		break;
+	case SNK_TRYWAIT:
 	case SNK_TRYWAIT_VBUS:
-		tcpm_set_state(port, SNK_TRYWAIT, 0);
+	case SNK_TRYWAIT_DEBOUNCE:
 		break;
-
 	case SNK_ATTACH_WAIT:
 		tcpm_set_state(port, SNK_UNATTACHED, 0);
 		break;
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/11 v3] staging: typec: tcpm: Consider port_type while determining unattached_state
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (4 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 06/11 v3] staging: typec: tcpm: Comply with TryWait.SNK State Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 08/11 v3] staging: typec: tcpm: add cc change handling in src states Badhri Jagan Sridharan
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

While performing PORT_RESET, upon receiving the cc disconnect
signal from the underlaying tcpc device, TCPM transitions into
unattached state. Consider the current type of port while determining
the unattached state.

In the below logs, although the port_type was set to sink, TCPM
transitioned into SRC_UNATTACHED.

[  762.290654] state change SRC_READY -> PORT_RESET
[  762.324531] Setting voltage/current limit 0 mV 0 mA
[  762.327912] polarity 0
[  762.334864] cc:=0
[  762.347193] pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms
[  762.347200] VBUS off
[  762.347203] CC1: 2 -> 0, CC2: 0 -> 0 [state PORT_RESET, polarity 0, disconnected]
[  762.347206] state change PORT_RESET -> SRC_UNATTACHED

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since previous version:
- Only one previous version of the patch was sent.
  Numbering this V3 instead of V2 to keep the sequence
  number in sync with the rest of the patches in the
  patch list.
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers
- addressed comment nit

 drivers/staging/typec/tcpm.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 0ae33330a5c7..645f43ee83df 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -2117,10 +2117,16 @@ static inline enum tcpm_state ready_state(struct tcpm_port *port)
 
 static inline enum tcpm_state unattached_state(struct tcpm_port *port)
 {
-	if (port->pwr_role == TYPEC_SOURCE)
+	if (port->port_type == TYPEC_PORT_DRP) {
+		if (port->pwr_role == TYPEC_SOURCE)
+			return SRC_UNATTACHED;
+		else
+			return SNK_UNATTACHED;
+	} else if (port->port_type == TYPEC_PORT_DFP) {
 		return SRC_UNATTACHED;
-	else
-		return SNK_UNATTACHED;
+	}
+
+	return SNK_UNATTACHED;
 }
 
 static void tcpm_check_send_discover(struct tcpm_port *port)
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/11 v3] staging: typec: tcpm: add cc change handling in src states
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (5 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 07/11 v3] staging: typec: tcpm: Consider port_type while determining unattached_state Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 09/11 v3] staging: typec: tcpm: typec: tcpm: Wait for CC debounce before PD excg Badhri Jagan Sridharan
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

In the case that the lower layer driver reports a cc change directly
from SINK state to SOURCE state, TCPM doesn't handle these cc change
in SRC_SEND_CAPABILITIES, SRC_READY states. And with SRC_ATTACHED
state, the change is not handled as the port is still considered
connected.

[49606.131672] state change DRP_TOGGLING -> SRC_ATTACH_WAIT
[49606.131701] pending state change SRC_ATTACH_WAIT -> SRC_ATTACHED @
200 ms
[49606.329952] state change SRC_ATTACH_WAIT -> SRC_ATTACHED [delayed 200
ms]
[49606.329978] polarity 0
[49606.329989] Requesting mux mode 1, config 0, polarity 0
[49606.349416] vbus:=1 charge=0
[49606.372274] pending state change SRC_ATTACHED -> SRC_UNATTACHED @ 480
ms
[49606.372431] VBUS on
[49606.372488] state change SRC_ATTACHED -> SRC_STARTUP
...
(the lower layer driver reports a direct change from source to sink)
[49606.536927] pending state change SRC_SEND_CAPABILITIES ->
SRC_SEND_CAPABILITIES @ 150 ms
[49606.547244] CC1: 2 -> 5, CC2: 0 -> 0 [state SRC_SEND_CAPABILITIES,
polarity 0, connected]

This can happen when the lower layer driver and/or the hardware
handles a portion of the Type-C state machine work, and quietly goes
through the unattached state.

Originally-from: Yueyao Zhu <yueyao@google.com>
Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since previous version:
- Only one previous version of the patch was sent.
  Numbering this V3 instead of V2 to keep the sequence
  number in sync with the rest of the patches in the
  patch list.
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 645f43ee83df..1f6827f32b29 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -2874,10 +2874,12 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 			tcpm_set_state(port, SRC_ATTACH_WAIT, 0);
 		break;
 	case SRC_ATTACHED:
-		if (tcpm_port_is_disconnected(port))
+	case SRC_SEND_CAPABILITIES:
+	case SRC_READY:
+		if (tcpm_port_is_disconnected(port) ||
+		    !tcpm_port_is_source(port))
 			tcpm_set_state(port, SRC_UNATTACHED, 0);
 		break;
-
 	case SNK_UNATTACHED:
 		if (tcpm_port_is_sink(port))
 			tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/11 v3] staging: typec: tcpm: typec: tcpm: Wait for CC debounce before PD excg
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (6 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 08/11 v3] staging: typec: tcpm: add cc change handling in src states Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 10/11 v3] staging: typec: tcpm: Do not send PING msgs in TCPM Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 11/11 v3] staging: typec: tcpm: Switch to PORT_RESET instead of SNK_UNATTACHED Badhri Jagan Sridharan
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

Once, Rp or Rd is switched, wait for PD_T_CC_DEBOUNCE. If not the
PS_RDY message transmitted might result in failure.
Also, Only wait for PD_T_SRCSWAPSTDBY while in
PR_SWAP_SRC_SNK_TRANSITION_OFF. PD_T_PS_SOURCE_OFF is the overall
time after which the initial sink would issue hard reset.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since previous version:
- Only one previous version of the patch was sent.
  Numbering this V3 instead of V2 to keep the sequence
  number in sync with the rest of the patches in the
  patch list.
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/pd.h   |  2 ++
 drivers/staging/typec/tcpm.c | 25 ++++++++++++++++++++++---
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/typec/pd.h b/drivers/staging/typec/pd.h
index 510ef7279900..30b32ad72acd 100644
--- a/drivers/staging/typec/pd.h
+++ b/drivers/staging/typec/pd.h
@@ -278,6 +278,8 @@ static inline unsigned int rdo_max_power(u32 rdo)
 #define PD_T_VCONN_SOURCE_ON	100
 #define PD_T_SINK_REQUEST	100	/* 100 ms minimum */
 #define PD_T_ERROR_RECOVERY	100	/* minimum 25 is insufficient */
+#define PD_T_SRCSWAPSTDBY      625     /* Maximum of 650ms */
+#define PD_T_NEWSRC            250     /* Maximum of 275ms */
 
 #define PD_T_DRP_TRY		100	/* 75 - 150 ms */
 #define PD_T_DRP_TRYWAIT	600	/* 400 - 800 ms */
diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 1f6827f32b29..a7da609006f5 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -90,9 +90,11 @@
 	S(PR_SWAP_START),			\
 	S(PR_SWAP_SRC_SNK_TRANSITION_OFF),	\
 	S(PR_SWAP_SRC_SNK_SOURCE_OFF),		\
+	S(PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED), \
 	S(PR_SWAP_SRC_SNK_SINK_ON),		\
 	S(PR_SWAP_SNK_SRC_SINK_OFF),		\
 	S(PR_SWAP_SNK_SRC_SOURCE_ON),		\
+	S(PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP),    \
 						\
 	S(VCONN_SWAP_ACCEPT),			\
 	S(VCONN_SWAP_SEND),			\
@@ -1395,7 +1397,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 					       SNK_TRANSITION_SINK_VBUS, 0);
 			}
 			break;
-		case PR_SWAP_SRC_SNK_SOURCE_OFF:
+		case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
 			tcpm_set_state(port, PR_SWAP_SRC_SNK_SINK_ON, 0);
 			break;
 		case PR_SWAP_SNK_SRC_SINK_OFF:
@@ -2679,11 +2681,17 @@ static void run_state_machine(struct tcpm_port *port)
 	case PR_SWAP_SRC_SNK_TRANSITION_OFF:
 		tcpm_set_vbus(port, false);
 		port->explicit_contract = false;
+		/* allow time for Vbus discharge, must be < tSrcSwapStdby */
 		tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF,
-			       PD_T_PS_SOURCE_OFF);
+			       PD_T_SRCSWAPSTDBY);
 		break;
 	case PR_SWAP_SRC_SNK_SOURCE_OFF:
 		tcpm_set_cc(port, TYPEC_CC_RD);
+		/* allow CC debounce */
+		tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED,
+			       PD_T_CC_DEBOUNCE);
+		break;
+	case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
 		/*
 		 * USB-PD standard, 6.2.1.4, Port Power Role:
 		 * "During the Power Role Swap Sequence, for the initial Source
@@ -2709,6 +2717,15 @@ static void run_state_machine(struct tcpm_port *port)
 	case PR_SWAP_SNK_SRC_SOURCE_ON:
 		tcpm_set_cc(port, tcpm_rp_cc(port));
 		tcpm_set_vbus(port, true);
+		/*
+		 * allow time VBUS ramp-up, must be < tNewSrc
+		 * Also, this window overlaps with CC debounce as well.
+		 * So, Wait for the max of two which is PD_T_NEWSRC
+		 */
+		tcpm_set_state(port, PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP,
+			       PD_T_NEWSRC);
+		break;
+	case PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP:
 		/*
 		 * USB PD standard, 6.2.1.4:
 		 * "Subsequent Messages initiated by the Policy Engine,
@@ -2979,8 +2996,10 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 	case PR_SWAP_SNK_SRC_SINK_OFF:
 	case PR_SWAP_SRC_SNK_TRANSITION_OFF:
 	case PR_SWAP_SRC_SNK_SOURCE_OFF:
+	case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
+	case PR_SWAP_SNK_SRC_SOURCE_ON:
 		/*
-		 * CC state change is expected here; we just turned off power.
+		 * CC state change is expected in PR_SWAP
 		 * Ignore it.
 		 */
 		break;
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/11 v3] staging: typec: tcpm: Do not send PING msgs in TCPM
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (7 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 09/11 v3] staging: typec: tcpm: typec: tcpm: Wait for CC debounce before PD excg Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  2017-08-28 17:23 ` [PATCH 11/11 v3] staging: typec: tcpm: Switch to PORT_RESET instead of SNK_UNATTACHED Badhri Jagan Sridharan
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

PING messages are used to monitor the connect/disconnect.
However, when PD is carried over CC, so this is not required.

Also, the spec does not clearly say if PD is possible when
Type-c is connected to Type-A/B. So, removing sending
PING messages altogether.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since previous version:
- Only one previous version of the patch was sent.
  Numbering this V3 instead of V2 to keep the sequence
  number in sync with the rest of the patches in the
  patch list.
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index a7da609006f5..9e0111dea7c4 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -2335,14 +2335,11 @@ static void run_state_machine(struct tcpm_port *port)
 		 * - The system is not operating in PD mode
 		 * or
 		 * - Both partners are connected using a Type-C connector
-		 *   XXX How do we know that ?
+		 *
+		 * There is no actual need to send PD messages since the local
+		 * port type-c and the spec does not clearly say whether PD is
+		 * possible when type-c is connected to Type-A/B
 		 */
-		if (port->pwr_opmode == TYPEC_PWR_MODE_PD &&
-		    !port->op_vsafe5v) {
-			tcpm_pd_send_control(port, PD_CTRL_PING);
-			tcpm_set_state_cond(port, SRC_READY,
-					    PD_T_SOURCE_ACTIVITY);
-		}
 		break;
 	case SRC_WAIT_NEW_CAPABILITIES:
 		/* Nothing to do... */
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 11/11 v3] staging: typec: tcpm: Switch to PORT_RESET instead of SNK_UNATTACHED
  2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
                   ` (8 preceding siblings ...)
  2017-08-28 17:23 ` [PATCH 10/11 v3] staging: typec: tcpm: Do not send PING msgs in TCPM Badhri Jagan Sridharan
@ 2017-08-28 17:23 ` Badhri Jagan Sridharan
  9 siblings, 0 replies; 11+ messages in thread
From: Badhri Jagan Sridharan @ 2017-08-28 17:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck
  Cc: devel, linux-kernel, Badhri Jagan Sridharan

When VBUS is not discovered within PD_T_PS_SOURCE_ON although Rp
is detected on CC, TCPM switches the port to SNK_UNATTACHED
state. SNK_UNATTACHED, however does not force TYPEC_CC_OPEN which
makes the partner(source) to think that it is connected.

To overcome this issue, force the port into PORT_RESET state
to make sure the CC lines are open.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
---
Changelog since previous version:
- Only one previous version of the patch was sent.
  Numbering this V3 instead of V2 to keep the sequence
  number in sync with the rest of the patches in the
  patch list.
- added Reviewed-by: Guenter Roeck <linux@roeck-us.net>
- fixed version/sequence numbers

 drivers/staging/typec/tcpm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 9e0111dea7c4..47b8fec5ea36 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -2380,7 +2380,7 @@ static void run_state_machine(struct tcpm_port *port)
 				       0);
 		else
 			/* Wait for VBUS, but not forever */
-			tcpm_set_state(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
+			tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON);
 		break;
 
 	case SRC_TRY:
-- 
2.14.1.342.g6490525c54-goog

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-08-28 17:25 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-28 17:23 [PATCH 01/11 v3] staging: typec: tcpm: set port type callback Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 02/11 v3] staging: typec: tcpm: Check for port type for Try.SRC/Try.SNK Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 03/11 v3] staging: typec: tcpm: Prevent TCPM from looping in SRC_TRYWAIT Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 04/11 v3] staging: usb: tcpm: usb: type-c: tcpm: Check for Rp for tPDDebounce Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 05/11 v3] staging: typec: tcpm: Follow Try.SRC exit requirements Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 06/11 v3] staging: typec: tcpm: Comply with TryWait.SNK State Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 07/11 v3] staging: typec: tcpm: Consider port_type while determining unattached_state Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 08/11 v3] staging: typec: tcpm: add cc change handling in src states Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 09/11 v3] staging: typec: tcpm: typec: tcpm: Wait for CC debounce before PD excg Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 10/11 v3] staging: typec: tcpm: Do not send PING msgs in TCPM Badhri Jagan Sridharan
2017-08-28 17:23 ` [PATCH 11/11 v3] staging: typec: tcpm: Switch to PORT_RESET instead of SNK_UNATTACHED Badhri Jagan Sridharan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).