summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorKevin K Wong <kevin.k.wong@intel.com>2016-09-21 08:57:40 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-11-02 06:42:04 -0700
commit180ac77e16e1e5a57769a2a20411b6e37d649107 (patch)
tree7b9d5cb676836a9e368c36aabd004734c8b55f59 /driver
parentdd652accd0c26d56af3511d178507af738912885 (diff)
downloadchrome-ec-180ac77e16e1e5a57769a2a20411b6e37d649107.tar.gz
reef: enable tcpc-controlled drp toggle
BUG=chrome-os-partner:54668 BRANCH=none TEST=Verified SNK is detected in S0 (toggle on), S3 (toggle off), and S5 (force sink). SRC is detect in S0 only, stays detected when entered S3, but unplug/plug while in S3 will not re-detect until system back in S0. When go to S5, SRC will get disconnected until back in S0, and hotplug SRC in S5 will not get detected. Checked power role swap with another chromebook in the above scenario also. Change-Id: I2a487fca5cb04c45524aa3efde84fcd10ff0579e Signed-off-by: Kevin K Wong <kevin.k.wong@intel.com> Reviewed-on: https://chromium-review.googlesource.com/396918 Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/tcpm/anx74xx.c48
-rw-r--r--driver/tcpm/tcpci.c59
-rw-r--r--driver/tcpm/tcpci.h3
-rw-r--r--driver/tcpm/tcpm.h13
4 files changed, 91 insertions, 32 deletions
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index c96cab36b0..5e3681e643 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -35,7 +35,7 @@ static struct anx_state anx[CONFIG_USB_PD_PORT_COUNT];
static int anx74xx_set_mux(int port, int polarity);
/* Save the selected rp value */
-static int selected_rp = TYPEC_RP_USB;
+static int selected_rp[CONFIG_USB_PD_PORT_COUNT];
static void anx74xx_tcpm_set_auto_good_crc(int port, int enable)
{
@@ -472,21 +472,36 @@ static int anx74xx_rp_control(int port, int rp)
static int anx74xx_tcpm_select_rp_value(int port, int rp)
{
/* For ANX3429 cannot get cc correctly when Rp != USB_Default */
- selected_rp = rp;
- return 1;
+ selected_rp[port] = rp;
+ return EC_SUCCESS;
}
-static int anx74xx_tcpm_set_cc(int port, int pull)
+
+static int anx74xx_cc_software_ctrl(int port, int enable)
{
- int rv = EC_SUCCESS;
+ int rv;
int reg;
- /* Enable CC software Control */
- rv |= tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
+ rv = tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
if (rv)
return EC_ERROR_UNKNOWN;
- reg |= ANX74XX_REG_CC_SW_CTRL_ENABLE;
+
+ if (enable)
+ reg |= ANX74XX_REG_CC_SW_CTRL_ENABLE;
+ else
+ reg &= ~ANX74XX_REG_CC_SW_CTRL_ENABLE;
+
rv |= tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg);
+ return rv;
+}
+
+static int anx74xx_tcpm_set_cc(int port, int pull)
+{
+ int rv = EC_SUCCESS;
+ int reg;
+
+ /* Enable CC software Control */
+ rv = anx74xx_cc_software_ctrl(port, 1);
if (rv)
return EC_ERROR_UNKNOWN;
@@ -515,6 +530,18 @@ static int anx74xx_tcpm_set_cc(int port, int pull)
return rv;
}
+#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+static int anx74xx_tcpc_drp_toggle(int port)
+{
+ int rv;
+
+ /* Disable CC software Control */
+ rv = anx74xx_cc_software_ctrl(port, 0);
+
+ return rv;
+}
+#endif
+
static int anx74xx_tcpm_set_polarity(int port, int polarity)
{
int reg, mux_state, rv = EC_SUCCESS;
@@ -638,7 +665,7 @@ static int anx74xx_tcpm_set_rx_enable(int port, int enable)
if (enable) {
reg &= ~(ANX74XX_REG_IRQ_CC_MSG_INT);
anx74xx_tcpm_set_auto_good_crc(port, 1);
- anx74xx_rp_control(port, selected_rp);
+ anx74xx_rp_control(port, selected_rp[port]);
} else {
/* Disable RX message by masking interrupt */
reg |= (ANX74XX_REG_IRQ_CC_MSG_INT);
@@ -879,6 +906,9 @@ const struct tcpm_drv anx74xx_tcpm_drv = {
#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
.tcpc_discharge_vbus = &anx74xx_tcpc_discharge_vbus,
#endif
+#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+ .drp_toggle = &anx74xx_tcpc_drp_toggle,
+#endif
};
#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index f69e8a96d6..a9232e411c 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -17,6 +17,9 @@
static int tcpc_vbus[CONFIG_USB_PD_PORT_COUNT];
+/* Save the selected rp value */
+static int selected_rp[CONFIG_USB_PD_PORT_COUNT];
+
static int init_alert_mask(int port)
{
uint16_t mask;
@@ -65,9 +68,12 @@ int tcpci_tcpm_get_cc(int port, int *cc1, int *cc2)
rv = tcpc_read(port, TCPC_REG_CC_STATUS, &status);
- /* If tcpc read fails, return error */
- if (rv)
+ /* If tcpc read fails, return error and CC as open */
+ if (rv) {
+ *cc1 = TYPEC_CC_VOLT_OPEN;
+ *cc2 = TYPEC_CC_VOLT_OPEN;
return rv;
+ }
*cc1 = TCPC_REG_CC_STATUS_CC1(status);
*cc2 = TCPC_REG_CC_STATUS_CC2(status);
@@ -91,15 +97,8 @@ static int tcpci_tcpm_get_power_status(int port, int *status)
int tcpci_tcpm_select_rp_value(int port, int rp)
{
- int reg;
- int rv;
-
- rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &reg);
- if (rv)
- return rv;
- reg = (reg & ~TCPC_REG_ROLE_CTRL_RP_MASK)
- | ((rp << 4) & TCPC_REG_ROLE_CTRL_RP_MASK);
- return tcpc_write(port, TCPC_REG_ROLE_CTRL, reg);
+ selected_rp[port] = rp;
+ return EC_SUCCESS;
}
#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
@@ -119,22 +118,33 @@ static void tcpci_tcpc_discharge_vbus(int port, int enable)
}
#endif
+static int set_role_ctrl(int port, int toggle, int rp, int pull)
+{
+ return tcpc_write(port, TCPC_REG_ROLE_CTRL,
+ TCPC_REG_ROLE_CTRL_SET(toggle, rp, pull, pull));
+}
+
int tcpci_tcpm_set_cc(int port, int pull)
{
- int reg, rv;
- uint8_t rp;
+ /* Set manual control, and set both CC lines to the same pull */
+ return set_role_ctrl(port, 0, selected_rp[port], pull);
+}
- rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &reg);
- if (rv)
- return rv;
- rp = TCPC_REG_ROLE_CTRL_RP(reg);
- /*
- * Set manual control of Rp/Rd, and set both CC lines to the same
- * pull.
- */
- return tcpc_write(port, TCPC_REG_ROLE_CTRL,
- TCPC_REG_ROLE_CTRL_SET(0, rp, pull, pull));
+#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+static int tcpci_tcpc_drp_toggle(int port)
+{
+ int rv;
+
+ /* Set auto drp toggle */
+ rv = set_role_ctrl(port, 1, TYPEC_RP_USB, TYPEC_CC_OPEN);
+
+ /* Set Look4Connection command */
+ rv |= tcpc_write(port, TCPC_REG_COMMAND,
+ TCPC_REG_COMMAND_LOOK4CONNECTION);
+
+ return rv;
}
+#endif
int tcpci_tcpm_set_polarity(int port, int polarity)
{
@@ -408,4 +418,7 @@ const struct tcpm_drv tcpci_tcpm_drv = {
#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
.tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
#endif
+#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+ .drp_toggle = &tcpci_tcpc_drp_toggle,
+#endif
};
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
index 141d3daf14..165b206bf1 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -66,6 +66,7 @@
#define TCPC_REG_POWER_CTRL_VCONN(reg) ((reg) & 0x1)
#define TCPC_REG_CC_STATUS 0x1d
+#define TCPC_REG_CC_STATUS_LOOK4CONNECTION(reg) ((reg & 0x20) >> 5)
#define TCPC_REG_CC_STATUS_SET(term, cc1, cc2) \
((term) << 4 | ((cc2) & 0x3) << 2 | ((cc1) & 0x3))
#define TCPC_REG_CC_STATUS_TERM(reg) (((reg) & 0x10) >> 4)
@@ -80,6 +81,8 @@
#define TCPC_REG_FAULT_STATUS 0x1f
#define TCPC_REG_COMMAND 0x23
+#define TCPC_REG_COMMAND_LOOK4CONNECTION 0x99
+
#define TCPC_REG_DEV_CAP_1 0x24
#define TCPC_REG_DEV_CAP_2 0x26
#define TCPC_REG_STD_INPUT_CAP 0x28
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
index 7903cccffd..57950dc34d 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -13,6 +13,12 @@
#include "i2c.h"
#include "usb_pd_tcpm.h"
+#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \
+ !defined(CONFIG_USB_PD_DUAL_ROLE)
+#error "DRP auto toggle requires board to have DRP support"
+#error "Please upgrade your board configuration"
+#endif
+
#ifndef CONFIG_USB_PD_TCPC
extern const struct tcpc_config_t tcpc_config[];
@@ -130,6 +136,13 @@ static inline void tcpc_discharge_vbus(int port, int enable)
tcpc_config[port].drv->tcpc_discharge_vbus(port, enable);
}
+#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+static inline int tcpm_set_drp_toggle(int port)
+{
+ return tcpc_config[port].drv->drp_toggle(port);
+}
+#endif
+
#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
static inline int tcpc_i2c_read(const int port, const int addr,
const int reg, int *data)