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.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 606b84e31c..939ab9ccf2 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -9,6 +9,7 @@
#include "task.h"
#include "tcpci.h"
#include "timer.h"
+#include "usb_charge.h"
#include "usb_pd.h"
#include "usb_pd_tcpc.h"
#include "usb_pd_tcpm.h"
@@ -17,7 +18,7 @@
/* Convert port number to tcpc i2c address */
#define I2C_ADDR_TCPC(p) (CONFIG_TCPC_I2C_BASE_ADDR + 2*(p))
-static int tcpc_polarity, tcpc_vconn;
+static int tcpc_polarity, tcpc_vconn, tcpc_vbus[CONFIG_USB_PD_PORT_COUNT];
static int init_alert_mask(int port)
{
@@ -30,13 +31,30 @@ static int init_alert_mask(int port)
*/
mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED |
TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS |
- TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS;
+ TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+ | TCPC_REG_ALERT_POWER_STATUS
+#endif
+ ;
/* Set the alert mask in TCPC */
rv = tcpm_alert_mask_set(port, mask);
return rv;
}
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+static int init_power_status_mask(int port)
+{
+ uint8_t mask;
+ int rv;
+
+ mask = TCPC_REG_POWER_VBUS_PRES;
+ rv = tcpm_set_power_status_mask(port, mask);
+
+ return rv;
+}
+#endif
+
int tcpm_init(int port)
{
int rv, err = 0;
@@ -52,6 +70,10 @@ int tcpm_init(int port)
if (rv == EC_SUCCESS && !(err & TCPC_REG_ERROR_STATUS_UNINIT)) {
i2c_write16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
TCPC_REG_ALERT, 0xff);
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+ /* Initialize power_status_mask */
+ init_power_status_mask(port);
+#endif
return init_alert_mask(port);
}
msleep(10);
@@ -85,6 +107,12 @@ int tcpm_get_cc(int port, int *cc1, int *cc2)
return rv;
}
+int tcpm_get_power_status(int port, int *status)
+{
+ return i2c_read8(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
+ TCPC_REG_POWER_STATUS, status);
+}
+
int tcpm_set_cc(int port, int pull)
{
/*
@@ -124,11 +152,9 @@ int tcpm_set_msg_header(int port, int power_role, int data_role)
int tcpm_alert_status(int port, int *alert)
{
- int rv;
/* Read TCPC Alert register */
- rv = i2c_read16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
- TCPC_REG_ALERT, alert);
- return rv;
+ return i2c_read16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
+ TCPC_REG_ALERT, alert);
}
int tcpm_set_rx_enable(int port, int enable)
@@ -139,18 +165,26 @@ int tcpm_set_rx_enable(int port, int enable)
enable ? TCPC_REG_RX_DETECT_SOP_HRST_MASK : 0);
}
-int tcpm_alert_mask_set(int port, uint16_t mask)
+int tcpm_set_power_status_mask(int port, uint8_t mask)
{
- int rv;
/* write to the Alert Mask register */
- rv = i2c_write16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
- TCPC_REG_ALERT_MASK, mask);
+ return i2c_write8(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
+ TCPC_REG_POWER_STATUS_MASK , mask);
+}
- if (rv)
- return rv;
+int tcpm_alert_mask_set(int port, uint16_t mask)
+{
+ /* write to the Alert Mask register */
+ return i2c_write16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port),
+ TCPC_REG_ALERT_MASK, mask);
+}
- return rv;
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+int tcpm_get_vbus_level(int port)
+{
+ return tcpc_vbus[port];
}
+#endif
int tcpm_get_message(int port, uint32_t *payload, int *head)
{
@@ -215,6 +249,7 @@ int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header,
void tcpc_alert(int port)
{
int status;
+ int power_status;
/* Read the Alert register from the TCPC */
tcpm_alert_status(port, &status);
@@ -231,6 +266,18 @@ void tcpc_alert(int port)
/* CC status changed, wake task */
task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
}
+ if (status & TCPC_REG_ALERT_POWER_STATUS) {
+ /* Read Power Status register */
+ tcpm_get_power_status(port, &power_status);
+ /* Update VBUS status */
+ tcpc_vbus[port] = power_status &
+ TCPC_REG_POWER_VBUS_PRES ? 1 : 0;
+#if defined(CONFIG_USB_PD_TCPM_VBUS) && defined(CONFIG_USB_CHARGER)
+ /* Update charge manager with new VBUS state */
+ usb_charger_vbus_change(port, tcpc_vbus[port]);
+#endif /* CONFIG_USB_PD_TCPM_VBUS && CONFIG_USB_CHARGER */
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ }
if (status & TCPC_REG_ALERT_RX_STATUS) {
/* message received */
task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_RX, 0);