2023-11-21 20:39:23

by RD Babiera

[permalink] [raw]
Subject: [PATCH v1 0/2] usb: typec: handle tcpc vconn oc fault by triggering tcpm error recovery

When a Vconn swap results in a Vconn over current fault, typec port
interoperability is affected and cannot be recovered unless the connection
is reset and restablished.

The tcpm currently does not have an export symbol to set the port to the
error recovery state in the event of tcpc faults. This patch set adds
tcpm_port_error_recovery for tcpci drivers to use when a fault should
result in a connection reset. Vconn over current fault handling is added
to the maxim tcpci driver.

RD Babiera (2):
usb: typec: tcpm: add tcpm_port_error_recovery symbol
usb: typec: tcpci: add vconn over current fault handling to maxim_core

drivers/usb/typec/tcpm/tcpci_maxim_core.c | 20 +++++++++++++++++++-
drivers/usb/typec/tcpm/tcpm.c | 14 ++++++++++++++
include/linux/usb/tcpci.h | 5 ++++-
include/linux/usb/tcpm.h | 1 +
4 files changed, 38 insertions(+), 2 deletions(-)

--
2.43.0.rc1.413.gea7ed67945-goog


2023-11-21 20:39:23

by RD Babiera

[permalink] [raw]
Subject: [PATCH v1 1/2] usb: typec: tcpm: add tcpm_port_error_recovery symbol

Add tcpm_port_error_recovery symbol and corresponding event that runs in
tcpm_pd_event handler to set the port to the ERROR_RECOVERY state. tcpci
drivers can use the symbol to reset the port when tcpc faults affect port
functionality.

Signed-off-by: RD Babiera <[email protected]>
---
drivers/usb/typec/tcpm/tcpm.c | 14 ++++++++++++++
include/linux/usb/tcpm.h | 1 +
2 files changed, 15 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 058d5b853b57..2e553dc63619 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -251,6 +251,7 @@ enum frs_typec_current {
#define TCPM_FRS_EVENT BIT(3)
#define TCPM_SOURCING_VBUS BIT(4)
#define TCPM_PORT_CLEAN BIT(5)
+#define TCPM_PORT_ERROR BIT(6)

#define LOG_BUFFER_ENTRIES 1024
#define LOG_BUFFER_ENTRY_SIZE 128
@@ -5477,6 +5478,10 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
tcpm_set_state(port, tcpm_default_state(port), 0);
}
}
+ if (events & TCPM_PORT_ERROR) {
+ tcpm_log(port, "port triggering error recovery");
+ tcpm_set_state(port, ERROR_RECOVERY, 0);
+ }

spin_lock(&port->pd_event_lock);
}
@@ -5544,6 +5549,15 @@ bool tcpm_port_is_toggling(struct tcpm_port *port)
}
EXPORT_SYMBOL_GPL(tcpm_port_is_toggling);

+void tcpm_port_error_recovery(struct tcpm_port *port)
+{
+ spin_lock(&port->pd_event_lock);
+ port->pd_events |= TCPM_PORT_ERROR;
+ spin_unlock(&port->pd_event_lock);
+ kthread_queue_work(port->wq, &port->event_work);
+}
+EXPORT_SYMBOL_GPL(tcpm_port_error_recovery);
+
static void tcpm_enable_frs_work(struct kthread_work *work)
{
struct tcpm_port *port = container_of(work, struct tcpm_port, enable_frs);
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index ab7ca872950b..65fac5e1f317 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -173,5 +173,6 @@ void tcpm_pd_hard_reset(struct tcpm_port *port);
void tcpm_tcpc_reset(struct tcpm_port *port);
void tcpm_port_clean(struct tcpm_port *port);
bool tcpm_port_is_toggling(struct tcpm_port *port);
+void tcpm_port_error_recovery(struct tcpm_port *port);

#endif /* __LINUX_USB_TCPM_H */
--
2.43.0.rc1.413.gea7ed67945-goog

2023-11-21 20:39:27

by RD Babiera

[permalink] [raw]
Subject: [PATCH v1 2/2] usb: typec: tcpci: add vconn over current fault handling to maxim_core

Add TCPC_FAULT_STATUS_VCONN_OC constant and corresponding mask definition.
Maxim TCPC is capable of detecting VConn over current faults, so add
fault to alert mask. When a Vconn over current fault is triggered, put the
port in an error recovery state via tcpm_port_error_recovery.

Signed-off-by: RD Babiera <[email protected]>
---
drivers/usb/typec/tcpm/tcpci_maxim_core.c | 20 +++++++++++++++++++-
include/linux/usb/tcpci.h | 5 ++++-
2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
index 9454b12a073c..7fb966fd639b 100644
--- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c
+++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
@@ -92,11 +92,16 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip)
return;
}

