summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@chromium.org>2019-11-27 11:03:16 -0700
committerCommit Bot <commit-bot@chromium.org>2019-12-05 20:58:28 +0000
commit3dd62a63e18927d6f9c87fef6b5160d3f49d88d7 (patch)
tree416ea77919ba5bd4c1b277c2d92795ca4590c612
parentbf0057e2bff9a68dc9a9f00d660193143d8233c0 (diff)
downloadchrome-ec-3dd62a63e18927d6f9c87fef6b5160d3f49d88d7.tar.gz
tcpci: POWER_CTRL auto discharge disconnect init
Change TCPCI to use HOOK_USB_PD_CONNECT/DISCONNECT to set/clear TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT according to the TCPCI spec. Change the definition of HOOK_USB_PD_CONNECT to occur after CC and VBus are stable. BUG=b:144126745,chromium:951683 BRANCH=none TEST=Charger attach/pull with AP not running Change-Id: I625efbba80f190322e3e92de6318b710b3ce7ade Signed-off-by: Denis Brockus <dbrockus@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1940777
-rw-r--r--common/usb_pd_protocol.c18
-rw-r--r--driver/tcpm/nct38xx.c53
-rw-r--r--driver/tcpm/tcpci.c55
-rw-r--r--driver/tcpm/tcpci.h2
-rw-r--r--include/hooks.h2
-rw-r--r--include/usb_pd_tcpm.h9
6 files changed, 80 insertions, 59 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index d4f6f0c06b..cee2c5ca0f 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -28,7 +28,6 @@
#include "usb_pd_tcpm.h"
#include "usb_pd_tcpc.h"
#include "usbc_ppc.h"
-#include "tcpm.h"
#include "version.h"
#include "vboot.h"
@@ -841,10 +840,10 @@ static inline void set_state(int port, enum pd_states next_state)
/* Invalidate message IDs. */
invalidate_last_message_id(port);
-#ifdef CONFIG_COMMON_RUNTIME
+
/* detect USB PD cc disconnect */
- hook_notify(HOOK_USB_PD_DISCONNECT);
-#endif
+ if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
+ hook_notify(HOOK_USB_PD_DISCONNECT);
}
#ifdef CONFIG_LOW_POWER_IDLE
@@ -3314,9 +3313,6 @@ void pd_task(void *u)
break;
/* Debounce complete */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_CONNECT);
-
#ifdef CONFIG_USBC_PPC
/*
* If the port is latched off, just continue to
@@ -3400,6 +3396,10 @@ void pd_task(void *u)
PD_FLAGS_CHECK_DR_ROLE;
hard_reset_count = 0;
timeout = 5*MSEC;
+
+ if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
+ hook_notify(HOOK_USB_PD_CONNECT);
+
set_state(port, PD_STATE_SRC_STARTUP);
}
/*
@@ -3965,8 +3965,6 @@ void pd_task(void *u)
}
/* We are attached */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_CONNECT);
pd[port].polarity = get_snk_polarity(cc1, cc2);
set_polarity(port, pd[port].polarity);
/* reset message ID on connection */
@@ -4001,6 +3999,8 @@ void pd_task(void *u)
&pd_usb_billboard_deferred_data,
PD_T_AME);
}
+ if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
+ hook_notify(HOOK_USB_PD_CONNECT);
break;
case PD_STATE_SNK_HARD_RESET_RECOVER:
if (pd[port].last_state != pd[port].task_state)
diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c
index 9d91c21b30..8939c52924 100644
--- a/driver/tcpm/nct38xx.c
+++ b/driver/tcpm/nct38xx.c
@@ -105,29 +105,6 @@ static int nct38xx_tcpm_init(int port)
return rv;
}
-static int tcpci_nct38xx_select_rp_value(int port, int rp)
-{
- selected_rp[port] = rp;
- return EC_SUCCESS;
-}
-
-static int auto_discharge_disconnect(int port, int enable)
-{
- int reg, rv;
-
- rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &reg);
- if (rv)
- return rv;
-
- if (enable)
- reg = reg | TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
- else
- reg = reg & ~TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
- rv = tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
- return rv;
-
-}
-
static int tcpci_nct38xx_check_cable_polarity(int port)
{
int cc, rv;
@@ -222,23 +199,9 @@ static int tcpci_nct38xx_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
int tcpci_nct38xx_drp_toggle(int port)
{
- int rv;
-
cable_polarity[port] = POLARITY_NONE;
- /*
- * The port was disconnected so it is probably a good place to set
- * auto-discharge-disconnect to '0'
- *
- * TODO(crbug.com/951683: this should be removed when common code adds
- * auto discharge.
- */
- rv = auto_discharge_disconnect(port, 0);
- if (rv)
- return rv;
-
return tcpci_tcpc_drp_toggle(port);
-
}
int tcpci_nct38xx_set_polarity(int port, int polarity)
@@ -252,16 +215,7 @@ int tcpci_nct38xx_set_polarity(int port, int polarity)
reg = polarity ? (reg | TCPC_REG_TCPC_CTRL_SET(1)) :
(reg & ~TCPC_REG_TCPC_CTRL_SET(1));
- rv = tcpc_write(port, TCPC_REG_TCPC_CTRL, reg);
- if (rv)
- return rv;
-
- /*
- * Polarity is set after connection so it is probably a good time to set
- * auto-discharge-disconnect to '1'
- */
- rv = auto_discharge_disconnect(port, 1);
- return rv;
+ return tcpc_write(port, TCPC_REG_TCPC_CTRL, reg);
}
int tcpci_nct38xx_transmit(int port, enum tcpm_transmit_type type,
@@ -348,6 +302,7 @@ static void nct38xx_tcpc_alert(int port)
nct38xx_ioex_event_handler(port);
}
+
const struct tcpm_drv nct38xx_tcpm_drv = {
.init = &nct38xx_tcpm_init,
.release = &tcpci_tcpm_release,
@@ -355,7 +310,7 @@ const struct tcpm_drv nct38xx_tcpm_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &tcpci_tcpm_get_vbus_level,
#endif
- .select_rp_value = &tcpci_nct38xx_select_rp_value,
+ .select_rp_value = &tcpci_tcpm_select_rp_value,
.set_cc = &tcpci_nct38xx_set_cc,
.set_polarity = &tcpci_nct38xx_set_polarity,
.set_vconn = &tcpci_tcpm_set_vconn,
@@ -367,6 +322,8 @@ const struct tcpm_drv nct38xx_tcpm_drv = {
#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
.tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
#endif
+ .tcpc_connect_state_change =
+ &tcpci_tcpc_connect_state_change,
#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
.drp_toggle = &tcpci_nct38xx_drp_toggle,
#endif
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 9a0e45f1df..74519ef18e 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -10,6 +10,7 @@
#include "compile_time_macros.h"
#include "console.h"
#include "ec_commands.h"
+#include "hooks.h"
#include "ps8xxx.h"
#include "task.h"
#include "tcpci.h"
@@ -241,7 +242,6 @@ int tcpci_tcpm_select_rp_value(int port, int rp)
return EC_SUCCESS;
}
-#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
void tcpci_tcpc_discharge_vbus(int port, int enable)
{
int reg;
@@ -256,7 +256,56 @@ void tcpci_tcpc_discharge_vbus(int port, int enable)
tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
}
-#endif
+
+/*
+ * On a connection state change, it is necessary for TCPCI devices to
+ * set the AUTO_DISCHARGE_DISCONNECT bit appropriately.
+ */
+void tcpci_tcpc_connect_state_change(int port, int connected)
+{
+ int reg, oldreg, rv;
+
+ rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &oldreg);
+ if (rv) {
+ /* CPRINTS("%s: failed read POWER_CTRL", __func__); */
+ return;
+ }
+
+ if (connected)
+ reg = oldreg | TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
+ else
+ reg = oldreg & ~TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
+
+ if (reg != oldreg) {
+ rv = tcpc_write(port, TCPC_REG_POWER_CTRL, reg);
+ if (rv) {
+ /* CPRINTS("%s: failed write POWER_CTRL", __func__); */
+ return;
+ }
+ }
+}
+
+static void connect_state_change(int port, int connected)
+{
+ const struct tcpm_drv *tcpc = tcpc_config[port].drv;
+
+ if (tcpc->tcpc_connect_state_change)
+ tcpc->tcpc_connect_state_change(port, connected);
+}
+static void connect_hook(void)
+{
+ int port = TASK_ID_TO_PD_PORT(task_get_current());
+
+ connect_state_change(port, 1);
+}
+DECLARE_HOOK(HOOK_USB_PD_CONNECT, connect_hook, HOOK_PRIO_DEFAULT);
+static void disconnect_hook(void)
+{
+ int port = TASK_ID_TO_PD_PORT(task_get_current());
+
+ connect_state_change(port, 0);
+}
+DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, disconnect_hook, HOOK_PRIO_DEFAULT);
static int set_role_ctrl(int port, int toggle, int rp, int pull)
{
@@ -1016,6 +1065,8 @@ const struct tcpm_drv tcpci_tcpm_drv = {
#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
.tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus,
#endif
+ .tcpc_connect_state_change =
+ &tcpci_tcpc_connect_state_change,
#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 81baba83bb..46e1d024aa 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -183,6 +183,8 @@ int tcpci_enter_low_power_mode(int port);
void tcpci_tcpc_discharge_vbus(int port, int enable);
#endif
+void tcpci_tcpc_connect_state_change(int port, int connected);
+
int tcpci_tcpm_mux_init(int i2c_addr);
int tcpci_tcpm_mux_set(int i2c_addr, mux_state_t mux_state);
int tcpci_tcpm_mux_get(int i2c_addr, mux_state_t *mux_state);
diff --git a/include/hooks.h b/include/hooks.h
index e30c420fbb..5c699f9555 100644
--- a/include/hooks.h
+++ b/include/hooks.h
@@ -216,6 +216,8 @@ enum hook_type {
/*
* USB PD cc connection event.
+ *
+ * CC lines and VBus are stable when this hook is called.
*/
HOOK_USB_PD_CONNECT,
};
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index ab70c9a7f7..7a7bd0b3a1 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -266,6 +266,15 @@ struct tcpm_drv {
*/
void (*tcpc_discharge_vbus)(int port, int enable);
+ /**
+ * Connection State Change
+ *
+ * @param port Type-C port number
+ * @param connected Connection state
+ */
+ void (*tcpc_connect_state_change)(int port,
+ int connected);
+
#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
/**
* Enable TCPC auto DRP toggling.