linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled
@ 2021-05-15  5:26 Badhri Jagan Sridharan
  2021-05-15  5:26 ` [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge Badhri Jagan Sridharan
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Badhri Jagan Sridharan @ 2021-05-15  5:26 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Kyle Tso, stable, Badhri Jagan Sridharan

During PR_SWAP, When TCPM is in PR_SWAP_SNK_SRC_SINK_OFF, vbus is
expected to reach VSAFE0V when source turns of vbus. Do not move
to SNK_UNATTACHED state when this happens.

Fixes: 28b43d3d746b ("usb: typec: tcpm: Introduce vsafe0v for vbus")
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index c4fdc00a3bc8..b93c4c8d7b15 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -5114,6 +5114,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
 				tcpm_set_state(port, SNK_UNATTACHED, 0);
 		}
 		break;
+	case PR_SWAP_SNK_SRC_SINK_OFF:
+		/* Do nothing, vsafe0v is expected during transition */
+		break;
 	default:
 		if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
 			tcpm_set_state(port, SNK_UNATTACHED, 0);
-- 
2.31.1.751.gd2f1c929bd-goog


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

* [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge
  2021-05-15  5:26 [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Badhri Jagan Sridharan
@ 2021-05-15  5:26 ` Badhri Jagan Sridharan
  2021-05-17 14:33   ` Guenter Roeck
  2021-05-15  5:26 ` [PATCH v1 3/4] usb: typec: tcpm: Move TCPC to APPLY_RC state during PR_SWAP Badhri Jagan Sridharan
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Badhri Jagan Sridharan @ 2021-05-15  5:26 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Kyle Tso, stable, Badhri Jagan Sridharan

The logic to enable vbus auto discharge on disconnect is used in
more than one place. Since this is repetitive code, moving this into
its own method.

Fixes: f321a02caebd ("usb: typec: tcpm: Implement enabling Auto Discharge disconnect support")
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 39 ++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index b93c4c8d7b15..b475d9b9d38d 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -771,6 +771,21 @@ static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc)
 	port->tcpc->set_cc(port->tcpc, cc);
 }
 