+ /* Vconn Over Current Protection */
+ ret = max_tcpci_write8(chip, TCPC_FAULT_STATUS_MASK, TCPC_FAULT_STATUS_MASK_VCONN_OC);
+ if (ret < 0)
+ return;
+
alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_TX_FAILED |
TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_RX_STATUS | TCPC_ALERT_CC_STATUS |
TCPC_ALERT_VBUS_DISCNCT | TCPC_ALERT_RX_BUF_OVF | TCPC_ALERT_POWER_STATUS |
/* Enable Extended alert for detecting Fast Role Swap Signal */
- TCPC_ALERT_EXTND | TCPC_ALERT_EXTENDED_STATUS;
+ TCPC_ALERT_EXTND | TCPC_ALERT_EXTENDED_STATUS | TCPC_ALERT_FAULT;

ret = max_tcpci_write16(chip, TCPC_ALERT_MASK, alert_mask);
if (ret < 0) {
@@ -295,6 +300,19 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status)
}
}

+ if (status & TCPC_ALERT_FAULT) {
+ ret = max_tcpci_read8(chip, TCPC_FAULT_STATUS, &reg_status);
+ if (ret < 0)
+ return ret;
+
+ ret = max_tcpci_write8(chip, TCPC_FAULT_STATUS, reg_status);
+ if (ret < 0)
+ return ret;
+
+ if (reg_status & TCPC_FAULT_STATUS_VCONN_OC)
+ tcpm_port_error_recovery(chip->port);
+ }
+
if (status & TCPC_ALERT_EXTND) {
ret = max_tcpci_read8(chip, TCPC_ALERT_EXTENDED, &reg_status);
if (ret < 0)
diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h
index 83376473ac76..467e8045e9f8 100644
--- a/include/linux/usb/tcpci.h
+++ b/include/linux/usb/tcpci.h
@@ -36,7 +36,9 @@

#define TCPC_ALERT_MASK 0x12
#define TCPC_POWER_STATUS_MASK 0x14
-#define TCPC_FAULT_STATUS_MASK 0x15
+
+#define TCPC_FAULT_STATUS_MASK 0x15
+#define TCPC_FAULT_STATUS_MASK_VCONN_OC BIT(1)

#define TCPC_EXTENDED_STATUS_MASK 0x16
#define TCPC_EXTENDED_STATUS_MASK_VSAFE0V BIT(0)
@@ -104,6 +106,7 @@

#define TCPC_FAULT_STATUS 0x1f
#define TCPC_FAULT_STATUS_ALL_REG_RST_TO_DEFAULT BIT(7)
+#define TCPC_FAULT_STATUS_VCONN_OC BIT(1)

#define TCPC_ALERT_EXTENDED 0x21

--
2.43.0.rc1.413.gea7ed67945-goog

2023-11-28 07:57:43

by Heikki Krogerus

[permalink] [raw]
Subject: Re: [PATCH v1 1/2] usb: typec: tcpm: add tcpm_port_error_recovery symbol

On Tue, Nov 21, 2023 at 08:38:47PM +0000, RD Babiera wrote:
> Add tcpm_port_error_recovery symbol and corresponding event that runs in
> tcpm_pd_event handler to set the port to the ERROR_RECOVERY state. tcpci
> drivers can use the symbol to reset the port when tcpc faults affect port
> functionality.
>
> Signed-off-by: RD Babiera <[email protected]>

Reviewed-by: Heikki Krogerus <[email protected]>

> ---
> drivers/usb/typec/tcpm/tcpm.c | 14 ++++++++++++++
> include/linux/usb/tcpm.h | 1 +
> 2 files changed, 15 insertions(+)
>
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index 058d5b853b57..2e553dc63619 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -251,6 +251,7 @@ enum frs_typec_current {
> #define TCPM_FRS_EVENT BIT(3)
> #define TCPM_SOURCING_VBUS BIT(4)
> #define TCPM_PORT_CLEAN BIT(5)
> +#define TCPM_PORT_ERROR BIT(6)
>
> #define LOG_BUFFER_ENTRIES 1024
> #define LOG_BUFFER_ENTRY_SIZE 128
> @@ -5477,6 +5478,10 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
> tcpm_set_state(port, tcpm_default_state(port), 0);
> }
> }
> + if (events & TCPM_PORT_ERROR) {
> + tcpm_log(port, "port triggering error recovery");
> + tcpm_set_state(port, ERROR_RECOVERY, 0);
> + }
>
> spin_lock(&port->pd_event_lock);
> }
> @@ -5544,6 +5549,15 @@ bool tcpm_port_is_toggling(struct tcpm_port *port)
> }
> EXPORT_SYMBOL_GPL(tcpm_port_is_toggling);
>
> +void tcpm_port_error_recovery(struct tcpm_port *port)
> +{
> + spin_lock(&port->pd_event_lock);
> + port->pd_events |= TCPM_PORT_ERROR;
> + spin_unlock(&port->pd_event_lock);
> + kthread_queue_work(port->wq, &port->event_work);
> +}
> +EXPORT_SYMBOL_GPL(tcpm_port_error_recovery);
> +
> static void tcpm_enable_frs_work(struct kthread_work *work)
> {
> struct tcpm_port *port = container_of(work, struct tcpm_port, enable_frs);
> diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
> index ab7ca872950b..65fac5e1f317 100644
> --- a/include/linux/usb/tcpm.h
> +++ b/include/linux/usb/tcpm.h
> @@ -173,5 +173,6 @@ void tcpm_pd_hard_reset(struct tcpm_port *port);
> void tcpm_tcpc_reset(struct tcpm_port *port);
> void tcpm_port_clean(struct tcpm_port *port);
> bool tcpm_port_is_toggling(struct tcpm_port *port);
> +void tcpm_port_error_recovery(struct tcpm_port *port);
>
> #endif /* __LINUX_USB_TCPM_H */
> --
> 2.43.0.rc1.413.gea7ed67945-goog

--
heikki

2023-11-28 07:59:39

by Heikki Krogerus

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] usb: typec: tcpci: add vconn over current fault handling to maxim_core

