summaryrefslogtreecommitdiff
path: root/driver/tcpm/tcpci.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/tcpm/tcpci.c')
-rw-r--r--driver/tcpm/tcpci.c45
1 files changed, 44 insertions, 1 deletions
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