summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/mock/tcpc_mock.c5
-rw-r--r--driver/tcpm/anx74xx.c5
-rw-r--r--driver/tcpm/anx7688.c6
-rw-r--r--driver/tcpm/fusb302.c5
-rw-r--r--driver/tcpm/tcpci.c80
-rw-r--r--driver/tcpm/tcpci.h6
6 files changed, 93 insertions, 14 deletions
diff --git a/common/mock/tcpc_mock.c b/common/mock/tcpc_mock.c
index c67ce8a040..657e18e5bb 100644
--- a/common/mock/tcpc_mock.c
+++ b/common/mock/tcpc_mock.c
@@ -44,7 +44,10 @@ static int mock_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
static bool mock_check_vbus_level(int port, enum vbus_level level)
{
- return mock_tcpc.vbus_level;
+ if (level == VBUS_PRESENT)
+ return mock_tcpc.vbus_level;
+ else
+ return !mock_tcpc.vbus_level;
}
static int mock_select_rp_value(int port, int rp)
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index c40c65e312..26749891c9 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -865,7 +865,10 @@ static bool anx74xx_tcpm_check_vbus_level(int port, enum vbus_level level)
int reg = 0;
tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, &reg);
- return ((reg & ANX74XX_REG_VBUS_STATUS) ? 1 : 0);
+ if (level == VBUS_PRESENT)
+ return ((reg & ANX74XX_REG_VBUS_STATUS) ? 1 : 0);
+ else
+ return ((reg & ANX74XX_REG_VBUS_STATUS) ? 0 : 1);
}
#endif
diff --git a/driver/tcpm/anx7688.c b/driver/tcpm/anx7688.c
index a4baad42c3..af585db562 100644
--- a/driver/tcpm/anx7688.c
+++ b/driver/tcpm/anx7688.c
@@ -181,7 +181,11 @@ static bool anx7688_tcpm_check_vbus_level(int port, enum vbus_level level)
* value. See crosbug.com/p/55221 .
*/
i2c_read8(I2C_PORT_TCPC, 0x28, 0x40, &reg);
- return ((reg & 0x10) ? 1 : 0);
+
+ if (level == VBUS_PRESENT)
+ return ((reg & 0x10) ? 1 : 0);
+ else
+ return ((reg & 0x10) ? 0 : 1);
}
#endif
diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c
index 67121cba28..8b783683d4 100644
--- a/driver/tcpm/fusb302.c
+++ b/driver/tcpm/fusb302.c
@@ -911,7 +911,10 @@ static bool fusb302_tcpm_check_vbus_level(int port, enum vbus_level level)
/* Read status register */
tcpc_read(port, TCPC_REG_STATUS0, &reg);
- return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0;
+ if (level == VBUS_PRESENT)
+ return (reg & TCPC_REG_STATUS0_VBUSOK) ? 1 : 0;
+ else
+ return (reg & TCPC_REG_STATUS0_VBUSOK) ? 0 : 1;
}
#endif
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 742f9c0d37..3ec12e9860 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -29,6 +29,13 @@
static int vconn_en[CONFIG_USB_PD_PORT_MAX_COUNT];
static int rx_en[CONFIG_USB_PD_PORT_MAX_COUNT];
#endif
+
+/*
+ * Last reported VBus Level
+ *
+ * BIT(VBUS_SAFE0V) will indicate if in SAFE0V
+ * BIT(VBUS_PRESENT) will indicate if in PRESENT
+ */
static int tcpc_vbus[CONFIG_USB_PD_PORT_MAX_COUNT];
/* Cached RP role values */
@@ -211,6 +218,11 @@ static int init_alert_mask(int port)
| TCPC_REG_ALERT_POWER_STATUS
#endif
;
+
+ /* TCPCI Rev2 includes SAFE0V alerts */
+ if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0)
+ mask |= TCPC_REG_ALERT_EXT_STATUS;
+
/* Set the alert mask in TCPC */
rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
@@ -595,6 +607,12 @@ static int tcpm_alert_ext_status(int port, int *alert_ext)
return tcpc_read(port, TCPC_REG_ALERT_EXT, alert_ext);
}
+static int tcpm_ext_status(int port, int *ext_status)
+{
+ /* Read TCPC Extended Status register */
+ return tcpc_read(port, TCPC_REG_EXT_STATUS, ext_status);
+}
+
int tcpci_tcpm_set_rx_enable(int port, int enable)
{
int detect_sop_en = 0;
@@ -636,7 +654,10 @@ void tcpci_tcpc_fast_role_swap_enable(int port, int enable)
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
bool tcpci_tcpm_check_vbus_level(int port, enum vbus_level level)
{
- return tcpc_vbus[port];
+ if (level == VBUS_SAFE0V)
+ return !!(tcpc_vbus[port] & BIT(VBUS_SAFE0V));
+ else
+ return !!(tcpc_vbus[port] & BIT(VBUS_PRESENT));
}
#endif
@@ -1050,23 +1071,45 @@ void tcpci_tcpc_alert(int port)
pd_event |= PD_EVENT_CC;
}
}
+
+ /* Check for VBus change */
+ if ((tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) &&
+ (alert & TCPC_REG_ALERT_EXT_STATUS)) {
+ int ext_status = 0;
+
+ /* Read Extended Status register */
+ tcpm_ext_status(port, &ext_status);
+ /* Safe0V and not Safe5V */
+ if (ext_status & TCPC_REG_EXT_STATUS_SAFE0V)
+ tcpc_vbus[port] = BIT(VBUS_SAFE0V);
+ }
if (alert & TCPC_REG_ALERT_POWER_STATUS) {
int pwr_status = 0;
/* Read Power Status register */
tcpci_tcpm_get_power_status(port, &pwr_status);
/* Update VBUS status */
- tcpc_vbus[port] = pwr_status &
- TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0;
+ if (pwr_status & TCPC_REG_POWER_STATUS_VBUS_PRES)
+ /* Safe5V and not Safe0V */
+ tcpc_vbus[port] = BIT(VBUS_PRESENT);
+ else if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0)
+ /* not Safe5V */
+ tcpc_vbus[port] &= ~BIT(VBUS_PRESENT);
+ else
+ /* not Safe5V and not Safe0V */
+ tcpc_vbus[port] = BIT(VBUS_SAFE0V);
+
#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
/* Update charge manager with new VBUS state */
- usb_charger_vbus_change(port, tcpc_vbus[port]);
+ usb_charger_vbus_change(port,
+ !!(tcpc_vbus[port] & BIT(VBUS_PRESENT)));
pd_event |= TASK_EVENT_WAKE;
#endif /* CONFIG_USB_PD_VBUS_DETECT_TCPC && CONFIG_USB_CHARGER */
if (pwr_status & TCPC_REG_POWER_STATUS_VBUS_DET)
board_vbus_present_change();
}
+ /* Check for Hard Reset received */
if (alert & TCPC_REG_ALERT_RX_HARD_RST) {
/* hard reset received */
CPRINTS("C%d Hard Reset received", port);
@@ -1231,15 +1274,33 @@ int tcpci_tcpm_init(int port)
tcpc_alert(port);
/* Initialize power_status_mask */
init_power_status_mask(port);
- /* Update VBUS status */
- tcpc_vbus[port] = power_status &
- TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0;
+
+ if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) {
+ int ext_status = 0;
+
+ /* Read Extended Status register */
+ tcpm_ext_status(port, &ext_status);
+ /* Initial level, set appropriately */
+ if (power_status & TCPC_REG_POWER_STATUS_VBUS_PRES)
+ tcpc_vbus[port] = BIT(VBUS_PRESENT);
+ else if (ext_status & TCPC_REG_EXT_STATUS_SAFE0V)
+ tcpc_vbus[port] = BIT(VBUS_SAFE0V);
+ else
+ tcpc_vbus[port] = 0;
+ } else {
+ /* Initial level, set appropriately */
+ tcpc_vbus[port] = (power_status &
+ TCPC_REG_POWER_STATUS_VBUS_PRES)
+ ? BIT(VBUS_PRESENT)
+ : BIT(VBUS_SAFE0V);
+ }
+
#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
/*
* Set Vbus change now in case the TCPC doesn't send a power status
* changed interrupt for it later.
*/
- usb_charger_vbus_change(port, tcpc_vbus[port]);
+ usb_charger_vbus_change(port, !!(tcpc_vbus[port] & BIT(VBUS_PRESENT)));
#endif
error = init_alert_mask(port);
if (error)
@@ -1373,7 +1434,7 @@ static const struct tcpci_reg tcpci_regs[] = {
TCPCI_REG(TCPC_REG_ALERT_MASK, 2),
TCPCI_REG(TCPC_REG_POWER_STATUS_MASK, 1),
TCPCI_REG(TCPC_REG_FAULT_STATUS_MASK, 1),
- TCPCI_REG(TCPC_REG_EXTENDED_STATUS_MASK, 1),
+ TCPCI_REG(TCPC_REG_EXT_STATUS_MASK, 1),
TCPCI_REG(TCPC_REG_ALERT_EXTENDED_MASK, 1),
TCPCI_REG(TCPC_REG_CONFIG_STD_OUTPUT, 1),
TCPCI_REG(TCPC_REG_TCPC_CTRL, 1),
@@ -1383,6 +1444,7 @@ static const struct tcpci_reg tcpci_regs[] = {
TCPCI_REG(TCPC_REG_CC_STATUS, 1),
TCPCI_REG(TCPC_REG_POWER_STATUS, 1),
TCPCI_REG(TCPC_REG_FAULT_STATUS, 1),
+ TCPCI_REG(TCPC_REG_EXT_STATUS, 1),
TCPCI_REG(TCPC_REG_ALERT_EXT, 1),
TCPCI_REG(TCPC_REG_DEV_CAP_1, 2),
TCPCI_REG(TCPC_REG_DEV_CAP_2, 2),
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
index 6a05b1aaca..9c9fa111e9 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -24,6 +24,7 @@
#define TCPC_REG_ALERT_MASK_ALL 0xffff
#define TCPC_REG_ALERT_VENDOR_DEF BIT(15)
#define TCPC_REG_ALERT_ALERT_EXT BIT(14)
+#define TCPC_REG_ALERT_EXT_STATUS BIT(13)
#define TCPC_REG_ALERT_VBUS_DISCNCT BIT(11)
#define TCPC_REG_ALERT_RX_BUF_OVF BIT(10)
#define TCPC_REG_ALERT_FAULT BIT(9)
@@ -43,7 +44,7 @@
#define TCPC_REG_ALERT_MASK 0x12
#define TCPC_REG_POWER_STATUS_MASK 0x14
#define TCPC_REG_FAULT_STATUS_MASK 0x15
-#define TCPC_REG_EXTENDED_STATUS_MASK 0x16
+#define TCPC_REG_EXT_STATUS_MASK 0x16
#define TCPC_REG_ALERT_EXTENDED_MASK 0x17
#define TCPC_REG_CONFIG_STD_OUTPUT 0x18
@@ -122,6 +123,9 @@
#define TCPC_REG_FAULT_STATUS_VCONN_OVER_CURRENT BIT(1)
#define TCPC_REG_FAULT_STATUS_I2C_INTERFACE_ERR BIT(0)
+#define TCPC_REG_EXT_STATUS 0x20
+#define TCPC_REG_EXT_STATUS_SAFE0V BIT(0)
+
#define TCPC_REG_ALERT_EXT 0x21
#define TCPC_REG_ALERT_EXT_TIMER_EXPIRED BIT(2)
#define TCPC_REG_ALERT_EXT_SRC_FRS BIT(1)