On Tue, Nov 21, 2023 at 08:38:48PM +0000, RD Babiera wrote:
> Add TCPC_FAULT_STATUS_VCONN_OC constant and corresponding mask definition.
> Maxim TCPC is capable of detecting VConn over current faults, so add
> fault to alert mask. When a Vconn over current fault is triggered, put the
> port in an error recovery state via tcpm_port_error_recovery.
>
> Signed-off-by: RD Babiera <[email protected]>

Reviewed-by: Heikki Krogerus <[email protected]>

> ---
> drivers/usb/typec/tcpm/tcpci_maxim_core.c | 20 +++++++++++++++++++-
> include/linux/usb/tcpci.h | 5 ++++-
> 2 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
> index 9454b12a073c..7fb966fd639b 100644
> --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c
> +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
> @@ -92,11 +92,16 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip)
> return;
> }
>
> + /* Vconn Over Current Protection */
> + ret = max_tcpci_write8(chip, TCPC_FAULT_STATUS_MASK, TCPC_FAULT_STATUS_MASK_VCONN_OC);
> + if (ret < 0)
> + return;
> +
> alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_TX_FAILED |
> TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_RX_STATUS | TCPC_ALERT_CC_STATUS |
> TCPC_ALERT_VBUS_DISCNCT | TCPC_ALERT_RX_BUF_OVF | TCPC_ALERT_POWER_STATUS |
> /* Enable Extended alert for detecting Fast Role Swap Signal */
> - TCPC_ALERT_EXTND | TCPC_ALERT_EXTENDED_STATUS;
> + TCPC_ALERT_EXTND | TCPC_ALERT_EXTENDED_STATUS | TCPC_ALERT_FAULT;
>
> ret = max_tcpci_write16(chip, TCPC_ALERT_MASK, alert_mask);
> if (ret < 0) {
> @@ -295,6 +300,19 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status)
> }
> }
>
> + if (status & TCPC_ALERT_FAULT) {
> + ret = max_tcpci_read8(chip, TCPC_FAULT_STATUS, &reg_status);
> + if (ret < 0)
> + return ret;
> +
> + ret = max_tcpci_write8(chip, TCPC_FAULT_STATUS, reg_status);
> + if (ret < 0)
> + return ret;
> +
> + if (reg_status & TCPC_FAULT_STATUS_VCONN_OC)
> + tcpm_port_error_recovery(chip->port);
> + }
> +
> if (status & TCPC_ALERT_EXTND) {
> ret = max_tcpci_read8(chip, TCPC_ALERT_EXTENDED, &reg_status);
> if (ret < 0)
> diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h
> index 83376473ac76..467e8045e9f8 100644
> --- a/include/linux/usb/tcpci.h
> +++ b/include/linux/usb/tcpci.h
> @@ -36,7 +36,9 @@
>
> #define TCPC_ALERT_MASK 0x12
> #define TCPC_POWER_STATUS_MASK 0x14
> -#define TCPC_FAULT_STATUS_MASK 0x15
> +
> +#define TCPC_FAULT_STATUS_MASK 0x15
> +#define TCPC_FAULT_STATUS_MASK_VCONN_OC BIT(1)
>
> #define TCPC_EXTENDED_STATUS_MASK 0x16
> #define TCPC_EXTENDED_STATUS_MASK_VSAFE0V BIT(0)
> @@ -104,6 +106,7 @@
>
> #define TCPC_FAULT_STATUS 0x1f
> #define TCPC_FAULT_STATUS_ALL_REG_RST_TO_DEFAULT BIT(7)
> +#define TCPC_FAULT_STATUS_VCONN_OC BIT(1)
>
> #define TCPC_ALERT_EXTENDED 0x21
>
> --
> 2.43.0.rc1.413.gea7ed67945-goog

--
heikki

2023-11-28 15:10:18

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v1 1/2] usb: typec: tcpm: add tcpm_port_error_recovery symbol

On 11/21/23 12:38, RD Babiera wrote:
> Add tcpm_port_error_recovery symbol and corresponding event that runs in
> tcpm_pd_event handler to set the port to the ERROR_RECOVERY state. tcpci
> drivers can use the symbol to reset the port when tcpc faults affect port
> functionality.
>
> Signed-off-by: RD Babiera <[email protected]>

Reviewed-by: Guenter Roeck <[email protected]>

2023-11-28 15:12:05

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] usb: typec: tcpci: add vconn over current fault handling to maxim_core

On 11/21/23 12:38, RD Babiera wrote:
> Add TCPC_FAULT_STATUS_VCONN_OC constant and corresponding mask definition.
> Maxim TCPC is capable of detecting VConn over current faults, so add
> fault to alert mask. When a Vconn over current fault is triggered, put the
> port in an error recovery state via tcpm_port_error_recovery.
>
> Signed-off-by: RD Babiera <[email protected]>

Reviewed-by: Guenter Roeck <[email protected]>