* [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect
@ 2020-08-25 4:21 Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 01/14 v1] usb: typec: tcpci: Add register definitions to tcpci Badhri Jagan Sridharan
` (13 more replies)
0 siblings, 14 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:21 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Hi all,
With this patchset, I am hoping to add Sink Fast Role swap support to TCPM.
Sink Fast Role swap is described by the USB Power Delivery Specification
Revision 3.0. The patchset also adds support to Auto Discharge Disconnect
described in the USB Type-C Port Controller Interface Specification.
I am also sending the chip level driver for the TCPCI based type-c controller
that supports Fast role swap.
I tested the fast role swap implementation with the following
accessories:
1. https://ezq.com/usb-c-multimedia-hub-adapter-8-ports.html
2. https://www.iogear.com/product/GUH3C22P/
Note: I will rebase the patchset on top of https://lkml.org/lkml/2020/8/19/52
once it's picked up in usb-next.
Badhri Jagan Sridharan (14):
usb: typec: tcpci: Add register definitions to tcpci
usb: typec: tcpci: Add support when hidden tx registers are
inaccessible
usb: typec: tcpci: update ROLE_CONTROL for DRP
usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference
usb: typec: tcpci: Add set_vbus tcpci callback
dt-bindings: usb: Maxim type-c controller device tree binding document
usb: typec: tcpci_maxim: Chip level TCPC driver
dt-bindings: connector: Add property to set initial current cap for
FRS
usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)
usb: typec: tcpci: Implement callbacks for FRS
usb: typec: tcpci_maxim: Add support for Sink FRS
usb: typec: tcpm: Implement enabling Auto Discharge disconnect support
usb: typec: tcpci: Implement Auto discharge disconnect callbacks
usb: typec: tcpci_maxim: Implemnent set_auto_vbus_discharge_threshold
.../bindings/connector/usb-connector.txt | 128 ++++
.../devicetree/bindings/usb/maxim,tcpci.txt | 44 ++
drivers/usb/typec/tcpm/Kconfig | 6 +
drivers/usb/typec/tcpm/Makefile | 13 +-
drivers/usb/typec/tcpm/tcpci.c | 149 ++++-
drivers/usb/typec/tcpm/tcpci.h | 43 ++
drivers/usb/typec/tcpm/tcpci_maxim.c | 564 ++++++++++++++++++
drivers/usb/typec/tcpm/tcpm.c | 271 ++++++++-
include/dt-bindings/usb/pd.h | 10 +
include/linux/usb/pd.h | 20 +-
include/linux/usb/tcpm.h | 24 +-
include/linux/usb/typec.h | 13 +
12 files changed, 1249 insertions(+), 36 deletions(-)
create mode 100644 Documentation/devicetree/bindings/connector/usb-connector.txt
create mode 100644 Documentation/devicetree/bindings/usb/maxim,tcpci.txt
create mode 100644 drivers/usb/typec/tcpm/tcpci_maxim.c
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/14 v1] usb: typec: tcpci: Add register definitions to tcpci
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
@ 2020-08-25 4:21 ` Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible Badhri Jagan Sridharan
` (12 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:21 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Add register definitions to trap extended alerts.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index 11c36d086c86..fd26ca35814c 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -16,6 +16,7 @@
#define TCPC_PD_INT_REV 0xa
#define TCPC_ALERT 0x10
+#define TCPC_ALERT_EXTENDED_STATUS BIT(13)
#define TCPC_ALERT_VBUS_DISCNCT BIT(11)
#define TCPC_ALERT_RX_BUF_OVF BIT(10)
#define TCPC_ALERT_FAULT BIT(9)
@@ -32,6 +33,10 @@
#define TCPC_ALERT_MASK 0x12
#define TCPC_POWER_STATUS_MASK 0x14
#define TCPC_FAULT_STATUS_MASK 0x15
+
+#define TCPC_EXTENDED_STATUS_MASK 0x16
+#define TCPC_EXTENDED_STATUS_MASK_VSAFE0V BIT(0)
+
#define TCPC_CONFIG_STD_OUTPUT 0x18
#define TCPC_TCPC_CTRL 0x19
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 01/14 v1] usb: typec: tcpci: Add register definitions to tcpci Badhri Jagan Sridharan
@ 2020-08-25 4:21 ` Badhri Jagan Sridharan
2020-08-28 13:12 ` Heikki Krogerus
2020-08-25 4:21 ` [PATCH 03/14 v1] usb: typec: tcpci: update ROLE_CONTROL for DRP Badhri Jagan Sridharan
` (11 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:21 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
TCPCI spec forbids direct access of TX_BUF_BYTE_x register.
The existing version of tcpci driver assumes that those registers
are directly addressible. Add support for tcpci chips which do
not support direct access to TX_BUF_BYTE_x registers. TX_BUF_BYTE_x
can only be accessed by I2C_WRITE_BYTE_COUNT.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.c | 49 +++++++++++++++++++++++++---------
drivers/usb/typec/tcpm/tcpci.h | 8 ++++++
2 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index f57d91fd0e09..90d348caa6a8 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -320,8 +320,7 @@ static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
return 0;
}
-static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
- enum tcpm_transmit_type type,
+static int tcpci_pd_transmit(struct tcpc_dev *tcpc, enum tcpm_transmit_type type,
const struct pd_message *msg)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
@@ -330,23 +329,47 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
int ret;
cnt = msg ? pd_header_cnt(header) * 4 : 0;
- ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
- if (ret < 0)
- return ret;
+ /**
+ * TCPCI spec forbids direct access of TCPC_TX_DATA.
+ * But, since some of the chipsets offer this capability,
+ * it's fair to support both.
+ */
+ if (!tcpci->data->TX_BUF_BYTE_x_hidden) {
+ ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
+ if (ret < 0)
+ return ret;
- ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
- if (ret < 0)
- return ret;
+ ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
+ if (ret < 0)
+ return ret;
+
+ if (cnt > 0) {
+ ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, &msg->payload, cnt);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+ u8 buf[TCPC_TRANSMIT_BUFFER_MAX_LEN] = {0,};
+ u8 pos = 0;
+
+ /* Payload + header + TCPC_TX_BYTE_CNT */
+ buf[pos++] = cnt + 2;
+
+ if (msg)
+ memcpy(&buf[pos], &msg->header, sizeof(msg->header));
+
+ pos += sizeof(header);
+
+ if (cnt > 0)
+ memcpy(&buf[pos], msg->payload, cnt);
- if (cnt > 0) {
- ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA,
- &msg->payload, cnt);
+ pos += cnt;
+ ret = regmap_raw_write(tcpci->regmap, TCPC_TX_BYTE_CNT, buf, pos);
if (ret < 0)
return ret;
}
- reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
- (type << TCPC_TRANSMIT_TYPE_SHIFT);
+ reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | (type << TCPC_TRANSMIT_TYPE_SHIFT);
ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg);
if (ret < 0)
return ret;
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index fd26ca35814c..cf9d8b63adcb 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -128,9 +128,17 @@
#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
+/* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */
+#define TCPC_TRANSMIT_BUFFER_MAX_LEN 31
+
+/*
+ * @TX_BUF_BYTE_x_hidden
+ * optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT.
+ */
struct tcpci;
struct tcpci_data {
struct regmap *regmap;
+ unsigned char TX_BUF_BYTE_x_hidden:1;
int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
bool enable);
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 03/14 v1] usb: typec: tcpci: update ROLE_CONTROL for DRP
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 01/14 v1] usb: typec: tcpci: Add register definitions to tcpci Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible Badhri Jagan Sridharan
@ 2020-08-25 4:21 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference Badhri Jagan Sridharan
` (10 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:21 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
ROLE_CONTROL register would not have the actual CC terminations
unless the port does not set ROLE_CONTROL.DRP. For DRP ports,
CC_STATUS.cc1/cc2 indicates the final terminations applied
when TCPC enters potential_connect_as_source/_sink.
For DRP ports, infer port role from CC_STATUS and set corresponding
CC terminations before setting the orientation.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.c | 37 +++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 90d348caa6a8..9e814d454d14 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -191,12 +191,47 @@ static int tcpci_set_polarity(struct tcpc_dev *tcpc,
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg;
int ret;
+ enum typec_cc_status cc1, cc2;
- /* Keep the disconnect cc line open */
+ /* Obtain Rp setting from role control */
ret = regmap_read(tcpci->regmap, TCPC_ROLE_CTRL, ®);
if (ret < 0)
return ret;
+ ret = tcpci_get_cc(tcpc, &cc1, &cc2);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * When port has drp toggling enabled, ROLE_CONTROL would only have the initial
+ * terminations for the toggling and does not indicate the final cc
+ * terminations when ConnectionResult is 0 i.e. drp toggling stops and
+ * the connection is resolbed. Infer port role from TCPC_CC_STATUS based on the
+ * terminations seen. The port role is then used to set the cc terminations.
+ */
+ if (reg & TCPC_ROLE_CTRL_DRP) {
+ /* Disable DRP for the OPEN setting to take effect */
+ reg = reg & ~TCPC_ROLE_CTRL_DRP;
+
+ if (polarity == TYPEC_POLARITY_CC2) {
+ reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
+ /* Local port is source */
+ if (cc2 == TYPEC_CC_RD)
+ /* Role control would have the Rp setting when DRP was enabled */
+ reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT;
+ else
+ reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT;
+ } else {
+ reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
+ /* Local port is source */
+ if (cc1 == TYPEC_CC_RD)
+ /* Role control would have the Rp setting when DRP was enabled */
+ reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT;
+ else
+ reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT;
+ }
+ }
+
if (polarity == TYPEC_POLARITY_CC2)
reg |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT;
else
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (2 preceding siblings ...)
2020-08-25 4:21 ` [PATCH 03/14 v1] usb: typec: tcpci: update ROLE_CONTROL for DRP Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-28 14:11 ` Heikki Krogerus
2020-08-25 4:22 ` [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback Badhri Jagan Sridharan
` (9 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Allow chip level drivers to retrieve reference to tcpm_port.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.c | 6 ++++++
drivers/usb/typec/tcpm/tcpci.h | 2 ++
2 files changed, 8 insertions(+)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 9e814d454d14..7b7991c8ac87 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -38,6 +38,12 @@ struct tcpci_chip {
struct tcpci_data data;
};
+struct tcpm_port *tcpci_get_tcpm_port(struct tcpci *tcpci)
+{
+ return tcpci->port;
+}
+EXPORT_SYMBOL_GPL(tcpci_get_tcpm_port);
+
static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
{
return container_of(tcpc, struct tcpci, tcpc);
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index cf9d8b63adcb..04c49a0b0368 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -150,4 +150,6 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data);
void tcpci_unregister_port(struct tcpci *tcpci);
irqreturn_t tcpci_irq(struct tcpci *tcpci);
+struct tcpm_port;
+struct tcpm_port *tcpci_get_tcpm_port(struct tcpci *tcpci);
#endif /* __LINUX_USB_TCPCI_H */
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (3 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-28 7:37 ` Greg Kroah-Hartman
2020-08-25 4:22 ` [PATCH 06/14 v1] dt-bindings: usb: Maxim type-c controller device tree binding document Badhri Jagan Sridharan
` (8 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
set_vbus callback allows TCPC which are TCPCI based, however,
does not support turning on sink and source mode through
Command.SinkVbus and Command.SourceVbusDefaultVoltage.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.c | 7 +++++++
drivers/usb/typec/tcpm/tcpci.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 7b7991c8ac87..89d28e3fbee8 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -328,6 +328,13 @@ static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
int ret;
+ if (tcpci->data->set_vbus) {
+ ret = tcpci->data->set_vbus(tcpci, tcpci->data, source, sink);
+ /* Bypass when ret > 0 */
+ if (ret != 0)
+ return ret < 0 ? ret : 0;
+ }
+
/* Disable both source and sink first before enabling anything */
if (!source) {
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index 04c49a0b0368..4d441bdf24d5 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -144,6 +144,7 @@ struct tcpci_data {
bool enable);
int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data,
enum typec_cc_status cc);
+ int (*set_vbus)(struct tcpci *tcpci, struct tcpci_data *data, bool source, bool sink);
};
struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data);
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 06/14 v1] dt-bindings: usb: Maxim type-c controller device tree binding document
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (4 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver Badhri Jagan Sridharan
` (7 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Add device tree binding document for Maxim TCPCI based Type-C chip driver
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
.../devicetree/bindings/usb/maxim,tcpci.txt | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/maxim,tcpci.txt
diff --git a/Documentation/devicetree/bindings/usb/maxim,tcpci.txt b/Documentation/devicetree/bindings/usb/maxim,tcpci.txt
new file mode 100644
index 000000000000..8a5b08e57b2d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/maxim,tcpci.txt
@@ -0,0 +1,44 @@
+Maxim TCPCI Type-C PD controller:
+---------------------------------
+
+Required properties:
+- compatible: should be set maxim,tcpci:
+
+- reg: 0x25:the i2c slave address of typec port controller device.
+- interrupt-parent: the phandle to the interrupt controller which provides
+ the interrupt.
+- usbpd,usbpd_int: interrupt specification for tcpci alert.
+
+Required sub-node:
+- connector: The "usb-c-connector" attached to the tcpci chip, the bindings
+ of connector node are specified in
+ Documentation/devicetree/bindings/connector/usb-connector.txt
+
+maxtcpc: maxtcpc@25 {
+ status = "okay";
+ compatible = "maxim,tcpc";
+ reg = <0x25>;
+ interrupt-parent = <&gpa8>;
+ usbpd,usbpd_int = <&gpa8 2 GPIO_ACTIVE_LOW>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "sink";
+ self-powered;
+ op-sink-microwatt = <2600000>;
+ source-pdos = <PDO_FIXED(5000, 900,
+ PDO_FIXED_SUSPEND |
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_DATA_SWAP |
+ PDO_FIXED_DUAL_ROLE)>;
+ sink-pdos = <PDO_FIXED(5000, 3000,
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_DATA_SWAP |
+ PDO_FIXED_DUAL_ROLE)
+ PDO_FIXED(9000, 2000, 0)
+ frs-typec-current = <FRS_5V_1P5A>;
+ };
+};
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (5 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 06/14 v1] dt-bindings: usb: Maxim type-c controller device tree binding document Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-25 5:16 ` Randy Dunlap
2020-08-25 4:22 ` [PATCH 08/14 v1] dt-bindings: connector: Add property to set initial current cap for FRS Badhri Jagan Sridharan
` (6 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Chip level TCPC driver for Maxim's TCPCI implementation.
This TCPC implementation does not support the following
commands: COMMAND.SinkVbus, COMMAND.SourceVbusDefaultVoltage,
COMMAND.SourceVbusHighVoltage. Instead the sinking and sourcing
from vbus is supported by writes to custom registers.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/Kconfig | 6 +
drivers/usb/typec/tcpm/Makefile | 13 +-
drivers/usb/typec/tcpm/tcpci.h | 1 +
drivers/usb/typec/tcpm/tcpci_maxim.c | 474 +++++++++++++++++++++++++++
4 files changed, 488 insertions(+), 6 deletions(-)
create mode 100644 drivers/usb/typec/tcpm/tcpci_maxim.c
diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
index fa3f39336246..7c9722b02afe 100644
--- a/drivers/usb/typec/tcpm/Kconfig
+++ b/drivers/usb/typec/tcpm/Kconfig
@@ -27,6 +27,12 @@ config TYPEC_RT1711H
Type-C Port Controller Manager to provide USB PD and USB
Type-C functionalities.
+config TYPEC_TCPCI_MAXIM
+ tristate "Maxim TCPCI based Type-C chip driver"
+ select USB_PSY
+ help
+ MAXIM TCPCI based Type-C chip driver
+
endif # TYPEC_TCPCI
config TYPEC_FUSB302
diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile
index a5ff6c8eb892..58d001cf0dd2 100644
--- a/drivers/usb/typec/tcpm/Makefile
+++ b/drivers/usb/typec/tcpm/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_TYPEC_TCPM) += tcpm.o
-obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o
-obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o
-typec_wcove-y := wcove.o
-obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o
-obj-$(CONFIG_TYPEC_RT1711H) += tcpci_rt1711h.o
+obj-$(CONFIG_TYPEC_TCPM) += tcpm.o
+obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o
+obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o
+typec_wcove-y := wcove.o
+obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o
+obj-$(CONFIG_TYPEC_RT1711H) += tcpci_rt1711h.o
+obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index 4d441bdf24d5..82f021a82456 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -109,6 +109,7 @@
#define TCPC_RX_BYTE_CNT 0x30
#define TCPC_RX_BUF_FRAME_TYPE 0x31
+#define TCPC_RX_BUF_FRAME_TYPE_SOP 0
#define TCPC_RX_HDR 0x32
#define TCPC_RX_DATA 0x34 /* through 0x4f */
diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.c b/drivers/usb/typec/tcpm/tcpci_maxim.c
new file mode 100644
index 000000000000..b61f290a8f96
--- /dev/null
+++ b/drivers/usb/typec/tcpm/tcpci_maxim.c
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020, Google LLC
+ *
+ * MAXIM TCPCI based TCPC driver
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/usb/pd.h>
+#include <linux/usb/tcpm.h>
+#include <linux/usb/typec.h>
+
+#include "tcpci.h"
+
+#define PD_ACTIVITY_TIMEOUT_MS 10000
+
+#define TCPC_VENDOR_ALERT 0x80
+
+#define TCPC_RECEIVE_BUFFER_COUNT_OFFSET 0
+#define TCPC_RECEIVE_BUFFER_FRAME_TYPE_OFFSET 1
+#define TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET 2
+
+/*
+ * LongMessage not supported, hence 32 bytes for buf to be read from RECEIVE_BUFFER.
+ * DEVICE_CAPABILITIES_2.LongMessage = 0, the value in READABLE_BYTE_COUNT reg shall be
+ * less than or equal to 31. Since, RECEIVE_BUFFER len = 31 + 1(READABLE_BYTE_COUNT).
+ */
+#define TCPC_RECEIVE_BUFFER_LEN 32
+
+#define MAX_BUCK_BOOST_SID 0x69
+#define MAX_BUCK_BOOST_OP 0xb9
+#define MAX_BUCK_BOOST_OFF 0
+#define MAX_BUCK_BOOST_SOURCE 0xa
+#define MAX_BUCK_BOOST_SINK 0x5
+
+struct max_tcpci_chip {
+ struct tcpci_data data;
+ struct tcpci *tcpci;
+ struct device *dev;
+ struct i2c_client *client;
+ struct tcpm_port *port;
+};
+
+static const struct regmap_range max_tcpci_tcpci_range[] = {
+ regmap_reg_range(0x00, 0x95)
+};
+
+const struct regmap_access_table max_tcpci_tcpci_write_table = {
+ .yes_ranges = max_tcpci_tcpci_range,
+ .n_yes_ranges = ARRAY_SIZE(max_tcpci_tcpci_range),
+};
+
+static const struct regmap_config max_tcpci_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x95,
+ .wr_table = &max_tcpci_tcpci_write_table,
+};
+
+static struct max_tcpci_chip *tdata_to_max_tcpci(struct tcpci_data *tdata)
+{
+ return container_of(tdata, struct max_tcpci_chip, data);
+}
+
+static int max_tcpci_read16(struct max_tcpci_chip *chip, unsigned int reg, u16 *val)
+{
+ return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u16));
+}
+
+static int max_tcpci_write16(struct max_tcpci_chip *chip, unsigned int reg, u16 val)
+{
+ return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u16));
+}
+
+static int max_tcpci_read8(struct max_tcpci_chip *chip, unsigned int reg, u8 *val)
+{
+ return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u8));
+}
+
+static int max_tcpci_write8(struct max_tcpci_chip *chip, unsigned int reg, u8 val)
+{
+ return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u8));
+}
+
+static void max_tcpci_init_regs(struct max_tcpci_chip *chip)
+{
+ u16 alert_mask = 0;
+ int ret;
+
+ ret = max_tcpci_write16(chip, TCPC_ALERT, 0xffff);
+ if (ret < 0) {
+ dev_err(chip->dev, "Error writing to TCPC_ALERT ret:%d\n", ret);
+ return;
+ }
+
+ ret = max_tcpci_write16(chip, TCPC_VENDOR_ALERT, 0xffff);
+ if (ret < 0) {
+ dev_err(chip->dev, "Error writing to TCPC_VENDOR_ALERT ret:%d\n", ret);
+ 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;
+
+ ret = max_tcpci_write16(chip, TCPC_ALERT_MASK, alert_mask);
+ if (ret < 0) {
+ dev_err(chip->dev, "Error writing to TCPC_ALERT_MASK ret:%d\n", ret);
+ return;
+ }
+
+ /* Enable vbus voltage monitoring and voltage alerts */
+ ret = max_tcpci_write8(chip, TCPC_POWER_CTRL, 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Error writing to TCPC_POWER_CTRL ret:%d\n", ret);
+ return;
+ }
+}
+
+static void process_rx(struct max_tcpci_chip *chip, u16 status)
+{
+ struct pd_message msg;
+ u8 count, frame_type, rx_buf[TCPC_RECEIVE_BUFFER_LEN];
+ int ret, payload_index;
+ u8 *rx_buf_ptr;
+
+ /*
+ * READABLE_BYTE_COUNT: Indicates the number of bytes in the RX_BUF_BYTE_x registers
+ * plus one (for the RX_BUF_FRAME_TYPE) Table 4-36.
+ * Read the count and frame type.
+ */
+ ret = regmap_raw_read(chip->data.regmap, TCPC_RX_BYTE_CNT, rx_buf, 2);
+ if (ret < 0) {
+ dev_err(chip->dev, "TCPC_RX_BYTE_CNT read failed ret:%d", ret);
+ return;
+ }
+
+ count = rx_buf[TCPC_RECEIVE_BUFFER_COUNT_OFFSET];
+ frame_type = rx_buf[TCPC_RECEIVE_BUFFER_FRAME_TYPE_OFFSET];
+
+ if (count == 0 || frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP) {
+ max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
+ dev_err(chip->dev, "%s", count == 0 ? "error: count is 0" :
+ "error frame_type is not SOP");
+ return;
+ }
+
+ if (count > sizeof(struct pd_message) || count + 1 > TCPC_RECEIVE_BUFFER_LEN) {
+ dev_err(chip->dev, "Invalid TCPC_RX_BYTE_CNT %d", count);
+ return;
+ }
+
+ /*
+ * Read count + 1 as RX_BUF_BYTE_x is hidden and can only be read through
+ * TCPC_RX_BYTE_CNT
+ */
+ count += 1;
+ ret = regmap_raw_read(chip->data.regmap, TCPC_RX_BYTE_CNT, rx_buf, count);
+ if (ret < 0) {
+ dev_err(chip->dev, "Error: TCPC_RX_BYTE_CNT read failed: %d", ret);
+ return;
+ }
+
+ rx_buf_ptr = rx_buf + TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET;
+ msg.header = cpu_to_le16(*(u16 *)rx_buf_ptr);
+ rx_buf_ptr = rx_buf_ptr + sizeof(msg.header);
+ for (payload_index = 0; payload_index < pd_header_cnt_le(msg.header); payload_index++,
+ rx_buf_ptr += sizeof(msg.payload[0]))
+ msg.payload[payload_index] = cpu_to_le32(*(u32 *)rx_buf_ptr);
+
+ /*
+ * Read complete, clear RX status alert bit.
+ * Clear overflow as well if set.
+ */
+ ret = max_tcpci_write16(chip, TCPC_ALERT, status & TCPC_ALERT_RX_BUF_OVF ?
+ TCPC_ALERT_RX_STATUS | TCPC_ALERT_RX_BUF_OVF :
+ TCPC_ALERT_RX_STATUS);
+ if (ret < 0)
+ return;
+
+ tcpm_pd_receive(chip->port, &msg);
+}
+
+static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdata, bool source, bool sink)
+{
+ struct max_tcpci_chip *chip = tdata_to_max_tcpci(tdata);
+ u8 buffer_source[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SOURCE};
+ u8 buffer_sink[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SINK};
+ u8 buffer_none[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_OFF};
+ struct i2c_client *i2c = chip->client;
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = MAX_BUCK_BOOST_SID,
+ .flags = i2c->flags & I2C_M_TEN,
+ .len = 2,
+ .buf = source ? buffer_source : sink ? buffer_sink : buffer_none,
+ },
+ };
+
+ if (source && sink) {
+ dev_err(chip->dev, "Both source and sink set\n");
+ return -EINVAL;
+ }
+
+ ret = i2c_transfer(i2c->adapter, msgs, 1);
+
+ return ret < 0 ? ret : 1;
+}
+
+static void process_power_status(struct max_tcpci_chip *chip)
+{
+ u8 pwr_status;
+ int ret;
+
+ ret = max_tcpci_read8(chip, TCPC_POWER_STATUS, &pwr_status);
+ if (ret < 0)
+ return;
+
+ if (pwr_status == 0xff)
+ max_tcpci_init_regs(chip);
+ else
+ tcpm_vbus_change(chip->port);
+}
+
+static void process_tx(struct max_tcpci_chip *chip, u16 status)
+{
+ if (status & TCPC_ALERT_TX_SUCCESS)
+ tcpm_pd_transmit_complete(chip->port, TCPC_TX_SUCCESS);
+ else if (status & TCPC_ALERT_TX_DISCARDED)
+ tcpm_pd_transmit_complete(chip->port, TCPC_TX_DISCARDED);
+ else if (status & TCPC_ALERT_TX_FAILED)
+ tcpm_pd_transmit_complete(chip->port, TCPC_TX_FAILED);
+
+ /* Reinit regs as Hard reset sets them to default value */
+ if ((status & TCPC_ALERT_TX_SUCCESS) && (status & TCPC_ALERT_TX_FAILED))
+ max_tcpci_init_regs(chip);
+}
+
+static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status)
+{
+ u16 mask;
+ int ret;
+
+ /*
+ * Clear alert status for everything except RX_STATUS, which shouldn't
+ * be cleared until we have successfully retrieved message.
+ */
+ if (status & ~TCPC_ALERT_RX_STATUS) {
+ mask = status & TCPC_ALERT_RX_BUF_OVF ?
+ status & ~(TCPC_ALERT_RX_STATUS | TCPC_ALERT_RX_BUF_OVF) :
+ status & ~TCPC_ALERT_RX_STATUS;
+ ret = max_tcpci_write16(chip, TCPC_ALERT, mask);
+ if (ret < 0) {
+ dev_err(chip->dev, "ALERT clear failed\n");
+ return ret;
+ }
+ }
+
+ if (status & TCPC_ALERT_RX_BUF_OVF && !(status & TCPC_ALERT_RX_STATUS)) {
+ ret = max_tcpci_write16(chip, TCPC_ALERT, (TCPC_ALERT_RX_STATUS |
+ TCPC_ALERT_RX_BUF_OVF));
+ if (ret < 0) {
+ dev_err(chip->dev, "ALERT clear failed\n");
+ return ret;
+ }
+ }
+
+ if (status & TCPC_ALERT_RX_STATUS)
+ process_rx(chip, status);
+
+ if (status & TCPC_ALERT_TX_DISCARDED)
+ dev_info(chip->dev, "TX_DISCARDED");
+
+ if (status & TCPC_ALERT_VBUS_DISCNCT)
+ tcpm_vbus_change(chip->port);
+
+ if (status & TCPC_ALERT_CC_STATUS)
+ tcpm_cc_change(chip->port);
+
+ if (status & TCPC_ALERT_POWER_STATUS)
+ process_power_status(chip);
+
+ if (status & TCPC_ALERT_RX_HARD_RST) {
+ tcpm_pd_hard_reset(chip->port);
+ max_tcpci_init_regs(chip);
+ }
+
+ if (status & TCPC_ALERT_TX_SUCCESS || status & TCPC_ALERT_TX_DISCARDED || status &
+ TCPC_ALERT_TX_FAILED)
+ process_tx(chip, status);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t max_tcpci_irq(int irq, void *dev_id)
+{
+ struct max_tcpci_chip *chip = dev_id;
+ u16 status;
+ irqreturn_t irq_return;
+ int ret;
+
+ if (!chip->port)
+ return IRQ_HANDLED;
+
+ ret = max_tcpci_read16(chip, TCPC_ALERT, &status);
+ if (ret < 0) {
+ dev_err(chip->dev, "ALERT read failed\n");
+ return ret;
+ }
+ while (status) {
+ irq_return = _max_tcpci_irq(chip, status);
+ /* Do not return if the ALERT is already set. */
+ ret = max_tcpci_read16(chip, TCPC_ALERT, &status);
+ if (ret < 0)
+ break;
+ }
+
+ return irq_return;
+}
+
+static irqreturn_t max_tcpci_isr(int irq, void *dev_id)
+{
+ struct max_tcpci_chip *chip = dev_id;
+
+ pm_wakeup_event(chip->dev, PD_ACTIVITY_TIMEOUT_MS);
+
+ if (!chip->port)
+ return IRQ_HANDLED;
+
+ return IRQ_WAKE_THREAD;
+}
+
+static int max_tcpci_init_alert(struct max_tcpci_chip *chip, struct i2c_client *client)
+{
+ int ret, irq_gpio;
+
+ irq_gpio = of_get_named_gpio(client->dev.of_node, "usbpd,usbpd_int", 0);
+ client->irq = gpio_to_irq(irq_gpio);
+ if (!client->irq)
+ return -ENODEV;
+
+ ret = devm_request_threaded_irq(chip->dev, client->irq, max_tcpci_isr, max_tcpci_irq,
+ (IRQF_TRIGGER_LOW | IRQF_ONESHOT), dev_name(chip->dev),
+ chip);
+
+ if (ret < 0)
+ return ret;
+
+ enable_irq_wake(client->irq);
+ return 0;
+}
+
+static int max_tcpci_start_toggling(struct tcpci *tcpci, struct tcpci_data *tdata,
+ enum typec_cc_status cc)
+{
+ struct max_tcpci_chip *chip = tdata_to_max_tcpci(tdata);
+
+ max_tcpci_init_regs(chip);
+
+ return 0;
+}
+
+static int tcpci_init(struct tcpci *tcpci, struct tcpci_data *data)
+{
+ /*
+ * Generic TCPCI overwrites the regs once this driver initializes
+ * them. Prevent this by returning -1.
+ */
+ return -1;
+}
+
+static int max_tcpci_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id)
+{
+ int ret;
+ struct max_tcpci_chip *chip;
+ u8 power_status;
+
+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->client = client;
+ chip->data.regmap = devm_regmap_init_i2c(client, &max_tcpci_regmap_config);
+ if (IS_ERR(chip->data.regmap)) {
+ dev_err(&client->dev, "Regmap init failed\n");
+ return PTR_ERR(chip->data.regmap);
+ }
+
+ chip->dev = &client->dev;
+ i2c_set_clientdata(client, chip);
+
+ ret = max_tcpci_read8(chip, TCPC_POWER_STATUS, &power_status);
+ if (ret < 0)
+ return ret;
+
+ if (power_status & TCPC_POWER_STATUS_UNINIT) {
+ dev_err(&client->dev, "TCPC not ready!");
+ return -EPROBE_DEFER;
+ }
+
+ /* Chip level tcpci callbacks */
+ chip->data.set_vbus = max_tcpci_set_vbus;
+ chip->data.start_drp_toggling = max_tcpci_start_toggling;
+ chip->data.TX_BUF_BYTE_x_hidden = true;
+ chip->data.init = tcpci_init;
+
+ max_tcpci_init_regs(chip);
+ chip->tcpci = tcpci_register_port(chip->dev, &chip->data);
+ if (IS_ERR_OR_NULL(chip->tcpci)) {
+ dev_err(&client->dev, "TCPCI port registration failed");
+ ret = PTR_ERR(chip->tcpci);
+ return PTR_ERR(chip->tcpci);
+ }
+ chip->port = tcpci_get_tcpm_port(chip->tcpci);
+ ret = max_tcpci_init_alert(chip, client);
+ if (ret < 0)
+ goto unreg_port;
+
+ device_init_wakeup(chip->dev, true);
+ return 0;
+
+unreg_port:
+ tcpci_unregister_port(chip->tcpci);
+
+ return ret;
+}
+
+static int max_tcpci_remove(struct i2c_client *client)
+{
+ struct max_tcpci_chip *chip = i2c_get_clientdata(client);
+
+ if (!IS_ERR_OR_NULL(chip->tcpci))
+ tcpci_unregister_port(chip->tcpci);
+
+ return 0;
+}
+
+static const struct i2c_device_id max_tcpci_id[] = {
+ { "maxtcpc", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max_tcpci_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id max_tcpci_of_match[] = {
+ { .compatible = "maxim,tcpc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, max_tcpci_of_match);
+#endif
+
+static struct i2c_driver max_tcpci_i2c_driver = {
+ .driver = {
+ .name = "maxtcpc",
+ .of_match_table = of_match_ptr(max_tcpci_of_match),
+ },
+ .probe = max_tcpci_probe,
+ .remove = max_tcpci_remove,
+ .id_table = max_tcpci_id,
+};
+module_i2c_driver(max_tcpci_i2c_driver);
+
+MODULE_AUTHOR("Badhri Jagan Sridharan <badhri@google.com>");
+MODULE_DESCRIPTION("Maxim TCPCI based USB Type-C Port Controller Interface Driver");
+MODULE_LICENSE("GPL v2");
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 08/14 v1] dt-bindings: connector: Add property to set initial current cap for FRS
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (6 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS) Badhri Jagan Sridharan
` (5 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
This change adds frs-typec-current which allows setting the initial current
capability of the new source when vSafe5V is applied during PD3.0
sink Fast Role Swap.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
.../bindings/connector/usb-connector.txt | 128 ++++++++++++++++++
include/dt-bindings/usb/pd.h | 10 ++
2 files changed, 138 insertions(+)
create mode 100644 Documentation/devicetree/bindings/connector/usb-connector.txt
diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt
new file mode 100644
index 000000000000..e2f6e0f07d00
--- /dev/null
+++ b/Documentation/devicetree/bindings/connector/usb-connector.txt
@@ -0,0 +1,128 @@
+USB Connector
+=============
+
+USB connector node represents physical USB connector. It should be
+a child of USB interface controller.
+
+Required properties:
+- compatible: describes type of the connector, must be one of:
+ "usb-a-connector",
+ "usb-b-connector",
+ "usb-c-connector".
+
+Optional properties:
+- label: symbolic name for the connector,
+- type: size of the connector, should be specified in case of USB-A, USB-B
+ non-fullsize connectors: "mini", "micro".
+
+Optional properties for usb-c-connector:
+- power-role: should be one of "source", "sink" or "dual"(DRP) if typec
+ connector has power support.
+- try-power-role: preferred power role if "dual"(DRP) can support Try.SNK
+ or Try.SRC, should be "sink" for Try.SNK or "source" for Try.SRC.
+- data-role: should be one of "host", "device", "dual"(DRD) if typec
+ connector supports USB data.
+- frs-typec-current - Initial current capability of the new source when vSafe5V
+ is applied during PD3.0 Fast Role Swap. "Table 6-14 Fixed Supply PDO - Sink"
+ of "USB Power Delivery Specification Revision 3.0, Version 1.2" provides the
+ different power levels and "6.4.1.3.1.6 Fast Role Swap USB Type-C Current"
+ provides a detailed description of the field.
+ 0: Fast role swap not supported
+ 1: Default USB Power
+ 2: 1.5A @ 5V
+ 3: 3A @ 5V.
+
+Required properties for usb-c-connector with power delivery support:
+- source-pdos: An array of u32 with each entry providing supported power
+ source data object(PDO), the detailed bit definitions of PDO can be found
+ in "Universal Serial Bus Power Delivery Specification" chapter 6.4.1.2
+ Source_Capabilities Message, the order of each entry(PDO) should follow
+ the PD spec chapter 6.4.1. Required for power source and power dual role.
+ User can specify the source PDO array via PDO_FIXED/BATT/VAR/PPS_APDO()
+ defined in dt-bindings/usb/pd.h.
+- sink-pdos: An array of u32 with each entry providing supported power
+ sink data object(PDO), the detailed bit definitions of PDO can be found
+ in "Universal Serial Bus Power Delivery Specification" chapter 6.4.1.3
+ Sink Capabilities Message, the order of each entry(PDO) should follow
+ the PD spec chapter 6.4.1. Required for power sink and power dual role.
+ User can specify the sink PDO array via PDO_FIXED/BATT/VAR/PPS_APDO() defined
+ in dt-bindings/usb/pd.h.
+- op-sink-microwatt: Sink required operating power in microwatt, if source
+ can't offer the power, Capability Mismatch is set. Required for power
+ sink and power dual role.
+
+Required nodes:
+- any data bus to the connector should be modeled using the OF graph bindings
+ specified in bindings/graph.txt, unless the bus is between parent node and
+ the connector. Since single connector can have multpile data buses every bus
+ has assigned OF graph port number as follows:
+ 0: High Speed (HS), present in all connectors,
+ 1: Super Speed (SS), present in SS capable connectors,
+ 2: Sideband use (SBU), present in USB-C.
+
+Examples
+--------
+
+1. Micro-USB connector with HS lines routed via controller (MUIC):
+
+muic-max77843@66 {
+ ...
+ usb_con: connector {
+ compatible = "usb-b-connector";
+ label = "micro-USB";
+ type = "micro";
+ };
+};
+
+2. USB-C connector attached to CC controller (s2mm005), HS lines routed
+to companion PMIC (max77865), SS lines to USB3 PHY and SBU to DisplayPort.
+DisplayPort video lines are routed to the connector via SS mux in USB3 PHY.
+
+ccic: s2mm005@33 {
+ ...
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usb_con_hs: endpoint {
+ remote-endpoint = <&max77865_usbc_hs>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ usb_con_ss: endpoint {
+ remote-endpoint = <&usbdrd_phy_ss>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ usb_con_sbu: endpoint {
+ remote-endpoint = <&dp_aux>;
+ };
+ };
+ };
+ };
+};
+
+3. USB-C connector attached to a typec port controller(ptn5110), which has
+power delivery support and enables drp.
+
+typec: ptn5110@50 {
+ ...
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ power-role = "dual";
+ try-power-role = "sink";
+ source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
+ sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
+ PDO_VAR(5000, 12000, 2000)>;
+ op-sink-microwatt = <10000000>;
+ };
+};
diff --git a/include/dt-bindings/usb/pd.h b/include/dt-bindings/usb/pd.h
index 985f2bbd4d24..db1ad4532197 100644
--- a/include/dt-bindings/usb/pd.h
+++ b/include/dt-bindings/usb/pd.h
@@ -35,6 +35,16 @@
#define VSAFE5V 5000 /* mv units */
+/*
+ * Based on "Table 6-14 Fixed Supply PDO - Sink" of "USB Power Delivery Specification Revision 3.0,
+ * Version 1.2"
+ * Initial current capability of the new source when vSafe5V is applied.
+ */
+#define FRS_NOT_SUPPORTED 0
+#define FRS_DEFAULT_POWER 1
+#define FRS_5V_1P5A 2
+#define FRS_5V_3A 3
+
#define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */
#define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */
#define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (7 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 08/14 v1] dt-bindings: connector: Add property to set initial current cap for FRS Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-26 12:42 ` kernel test robot
2020-08-25 4:22 ` [PATCH 10/14 v1] usb: typec: tcpci: Implement callbacks for FRS Badhri Jagan Sridharan
` (4 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
PD 3.0 spec defines a new mechanism for power role swap called
Fast role swap. This change enables TCPM to support FRS when
acting as sink.
Once the explicit contract is negotiated, sink port is
expected to query the source port for sink caps to
determine whether the source is FRS capable.
Bits 23 & 24 of fixed pdo of the sink caps from the source, when
set, indicates the current needed by the source when fast role
swap is in progress(Implicit contract phasae). 0 indicates that
the source does not support Fast Role Swap.
Upon receiving the FRS signal from the source,
TCPC(TCPM_FRS_EVENT) informs TCPM to start the Fast role swap sequence.
1. TCPM sends FRS PD message: FR_SWAP_SEND
2. If response is not received within the expiry of
SenderResponseTimer, Error recovery is triggered.:
FR_SWAP_SEND_TIMEOUT
3. Upon receipt of the accept message, TCPM waits for
PSSourceOffTimer for PS_READY message from the partner:
FR_SWAP_SNK_SRC_NEW_SINK_READY.
TCPC is expected to autonomously turn on vbus once the FRS
signal is received and vbus voltage falls below vsafe5v within
tSrcFrSwap. This is different from traditional power role swap
where the vbus sourcing is turned on by TCPM.
4. By this time, TCPC most likely would have started to
source vbus, TCPM waits for tSrcFrSwap to see if the
lower level TCPC driver signals TCPM_SOURCING_VBUS event:
FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED.
5. When TCPC signals sourcing vbus, TCPM sends PS_READY msg and
changes the CC pin from Rd to Rp. This is the end of fast
role swap sequence and TCPM initiates the sequnce to negotiate
explicit contract by transitioning into SRC_STARTUP after
SwapSrcStart.
The code is written based on the sequence described in "Figure 8-107:
Dual-role Port in Sink to Source Fast Role Swap State Diagram" of
USB Power Delivery Specification Revision 3.0, Version 1.2.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpm.c | 191 +++++++++++++++++++++++++++++++++-
include/linux/usb/pd.h | 20 ++--
include/linux/usb/tcpm.h | 8 +-
include/linux/usb/typec.h | 13 +++
4 files changed, 220 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 3ef37202ee37..6ea4613af905 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -103,6 +103,13 @@
S(VCONN_SWAP_TURN_ON_VCONN), \
S(VCONN_SWAP_TURN_OFF_VCONN), \
\
+ S(FR_SWAP_SEND), \
+ S(FR_SWAP_SEND_TIMEOUT), \
+ S(FR_SWAP_SNK_SRC_TRANSITION_TO_OFF), \
+ S(FR_SWAP_SNK_SRC_NEW_SINK_READY), \
+ S(FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED), \
+ S(FR_SWAP_CANCEL), \
+ \
S(SNK_TRY), \
S(SNK_TRY_WAIT), \
S(SNK_TRY_WAIT_DEBOUNCE), \
@@ -124,6 +131,9 @@
S(GET_PPS_STATUS_SEND), \
S(GET_PPS_STATUS_SEND_TIMEOUT), \
\
+ S(GET_SINK_CAP), \
+ S(GET_SINK_CAP_TIMEOUT), \
+ \
S(ERROR_RECOVERY), \
S(PORT_RESET), \
S(PORT_RESET_WAIT_OFF)
@@ -172,6 +182,8 @@ enum adev_actions {
#define TCPM_CC_EVENT BIT(0)
#define TCPM_VBUS_EVENT BIT(1)
#define TCPM_RESET_EVENT BIT(2)
+#define TCPM_FRS_EVENT BIT(3)
+#define TCPM_SOURCING_VBUS BIT(4)
#define LOG_BUFFER_ENTRIES 1024
#define LOG_BUFFER_ENTRY_SIZE 128
@@ -181,6 +193,8 @@ enum adev_actions {
#define SVID_DISCOVERY_MAX 16
#define ALTMODE_DISCOVERY_MAX (SVID_DISCOVERY_MAX * MODE_DISCOVERY_MAX)
+#define GET_SINK_CAP_RETRY_MS 100
+
struct pd_mode_data {
int svid_index; /* current SVID index */
int nsvids;
@@ -256,6 +270,7 @@ struct tcpm_port {
struct work_struct event_work;
struct delayed_work state_machine;
struct delayed_work vdm_state_machine;
+ struct delayed_work enable_frs;
bool state_machine_running;
struct completion tx_complete;
@@ -330,6 +345,12 @@ struct tcpm_port {
/* port belongs to a self powered device */
bool self_powered;
+ /* FRS */
+ enum frs_typec_current frs_current;
+
+ /* Sink caps have been queried */
+ bool sink_cap_done;
+
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
struct mutex logbuffer_lock; /* log buffer access lock */
@@ -1646,6 +1667,9 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
unsigned int cnt = pd_header_cnt_le(msg->header);
unsigned int rev = pd_header_rev_le(msg->header);
unsigned int i;
+ enum frs_typec_current frs_current;
+ bool frs_enable;
+ int ret;
switch (type) {
case PD_DATA_SOURCE_CAP:
@@ -1715,7 +1739,21 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
/* We don't do anything with this at the moment... */
for (i = 0; i < cnt; i++)
port->sink_caps[i] = le32_to_cpu(msg->payload[i]);
+
+ frs_current = (port->sink_caps[0] & PDO_FIXED_FRS_CURR_MASK) >>
+ PDO_FIXED_FRS_CURR_SHIFT;
+ frs_enable = frs_current && (frs_current <= port->typec_caps.frs_current);
+ tcpm_log(port,
+ "Port partner FRS capable partner_frs_current:%u port_frs_current:%u enable:%c",
+ frs_current, port->typec_caps.frs_current, frs_enable ? 'y' : 'n');
+ if (frs_enable) {
+ ret = port->tcpc->enable_frs(port->tcpc, true);
+ tcpm_log(port, "Enable FRS %s, ret:%d\n", ret ? "fail" : "success", ret);
+ }
+
port->nr_sink_caps = cnt;
+ port->sink_cap_done = true;
+ tcpm_set_state(port, SNK_READY, 0);
break;
case PD_DATA_VENDOR_DEF:
tcpm_handle_vdm_request(port, msg->payload, cnt);
@@ -1810,6 +1848,9 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
case VCONN_SWAP_WAIT_FOR_VCONN:
tcpm_set_state(port, VCONN_SWAP_TURN_OFF_VCONN, 0);
break;
+ case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+ tcpm_set_state(port, FR_SWAP_SNK_SRC_NEW_SINK_READY, 0);
+ break;
default:
break;
}
@@ -1849,6 +1890,13 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
-EAGAIN : -EOPNOTSUPP);
tcpm_set_state(port, VCONN_SWAP_CANCEL, 0);
break;
+ case FR_SWAP_SEND:
+ tcpm_set_state(port, FR_SWAP_CANCEL, 0);
+ break;
+ case GET_SINK_CAP:
+ port->sink_cap_done = true;
+ tcpm_set_state(port, ready_state(port), 0);
+ break;
default:
break;
}
@@ -1883,6 +1931,9 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
case VCONN_SWAP_SEND:
tcpm_set_state(port, VCONN_SWAP_START, 0);
break;
+ case FR_SWAP_SEND:
+ tcpm_set_state(port, FR_SWAP_SNK_SRC_TRANSITION_TO_OFF, 0);
+ break;
default:
break;
}
@@ -2783,6 +2834,10 @@ static void tcpm_reset_port(struct tcpm_port *port)
port->try_src_count = 0;
port->try_snk_count = 0;
port->usb_type = POWER_SUPPLY_USB_TYPE_C;
+ port->nr_sink_caps = 0;
+ port->sink_cap_done = false;
+ if (port->tcpc->enable_frs)
+ port->tcpc->enable_frs(port->tcpc, false);
power_supply_changed(port->psy);
}
@@ -3334,10 +3389,9 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_swap_complete(port, 0);
tcpm_typec_connect(port);
tcpm_check_send_discover(port);
+ mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(0));
tcpm_pps_complete(port, port->pps_status);
-
power_supply_changed(port->psy);
-
break;
/* Accessory states */
@@ -3361,9 +3415,13 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, HARD_RESET_START, 0);
break;
case HARD_RESET_START:
+ port->sink_cap_done = false;
+ if (port->tcpc->enable_frs)
+ port->tcpc->enable_frs(port->tcpc, false);
port->hard_reset_count++;
port->tcpc->set_pd_rx(port->tcpc, false);
tcpm_unregister_altmodes(port);
+ port->nr_sink_caps = 0;
port->send_discover = true;
if (port->pwr_role == TYPEC_SOURCE)
tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF,
@@ -3477,6 +3535,35 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, ready_state(port), 0);
break;
+ case FR_SWAP_SEND:
+ if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP)) {
+ tcpm_set_state(port, ERROR_RECOVERY, 0);
+ break;
+ }
+ tcpm_set_state_cond(port, FR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE);
+ break;
+ case FR_SWAP_SEND_TIMEOUT:
+ tcpm_set_state(port, ERROR_RECOVERY, 0);
+ break;
+ case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+ tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF);
+ break;
+ case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+ if (port->vbus_source)
+ tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0);
+ else
+ tcpm_set_state(port, ERROR_RECOVERY, PD_T_RECEIVER_RESPONSE);
+ break;
+ case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
+ tcpm_set_pwr_role(port, TYPEC_SOURCE);
+ if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
+ tcpm_set_state(port, ERROR_RECOVERY, 0);
+ break;
+ }
+ tcpm_set_cc(port, tcpm_rp_cc(port));
+ tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START);
+ break;
+
/* PR_Swap states */
case PR_SWAP_ACCEPT:
tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
@@ -3595,6 +3682,7 @@ static void run_state_machine(struct tcpm_port *port)
case PR_SWAP_CANCEL:
case VCONN_SWAP_CANCEL:
tcpm_swap_complete(port, port->swap_status);
+ case FR_SWAP_CANCEL:
if (port->pwr_role == TYPEC_SOURCE)
tcpm_set_state(port, SRC_READY, 0);
else
@@ -3634,6 +3722,14 @@ static void run_state_machine(struct tcpm_port *port)
case GET_PPS_STATUS_SEND_TIMEOUT:
tcpm_set_state(port, ready_state(port), 0);
break;
+ case GET_SINK_CAP:
+ tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP);
+ tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE);
+ break;
+ case GET_SINK_CAP_TIMEOUT:
+ port->sink_cap_done = true;
+ tcpm_set_state(port, ready_state(port), 0);
+ break;
case ERROR_RECOVERY:
tcpm_swap_complete(port, -EPROTO);
tcpm_pps_complete(port, -EPROTO);
@@ -3850,6 +3946,13 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
* Ignore it.
*/
break;
+ case FR_SWAP_SEND:
+ case FR_SWAP_SEND_TIMEOUT:
+ case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+ case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+ case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
+ /* Do nothing, CC change expected */
+ break;
case PORT_RESET:
case PORT_RESET_WAIT_OFF:
@@ -3920,6 +4023,9 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
case SRC_TRY_DEBOUNCE:
/* Do nothing, waiting for sink detection */
break;
+ case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+ tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0);
+ break;
case PORT_RESET:
case PORT_RESET_WAIT_OFF:
@@ -3995,6 +4101,14 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
*/
break;
+ case FR_SWAP_SEND:
+ case FR_SWAP_SEND_TIMEOUT:
+ case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
+ case FR_SWAP_SNK_SRC_NEW_SINK_READY:
+ case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
+ /* Do nothing, vbus drop expected */
+ break;
+
default:
if (port->pwr_role == TYPEC_SINK &&
port->attached)
@@ -4049,6 +4163,25 @@ static void tcpm_pd_event_handler(struct work_struct *work)
if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0)
_tcpm_cc_change(port, cc1, cc2);
}
+ if (events & TCPM_FRS_EVENT) {
+ if (port->state == SNK_READY)
+ tcpm_set_state(port, FR_SWAP_SEND, 0);
+ else
+ tcpm_log(port, "Discarding FRS_SIGNAL! Not in sink ready");
+ }
+ if (events & TCPM_SOURCING_VBUS) {
+ tcpm_log(port, "sourcing vbus");
+ /*
+ * In fast role swap case TCPC autonomously sources vbus. Set vbus_source
+ * true as TCPM wouldn't have called tcpm_set_vbus.
+ *
+ * When vbus is sourced on the command on TCPM i.e. TCPM called
+ * tcpm_set_vbus to source vbus, vbus_source would already be true.
+ */
+ port->vbus_source = true;
+ _tcpm_pd_vbus_on(port);
+ }
+
spin_lock(&port->pd_event_lock);
}
spin_unlock(&port->pd_event_lock);
@@ -4082,6 +4215,50 @@ void tcpm_pd_hard_reset(struct tcpm_port *port)
}
EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset);
+void tcpm_sink_frs(struct tcpm_port *port)
+{
+ spin_lock(&port->pd_event_lock);
+ port->pd_events = TCPM_FRS_EVENT;
+ spin_unlock(&port->pd_event_lock);
+ queue_work(port->wq, &port->event_work);
+}
+EXPORT_SYMBOL_GPL(tcpm_sink_frs);
+
+void tcpm_sourcing_vbus(struct tcpm_port *port)
+{
+ spin_lock(&port->pd_event_lock);
+ port->pd_events = TCPM_SOURCING_VBUS;
+ spin_unlock(&port->pd_event_lock);
+ queue_work(port->wq, &port->event_work);
+}
+EXPORT_SYMBOL_GPL(tcpm_sourcing_vbus);
+
+static void tcpm_enable_frs(struct work_struct *work)
+{
+ struct tcpm_port *port = container_of(work, struct tcpm_port, enable_frs.work);
+
+ mutex_lock(&port->lock);
+ /* Not FRS capable */
+ if (!port->connected || port->port_type != TYPEC_PORT_DRP ||
+ port->pwr_opmode != TYPEC_PWR_MODE_PD ||
+ !port->tcpc->enable_frs ||
+ /* Sink caps queried */
+ port->sink_cap_done || port->negotiated_rev < PD_REV30)
+ goto unlock;
+
+ /* Send when the state machine is idle */
+ if (port->state != SNK_READY || port->vdm_state != VDM_STATE_DONE || port->send_discover)
+ goto resched;
+
+ tcpm_set_state(port, GET_SINK_CAP, 0);
+ port->sink_cap_done = true;
+
+resched:
+ mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(GET_SINK_CAP_RETRY_MS));
+unlock:
+ mutex_unlock(&port->lock);
+}
+
static int tcpm_dr_set(struct typec_port *p, enum typec_data_role data)
{
struct tcpm_port *port = typec_get_drvdata(p);
@@ -4489,7 +4666,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port,
{
const char *cap_str;
int ret;
- u32 mw;
+ u32 mw, frs_current;
if (!fwnode)
return -EINVAL;
@@ -4558,6 +4735,13 @@ static int tcpm_fw_get_caps(struct tcpm_port *port,
port->self_powered = fwnode_property_read_bool(fwnode, "self-powered");
+ /* FRS can only be supported byb DRP ports */
+ if (port->port_type == TYPEC_PORT_DRP) {
+ ret = fwnode_property_read_u32(fwnode, "frs-typec-current", &frs_current);
+ if (ret >= 0 && frs_current <= FRS_5V_3A)
+ port->typec_caps.frs_current = frs_current;
+ }
+
return 0;
}
@@ -4813,6 +4997,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
INIT_DELAYED_WORK(&port->state_machine, tcpm_state_machine_work);
INIT_DELAYED_WORK(&port->vdm_state_machine, vdm_state_machine_work);
INIT_WORK(&port->event_work, tcpm_pd_event_handler);
+ INIT_DELAYED_WORK(&port->enable_frs, tcpm_enable_frs);
spin_lock_init(&port->pd_event_lock);
diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h
index b6c233e79bd4..5d8a29c683a4 100644
--- a/include/linux/usb/pd.h
+++ b/include/linux/usb/pd.h
@@ -219,14 +219,16 @@ enum pd_pdo_type {
#define PDO_CURR_MASK 0x3ff
#define PDO_PWR_MASK 0x3ff
-#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */
-#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */
-#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */
-#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */
-#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */
-#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */
-#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */
-#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */
+#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */
+#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */
+#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */
+#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */
+#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */
+#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */
+#define PDO_FIXED_FRS_CURR_MASK (BIT(24) | BIT(23)) /* FR_Swap Current (Sink) */
+#define PDO_FIXED_FRS_CURR_SHIFT 23
+#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */
+#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */
#define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT)
#define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT)
@@ -454,6 +456,7 @@ static inline unsigned int rdo_max_power(u32 rdo)
#define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */
#define PD_T_SEND_SOURCE_CAP 150 /* 100 - 200 ms */
#define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */
+#define PD_T_RECEIVER_RESPONSE 15 /* 15ms max */
#define PD_T_SOURCE_ACTIVITY 45
#define PD_T_SINK_ACTIVITY 135
#define PD_T_SINK_WAIT_CAP 240
@@ -473,6 +476,7 @@ static inline unsigned int rdo_max_power(u32 rdo)
#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_SWAP_SRC_START 20 /* Minimum of 20ms */
#define PD_T_DRP_TRY 100 /* 75 - 150 ms */
#define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index 89f58760cf48..09762d26fa0c 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -78,8 +78,11 @@ enum tcpm_transmit_type {
* automatically if a connection is established.
* @try_role: Optional; called to set a preferred role
* @pd_transmit:Called to transmit PD message
- * @mux: Pointer to multiplexer data
* @set_bist_data: Turn on/off bist data mode for compliance testing
+ * @enable_frs:
+ * Optional; Called to enable/disable PD 3.0 fast role swap.
+ * Enabling frs is accessory dependent as not all PD3.0
+ * accessories support fast role swap.
*/
struct tcpc_dev {
struct fwnode_handle *fwnode;
@@ -105,6 +108,7 @@ struct tcpc_dev {
int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type,
const struct pd_message *msg);
int (*set_bist_data)(struct tcpc_dev *dev, bool on);
+ int (*enable_frs)(struct tcpc_dev *dev, bool enable);
};
struct tcpm_port;
@@ -114,6 +118,8 @@ void tcpm_unregister_port(struct tcpm_port *port);
void tcpm_vbus_change(struct tcpm_port *port);
void tcpm_cc_change(struct tcpm_port *port);
+void tcpm_sink_frs(struct tcpm_port *port);
+void tcpm_sourcing_vbus(struct tcpm_port *port);
void tcpm_pd_receive(struct tcpm_port *port,
const struct pd_message *msg);
void tcpm_pd_transmit_complete(struct tcpm_port *port,
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 9cb1bec94b71..2ec7451a14ab 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -204,6 +204,18 @@ struct typec_operations {
enum typec_port_type type);
};
+/*
+ * Initial current capability of the new source when vSafe5V is applied during PD3.0 Fast Role Swap.
+ * Based on "Table 6-14 Fixed Supply PDO - Sink" of "USB Power Delivery Specification Revision 3.0,
+ * Version 1.2"
+ */
+enum frs_typec_current {
+ FRS_NOT_SUPPORTED,
+ FRS_DEFAULT_POWER,
+ FRS_5V_1P5A,
+ FRS_5V_3A,
+};
+
/*
* struct typec_capability - USB Type-C Port Capabilities
* @type: Supported power role of the port
@@ -226,6 +238,7 @@ struct typec_capability {
int prefer_role;
enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
unsigned int orientation_aware:1;
+ enum frs_typec_current frs_current;
struct fwnode_handle *fwnode;
void *driver_data;
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 10/14 v1] usb: typec: tcpci: Implement callbacks for FRS
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (8 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS) Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 11/14 v1] usb: typec: tcpci_maxim: Add support for Sink FRS Badhri Jagan Sridharan
` (3 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Implement tcpc.enable_frs to enable TCPC to receive
Fast role swap signal.
Additionally set the sink disconnect threshold to 4v
to prevent disconnect during Fast Role swap.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.c | 17 +++++++++++++++++
drivers/usb/typec/tcpm/tcpci.h | 8 ++++++++
2 files changed, 25 insertions(+)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 89d28e3fbee8..13d2e1c2ff20 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -268,6 +268,22 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0);
}
+static int tcpci_enable_frs(struct tcpc_dev *dev, bool enable)
+{
+ struct tcpci *tcpci = tcpc_to_tcpci(dev);
+ int ret;
+
+ /* To prevent disconnect during FRS, set disconnect threshold to 3.5V */
+ ret = tcpci_write16(tcpci, TCPC_VBUS_SINK_DISCONNECT_THRESH, enable ? 0 : 0x8c);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_update_bits(tcpci->regmap, TCPC_POWER_CTRL, TCPC_FAST_ROLE_SWAP_EN, enable ?
+ TCPC_FAST_ROLE_SWAP_EN : 0);
+
+ return ret;
+}
+
static int tcpci_set_bist_data(struct tcpc_dev *tcpc, bool enable)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
@@ -610,6 +626,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
tcpci->tcpc.set_roles = tcpci_set_roles;
tcpci->tcpc.pd_transmit = tcpci_pd_transmit;
tcpci->tcpc.set_bist_data = tcpci_set_bist_data;
+ tcpci->tcpc.enable_frs = tcpci_enable_frs;
err = tcpci_parse_config(tcpci);
if (err < 0)
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index 82f021a82456..5ef07a56d67a 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -16,6 +16,7 @@
#define TCPC_PD_INT_REV 0xa
#define TCPC_ALERT 0x10
+#define TCPC_ALERT_EXTND BIT(14)
#define TCPC_ALERT_EXTENDED_STATUS BIT(13)
#define TCPC_ALERT_VBUS_DISCNCT BIT(11)
#define TCPC_ALERT_RX_BUF_OVF BIT(10)
@@ -37,6 +38,9 @@
#define TCPC_EXTENDED_STATUS_MASK 0x16
#define TCPC_EXTENDED_STATUS_MASK_VSAFE0V BIT(0)
+#define TCPC_ALERT_EXTENDED_MASK 0x17
+#define TCPC_SINK_FAST_ROLE_SWAP BIT(0)
+
#define TCPC_CONFIG_STD_OUTPUT 0x18
#define TCPC_TCPC_CTRL 0x19
@@ -63,6 +67,7 @@
#define TCPC_POWER_CTRL 0x1c
#define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0)
+#define TCPC_FAST_ROLE_SWAP_EN BIT(7)
#define TCPC_CC_STATUS 0x1d
#define TCPC_CC_STATUS_TOGGLING BIT(5)
@@ -74,11 +79,14 @@
#define TCPC_POWER_STATUS 0x1e
#define TCPC_POWER_STATUS_UNINIT BIT(6)
+#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4)
#define TCPC_POWER_STATUS_VBUS_DET BIT(3)
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2)
#define TCPC_FAULT_STATUS 0x1f
+#define TCPC_ALERT_EXTENDED 0x21
+
#define TCPC_COMMAND 0x23
#define TCPC_CMD_WAKE_I2C 0x11
#define TCPC_CMD_DISABLE_VBUS_DETECT 0x22
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 11/14 v1] usb: typec: tcpci_maxim: Add support for Sink FRS
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (9 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 10/14 v1] usb: typec: tcpci: Implement callbacks for FRS Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support Badhri Jagan Sridharan
` (2 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Upon receiving ALERT_EXTENDED.TCPC_SINK_FAST_ROLE_SWAP signal
tcpm to start Sink fast role swap signal.
Inform when TCPM is sourcing vbus.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci_maxim.c | 50 +++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.c b/drivers/usb/typec/tcpm/tcpci_maxim.c
index b61f290a8f96..6ba808ad901a 100644
--- a/drivers/usb/typec/tcpm/tcpci_maxim.c
+++ b/drivers/usb/typec/tcpm/tcpci_maxim.c
@@ -106,13 +106,22 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip)
return;
}
+ ret = max_tcpci_write8(chip, TCPC_ALERT_EXTENDED, 0xff);
+ if (ret < 0) {
+ dev_err(chip->dev, "Unable to clear TCPC_ALERT_EXTENDED ret:%d\n", ret);
+ 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;
+ 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;
ret = max_tcpci_write16(chip, TCPC_ALERT_MASK, alert_mask);
if (ret < 0) {
- dev_err(chip->dev, "Error writing to TCPC_ALERT_MASK ret:%d\n", ret);
+ dev_err(chip->dev,
+ "Error enabling TCPC_ALERT: TCPC_ALERT_MASK write failed ret:%d\n", ret);
return;
}
@@ -122,6 +131,10 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip)
dev_err(chip->dev, "Error writing to TCPC_POWER_CTRL ret:%d\n", ret);
return;
}
+
+ ret = max_tcpci_write8(chip, TCPC_ALERT_EXTENDED_MASK, TCPC_SINK_FAST_ROLE_SWAP);
+ if (ret < 0)
+ return;
}
static void process_rx(struct max_tcpci_chip *chip, u16 status)
@@ -225,10 +238,23 @@ static void process_power_status(struct max_tcpci_chip *chip)
if (ret < 0)
return;
- if (pwr_status == 0xff)
+ if (pwr_status == 0xff) {
max_tcpci_init_regs(chip);
- else
+ } else if (pwr_status & TCPC_POWER_STATUS_SOURCING_VBUS) {
+ tcpm_sourcing_vbus(chip->port);
+ /*
+ * Alawys re-enable boost here.
+ * In normal case, when say an headset is attached, TCPM would
+ * have instructed to TCPC to enable boost, so the call is a
+ * no-op.
+ * But for Fast Role Swap case, Boost turns on autonomously without
+ * AP intervention, but, needs AP to enable source mode explicitly
+ * for AP to regain control.
+ */
+ max_tcpci_set_vbus(chip->tcpci, &chip->data, true, false);
+ } else {
tcpm_vbus_change(chip->port);
+ }
}
static void process_tx(struct max_tcpci_chip *chip, u16 status)
@@ -249,6 +275,7 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status)
{
u16 mask;
int ret;
+ u8 reg_status;
/*
* Clear alert status for everything except RX_STATUS, which shouldn't
@@ -274,6 +301,21 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status)
}
}
+ if (status & TCPC_ALERT_EXTND) {
+ ret = max_tcpci_read8(chip, TCPC_ALERT_EXTENDED, ®_status);
+ if (ret < 0)
+ return ret;
+
+ ret = max_tcpci_write8(chip, TCPC_ALERT_EXTENDED, reg_status);
+ if (ret < 0)
+ return ret;
+
+ if (reg_status & TCPC_SINK_FAST_ROLE_SWAP) {
+ dev_info(chip->dev, "FRS Signal");
+ tcpm_sink_frs(chip->port);
+ }
+ }
+
if (status & TCPC_ALERT_RX_STATUS)
process_rx(chip, status);
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (10 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 11/14 v1] usb: typec: tcpci_maxim: Add support for Sink FRS Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-28 14:13 ` Heikki Krogerus
2020-08-25 4:22 ` [PATCH 13/14 v1] usb: typec: tcpci: Implement Auto discharge disconnect callbacks Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 14/14 v1] usb: typec: tcpci_maxim: Implemnent set_auto_vbus_discharge_threshold Badhri Jagan Sridharan
13 siblings, 1 reply; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
TCPCI spec allows TCPC hardware to autonomously discharge the vbus
capacitance upon disconnect. The expectation is that the TCPM enables
AutoDischargeDisconnect while entering SNK/SRC_ATTACHED states. Hardware
then automously discharges vbus when the vbus falls below a certain
threshold i.e. VBUS_SINK_DISCONNECT_THRESHOLD.
Apart from enabling the vbus discharge circuit, AutoDischargeDisconnect
is also used a flag to move TCPCI based TCPC implementations into
Attached.Snk/Attached.Src state as mentioned in
Figure 4-15. TCPC State Diagram before a Connection of the
USB Type-C Port Controller Interface Specification.
In such TCPC implementations, setting AutoDischargeDisconnect would
prevent TCPC into entering "Connection_Invalid" state as well.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
Change-Id: I09c407eb228d69eb1259008eeb14c429b0fda765
---
drivers/usb/typec/tcpm/tcpm.c | 80 +++++++++++++++++++++++++++++++++--
include/linux/usb/tcpm.h | 16 +++++++
2 files changed, 92 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 6ea4613af905..fe58cf908144 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -1660,6 +1660,25 @@ static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,
}
}
+static int tcpm_set_auto_vbus_discharge_threshold(struct tcpm_port *port, enum typec_role port_role,
+ enum typec_pwr_opmode mode, bool pps_active,
+ u32 requested_vbus_voltage)
+{
+ int ret;
+
+ if (!port->tcpc->set_auto_vbus_discharge_threshold)
+ return 0;
+
+ ret = port->tcpc->set_auto_vbus_discharge_threshold(port->tcpc, port_role, mode, pps_active,
+ requested_vbus_voltage);
+ tcpm_log_force(port,
+ "set_auto_vbus_discharge_threshold pwr_role:%s mode:%d pps_active:%c vbus:%u ret:%d",
+ port_role == TYPEC_SINK ? "sink" : "source", mode, pps_active ? 'y' : 'n',
+ requested_vbus_voltage, ret);
+
+ return ret;
+}
+
static void tcpm_pd_data_request(struct tcpm_port *port,
const struct pd_message *msg)
{
@@ -1829,6 +1848,10 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
port->current_limit,
port->supply_voltage);
port->explicit_contract = true;
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK,
+ TYPEC_PWR_MODE_PD,
+ port->pps_data.active,
+ port->supply_voltage);
tcpm_set_state(port, SNK_READY, 0);
} else {
/*
@@ -2743,8 +2766,14 @@ static int tcpm_src_attach(struct tcpm_port *port)
if (ret < 0)
return ret;
- ret = tcpm_set_roles(port, true, TYPEC_SOURCE,
- tcpm_data_role_for_source(port));
+ if (port->tcpc->enable_auto_vbus_discharge) {
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, 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);
+ }
+
+ ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_sink(port));
if (ret < 0)
return ret;
@@ -2811,6 +2840,12 @@ static void tcpm_unregister_altmodes(struct tcpm_port *port)
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);
+ }
tcpm_unregister_altmodes(port);
tcpm_typec_disconnect(port);
port->attached = false;
@@ -2875,8 +2910,14 @@ static int tcpm_snk_attach(struct tcpm_port *port)
if (ret < 0)
return ret;
- ret = tcpm_set_roles(port, true, TYPEC_SINK,
- tcpm_data_role_for_sink(port));
+ if (port->tcpc->enable_auto_vbus_discharge) {
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, 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);
+ }
+
+ ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port));
if (ret < 0)
return ret;
@@ -3430,6 +3471,14 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0);
break;
case SRC_HARD_RESET_VBUS_OFF:
+ /*
+ * 7.1.5 Response to Hard Resets
+ * Hard Reset Signaling indicates a communication failure has occurred and the
+ * Source Shall stop driving VCONN, Shall remove Rp from the VCONN pin and Shall
+ * drive VBUS to vSafe0V as shown in Figure 7-9.
+ */
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB,
+ false, 0);
tcpm_set_vconn(port, true);
tcpm_set_vbus(port, false);
tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
@@ -3440,9 +3489,13 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_vbus(port, true);
port->tcpc->set_pd_rx(port->tcpc, true);
tcpm_set_attached_state(port, true);
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB,
+ false, VSAFE5V);
tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
case SNK_HARD_RESET_SINK_OFF:
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false,
+ 0);
memset(&port->pps_data, 0, sizeof(port->pps_data));
tcpm_set_vconn(port, false);
if (port->pd_capable)
@@ -3485,6 +3538,8 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_charge(port, true);
}
tcpm_set_attached_state(port, true);
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false,
+ VSAFE5V);
tcpm_set_state(port, SNK_STARTUP, 0);
break;
@@ -3586,6 +3641,12 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, PR_SWAP_SNK_SRC_SINK_OFF, 0);
break;
case PR_SWAP_SRC_SNK_TRANSITION_OFF:
+ /*
+ * Prevent vbus discharge circuit from turning on during PR_SWAP
+ * as this is not a disconnect.
+ */
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB,
+ port->pps_data.active, 0);
tcpm_set_vbus(port, false);
port->explicit_contract = false;
/* allow time for Vbus discharge, must be < tSrcSwapStdby */
@@ -3614,9 +3675,18 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
case PR_SWAP_SRC_SNK_SINK_ON:
+ /* Set the vbus disconnect threshold for implicit contract */
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false,
+ VSAFE5V);
tcpm_set_state(port, SNK_STARTUP, 0);
break;
case PR_SWAP_SNK_SRC_SINK_OFF:
+ /*
+ * Prevent vbus discharge circuit from turning on during PR_SWAP
+ * as this is not a disconnect.
+ */
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB,
+ port->pps_data.active, 0);
tcpm_set_charge(port, false);
tcpm_set_state(port, hard_reset_state(port),
PD_T_PS_SOURCE_OFF);
@@ -3642,6 +3712,8 @@ static void run_state_machine(struct tcpm_port *port)
*/
tcpm_set_pwr_role(port, TYPEC_SOURCE);
tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
+ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB,
+ false, VSAFE5V);
tcpm_set_state(port, SRC_STARTUP, 0);
break;
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index 09762d26fa0c..a1707def51c3 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -83,6 +83,18 @@ enum tcpm_transmit_type {
* Optional; Called to enable/disable PD 3.0 fast role swap.
* Enabling frs is accessory dependent as not all PD3.0
* accessories support fast role swap.
+ * @enable_auto_vbus_discharge:
+ * Optional; TCPCI spec based TCPC implementations can optionally
+ * support hardware to autonomously dischrge vbus upon disconnecting
+ * as sink or source. TCPM signals TCPC to enable the mechanism upon
+ * entering connected state and signals disabling upon disconnect.
+ * @set_auto_vbus_discharge_threshold:
+ * Mandatory when enable_auto_vbus_discharge is implemented. TCPM
+ * calls this function to allow lower levels drivers to program the
+ * vbus threshold voltage below which the vbus discharge circuit
+ * will be turned on. requested_vbus_voltage is set to 0 when vbus
+ * is going to disappear knowingly i.e. during PR_SWAP and
+ * HARD_RESET etc.
*/
struct tcpc_dev {
struct fwnode_handle *fwnode;
@@ -109,6 +121,10 @@ struct tcpc_dev {
const struct pd_message *msg);
int (*set_bist_data)(struct tcpc_dev *dev, bool on);
int (*enable_frs)(struct tcpc_dev *dev, bool enable);
+ int (*enable_auto_vbus_discharge)(struct tcpc_dev *dev, bool enable);
+ int (*set_auto_vbus_discharge_threshold)(struct tcpc_dev *dev, enum typec_role port_role,
+ enum typec_pwr_opmode mode, bool pps_active,
+ u32 requested_vbus_voltage);
};
struct tcpm_port;
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 13/14 v1] usb: typec: tcpci: Implement Auto discharge disconnect callbacks
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (11 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 14/14 v1] usb: typec: tcpci_maxim: Implemnent set_auto_vbus_discharge_threshold Badhri Jagan Sridharan
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Implement callbacks for enabling/disabling
POWER_CONTROL.AutoDischargeDisconnect.
TCPCI spec allows TCPC hardware to autonomously discharge the vbus
capacitance upon disconnect. The expectation is that the TCPM enables
AutoDischargeDisconnect while entering SNK/SRC_ATTACHED states. Hardware
then automously discharges vbus when the vbus falls below a certain
threshold i.e. VBUS_SINK_DISCONNECT_THRESHOLD.
Apart from enabling the vbus discharge circuit, AutoDischargeDisconnect
is also used a flag to move TCPCI based TCPC implementations into
Attached.Snk/Attached.Src state as mentioned in
Figure 4-15. TCPC State Diagram before a Connection of the
USB Type-C Port Controller Interface Specification.
In such TCPC implementations, setting AutoDischargeDisconnect would
prevent TCPC into entering "Connection_Invalid" state as well.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci.c | 33 +++++++++++++++++++++++++++++++++
drivers/usb/typec/tcpm/tcpci.h | 22 ++++++++++++++++++++--
2 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 13d2e1c2ff20..e876f13ddf31 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -268,6 +268,33 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0);
}
+static int tcpci_enable_auto_vbus_discharge(struct tcpc_dev *dev, bool enable)
+{
+ struct tcpci *tcpci = tcpc_to_tcpci(dev);
+ int ret;
+
+ ret = regmap_update_bits(tcpci->regmap, TCPC_POWER_CTRL, TCPC_POWER_CTRL_AUTO_DISCHARGE,
+ enable ? TCPC_POWER_CTRL_AUTO_DISCHARGE : 0);
+ return ret;
+}
+
+static int tcpci_set_auto_vbus_discharge_threshold(struct tcpc_dev *dev, enum typec_role port_role,
+ enum typec_pwr_opmode mode, bool pps_active,
+ u32 requested_vbus_voltage)
+{
+ struct tcpci *tcpci = tcpc_to_tcpci(dev);
+ int (*set_auto_vbus_threshold)(struct tcpci *tcpci, struct tcpci_data *data,
+ enum typec_role port_role, enum typec_pwr_opmode mode,
+ bool pps_active, u32 requested_vbus_voltage);
+
+ set_auto_vbus_threshold = tcpci->data->set_auto_vbus_discharge_threshold;
+ if (set_auto_vbus_threshold)
+ return set_auto_vbus_threshold(tcpci, tcpci->data, port_role, mode, pps_active,
+ requested_vbus_voltage);
+
+ return 0;
+}
+
static int tcpci_enable_frs(struct tcpc_dev *dev, bool enable)
{
struct tcpci *tcpci = tcpc_to_tcpci(dev);
@@ -628,6 +655,12 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
tcpci->tcpc.set_bist_data = tcpci_set_bist_data;
tcpci->tcpc.enable_frs = tcpci_enable_frs;
+ if (tcpci->data->auto_discharge_disconnect) {
+ tcpci->tcpc.enable_auto_vbus_discharge = tcpci_enable_auto_vbus_discharge;
+ tcpci->tcpc.set_auto_vbus_discharge_threshold =
+ tcpci_set_auto_vbus_discharge_threshold;
+ }
+
err = tcpci_parse_config(tcpci);
if (err < 0)
return ERR_PTR(err);
diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
index 5ef07a56d67a..6a0aea34e544 100644
--- a/drivers/usb/typec/tcpm/tcpci.h
+++ b/drivers/usb/typec/tcpm/tcpci.h
@@ -8,6 +8,8 @@
#ifndef __LINUX_USB_TCPCI_H
#define __LINUX_USB_TCPCI_H
+#include <linux/usb/typec.h>
+
#define TCPC_VENDOR_ID 0x0
#define TCPC_PRODUCT_ID 0x2
#define TCPC_BCD_DEV 0x4
@@ -67,6 +69,7 @@
#define TCPC_POWER_CTRL 0x1c
#define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0)
+#define TCPC_POWER_CTRL_AUTO_DISCHARGE BIT(4)
#define TCPC_FAST_ROLE_SWAP_EN BIT(7)
#define TCPC_CC_STATUS 0x1d
@@ -133,6 +136,8 @@
#define TCPC_VBUS_VOLTAGE 0x70
#define TCPC_VBUS_SINK_DISCONNECT_THRESH 0x72
+#define TCPC_VBUS_SINK_DISCONNECT_THRESH_LSB 25
+#define TCPC_VBUS_SINK_DISCONNECT_THRESH_MAX 1023
#define TCPC_VBUS_STOP_DISCHARGE_THRESH 0x74
#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
@@ -140,20 +145,33 @@
/* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */
#define TCPC_TRANSMIT_BUFFER_MAX_LEN 31
+struct tcpci;
+
/*
- * @TX_BUF_BYTE_x_hidden
+ * @TX_BUF_BYTE_x_hidden:
* optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT.
+ * @auto_discharge_disconnect:
+ * Optional; Enables TCPC to autonously discharge vbus on disconnect.
+ * @set_auto_vbus_discharge_threshold:
+ * Mandatory when @auto_discharge_disconnect is sets. Allows
+ * programming the voltage threshold of vbus below which TCPC
+ * enables the vbus discharge circuit.
*/
-struct tcpci;
struct tcpci_data {
struct regmap *regmap;
unsigned char TX_BUF_BYTE_x_hidden:1;
+ unsigned char auto_discharge_disconnect:1;
+
int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
bool enable);
int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data,
enum typec_cc_status cc);
int (*set_vbus)(struct tcpci *tcpci, struct tcpci_data *data, bool source, bool sink);
+ int (*set_auto_vbus_discharge_threshold)(struct tcpci *tcpci, struct tcpci_data *data,
+ enum typec_role port_role,
+ enum typec_pwr_opmode mode, bool pps_active,
+ u32 requested_vbus_voltage);
};
struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data);
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 14/14 v1] usb: typec: tcpci_maxim: Implemnent set_auto_vbus_discharge_threshold
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
` (12 preceding siblings ...)
2020-08-25 4:22 ` [PATCH 13/14 v1] usb: typec: tcpci: Implement Auto discharge disconnect callbacks Badhri Jagan Sridharan
@ 2020-08-25 4:22 ` Badhri Jagan Sridharan
13 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-25 4:22 UTC (permalink / raw)
To: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Badhri Jagan Sridharan
Programs VBUS_SINK_DISCONNECT_THRESHOLD based on the power_role,
voltage requested as sink, mode of operation.
The programmed threshold is based on vSinkDisconnect and
vSinkDisconnectPD values.
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
drivers/usb/typec/tcpm/tcpci_maxim.c | 48 ++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.c b/drivers/usb/typec/tcpm/tcpci_maxim.c
index 6ba808ad901a..e35bd995c037 100644
--- a/drivers/usb/typec/tcpm/tcpci_maxim.c
+++ b/drivers/usb/typec/tcpm/tcpci_maxim.c
@@ -137,6 +137,52 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip)
return;
}
+static int max_tcpci_set_auto_vbus_discharge_threshold(struct tcpci *tcpci, struct tcpci_data *data,
+ enum typec_role port_role,
+ enum typec_pwr_opmode mode, bool pps_active,
+ u32 requested_vbus_voltage_mv)
+{
+ struct max_tcpci_chip *chip = tdata_to_max_tcpci(data);
+ u32 threshold = 0;
+ u8 pwr_ctrl;
+
+ /*
+ * Indicates that vbus is going to go away due PR_SWAP, hard reset etc.
+ * Do not discharge vbus here.
+ */
+ if (requested_vbus_voltage_mv == 0)
+ goto write_thresh;
+
+ if (port_role == TYPEC_SINK) {
+ max_tcpci_read8(chip, TCPC_POWER_CTRL, &pwr_ctrl);
+ if (pwr_ctrl & TCPC_FAST_ROLE_SWAP_EN) {
+ /* To prevent disconnect when the source is fast role swap is capable. */
+ threshold = 3500;
+ } else if (mode == TYPEC_PWR_MODE_PD) {
+ if (pps_active)
+ threshold = (95 * requested_vbus_voltage_mv / 100) - 850;
+ else
+ threshold = (95 * requested_vbus_voltage_mv / 100) - 1250;
+ } else {
+ /* 3.5V for non-pd sink */
+ threshold = 3500;
+ }
+ } else {
+ /* 4V for source */
+ threshold = 4000;
+ }
+
+ threshold = threshold / TCPC_VBUS_SINK_DISCONNECT_THRESH_LSB;
+
+ if (threshold > TCPC_VBUS_SINK_DISCONNECT_THRESH_MAX) {
+ dev_err(chip->dev, "VBUS_SINK_DISCONNECT_THRESH out of range");
+ return -EINVAL;
+ }
+
+write_thresh:
+ return max_tcpci_write16(chip, TCPC_VBUS_SINK_DISCONNECT_THRESH, threshold);
+}
+
static void process_rx(struct max_tcpci_chip *chip, u16 status)
{
struct pd_message msg;
@@ -454,6 +500,8 @@ static int max_tcpci_probe(struct i2c_client *client, const struct i2c_device_id
chip->data.start_drp_toggling = max_tcpci_start_toggling;
chip->data.TX_BUF_BYTE_x_hidden = true;
chip->data.init = tcpci_init;
+ chip->data.set_auto_vbus_discharge_threshold = max_tcpci_set_auto_vbus_discharge_threshold;
+ chip->data.auto_discharge_disconnect = true;
max_tcpci_init_regs(chip);
chip->tcpci = tcpci_register_port(chip->dev, &chip->data);
--
2.28.0.297.g1956fa8f8d-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver
2020-08-25 4:22 ` [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver Badhri Jagan Sridharan
@ 2020-08-25 5:16 ` Randy Dunlap
2020-08-28 14:51 ` Badhri Jagan Sridharan
0 siblings, 1 reply; 23+ messages in thread
From: Randy Dunlap @ 2020-08-25 5:16 UTC (permalink / raw)
To: Badhri Jagan Sridharan, Guenter Roeck, Heikki Krogerus,
Greg Kroah-Hartman
Cc: linux-usb, linux-kernel
On 8/24/20 9:22 PM, Badhri Jagan Sridharan wrote:
> diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
> index fa3f39336246..7c9722b02afe 100644
> --- a/drivers/usb/typec/tcpm/Kconfig
> +++ b/drivers/usb/typec/tcpm/Kconfig
> @@ -27,6 +27,12 @@ config TYPEC_RT1711H
> Type-C Port Controller Manager to provide USB PD and USB
> Type-C functionalities.
>
> +config TYPEC_TCPCI_MAXIM
> + tristate "Maxim TCPCI based Type-C chip driver"
> + select USB_PSY
is that USB_PHY
?
> + help
> + MAXIM TCPCI based Type-C chip driver
end that with '.' please.
> +
> endif # TYPEC_TCPCI
>
> config TYPEC_FUSB302
--
~Randy
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)
2020-08-25 4:22 ` [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS) Badhri Jagan Sridharan
@ 2020-08-26 12:42 ` kernel test robot
0 siblings, 0 replies; 23+ messages in thread
From: kernel test robot @ 2020-08-26 12:42 UTC (permalink / raw)
To: Badhri Jagan Sridharan, Guenter Roeck, Heikki Krogerus,
Greg Kroah-Hartman
Cc: kbuild-all, linux-usb, linux-kernel, Badhri Jagan Sridharan
[-- Attachment #1: Type: text/plain, Size: 91847 bytes --]
Hi Badhri,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on usb/usb-testing]
[also build test WARNING on robh/for-next v5.9-rc2 next-20200826]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Badhri-Jagan-Sridharan/TCPM-support-for-FRS-and-AutoDischarge-Disconnect/20200825-122527
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
config: arm-randconfig-r005-20200826 (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
drivers/usb/typec/tcpm/tcpm.c: In function 'run_state_machine':
>> drivers/usb/typec/tcpm/tcpm.c:3684:3: warning: this statement may fall through [-Wimplicit-fallthrough=]
3684 | tcpm_swap_complete(port, port->swap_status);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/usb/typec/tcpm/tcpm.c:3685:2: note: here
3685 | case FR_SWAP_CANCEL:
| ^~~~
At top level:
drivers/usb/typec/tcpm/tcpm.c:1618:39: warning: 'tcpm_altmode_ops' defined but not used [-Wunused-const-variable=]
1618 | static const struct typec_altmode_ops tcpm_altmode_ops = {
| ^~~~~~~~~~~~~~~~
# https://github.com/0day-ci/linux/commit/a8727cbd1e6baa15662e368128ac96b196fe540f
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Badhri-Jagan-Sridharan/TCPM-support-for-FRS-and-AutoDischarge-Disconnect/20200825-122527
git checkout a8727cbd1e6baa15662e368128ac96b196fe540f
vim +3684 drivers/usb/typec/tcpm/tcpm.c
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 2982
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2983 static void run_state_machine(struct tcpm_port *port)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2984 {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2985 int ret;
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 2986 enum typec_pwr_opmode opmode;
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 2987 unsigned int msecs;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2988
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2989 port->enter_state = port->state;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2990 switch (port->state) {
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-04-16 2991 case TOGGLING:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2992 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2993 /* SRC states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2994 case SRC_UNATTACHED:
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 2995 if (!port->non_pd_role_swap)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2996 tcpm_swap_complete(port, -ENOTCONN);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 2997 tcpm_src_detach(port);
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-04-16 2998 if (tcpm_start_toggling(port, tcpm_rp_cc(port))) {
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-04-16 2999 tcpm_set_state(port, TOGGLING, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3000 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3001 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3002 tcpm_set_cc(port, tcpm_rp_cc(port));
9b0ae69909c281 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3003 if (port->port_type == TYPEC_PORT_DRP)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3004 tcpm_set_state(port, SNK_UNATTACHED, PD_T_DRP_SNK);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3005 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3006 case SRC_ATTACH_WAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3007 if (tcpm_port_is_debug(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3008 tcpm_set_state(port, DEBUG_ACC_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3009 PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3010 else if (tcpm_port_is_audio(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3011 tcpm_set_state(port, AUDIO_ACC_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3012 PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3013 else if (tcpm_port_is_source(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3014 tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3015 tcpm_try_snk(port) ? SNK_TRY
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3016 : SRC_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3017 PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3018 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3019
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3020 case SNK_TRY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3021 port->try_snk_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3022 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3023 * Requirements:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3024 * - Do not drive vconn or vbus
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3025 * - Terminate CC pins (both) to Rd
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3026 * Action:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3027 * - Wait for tDRPTry (PD_T_DRP_TRY).
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3028 * Until then, ignore any state changes.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3029 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3030 tcpm_set_cc(port, TYPEC_CC_RD);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3031 tcpm_set_state(port, SNK_TRY_WAIT, PD_T_DRP_TRY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3032 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3033 case SNK_TRY_WAIT:
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3034 if (tcpm_port_is_sink(port)) {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3035 tcpm_set_state(port, SNK_TRY_WAIT_DEBOUNCE, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3036 } else {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3037 tcpm_set_state(port, SRC_TRYWAIT, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3038 port->max_wait = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3039 }
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3040 break;
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3041 case SNK_TRY_WAIT_DEBOUNCE:
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3042 tcpm_set_state(port, SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3043 PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3044 break;
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3045 case SNK_TRY_WAIT_DEBOUNCE_CHECK_VBUS:
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3046 if (port->vbus_present && tcpm_port_is_sink(port)) {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3047 tcpm_set_state(port, SNK_ATTACHED, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3048 } else {
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3049 tcpm_set_state(port, SRC_TRYWAIT, 0);
a0a3e04e6b2c7c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3050 port->max_wait = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3051 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3052 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3053 case SRC_TRYWAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3054 tcpm_set_cc(port, tcpm_rp_cc(port));
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3055 if (port->max_wait == 0) {
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3056 port->max_wait = jiffies +
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3057 msecs_to_jiffies(PD_T_DRP_TRY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3058 tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3059 PD_T_DRP_TRY);
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3060 } else {
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3061 if (time_is_after_jiffies(port->max_wait))
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3062 tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED,
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3063 jiffies_to_msecs(port->max_wait -
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3064 jiffies));
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3065 else
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3066 tcpm_set_state(port, SNK_UNATTACHED, 0);
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3067 }
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3068 break;
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3069 case SRC_TRYWAIT_DEBOUNCE:
02d5be466b68f6 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3070 tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3071 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3072 case SRC_TRYWAIT_UNATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3073 tcpm_set_state(port, SNK_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3074 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3075
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3076 case SRC_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3077 ret = tcpm_src_attach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3078 tcpm_set_state(port, SRC_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3079 ret < 0 ? 0 : PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3080 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3081 case SRC_STARTUP:
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 3082 opmode = tcpm_get_pwr_opmode(tcpm_rp_cc(port));
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 3083 typec_set_pwr_opmode(port->typec_port, opmode);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3084 port->pwr_opmode = TYPEC_PWR_MODE_USB;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3085 port->caps_count = 0;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3086 port->negotiated_rev = PD_MAX_REV;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3087 port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3088 port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3089 port->explicit_contract = false;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3090 tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3091 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3092 case SRC_SEND_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3093 port->caps_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3094 if (port->caps_count > PD_N_CAPS_COUNT) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3095 tcpm_set_state(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3096 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3097 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3098 ret = tcpm_pd_send_source_caps(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3099 if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3100 tcpm_set_state(port, SRC_SEND_CAPABILITIES,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3101 PD_T_SEND_SOURCE_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3102 } else {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3103 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3104 * Per standard, we should clear the reset counter here.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3105 * However, that can result in state machine hang-ups.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3106 * Reset it only in READY state to improve stability.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3107 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3108 /* port->hard_reset_count = 0; */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3109 port->caps_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3110 port->pd_capable = true;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3111 tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3112 PD_T_SEND_SOURCE_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3113 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3114 break;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3115 case SRC_SEND_CAPABILITIES_TIMEOUT:
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3116 /*
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3117 * Error recovery for a PD_DATA_SOURCE_CAP reply timeout.
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3118 *
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3119 * PD 2.0 sinks are supposed to accept src-capabilities with a
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3120 * 3.0 header and simply ignore any src PDOs which the sink does
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3121 * not understand such as PPS but some 2.0 sinks instead ignore
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3122 * the entire PD_DATA_SOURCE_CAP message, causing contract
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3123 * negotiation to fail.
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3124 *
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3125 * After PD_N_HARD_RESET_COUNT hard-reset attempts, we try
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3126 * sending src-capabilities with a lower PD revision to
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3127 * make these broken sinks work.
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3128 */
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3129 if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3130 tcpm_set_state(port, HARD_RESET_SEND, 0);
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3131 } else if (port->negotiated_rev > PD_REV20) {
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3132 port->negotiated_rev--;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3133 port->hard_reset_count = 0;
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3134 tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3135 } else {
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3136 tcpm_set_state(port, hard_reset_state(port), 0);
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3137 }
976daf9d119993 drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-03-16 3138 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3139 case SRC_NEGOTIATE_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3140 ret = tcpm_pd_check_request(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3141 if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3142 tcpm_pd_send_control(port, PD_CTRL_REJECT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3143 if (!port->explicit_contract) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3144 tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3145 SRC_WAIT_NEW_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3146 } else {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3147 tcpm_set_state(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3148 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3149 } else {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3150 tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3151 tcpm_set_state(port, SRC_TRANSITION_SUPPLY,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3152 PD_T_SRC_TRANSITION);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3153 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3154 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3155 case SRC_TRANSITION_SUPPLY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3156 /* XXX: regulator_set_voltage(vbus, ...) */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3157 tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3158 port->explicit_contract = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3159 typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3160 port->pwr_opmode = TYPEC_PWR_MODE_PD;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3161 tcpm_set_state_cond(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3162 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3163 case SRC_READY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3164 #if 1
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3165 port->hard_reset_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3166 #endif
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3167 port->try_src_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3168
3113bf1a5da35f drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3169 tcpm_swap_complete(port, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3170 tcpm_typec_connect(port);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3171
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3172 tcpm_check_send_discover(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3173 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3174 * 6.3.5
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3175 * Sending ping messages is not necessary if
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3176 * - the source operates at vSafe5V
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3177 * or
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3178 * - The system is not operating in PD mode
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3179 * or
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3180 * - Both partners are connected using a Type-C connector
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3181 *
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3182 * There is no actual need to send PD messages since the local
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3183 * port type-c and the spec does not clearly say whether PD is
f451ac9e4c6dd2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3184 * possible when type-c is connected to Type-A/B
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3185 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3186 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3187 case SRC_WAIT_NEW_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3188 /* Nothing to do... */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3189 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3190
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3191 /* SNK states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3192 case SNK_UNATTACHED:
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3193 if (!port->non_pd_role_swap)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3194 tcpm_swap_complete(port, -ENOTCONN);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3195 tcpm_pps_complete(port, -ENOTCONN);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3196 tcpm_snk_detach(port);
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-04-16 3197 if (tcpm_start_toggling(port, TYPEC_CC_RD)) {
7893f9e1c26d1f drivers/usb/typec/tcpm/tcpm.c Hans de Goede 2019-04-16 3198 tcpm_set_state(port, TOGGLING, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3199 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3200 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3201 tcpm_set_cc(port, TYPEC_CC_RD);
9b0ae69909c281 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3202 if (port->port_type == TYPEC_PORT_DRP)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3203 tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3204 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3205 case SNK_ATTACH_WAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3206 if ((port->cc1 == TYPEC_CC_OPEN &&
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3207 port->cc2 != TYPEC_CC_OPEN) ||
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3208 (port->cc1 != TYPEC_CC_OPEN &&
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3209 port->cc2 == TYPEC_CC_OPEN))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3210 tcpm_set_state(port, SNK_DEBOUNCED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3211 PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3212 else if (tcpm_port_is_disconnected(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3213 tcpm_set_state(port, SNK_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3214 PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3215 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3216 case SNK_DEBOUNCED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3217 if (tcpm_port_is_disconnected(port))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3218 tcpm_set_state(port, SNK_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3219 PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3220 else if (port->vbus_present)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3221 tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3222 tcpm_try_src(port) ? SRC_TRY
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3223 : SNK_ATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3224 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3225 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3226 /* Wait for VBUS, but not forever */
56277035c294ec drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3227 tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3228 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3229
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3230 case SRC_TRY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3231 port->try_src_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3232 tcpm_set_cc(port, tcpm_rp_cc(port));
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3233 port->max_wait = 0;
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3234 tcpm_set_state(port, SRC_TRY_WAIT, 0);
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3235 break;
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3236 case SRC_TRY_WAIT:
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3237 if (port->max_wait == 0) {
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3238 port->max_wait = jiffies +
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3239 msecs_to_jiffies(PD_T_DRP_TRY);
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3240 msecs = PD_T_DRP_TRY;
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3241 } else {
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3242 if (time_is_after_jiffies(port->max_wait))
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3243 msecs = jiffies_to_msecs(port->max_wait -
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3244 jiffies);
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3245 else
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3246 msecs = 0;
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3247 }
131c7d12ef21e1 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3248 tcpm_set_state(port, SNK_TRYWAIT, msecs);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3249 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3250 case SRC_TRY_DEBOUNCE:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3251 tcpm_set_state(port, SRC_ATTACHED, PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3252 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3253 case SNK_TRYWAIT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3254 tcpm_set_cc(port, TYPEC_CC_RD);
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3255 tcpm_set_state(port, SNK_TRYWAIT_VBUS, PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3256 break;
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3257 case SNK_TRYWAIT_VBUS:
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3258 /*
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3259 * TCPM stays in this state indefinitely until VBUS
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3260 * is detected as long as Rp is not detected for
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3261 * more than a time period of tPDDebounce.
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3262 */
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3263 if (port->vbus_present && tcpm_port_is_sink(port)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3264 tcpm_set_state(port, SNK_ATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3265 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3266 }
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3267 if (!tcpm_port_is_sink(port))
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3268 tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3269 break;
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3270 case SNK_TRYWAIT_DEBOUNCE:
af450ebb500ad2 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3271 tcpm_set_state(port, SNK_UNATTACHED, PD_T_PD_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3272 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3273 case SNK_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3274 ret = tcpm_snk_attach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3275 if (ret < 0)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3276 tcpm_set_state(port, SNK_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3277 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3278 tcpm_set_state(port, SNK_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3279 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3280 case SNK_STARTUP:
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 3281 opmode = tcpm_get_pwr_opmode(port->polarity ?
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 3282 port->cc2 : port->cc1);
fce042f02ef03c drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-15 3283 typec_set_pwr_opmode(port->typec_port, opmode);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3284 port->pwr_opmode = TYPEC_PWR_MODE_USB;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3285 port->negotiated_rev = PD_MAX_REV;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3286 port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3287 port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3288 port->explicit_contract = false;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3289 tcpm_set_state(port, SNK_DISCOVERY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3290 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3291 case SNK_DISCOVERY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3292 if (port->vbus_present) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3293 tcpm_set_current_limit(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3294 tcpm_get_current_limit(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3295 5000);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3296 tcpm_set_charge(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3297 tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3298 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3299 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3300 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3301 * For DRP, timeouts differ. Also, handling is supposed to be
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3302 * different and much more complex (dead battery detection;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3303 * see USB power delivery specification, section 8.3.3.6.1.5.1).
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3304 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3305 tcpm_set_state(port, hard_reset_state(port),
9b0ae69909c281 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3306 port->port_type == TYPEC_PORT_DRP ?
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3307 PD_T_DB_DETECT : PD_T_NO_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3308 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3309 case SNK_DISCOVERY_DEBOUNCE:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3310 tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3311 PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3312 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3313 case SNK_DISCOVERY_DEBOUNCE_DONE:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3314 if (!tcpm_port_is_disconnected(port) &&
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3315 tcpm_port_is_sink(port) &&
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3316 time_is_after_jiffies(port->delayed_runtime)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3317 tcpm_set_state(port, SNK_DISCOVERY,
9578bcd0bb487b drivers/usb/typec/tcpm.c Dan Carpenter 2018-06-07 3318 jiffies_to_msecs(port->delayed_runtime -
9578bcd0bb487b drivers/usb/typec/tcpm.c Dan Carpenter 2018-06-07 3319 jiffies));
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3320 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3321 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3322 tcpm_set_state(port, unattached_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3323 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3324 case SNK_WAIT_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3325 ret = port->tcpc->set_pd_rx(port->tcpc, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3326 if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3327 tcpm_set_state(port, SNK_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3328 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3329 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3330 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3331 * If VBUS has never been low, and we time out waiting
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3332 * for source cap, try a soft reset first, in case we
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3333 * were already in a stable contract before this boot.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3334 * Do this only once.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3335 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3336 if (port->vbus_never_low) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3337 port->vbus_never_low = false;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3338 tcpm_set_state(port, SOFT_RESET_SEND,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3339 PD_T_SINK_WAIT_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3340 } else {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3341 tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3342 PD_T_SINK_WAIT_CAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3343 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3344 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3345 case SNK_NEGOTIATE_CAPABILITIES:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3346 port->pd_capable = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3347 port->hard_reset_count = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3348 ret = tcpm_pd_send_request(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3349 if (ret < 0) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3350 /* Let the Source send capabilities again. */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3351 tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3352 } else {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3353 tcpm_set_state_cond(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3354 PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3355 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3356 break;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3357 case SNK_NEGOTIATE_PPS_CAPABILITIES:
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3358 ret = tcpm_pd_send_pps_request(port);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3359 if (ret < 0) {
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3360 port->pps_status = ret;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3361 /*
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3362 * If this was called due to updates to sink
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3363 * capabilities, and pps is no longer valid, we should
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3364 * safely fall back to a standard PDO.
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3365 */
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3366 if (port->update_sink_caps)
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3367 tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3368 else
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3369 tcpm_set_state(port, SNK_READY, 0);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3370 } else {
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3371 tcpm_set_state_cond(port, hard_reset_state(port),
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3372 PD_T_SENDER_RESPONSE);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3373 }
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3374 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3375 case SNK_TRANSITION_SINK:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3376 case SNK_TRANSITION_SINK_VBUS:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3377 tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3378 PD_T_PS_TRANSITION);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3379 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3380 case SNK_READY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3381 port->try_snk_count = 0;
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3382 port->update_sink_caps = false;
8bf05746cffa34 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-17 3383 if (port->explicit_contract) {
8bf05746cffa34 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-17 3384 typec_set_pwr_opmode(port->typec_port,
8bf05746cffa34 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-17 3385 TYPEC_PWR_MODE_PD);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3386 port->pwr_opmode = TYPEC_PWR_MODE_PD;
8bf05746cffa34 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-17 3387 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3388
3113bf1a5da35f drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3389 tcpm_swap_complete(port, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3390 tcpm_typec_connect(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3391 tcpm_check_send_discover(port);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3392 mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(0));
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3393 tcpm_pps_complete(port, port->pps_status);
f2a8aa053c1761 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3394 power_supply_changed(port->psy);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3395 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3396
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3397 /* Accessory states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3398 case ACC_UNATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3399 tcpm_acc_detach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3400 tcpm_set_state(port, SRC_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3401 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3402 case DEBUG_ACC_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3403 case AUDIO_ACC_ATTACHED:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3404 ret = tcpm_acc_attach(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3405 if (ret < 0)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3406 tcpm_set_state(port, ACC_UNATTACHED, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3407 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3408 case AUDIO_ACC_DEBOUNCE:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3409 tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3410 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3411
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3412 /* Hard_Reset states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3413 case HARD_RESET_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3414 tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3415 tcpm_set_state(port, HARD_RESET_START, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3416 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3417 case HARD_RESET_START:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3418 port->sink_cap_done = false;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3419 if (port->tcpc->enable_frs)
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3420 port->tcpc->enable_frs(port->tcpc, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3421 port->hard_reset_count++;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3422 port->tcpc->set_pd_rx(port->tcpc, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3423 tcpm_unregister_altmodes(port);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3424 port->nr_sink_caps = 0;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3425 port->send_discover = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3426 if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3427 tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3428 PD_T_PS_HARD_RESET);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3429 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3430 tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3431 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3432 case SRC_HARD_RESET_VBUS_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3433 tcpm_set_vconn(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3434 tcpm_set_vbus(port, false);
23b5f73266e59a drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3435 tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
6ecc632d4b35d2 drivers/usb/typec/tcpm/tcpm.c Li Jun 2020-02-14 3436 tcpm_data_role_for_source(port));
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3437 tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3438 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3439 case SRC_HARD_RESET_VBUS_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3440 tcpm_set_vbus(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3441 port->tcpc->set_pd_rx(port->tcpc, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3442 tcpm_set_attached_state(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3443 tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3444 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3445 case SNK_HARD_RESET_SINK_OFF:
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3446 memset(&port->pps_data, 0, sizeof(port->pps_data));
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3447 tcpm_set_vconn(port, false);
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3448 if (port->pd_capable)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3449 tcpm_set_charge(port, false);
23b5f73266e59a drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3450 tcpm_set_roles(port, port->self_powered, TYPEC_SINK,
6ecc632d4b35d2 drivers/usb/typec/tcpm/tcpm.c Li Jun 2020-02-14 3451 tcpm_data_role_for_sink(port));
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3452 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3453 * VBUS may or may not toggle, depending on the adapter.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3454 * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3455 * directly after timeout.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3456 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3457 tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, PD_T_SAFE_0V);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3458 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3459 case SNK_HARD_RESET_WAIT_VBUS:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3460 /* Assume we're disconnected if VBUS doesn't come back. */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3461 tcpm_set_state(port, SNK_UNATTACHED,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3462 PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3463 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3464 case SNK_HARD_RESET_SINK_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3465 /* Note: There is no guarantee that VBUS is on in this state */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3466 /*
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3467 * XXX:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3468 * The specification suggests that dual mode ports in sink
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3469 * mode should transition to state PE_SRC_Transition_to_default.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3470 * See USB power delivery specification chapter 8.3.3.6.1.3.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3471 * This would mean to to
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3472 * - turn off VCONN, reset power supply
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3473 * - request hardware reset
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3474 * - turn on VCONN
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3475 * - Transition to state PE_Src_Startup
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3476 * SNK only ports shall transition to state Snk_Startup
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3477 * (see chapter 8.3.3.3.8).
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3478 * Similar, dual-mode ports in source mode should transition
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3479 * to PE_SNK_Transition_to_default.
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3480 */
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3481 if (port->pd_capable) {
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3482 tcpm_set_current_limit(port,
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3483 tcpm_get_current_limit(port),
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3484 5000);
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3485 tcpm_set_charge(port, true);
157c0f2f641a99 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2018-10-01 3486 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3487 tcpm_set_attached_state(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3488 tcpm_set_state(port, SNK_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3489 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3490
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3491 /* Soft_Reset states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3492 case SOFT_RESET:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3493 port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3494 port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3495 tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3496 if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3497 tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3498 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3499 tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3500 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3501 case SOFT_RESET_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3502 port->message_id = 0;
5fec4b54d0bf6c drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3503 port->rx_msgid = -1;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3504 if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3505 tcpm_set_state_cond(port, hard_reset_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3506 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3507 tcpm_set_state_cond(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3508 PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3509 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3510
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3511 /* DR_Swap states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3512 case DR_SWAP_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3513 tcpm_pd_send_control(port, PD_CTRL_DR_SWAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3514 tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3515 PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3516 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3517 case DR_SWAP_ACCEPT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3518 tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3519 tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3520 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3521 case DR_SWAP_SEND_TIMEOUT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3522 tcpm_swap_complete(port, -ETIMEDOUT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3523 tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3524 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3525 case DR_SWAP_CHANGE_DR:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3526 if (port->data_role == TYPEC_HOST) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3527 tcpm_unregister_altmodes(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3528 tcpm_set_roles(port, true, port->pwr_role,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3529 TYPEC_DEVICE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3530 } else {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3531 tcpm_set_roles(port, true, port->pwr_role,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3532 TYPEC_HOST);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3533 port->send_discover = true;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3534 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3535 tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3536 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3537
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3538 case FR_SWAP_SEND:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3539 if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP)) {
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3540 tcpm_set_state(port, ERROR_RECOVERY, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3541 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3542 }
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3543 tcpm_set_state_cond(port, FR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3544 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3545 case FR_SWAP_SEND_TIMEOUT:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3546 tcpm_set_state(port, ERROR_RECOVERY, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3547 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3548 case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3549 tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3550 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3551 case FR_SWAP_SNK_SRC_NEW_SINK_READY:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3552 if (port->vbus_source)
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3553 tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3554 else
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3555 tcpm_set_state(port, ERROR_RECOVERY, PD_T_RECEIVER_RESPONSE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3556 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3557 case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3558 tcpm_set_pwr_role(port, TYPEC_SOURCE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3559 if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3560 tcpm_set_state(port, ERROR_RECOVERY, 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3561 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3562 }
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3563 tcpm_set_cc(port, tcpm_rp_cc(port));
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3564 tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3565 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3566
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3567 /* PR_Swap states */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3568 case PR_SWAP_ACCEPT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3569 tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3570 tcpm_set_state(port, PR_SWAP_START, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3571 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3572 case PR_SWAP_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3573 tcpm_pd_send_control(port, PD_CTRL_PR_SWAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3574 tcpm_set_state_cond(port, PR_SWAP_SEND_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3575 PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3576 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3577 case PR_SWAP_SEND_TIMEOUT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3578 tcpm_swap_complete(port, -ETIMEDOUT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3579 tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3580 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3581 case PR_SWAP_START:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3582 if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3583 tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3584 PD_T_SRC_TRANSITION);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3585 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3586 tcpm_set_state(port, PR_SWAP_SNK_SRC_SINK_OFF, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3587 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3588 case PR_SWAP_SRC_SNK_TRANSITION_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3589 tcpm_set_vbus(port, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3590 port->explicit_contract = false;
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3591 /* allow time for Vbus discharge, must be < tSrcSwapStdby */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3592 tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF,
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3593 PD_T_SRCSWAPSTDBY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3594 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3595 case PR_SWAP_SRC_SNK_SOURCE_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3596 tcpm_set_cc(port, TYPEC_CC_RD);
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3597 /* allow CC debounce */
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3598 tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED,
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3599 PD_T_CC_DEBOUNCE);
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3600 break;
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3601 case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3602 /*
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3603 * USB-PD standard, 6.2.1.4, Port Power Role:
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3604 * "During the Power Role Swap Sequence, for the initial Source
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3605 * Port, the Port Power Role field shall be set to Sink in the
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3606 * PS_RDY Message indicating that the initial Source’s power
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3607 * supply is turned off"
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3608 */
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3609 tcpm_set_pwr_role(port, TYPEC_SINK);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3610 if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3611 tcpm_set_state(port, ERROR_RECOVERY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3612 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3613 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3614 tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3615 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3616 case PR_SWAP_SRC_SNK_SINK_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3617 tcpm_set_state(port, SNK_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3618 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3619 case PR_SWAP_SNK_SRC_SINK_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3620 tcpm_set_charge(port, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3621 tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3622 PD_T_PS_SOURCE_OFF);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3623 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3624 case PR_SWAP_SNK_SRC_SOURCE_ON:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3625 tcpm_set_cc(port, tcpm_rp_cc(port));
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3626 tcpm_set_vbus(port, true);
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3627 /*
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3628 * allow time VBUS ramp-up, must be < tNewSrc
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3629 * Also, this window overlaps with CC debounce as well.
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3630 * So, Wait for the max of two which is PD_T_NEWSRC
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3631 */
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3632 tcpm_set_state(port, PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP,
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3633 PD_T_NEWSRC);
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3634 break;
b965b6317ff147 drivers/staging/typec/tcpm.c Badhri Jagan Sridharan 2017-08-28 3635 case PR_SWAP_SNK_SRC_SOURCE_ON_VBUS_RAMPED_UP:
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3636 /*
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3637 * USB PD standard, 6.2.1.4:
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3638 * "Subsequent Messages initiated by the Policy Engine,
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3639 * such as the PS_RDY Message sent to indicate that Vbus
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3640 * is ready, will have the Port Power Role field set to
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3641 * Source."
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3642 */
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3643 tcpm_set_pwr_role(port, TYPEC_SOURCE);
050161ea3268ad drivers/staging/typec/tcpm.c Guenter Roeck 2017-05-09 3644 tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3645 tcpm_set_state(port, SRC_STARTUP, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3646 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3647
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3648 case VCONN_SWAP_ACCEPT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3649 tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3650 tcpm_set_state(port, VCONN_SWAP_START, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3651 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3652 case VCONN_SWAP_SEND:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3653 tcpm_pd_send_control(port, PD_CTRL_VCONN_SWAP);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3654 tcpm_set_state(port, VCONN_SWAP_SEND_TIMEOUT,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3655 PD_T_SENDER_RESPONSE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3656 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3657 case VCONN_SWAP_SEND_TIMEOUT:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3658 tcpm_swap_complete(port, -ETIMEDOUT);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3659 tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3660 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3661 case VCONN_SWAP_START:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3662 if (port->vconn_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3663 tcpm_set_state(port, VCONN_SWAP_WAIT_FOR_VCONN, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3664 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3665 tcpm_set_state(port, VCONN_SWAP_TURN_ON_VCONN, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3666 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3667 case VCONN_SWAP_WAIT_FOR_VCONN:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3668 tcpm_set_state(port, hard_reset_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3669 PD_T_VCONN_SOURCE_ON);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3670 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3671 case VCONN_SWAP_TURN_ON_VCONN:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3672 tcpm_set_vconn(port, true);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3673 tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3674 tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3675 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3676 case VCONN_SWAP_TURN_OFF_VCONN:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3677 tcpm_set_vconn(port, false);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3678 tcpm_set_state(port, ready_state(port), 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3679 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3680
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3681 case DR_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3682 case PR_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3683 case VCONN_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 @3684 tcpm_swap_complete(port, port->swap_status);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3685 case FR_SWAP_CANCEL:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3686 if (port->pwr_role == TYPEC_SOURCE)
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3687 tcpm_set_state(port, SRC_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3688 else
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3689 tcpm_set_state(port, SNK_READY, 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3690 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3691
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3692 case BIST_RX:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3693 switch (BDO_MODE_MASK(port->bist_request)) {
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3694 case BDO_MODE_CARRIER2:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3695 tcpm_pd_transmit(port, TCPC_TX_BIST_MODE_2, NULL);
6e1c2241f4cecf drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3696 tcpm_set_state(port, unattached_state(port),
6e1c2241f4cecf drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3697 PD_T_BIST_CONT_MODE);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3698 break;
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3699 case BDO_MODE_TESTDATA:
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3700 if (port->tcpc->set_bist_data) {
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3701 tcpm_log(port, "Enable BIST MODE TESTDATA");
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3702 port->tcpc->set_bist_data(port->tcpc, true);
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3703 }
b2dcfefc43f783 drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-07-15 3704 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3705 default:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3706 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3707 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3708 break;
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3709 case GET_STATUS_SEND:
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3710 tcpm_pd_send_control(port, PD_CTRL_GET_STATUS);
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3711 tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT,
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3712 PD_T_SENDER_RESPONSE);
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3713 break;
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3714 case GET_STATUS_SEND_TIMEOUT:
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3715 tcpm_set_state(port, ready_state(port), 0);
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3716 break;
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3717 case GET_PPS_STATUS_SEND:
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3718 tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS);
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3719 tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT,
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3720 PD_T_SENDER_RESPONSE);
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3721 break;
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3722 case GET_PPS_STATUS_SEND_TIMEOUT:
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3723 tcpm_set_state(port, ready_state(port), 0);
64f7c494a3c02b drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3724 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3725 case GET_SINK_CAP:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3726 tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3727 tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3728 break;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3729 case GET_SINK_CAP_TIMEOUT:
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3730 port->sink_cap_done = true;
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3731 tcpm_set_state(port, ready_state(port), 0);
a8727cbd1e6baa drivers/usb/typec/tcpm/tcpm.c Badhri Jagan Sridharan 2020-08-24 3732 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3733 case ERROR_RECOVERY:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3734 tcpm_swap_complete(port, -EPROTO);
2eadc33f40d4c5 drivers/usb/typec/tcpm.c Adam Thomson 2018-04-23 3735 tcpm_pps_complete(port, -EPROTO);
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3736 tcpm_set_state(port, PORT_RESET, 0);
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3737 break;
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3738 case PORT_RESET:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3739 tcpm_reset_port(port);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3740 tcpm_set_cc(port, TYPEC_CC_OPEN);
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3741 tcpm_set_state(port, PORT_RESET_WAIT_OFF,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3742 PD_T_ERROR_RECOVERY);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3743 break;
b17dd57118fee7 drivers/staging/typec/tcpm.c Guenter Roeck 2017-08-10 3744 case PORT_RESET_WAIT_OFF:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3745 tcpm_set_state(port,
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3746 tcpm_default_state(port),
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3747 port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3748 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3749 default:
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3750 WARN(1, "Unexpected port state %d\n", port->state);
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3751 break;
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3752 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3753 }
f0690a25a140b8 drivers/staging/typec/tcpm.c Guenter Roeck 2017-04-27 3754
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 30680 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback
2020-08-25 4:22 ` [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback Badhri Jagan Sridharan
@ 2020-08-28 7:37 ` Greg Kroah-Hartman
0 siblings, 0 replies; 23+ messages in thread
From: Greg Kroah-Hartman @ 2020-08-28 7:37 UTC (permalink / raw)
To: Badhri Jagan Sridharan
Cc: Guenter Roeck, Heikki Krogerus, linux-usb, linux-kernel
On Mon, Aug 24, 2020 at 09:22:01PM -0700, Badhri Jagan Sridharan wrote:
> set_vbus callback allows TCPC which are TCPCI based, however,
> does not support turning on sink and source mode through
> Command.SinkVbus and Command.SourceVbusDefaultVoltage.
>
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> ---
> drivers/usb/typec/tcpm/tcpci.c | 7 +++++++
> drivers/usb/typec/tcpm/tcpci.h | 1 +
> 2 files changed, 8 insertions(+)
Why is this patch "v5" and the others "v1" in this series?
That's totally confusing, please just version the whole series, not
individual patches, as you are not providing version information about
what changed in this patch, right?
Make it easy for reviewers please...
thanks,
greg k-h
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible
2020-08-25 4:21 ` [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible Badhri Jagan Sridharan
@ 2020-08-28 13:12 ` Heikki Krogerus
2020-08-28 14:49 ` Badhri Jagan Sridharan
0 siblings, 1 reply; 23+ messages in thread
From: Heikki Krogerus @ 2020-08-28 13:12 UTC (permalink / raw)
To: Badhri Jagan Sridharan
Cc: Guenter Roeck, Greg Kroah-Hartman, linux-usb, linux-kernel
Looks like you forgot v1 somewhere :-)
On Mon, Aug 24, 2020 at 09:21:58PM -0700, Badhri Jagan Sridharan wrote:
> TCPCI spec forbids direct access of TX_BUF_BYTE_x register.
> The existing version of tcpci driver assumes that those registers
> are directly addressible. Add support for tcpci chips which do
> not support direct access to TX_BUF_BYTE_x registers. TX_BUF_BYTE_x
> can only be accessed by I2C_WRITE_BYTE_COUNT.
>
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> ---
> drivers/usb/typec/tcpm/tcpci.c | 49 +++++++++++++++++++++++++---------
> drivers/usb/typec/tcpm/tcpci.h | 8 ++++++
> 2 files changed, 44 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> index f57d91fd0e09..90d348caa6a8 100644
> --- a/drivers/usb/typec/tcpm/tcpci.c
> +++ b/drivers/usb/typec/tcpm/tcpci.c
> @@ -320,8 +320,7 @@ static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
> return 0;
> }
>
> -static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
> - enum tcpm_transmit_type type,
> +static int tcpci_pd_transmit(struct tcpc_dev *tcpc, enum tcpm_transmit_type type,
> const struct pd_message *msg)
That does not look like a relevant change.
> {
> struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
> @@ -330,23 +329,47 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
> int ret;
>
> cnt = msg ? pd_header_cnt(header) * 4 : 0;
> - ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
> - if (ret < 0)
> - return ret;
> + /**
> + * TCPCI spec forbids direct access of TCPC_TX_DATA.
> + * But, since some of the chipsets offer this capability,
> + * it's fair to support both.
> + */
> + if (!tcpci->data->TX_BUF_BYTE_x_hidden) {
Couldn't check if the flag is set first?
if (tcpci->data->TX_BUF_BYTE_x_hidden) {
...
> + ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
> + if (ret < 0)
> + return ret;
>
> - ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
> - if (ret < 0)
> - return ret;
> + ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
> + if (ret < 0)
> + return ret;
> +
> + if (cnt > 0) {
> + ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, &msg->payload, cnt);
> + if (ret < 0)
> + return ret;
> + }
> + } else {
> + u8 buf[TCPC_TRANSMIT_BUFFER_MAX_LEN] = {0,};
> + u8 pos = 0;
> +
> + /* Payload + header + TCPC_TX_BYTE_CNT */
> + buf[pos++] = cnt + 2;
> +
> + if (msg)
> + memcpy(&buf[pos], &msg->header, sizeof(msg->header));
> +
> + pos += sizeof(header);
> +
> + if (cnt > 0)
> + memcpy(&buf[pos], msg->payload, cnt);
>
> - if (cnt > 0) {
> - ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA,
> - &msg->payload, cnt);
> + pos += cnt;
> + ret = regmap_raw_write(tcpci->regmap, TCPC_TX_BYTE_CNT, buf, pos);
> if (ret < 0)
> return ret;
> }
>
> - reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
> - (type << TCPC_TRANSMIT_TYPE_SHIFT);
> + reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | (type << TCPC_TRANSMIT_TYPE_SHIFT);
> ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg);
> if (ret < 0)
> return ret;
> diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
> index fd26ca35814c..cf9d8b63adcb 100644
> --- a/drivers/usb/typec/tcpm/tcpci.h
> +++ b/drivers/usb/typec/tcpm/tcpci.h
> @@ -128,9 +128,17 @@
> #define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
> #define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
>
> +/* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */
> +#define TCPC_TRANSMIT_BUFFER_MAX_LEN 31
> +
> +/*
> + * @TX_BUF_BYTE_x_hidden
> + * optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT.
> + */
> struct tcpci;
> struct tcpci_data {
> struct regmap *regmap;
> + unsigned char TX_BUF_BYTE_x_hidden:1;
> int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
> int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
> bool enable);
> --
> 2.28.0.297.g1956fa8f8d-goog
thanks,
--
heikki
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference
2020-08-25 4:22 ` [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference Badhri Jagan Sridharan
@ 2020-08-28 14:11 ` Heikki Krogerus
0 siblings, 0 replies; 23+ messages in thread
From: Heikki Krogerus @ 2020-08-28 14:11 UTC (permalink / raw)
To: Badhri Jagan Sridharan, Guenter Roeck
Cc: Greg Kroah-Hartman, linux-usb, linux-kernel
On Mon, Aug 24, 2020 at 09:22:00PM -0700, Badhri Jagan Sridharan wrote:
> Allow chip level drivers to retrieve reference to tcpm_port.
>
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> ---
> drivers/usb/typec/tcpm/tcpci.c | 6 ++++++
> drivers/usb/typec/tcpm/tcpci.h | 2 ++
> 2 files changed, 8 insertions(+)
>
> diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> index 9e814d454d14..7b7991c8ac87 100644
> --- a/drivers/usb/typec/tcpm/tcpci.c
> +++ b/drivers/usb/typec/tcpm/tcpci.c
> @@ -38,6 +38,12 @@ struct tcpci_chip {
> struct tcpci_data data;
> };
>
> +struct tcpm_port *tcpci_get_tcpm_port(struct tcpci *tcpci)
> +{
> + return tcpci->port;
> +}
> +EXPORT_SYMBOL_GPL(tcpci_get_tcpm_port);
I wonder if it would be better if there were tpci callbacks, or
wrappers, for the tcpm functions that the glue drivers could then use
instead of directly calling the tcpm_*() functions? That would allow
tcpci.c to keep tabs on what is going on.
That would somehow feel like a better approach to me, but maybe it
would only complicate things. Guenter, what do you think?
thanks,
--
heikki
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support
2020-08-25 4:22 ` [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support Badhri Jagan Sridharan
@ 2020-08-28 14:13 ` Heikki Krogerus
0 siblings, 0 replies; 23+ messages in thread
From: Heikki Krogerus @ 2020-08-28 14:13 UTC (permalink / raw)
To: Badhri Jagan Sridharan
Cc: Guenter Roeck, Greg Kroah-Hartman, linux-usb, linux-kernel
On Mon, Aug 24, 2020 at 09:22:08PM -0700, Badhri Jagan Sridharan wrote:
> TCPCI spec allows TCPC hardware to autonomously discharge the vbus
> capacitance upon disconnect. The expectation is that the TCPM enables
> AutoDischargeDisconnect while entering SNK/SRC_ATTACHED states. Hardware
> then automously discharges vbus when the vbus falls below a certain
> threshold i.e. VBUS_SINK_DISCONNECT_THRESHOLD.
>
> Apart from enabling the vbus discharge circuit, AutoDischargeDisconnect
> is also used a flag to move TCPCI based TCPC implementations into
> Attached.Snk/Attached.Src state as mentioned in
> Figure 4-15. TCPC State Diagram before a Connection of the
> USB Type-C Port Controller Interface Specification.
> In such TCPC implementations, setting AutoDischargeDisconnect would
> prevent TCPC into entering "Connection_Invalid" state as well.
>
> Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> Change-Id: I09c407eb228d69eb1259008eeb14c429b0fda765
It looks like this patch is also formated a bit differently compared
to the others.
thanks,
--
heikki
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible
2020-08-28 13:12 ` Heikki Krogerus
@ 2020-08-28 14:49 ` Badhri Jagan Sridharan
0 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-28 14:49 UTC (permalink / raw)
To: Heikki Krogerus; +Cc: Guenter Roeck, Greg Kroah-Hartman, USB, LKML
On Fri, Aug 28, 2020 at 6:12 AM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>
> Looks like you forgot v1 somewhere :-)
Dumb me :P Yeah I was doing the patch numbers manually causing the confusion.
Greg was complaining as well.
These are all v1. I will re-upload everything as v2. Just noticed that
I can use the -v option.
>
>
> On Mon, Aug 24, 2020 at 09:21:58PM -0700, Badhri Jagan Sridharan wrote:
> > TCPCI spec forbids direct access of TX_BUF_BYTE_x register.
> > The existing version of tcpci driver assumes that those registers
> > are directly addressible. Add support for tcpci chips which do
> > not support direct access to TX_BUF_BYTE_x registers. TX_BUF_BYTE_x
> > can only be accessed by I2C_WRITE_BYTE_COUNT.
> >
> > Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
> > ---
> > drivers/usb/typec/tcpm/tcpci.c | 49 +++++++++++++++++++++++++---------
> > drivers/usb/typec/tcpm/tcpci.h | 8 ++++++
> > 2 files changed, 44 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> > index f57d91fd0e09..90d348caa6a8 100644
> > --- a/drivers/usb/typec/tcpm/tcpci.c
> > +++ b/drivers/usb/typec/tcpm/tcpci.c
> > @@ -320,8 +320,7 @@ static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
> > return 0;
> > }
> >
> > -static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
> > - enum tcpm_transmit_type type,
> > +static int tcpci_pd_transmit(struct tcpc_dev *tcpc, enum tcpm_transmit_type type,
> > const struct pd_message *msg)
>
> That does not look like a relevant change.
>
> > {
> > struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
> > @@ -330,23 +329,47 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
> > int ret;
> >
> > cnt = msg ? pd_header_cnt(header) * 4 : 0;
> > - ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
> > - if (ret < 0)
> > - return ret;
> > + /**
> > + * TCPCI spec forbids direct access of TCPC_TX_DATA.
> > + * But, since some of the chipsets offer this capability,
> > + * it's fair to support both.
> > + */
> > + if (!tcpci->data->TX_BUF_BYTE_x_hidden) {
>
> Couldn't check if the flag is set first?
Yes will do !
>
> if (tcpci->data->TX_BUF_BYTE_x_hidden) {
> ...
>
> > + ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
> > + if (ret < 0)
> > + return ret;
> >
> > - ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
> > - if (ret < 0)
> > - return ret;
> > + ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
> > + if (ret < 0)
> > + return ret;
> > +
> > + if (cnt > 0) {
> > + ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, &msg->payload, cnt);
> > + if (ret < 0)
> > + return ret;
> > + }
> > + } else {
> > + u8 buf[TCPC_TRANSMIT_BUFFER_MAX_LEN] = {0,};
> > + u8 pos = 0;
> > +
> > + /* Payload + header + TCPC_TX_BYTE_CNT */
> > + buf[pos++] = cnt + 2;
> > +
> > + if (msg)
> > + memcpy(&buf[pos], &msg->header, sizeof(msg->header));
> > +
> > + pos += sizeof(header);
> > +
> > + if (cnt > 0)
> > + memcpy(&buf[pos], msg->payload, cnt);
> >
> > - if (cnt > 0) {
> > - ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA,
> > - &msg->payload, cnt);
> > + pos += cnt;
> > + ret = regmap_raw_write(tcpci->regmap, TCPC_TX_BYTE_CNT, buf, pos);
> > if (ret < 0)
> > return ret;
> > }
> >
> > - reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
> > - (type << TCPC_TRANSMIT_TYPE_SHIFT);
> > + reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | (type << TCPC_TRANSMIT_TYPE_SHIFT);
> > ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg);
> > if (ret < 0)
> > return ret;
> > diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
> > index fd26ca35814c..cf9d8b63adcb 100644
> > --- a/drivers/usb/typec/tcpm/tcpci.h
> > +++ b/drivers/usb/typec/tcpm/tcpci.h
> > @@ -128,9 +128,17 @@
> > #define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
> > #define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
> >
> > +/* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */
> > +#define TCPC_TRANSMIT_BUFFER_MAX_LEN 31
> > +
> > +/*
> > + * @TX_BUF_BYTE_x_hidden
> > + * optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT.
> > + */
> > struct tcpci;
> > struct tcpci_data {
> > struct regmap *regmap;
> > + unsigned char TX_BUF_BYTE_x_hidden:1;
> > int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
> > int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
> > bool enable);
> > --
> > 2.28.0.297.g1956fa8f8d-goog
>
> thanks,
>
> --
> heikki
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver
2020-08-25 5:16 ` Randy Dunlap
@ 2020-08-28 14:51 ` Badhri Jagan Sridharan
0 siblings, 0 replies; 23+ messages in thread
From: Badhri Jagan Sridharan @ 2020-08-28 14:51 UTC (permalink / raw)
To: Randy Dunlap
Cc: Guenter Roeck, Heikki Krogerus, Greg Kroah-Hartman, USB, LKML
On Mon, Aug 24, 2020 at 10:16 PM Randy Dunlap <rdunlap@infradead.org> wrote:
>
> On 8/24/20 9:22 PM, Badhri Jagan Sridharan wrote:
> > diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
> > index fa3f39336246..7c9722b02afe 100644
> > --- a/drivers/usb/typec/tcpm/Kconfig
> > +++ b/drivers/usb/typec/tcpm/Kconfig
> > @@ -27,6 +27,12 @@ config TYPEC_RT1711H
> > Type-C Port Controller Manager to provide USB PD and USB
> > Type-C functionalities.
> >
> > +config TYPEC_TCPCI_MAXIM
> > + tristate "Maxim TCPCI based Type-C chip driver"
> > + select USB_PSY
>
> is that USB_PHY
> ?
Yes and not a dependency here. Will remove. Thanks for catching this !
>
> > + help
> > + MAXIM TCPCI based Type-C chip driver
>
> end that with '.' please.
Ack ! will fix it in the next version.
>
> > +
> > endif # TYPEC_TCPCI
> >
> > config TYPEC_FUSB302
>
>
> --
> ~Randy
>
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2020-08-28 14:52 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-25 4:21 [PATCH 00/14] TCPM support for FRS and AutoDischarge Disconnect Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 01/14 v1] usb: typec: tcpci: Add register definitions to tcpci Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible Badhri Jagan Sridharan
2020-08-28 13:12 ` Heikki Krogerus
2020-08-28 14:49 ` Badhri Jagan Sridharan
2020-08-25 4:21 ` [PATCH 03/14 v1] usb: typec: tcpci: update ROLE_CONTROL for DRP Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference Badhri Jagan Sridharan
2020-08-28 14:11 ` Heikki Krogerus
2020-08-25 4:22 ` [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback Badhri Jagan Sridharan
2020-08-28 7:37 ` Greg Kroah-Hartman
2020-08-25 4:22 ` [PATCH 06/14 v1] dt-bindings: usb: Maxim type-c controller device tree binding document Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver Badhri Jagan Sridharan
2020-08-25 5:16 ` Randy Dunlap
2020-08-28 14:51 ` Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 08/14 v1] dt-bindings: connector: Add property to set initial current cap for FRS Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS) Badhri Jagan Sridharan
2020-08-26 12:42 ` kernel test robot
2020-08-25 4:22 ` [PATCH 10/14 v1] usb: typec: tcpci: Implement callbacks for FRS Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 11/14 v1] usb: typec: tcpci_maxim: Add support for Sink FRS Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support Badhri Jagan Sridharan
2020-08-28 14:13 ` Heikki Krogerus
2020-08-25 4:22 ` [PATCH 13/14 v1] usb: typec: tcpci: Implement Auto discharge disconnect callbacks Badhri Jagan Sridharan
2020-08-25 4:22 ` [PATCH 14/14 v1] usb: typec: tcpci_maxim: Implemnent set_auto_vbus_discharge_threshold 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).