+static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable)
+{
+	int ret = 0;
+
+	if (port->tcpc->enable_auto_vbus_discharge) {
+		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, enable);
+		tcpm_log_force(port, "%s vbus discharge ret:%d", enable ? "enable" : "disable",
+			       ret);
+		if (!ret)
+			port->auto_vbus_discharge_enabled = enable;
+	}
+
+	return ret;
+}
+
 /*
  * Determine RP value to set based on maximum current supported
  * by a port if configured as source.
@@ -3445,12 +3460,7 @@ static int tcpm_src_attach(struct tcpm_port *port)
 	if (ret < 0)
 		return ret;
 
-	if (port->tcpc->enable_auto_vbus_discharge) {
-		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true);
-		tcpm_log_force(port, "enable vbus discharge ret:%d", ret);
-		if (!ret)
-			port->auto_vbus_discharge_enabled = true;
-	}
+	tcpm_enable_auto_vbus_discharge(port, true);
 
 	ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_source(port));
 	if (ret < 0)
@@ -3527,14 +3537,7 @@ static void tcpm_set_partner_usb_comm_capable(struct tcpm_port *port, bool capab
 
 static void tcpm_reset_port(struct tcpm_port *port)
 {
-	int ret;
-
-	if (port->tcpc->enable_auto_vbus_discharge) {
-		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, false);
-		tcpm_log_force(port, "Disable vbus discharge ret:%d", ret);
-		if (!ret)
-			port->auto_vbus_discharge_enabled = false;
-	}
+	tcpm_enable_auto_vbus_discharge(port, false);
 	port->in_ams = false;
 	port->ams = NONE_AMS;
 	port->vdm_sm_running = false;
@@ -3602,13 +3605,7 @@ static int tcpm_snk_attach(struct tcpm_port *port)
 	if (ret < 0)
 		return ret;
 
-	if (port->tcpc->enable_auto_vbus_discharge) {
-		tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V);
-		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true);
-		tcpm_log_force(port, "enable vbus discharge ret:%d", ret);
-		if (!ret)
-			port->auto_vbus_discharge_enabled = true;
-	}
+	tcpm_enable_auto_vbus_discharge(port, true);
 
 	ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port));
 	if (ret < 0)
-- 
2.31.1.751.gd2f1c929bd-goog


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

* [PATCH v1 3/4] usb: typec: tcpm: Move TCPC to APPLY_RC state during PR_SWAP
  2021-05-15  5:26 [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Badhri Jagan Sridharan
  2021-05-15  5:26 ` [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge Badhri Jagan Sridharan
@ 2021-05-15  5:26 ` Badhri Jagan Sridharan
  2021-05-17 14:37   ` Guenter Roeck
  2021-05-15  5:26 ` [PATCH v1 4/4] usb: typec: tcpci: Implement callback for apply_rc Badhri Jagan Sridharan
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Badhri Jagan Sridharan @ 2021-05-15  5:26 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Kyle Tso, stable, Badhri Jagan Sridharan

When vbus auto discharge is enabled, TCPCI based TCPC transitions
into Attached.SNK/Attached.SRC state. During PR_SWAP, TCPCI based
TCPC would disconnect when partner changes power roles. TCPC has
to be moved APPLY RC state during PR_SWAP. This is done by
ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and
POWER_CONTROL.AutodischargeDisconnect is 0. Once the swap sequence
is done, AutoDischargeDisconnect is re-enabled.

Fixes: f321a02caebd ("usb: typec: tcpm: Implement enabling Auto Discharge disconnect support")
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 16 ++++++++++++++++
 include/linux/usb/tcpm.h      |  4 ++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index b475d9b9d38d..5bac4978efb3 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -786,6 +786,19 @@ static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable)
 	return ret;
 }
 
+static void tcpm_apply_rc(struct tcpm_port *port)
+{
+	/*
+	 * TCPCI: Move to APPLY_RC state to prevent disconnect during PR_SWAP
+	 * when Vbus auto discharge on disconnect is enabled.
+	 */
+	if (port->tcpc->enable_auto_vbus_discharge) {
+		tcpm_log(port, "Apply_RC");
+		port->tcpc->apply_rc(port->tcpc, port->cc_req, port->polarity);
+		tcpm_enable_auto_vbus_discharge(port, false);
+	}
+}
+
 /*
  * Determine RP value to set based on maximum current supported
  * by a port if configured as source.
@@ -4428,6 +4441,7 @@ static void run_state_machine(struct tcpm_port *port)
 		tcpm_set_state(port, ready_state(port), 0);
 		break;
 	case PR_SWAP_START:
+		tcpm_apply_rc(port);
 		if (port->pwr_role == TYPEC_SOURCE)
 			tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF,
 				       PD_T_SRC_TRANSITION);
@@ -4467,6 +4481,7 @@ static void run_state_machine(struct tcpm_port *port)
 		tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_ON_PRS);
 		break;
 	case PR_SWAP_SRC_SNK_SINK_ON:
+		tcpm_enable_auto_vbus_discharge(port, true);
 		/* Set the vbus disconnect threshold for implicit contract */
 		tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V);
 		tcpm_set_state(port, SNK_STARTUP, 0);
@@ -4483,6 +4498,7 @@ static void run_state_machine(struct tcpm_port *port)
 			       PD_T_PS_SOURCE_OFF);
 		break;
 	case PR_SWAP_SNK_SRC_SOURCE_ON:
+		tcpm_enable_auto_vbus_discharge(port, true);
 		tcpm_set_cc(port, tcpm_rp_cc(port));
 		tcpm_set_vbus(port, true);
 		/*
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index 42fcfbe10590..bffc8d3e14ad 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -66,6 +66,8 @@ enum tcpm_transmit_type {
  *		For example, some tcpcs may include BC1.2 charger detection
  *		and use that in this case.
  * @set_cc:	Called to set value of CC pins
+ * @apply_rc:	Optional; Needed to move TCPCI based chipset to APPLY_RC state
+ *		as stated by the TCPCI specification.
  * @get_cc:	Called to read current CC pin values
  * @set_polarity:
  *		Called to set polarity
@@ -120,6 +122,8 @@ struct tcpc_dev {
 	int (*get_vbus)(struct tcpc_dev *dev);
 	int (*get_current_limit)(struct tcpc_dev *dev);
 	int (*set_cc)(struct tcpc_dev *dev, enum typec_cc_status cc);
+	int (*apply_rc)(struct tcpc_dev *dev, enum typec_cc_status cc,
+			enum typec_cc_polarity polarity);
 	int (*get_cc)(struct tcpc_dev *dev, enum typec_cc_status *cc1,
 		      enum typec_cc_status *cc2);
 	int (*set_polarity)(struct tcpc_dev *dev,
-- 
2.31.1.751.gd2f1c929bd-goog


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

* [PATCH v1 4/4] usb: typec: tcpci: Implement callback for apply_rc
  2021-05-15  5:26 [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Badhri Jagan Sridharan
  2021-05-15  5:26 ` [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge Badhri Jagan Sridharan
  2021-05-15  5:26 ` [PATCH v1 3/4] usb: typec: tcpm: Move TCPC to APPLY_RC state during PR_SWAP Badhri Jagan Sridharan
@ 2021-05-15  5:26 ` Badhri Jagan Sridharan
  2021-05-17 14:38   ` Guenter Roeck
  2021-05-17  1:30 ` [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Peter Chen
  2021-05-17 14:32 ` Guenter Roeck
  4 siblings, 1 reply; 9+ messages in thread
From: Badhri Jagan Sridharan @ 2021-05-15  5:26 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Kyle Tso, stable, Badhri Jagan Sridharan

APPLY RC is defined as ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and
POWER_CONTROL.AutodischargeDisconnect is 0. When ROLE_CONTROL.CC1 ==
ROLE_CONTROL.CC2, set the other CC to OPEN.

Fixes: f321a02caebd ("usb: typec: tcpm: Implement enabling Auto Discharge disconnect support")
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
 drivers/usb/typec/tcpm/tcpci.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 25b480752266..34b5095cc84f 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -115,6 +115,32 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
 	return 0;
 }
 
+int tcpci_apply_rc(struct tcpc_dev *tcpc, enum typec_cc_status cc, enum typec_cc_polarity polarity)
+{
+	struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
+	unsigned int reg;
+	int ret;
+
+	ret = regmap_read(tcpci->regmap, TCPC_ROLE_CTRL, &reg);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * APPLY_RC state is when ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and vbus autodischarge on
+	 * disconnect is disabled. Bail out when ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2.
+	 */
+	if (((reg & (TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT)) >>
+	     TCPC_ROLE_CTRL_CC2_SHIFT) !=
+	    ((reg & (TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT)) >>
+	     TCPC_ROLE_CTRL_CC1_SHIFT))
+		return 0;
+
+	return regmap_update_bits(tcpci->regmap, TCPC_ROLE_CTRL, polarity == TYPEC_POLARITY_CC1 ?
+				  TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT :
+				  TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT,
+				  TCPC_ROLE_CTRL_CC_OPEN);
+}
+
 static int tcpci_start_toggling(struct tcpc_dev *tcpc,
 				enum typec_port_type port_type,
 				enum typec_cc_status cc)
@@ -728,6 +754,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
 	tcpci->tcpc.get_vbus = tcpci_get_vbus;
 	tcpci->tcpc.set_vbus = tcpci_set_vbus;
 	tcpci->tcpc.set_cc = tcpci_set_cc;
