summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@chromium.org>2019-10-01 10:57:11 -0600
committerCommit Bot <commit-bot@chromium.org>2019-10-07 23:33:29 +0000
commit31428c89c02d4ce4f65006fcaf712bb7de86bc99 (patch)
treeec56a71218bbd3c105d56eb5847cc81c09a2adb2
parent0783b019fc880443a768acdc1286499a49594baa (diff)
downloadchrome-ec-31428c89c02d4ce4f65006fcaf712bb7de86bc99.tar.gz
tcpc: driver changes for FRS
BUG=b:138599955 BRANCH=none TEST=make buildall -j Change-Id: Ic8d386355f9297c3da69021999142f35120b214c Signed-off-by: Denis Brockus <dbrockus@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1834022 Reviewed-by: Edward Hill <ecgh@chromium.org>
-rw-r--r--driver/tcpm/nct38xx.c21
-rw-r--r--driver/tcpm/tcpci.c45
-rw-r--r--driver/tcpm/tcpci.h55
3 files changed, 99 insertions, 22 deletions
diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c
index 8061f7190c..1196621e71 100644
--- a/driver/tcpm/nct38xx.c
+++ b/driver/tcpm/nct38xx.c
@@ -64,15 +64,29 @@ static int nct38xx_tcpm_init(int port)
if (rv)
return rv;
- /* Enable VBus monitor */
+ /* Enable VBus monitor and Disable FRS */
rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &reg);
if (rv)
return rv;
- reg = reg & ~TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS;
+ reg = reg & ~(TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS |
+ TCPC_REG_POWER_CTRL_FRS_ENABLE);
rv = tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
if (rv)
return rv;
+ /* Set FRS direction for SNK detect, if FRS is enabled */
+ if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)) {
+ reg = TCPC_REG_DEV_CAP_2_SNK_FR_SWAP;
+ rv = tcpc_write(port, TCPC_REG_DEV_CAP_2, reg);
+ if (rv)
+ return rv;
+
+ reg = TCPC_REG_CONFIG_EXT_1_FR_SWAP_SNK_DIR;
+ rv = tcpc_write(port, TCPC_REG_CONFIG_EXT_1, reg);
+ if (rv)
+ return rv;
+ }
+
/* Start VBus monitor */
rv = tcpc_write(port, TCPC_REG_COMMAND,
TCPC_REG_COMMAND_ENABLE_VBUS_DETECT);
@@ -364,4 +378,7 @@ const struct tcpm_drv nct38xx_tcpm_drv = {
#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
.enter_low_power_mode = &tcpci_enter_low_power_mode,
#endif
+#ifdef CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP
+ .set_frs_enable = &tcpci_tcpc_fast_role_swap_enable,
+#endif
};
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 5d5bf4499a..257649fc66 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -146,6 +146,7 @@ int tcpc_xfer_unlocked(int port, const uint8_t *out, int out_size,
static int init_alert_mask(int port)
{
+ int rv;
uint16_t mask;
/*
@@ -160,7 +161,17 @@ static int init_alert_mask(int port)
#endif
;
/* Set the alert mask in TCPC */
- return tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
+ rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
+
+ if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)) {
+ if (rv)
+ return rv;
+
+ /* Sink FRS allowed */
+ mask = TCPC_REG_ALERT_EXT_SNK_FRS;
+ rv = tcpc_write(port, TCPC_REG_ALERT_EXT, mask);
+ }
+ return rv;
}
static int clear_alert_mask(int port)
@@ -345,6 +356,12 @@ static int tcpm_alert_status(int port, int *alert)
return tcpc_read16(port, TCPC_REG_ALERT, alert);
}
+static int tcpm_alert_ext_status(int port, int *alert_ext)
+{
+ /* Read TCPC Extended Alert register */
+ return tcpc_read(port, TCPC_REG_ALERT_EXT, alert_ext);
+}
+
int tcpci_tcpm_set_rx_enable(int port, int enable)
{
int detect_sop_en = 0;
@@ -371,6 +388,23 @@ int tcpci_tcpm_set_rx_enable(int port, int enable)
return tcpc_write(port, TCPC_REG_RX_DETECT, detect_sop_en);
}
+#ifdef CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP
+void tcpci_tcpc_fast_role_swap_enable(int port, int enable)
+{
+ int reg;
+
+ if (tcpc_read(port, TCPC_REG_POWER_CTRL, &reg))
+ return;
+
+ if (enable)
+ reg |= TCPC_REG_POWER_CTRL_FRS_ENABLE;
+ else
+ reg &= ~TCPC_REG_POWER_CTRL_FRS_ENABLE;
+
+ tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
+}
+#endif
+
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
int tcpci_tcpm_get_vbus_level(int port)
{
@@ -579,12 +613,17 @@ static int register_mask_reset(int port)
void tcpci_tcpc_alert(int port)
{
int status = 0;
+ int alert_ext = 0;
int failed_attempts;
uint32_t pd_event = 0;
/* Read the Alert register from the TCPC */
tcpm_alert_status(port, &status);
+ /* Get Extended Alert register if needed */
+ if (status & TCPC_REG_ALERT_ALERT_EXT)
+ tcpm_alert_ext_status(port, &alert_ext);
+
/*
* Check for TX complete first b/c PD state machine waits on TX
* completion events. This will send an event to the PD tasks
@@ -645,6 +684,10 @@ void tcpci_tcpc_alert(int port)
pd_event |= TASK_EVENT_WAKE;
}
+ if (IS_ENABLED(CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP)
+ && (alert_ext & TCPC_REG_ALERT_EXT_SNK_FRS))
+ pd_got_frs_signal(port);
+
#ifndef CONFIG_USB_PD_TCPC_LOW_POWER
/*
* Check registers to see if we can tell that the TCPC has reset. If
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
index 491fe195ed..930bfd6d70 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -18,22 +18,23 @@
#define TCPC_REG_TC_REV 0x6
#define TCPC_REG_PD_REV 0x8
#define TCPC_REG_PD_INT_REV 0xa
-#define TCPC_REG_ALERT 0x10
+#define TCPC_REG_ALERT 0x10
#define TCPC_REG_ALERT_MASK_ALL 0xffff
-#define TCPC_REG_ALERT_VENDOR_DEF (1<<15)
-#define TCPC_REG_ALERT_VBUS_DISCNCT (1<<11)
-#define TCPC_REG_ALERT_RX_BUF_OVF (1<<10)
-#define TCPC_REG_ALERT_FAULT (1<<9)
-#define TCPC_REG_ALERT_V_ALARM_LO (1<<8)
-#define TCPC_REG_ALERT_V_ALARM_HI (1<<7)
-#define TCPC_REG_ALERT_TX_SUCCESS (1<<6)
-#define TCPC_REG_ALERT_TX_DISCARDED (1<<5)
-#define TCPC_REG_ALERT_TX_FAILED (1<<4)
-#define TCPC_REG_ALERT_RX_HARD_RST (1<<3)
-#define TCPC_REG_ALERT_RX_STATUS (1<<2)
-#define TCPC_REG_ALERT_POWER_STATUS (1<<1)
-#define TCPC_REG_ALERT_CC_STATUS (1<<0)
+#define TCPC_REG_ALERT_VENDOR_DEF BIT(15)
+#define TCPC_REG_ALERT_ALERT_EXT BIT(14)
+#define TCPC_REG_ALERT_VBUS_DISCNCT BIT(11)
+#define TCPC_REG_ALERT_RX_BUF_OVF BIT(10)
+#define TCPC_REG_ALERT_FAULT BIT(9)
+#define TCPC_REG_ALERT_V_ALARM_LO BIT(8)
+#define TCPC_REG_ALERT_V_ALARM_HI BIT(7)
+#define TCPC_REG_ALERT_TX_SUCCESS BIT(6)
+#define TCPC_REG_ALERT_TX_DISCARDED BIT(5)
+#define TCPC_REG_ALERT_TX_FAILED BIT(4)
+#define TCPC_REG_ALERT_RX_HARD_RST BIT(3)
+#define TCPC_REG_ALERT_RX_STATUS BIT(2)
+#define TCPC_REG_ALERT_POWER_STATUS BIT(1)
+#define TCPC_REG_ALERT_CC_STATUS BIT(0)
#define TCPC_REG_ALERT_TX_COMPLETE (TCPC_REG_ALERT_TX_SUCCESS | \
TCPC_REG_ALERT_TX_DISCARDED | \
TCPC_REG_ALERT_TX_FAILED)
@@ -41,6 +42,7 @@
#define TCPC_REG_ALERT_MASK 0x12
#define TCPC_REG_POWER_STATUS_MASK 0x14
#define TCPC_REG_FAULT_STATUS_MASK 0x15
+
#define TCPC_REG_CONFIG_STD_OUTPUT 0x18
#define TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK (3 << 2)
#define TCPC_REG_CONFIG_STD_OUTPUT_MUX_NONE (0 << 2)
@@ -65,9 +67,10 @@
#define TCPC_REG_FAULT_CTRL_VBUS_OVP_FAULT_DIS BIT(1)
#define TCPC_REG_POWER_CTRL 0x1c
-#define TCPC_REG_POWER_CTRL_FORCE_DISCHARGE BIT(2)
-#define TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT BIT(4)
+#define TCPC_REG_POWER_CTRL_FRS_ENABLE BIT(7)
#define TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS BIT(6)
+#define TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT BIT(4)
+#define TCPC_REG_POWER_CTRL_FORCE_DISCHARGE BIT(2)
#define TCPC_REG_POWER_CTRL_SET(vconn) (vconn)
#define TCPC_REG_POWER_CTRL_VCONN(reg) ((reg) & 0x1)
@@ -81,11 +84,17 @@
#define TCPC_REG_POWER_STATUS 0x1e
#define TCPC_REG_POWER_STATUS_MASK_ALL 0xff
-#define TCPC_REG_POWER_STATUS_VBUS_PRES (1<<2)
-#define TCPC_REG_POWER_STATUS_VBUS_DET (1<<3)
-#define TCPC_REG_POWER_STATUS_UNINIT (1<<6)
+#define TCPC_REG_POWER_STATUS_UNINIT BIT(6)
+#define TCPC_REG_POWER_STATUS_VBUS_DET BIT(3)
+#define TCPC_REG_POWER_STATUS_VBUS_PRES BIT(2)
+
#define TCPC_REG_FAULT_STATUS 0x1f
+#define TCPC_REG_ALERT_EXT 0x21
+#define TCPC_REG_ALERT_EXT_TIMER_EXPIRED BIT(2)
+#define TCPC_REG_ALERT_EXT_SRC_FRS BIT(1)
+#define TCPC_REG_ALERT_EXT_SNK_FRS BIT(0)
+
#define TCPC_REG_COMMAND 0x23
#define TCPC_REG_COMMAND_ENABLE_VBUS_DETECT 0x33
#define TCPC_REG_COMMAND_SNK_CTRL_LOW 0x44
@@ -96,10 +105,16 @@
#define TCPC_REG_COMMAND_I2CIDLE 0xFF
#define TCPC_REG_DEV_CAP_1 0x24
+
#define TCPC_REG_DEV_CAP_2 0x26
+#define TCPC_REG_DEV_CAP_2_SNK_FR_SWAP BIT(9)
+
#define TCPC_REG_STD_INPUT_CAP 0x28
#define TCPC_REG_STD_OUTPUT_CAP 0x29
+#define TCPC_REG_CONFIG_EXT_1 0x2A
+#define TCPC_REG_CONFIG_EXT_1_FR_SWAP_SNK_DIR BIT(1)
+
#define TCPC_REG_MSG_HDR_INFO 0x2e
#define TCPC_REG_MSG_HDR_INFO_SET(drole, prole) \
((drole) << 3 | (PD_REV20 << 1) | (prole))
@@ -171,4 +186,6 @@ int tcpci_tcpm_set_snk_ctrl(int port, int enable);
int tcpci_tcpm_set_src_ctrl(int port, int enable);
#endif
+void tcpci_tcpc_fast_role_swap_enable(int port, int enable);
+
#endif /* __CROS_EC_USB_PD_TCPM_TCPCI_H */