+	tcpci->tcpc.apply_rc = tcpci_apply_rc;
 	tcpci->tcpc.get_cc = tcpci_get_cc;
 	tcpci->tcpc.set_polarity = tcpci_set_polarity;
 	tcpci->tcpc.set_vconn = tcpci_set_vconn;
-- 
2.31.1.751.gd2f1c929bd-goog


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

* Re: [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled
  2021-05-15  5:26 [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Badhri Jagan Sridharan
                   ` (2 preceding siblings ...)
  2021-05-15  5:26 ` [PATCH v1 4/4] usb: typec: tcpci: Implement callback for apply_rc Badhri Jagan Sridharan
@ 2021-05-17  1:30 ` Peter Chen
  2021-05-17 14:32 ` Guenter Roeck
  4 siblings, 0 replies; 9+ messages in thread
From: Peter Chen @ 2021-05-17  1:30 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman, linux-usb,
	linux-kernel, Kyle Tso, stable

On 21-05-14 22:26:10, Badhri Jagan Sridharan wrote:
> During PR_SWAP, When TCPM is in PR_SWAP_SNK_SRC_SINK_OFF, vbus is
> expected to reach VSAFE0V when source turns of vbus. Do not move

%s/of/off

Peter

> to SNK_UNATTACHED state when this happens.
> 
> Fixes: 28b43d3d746b ("usb: typec: tcpm: Introduce vsafe0v for vbus")
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> ---
>  drivers/usb/typec/tcpm/tcpm.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index c4fdc00a3bc8..b93c4c8d7b15 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -5114,6 +5114,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
>  				tcpm_set_state(port, SNK_UNATTACHED, 0);
>  		}
>  		break;
> +	case PR_SWAP_SNK_SRC_SINK_OFF:
> +		/* Do nothing, vsafe0v is expected during transition */
> +		break;
>  	default:
>  		if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
>  			tcpm_set_state(port, SNK_UNATTACHED, 0);
> -- 
> 2.31.1.751.gd2f1c929bd-goog
> 

-- 

Thanks,
Peter Chen


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

* Re: [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled
  2021-05-15  5:26 [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Badhri Jagan Sridharan
                   ` (3 preceding siblings ...)
  2021-05-17  1:30 ` [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Peter Chen
@ 2021-05-17 14:32 ` Guenter Roeck
  4 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2021-05-17 14:32 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Kyle Tso, stable

On Fri, May 14, 2021 at 10:26:10PM -0700, Badhri Jagan Sridharan wrote:
> During PR_SWAP, When TCPM is in PR_SWAP_SNK_SRC_SINK_OFF, vbus is
> expected to reach VSAFE0V when source turns of vbus. Do not move

s/of/off/ as already reported

> to SNK_UNATTACHED state when this happens.
> 
> Fixes: 28b43d3d746b ("usb: typec: tcpm: Introduce vsafe0v for vbus")
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>

Otherwise

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/usb/typec/tcpm/tcpm.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index c4fdc00a3bc8..b93c4c8d7b15 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -5114,6 +5114,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
>  				tcpm_set_state(port, SNK_UNATTACHED, 0);
>  		}
>  		break;
> +	case PR_SWAP_SNK_SRC_SINK_OFF:
> +		/* Do nothing, vsafe0v is expected during transition */
> +		break;
>  	default:
>  		if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
>  			tcpm_set_state(port, SNK_UNATTACHED, 0);
> -- 
> 2.31.1.751.gd2f1c929bd-goog
> 

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

* Re: [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge
  2021-05-15  5:26 ` [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge Badhri Jagan Sridharan
@ 2021-05-17 14:33   ` Guenter Roeck
  0 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2021-05-17 14:33 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Kyle Tso, stable

On Fri, May 14, 2021 at 10:26:11PM -0700, Badhri Jagan Sridharan wrote:
> The logic to enable vbus auto discharge on disconnect is used in
> more than one place. Since this is repetitive code, moving this into
> its own method.
> 
> Fixes: f321a02caebd ("usb: typec: tcpm: Implement enabling Auto Discharge disconnect support")
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/usb/typec/tcpm/tcpm.c | 39 ++++++++++++++++-------------------
>  1 file changed, 18 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index b93c4c8d7b15..b475d9b9d38d 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -771,6 +771,21 @@ static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc)
>  	port->tcpc->set_cc(port->tcpc, cc);
>  }
>  
> +static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable)
> +{
> +	int ret = 0;
> +
> +	if (port->tcpc->enable_auto_vbus_discharge) {
> +		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, enable);
> +		tcpm_log_force(port, "%s vbus discharge ret:%d", enable ? "enable" : "disable",
> +			       ret);
> +		if (!ret)
> +			port->auto_vbus_discharge_enabled = enable;
> +	}
> +
> +	return ret;
> +}
> +
>  /*
>   * Determine RP value to set based on maximum current supported
>   * by a port if configured as source.
> @@ -3445,12 +3460,7 @@ static int tcpm_src_attach(struct tcpm_port *port)
>  	if (ret < 0)
>  		return ret;
>  
> -	if (port->tcpc->enable_auto_vbus_discharge) {
> -		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true);
> -		tcpm_log_force(port, "enable vbus discharge ret:%d", ret);
> -		if (!ret)
> -			port->auto_vbus_discharge_enabled = true;
> -	}
> +	tcpm_enable_auto_vbus_discharge(port, true);
>  
>  	ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_source(port));
>  	if (ret < 0)
> @@ -3527,14 +3537,7 @@ static void tcpm_set_partner_usb_comm_capable(struct tcpm_port *port, bool capab
>  
>  static void tcpm_reset_port(struct tcpm_port *port)
>  {
> -	int ret;
> -
> -	if (port->tcpc->enable_auto_vbus_discharge) {
> -		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, false);
> -		tcpm_log_force(port, "Disable vbus discharge ret:%d", ret);
> -		if (!ret)
> -			port->auto_vbus_discharge_enabled = false;
> -	}
> +	tcpm_enable_auto_vbus_discharge(port, false);
>  	port->in_ams = false;
>  	port->ams = NONE_AMS;
>  	port->vdm_sm_running = false;
> @@ -3602,13 +3605,7 @@ static int tcpm_snk_attach(struct tcpm_port *port)
>  	if (ret < 0)
>  		return ret;
>  
> -	if (port->tcpc->enable_auto_vbus_discharge) {
> -		tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V);
> -		ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true);
> -		tcpm_log_force(port, "enable vbus discharge ret:%d", ret);
> -		if (!ret)
> -			port->auto_vbus_discharge_enabled = true;
> -	}
> +	tcpm_enable_auto_vbus_discharge(port, true);
>  
>  	ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port));
>  	if (ret < 0)
> -- 
> 2.31.1.751.gd2f1c929bd-goog
> 

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

* Re: [PATCH v1 3/4] usb: typec: tcpm: Move TCPC to APPLY_RC state during PR_SWAP
  2021-05-15  5:26 ` [PATCH v1 3/4] usb: typec: tcpm: Move TCPC to APPLY_RC state during PR_SWAP Badhri Jagan Sridharan
@ 2021-05-17 14:37   ` Guenter Roeck
  0 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2021-05-17 14:37 UTC (permalink / raw)
  To: Badhri Jagan Sridharan, Heikki Krogerus, Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Kyle Tso, stable

On 5/14/21 10:26 PM, Badhri Jagan Sridharan wrote:
> When vbus auto discharge is enabled, TCPCI based TCPC transitions
> into Attached.SNK/Attached.SRC state. During PR_SWAP, TCPCI based
> TCPC would disconnect when partner changes power roles. TCPC has
> to be moved APPLY RC state during PR_SWAP. This is done by
> ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and
> POWER_CONTROL.AutodischargeDisconnect is 0. Once the swap sequence
> is done, AutoDischargeDisconnect is re-enabled.
> 
> Fixes: f321a02caebd ("usb: typec: tcpm: Implement enabling Auto Discharge disconnect support")
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> ---
>   drivers/usb/typec/tcpm/tcpm.c | 16 ++++++++++++++++
>   include/linux/usb/tcpm.h      |  4 ++++
>   2 files changed, 20 insertions(+)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index b475d9b9d38d..5bac4978efb3 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -786,6 +786,19 @@ static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable)
>   	return ret;
>   }
>   
> +static void tcpm_apply_rc(struct tcpm_port *port)
> +{
> +	/*
> +	 * TCPCI: Move to APPLY_RC state to prevent disconnect during PR_SWAP
> +	 * when Vbus auto discharge on disconnect is enabled.
> +	 */
> +	if (port->tcpc->enable_auto_vbus_discharge) {
> +		tcpm_log(port, "Apply_RC");
> +		port->tcpc->apply_rc(port->tcpc, port->cc_req, port->polarity);

This is called unconditionally. I think you'll need an additional
		&& port->tcpc->apply_rc
in the if statement above.

> +		tcpm_enable_auto_vbus_discharge(port, false);
> +	}
> +}
> +
>   /*
>    * Determine RP value to set based on maximum current supported
>    * by a port if configured as source.
> @@ -4428,6 +4441,7 @@ static void run_state_machine(struct tcpm_port *port)
>   		tcpm_set_state(port, ready_state(port), 0);
>   		break;
>   	case PR_SWAP_START:
> +		tcpm_apply_rc(port);
>   		if (port->pwr_role == TYPEC_SOURCE)
>   			tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF,
>   				       PD_T_SRC_TRANSITION);
> @@ -4467,6 +4481,7 @@ static void run_state_machine(struct tcpm_port *port)
>   		tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_ON_PRS);
>   		break;
>   	case PR_SWAP_SRC_SNK_SINK_ON:
> +		tcpm_enable_auto_vbus_discharge(port, true);
>   		/* Set the vbus disconnect threshold for implicit contract */
>   		tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V);
>   		tcpm_set_state(port, SNK_STARTUP, 0);
> @@ -4483,6 +4498,7 @@ static void run_state_machine(struct tcpm_port *port)
>   			       PD_T_PS_SOURCE_OFF);
>   		break;
>   	case PR_SWAP_SNK_SRC_SOURCE_ON:
> +		tcpm_enable_auto_vbus_discharge(port, true);
>   		tcpm_set_cc(port, tcpm_rp_cc(port));
>   		tcpm_set_vbus(port, true);
>   		/*
> diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
> index 42fcfbe10590..bffc8d3e14ad 100644
> --- a/include/linux/usb/tcpm.h
> +++ b/include/linux/usb/tcpm.h
> @@ -66,6 +66,8 @@ enum tcpm_transmit_type {
>    *		For example, some tcpcs may include BC1.2 charger detection
>    *		and use that in this case.
>    * @set_cc:	Called to set value of CC pins
> + * @apply_rc:	Optional; Needed to move TCPCI based chipset to APPLY_RC state
> + *		as stated by the TCPCI specification.
>    * @get_cc:	Called to read current CC pin values
>    * @set_polarity:
>    *		Called to set polarity
> @@ -120,6 +122,8 @@ struct tcpc_dev {
>   	int (*get_vbus)(struct tcpc_dev *dev);
>   	int (*get_current_limit)(struct tcpc_dev *dev);
>   	int (*set_cc)(struct tcpc_dev *dev, enum typec_cc_status cc);
> +	int (*apply_rc)(struct tcpc_dev *dev, enum typec_cc_status cc,
> +			enum typec_cc_polarity polarity);
>   	int (*get_cc)(struct tcpc_dev *dev, enum typec_cc_status *cc1,
>   		      enum typec_cc_status *cc2);
>   	int (*set_polarity)(struct tcpc_dev *dev,
> 


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

* Re: [PATCH v1 4/4] usb: typec: tcpci: Implement callback for apply_rc
  2021-05-15  5:26 ` [PATCH v1 4/4] usb: typec: tcpci: Implement callback for apply_rc Badhri Jagan Sridharan
@ 2021-05-17 14:38   ` Guenter Roeck
  0 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2021-05-17 14:38 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Kyle Tso, stable

On Fri, May 14, 2021 at 10:26:13PM -0700, Badhri Jagan Sridharan wrote:
> APPLY RC is defined as ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and
> POWER_CONTROL.AutodischargeDisconnect is 0. When ROLE_CONTROL.CC1 ==
> ROLE_CONTROL.CC2, set the other CC to OPEN.
> 
> Fixes: f321a02caebd ("usb: typec: tcpm: Implement enabling Auto Discharge disconnect support")
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/usb/typec/tcpm/tcpci.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> index 25b480752266..34b5095cc84f 100644
> --- a/drivers/usb/typec/tcpm/tcpci.c
> +++ b/drivers/usb/typec/tcpm/tcpci.c
> @@ -115,6 +115,32 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
>  	return 0;
>  }
>  
> +int tcpci_apply_rc(struct tcpc_dev *tcpc, enum typec_cc_status cc, enum typec_cc_polarity polarity)
> +{
> +	struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
> +	unsigned int reg;
> +	int ret;
> +
> +	ret = regmap_read(tcpci->regmap, TCPC_ROLE_CTRL, &reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	/*
> +	 * APPLY_RC state is when ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and vbus autodischarge on
> +	 * disconnect is disabled. Bail out when ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2.
> +	 */
> +	if (((reg & (TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT)) >>
> +	     TCPC_ROLE_CTRL_CC2_SHIFT) !=
> +	    ((reg & (TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT)) >>
> +	     TCPC_ROLE_CTRL_CC1_SHIFT))
> +		return 0;
> +
> +	return regmap_update_bits(tcpci->regmap, TCPC_ROLE_CTRL, polarity == TYPEC_POLARITY_CC1 ?
> +				  TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT :
> +				  TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT,
> +				  TCPC_ROLE_CTRL_CC_OPEN);
> +}
> +
>  static int tcpci_start_toggling(struct tcpc_dev *tcpc,
>  				enum typec_port_type port_type,
>  				enum typec_cc_status cc)
> @@ -728,6 +754,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
>  	tcpci->tcpc.get_vbus = tcpci_get_vbus;
>  	tcpci->tcpc.set_vbus = tcpci_set_vbus;
>  	tcpci->tcpc.set_cc = tcpci_set_cc;
> +	tcpci->tcpc.apply_rc = tcpci_apply_rc;
>  	tcpci->tcpc.get_cc = tcpci_get_cc;
>  	tcpci->tcpc.set_polarity = tcpci_set_polarity;
>  	tcpci->tcpc.set_vconn = tcpci_set_vconn;
> -- 
> 2.31.1.751.gd2f1c929bd-goog
> 

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

end of thread, other threads:[~2021-05-17 16:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-15  5:26 [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Badhri Jagan Sridharan
2021-05-15  5:26 ` [PATCH v1 2/4] usb: typec: tcpm: Refactor logic to enable/disable auto vbus dicharge Badhri Jagan Sridharan
2021-05-17 14:33   ` Guenter Roeck
2021-05-15  5:26 ` [PATCH v1 3/4] usb: typec: tcpm: Move TCPC to APPLY_RC state during PR_SWAP Badhri Jagan Sridharan
2021-05-17 14:37   ` Guenter Roeck
2021-05-15  5:26 ` [PATCH v1 4/4] usb: typec: tcpci: Implement callback for apply_rc Badhri Jagan Sridharan
2021-05-17 14:38   ` Guenter Roeck
2021-05-17  1:30 ` [PATCH v1 1/4] usb: typec: tcpm: Fix up PR_SWAP when vsafe0v is signalled Peter Chen
2021-05-17 14:32 ` Guenter Roeck

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).