From db8d6edf26ba3f78bbab2bcda7a98e249331b8c1 Mon Sep 17 00:00:00 2001 From: Scott Collyer Date: Wed, 4 Apr 2018 10:38:50 -0700 Subject: ppc: Add tcpci snk/src control via the COMMAND register The ANX7447 has a sink/source control lines which can be connected to a PPC. The NX20P3483 PPC requires this control to set it's sink/source switch control. The ANX7447 contols these lines via the tcpci COMMAND register. This CL adds new tcpm_set functions to set either SNK or SRC control via the COMMAND register. BUG=b:77583452 BRANCH=NONE TEST=Tested on port 0 of Yorp with an external charger. Prior to this CL the PPC would remain in standby state because both snk/src control remained low. With these changes, verifed that snk_ctrl is driven high and vbus_sink_enable() function no longer returns an error. Change-Id: Icbea0d3edb63ad19f3d2c76636208497b6939a72 Signed-off-by: Scott Collyer Reviewed-on: https://chromium-review.googlesource.com/996239 Commit-Ready: Scott Collyer Tested-by: Scott Collyer Reviewed-by: Aseda Aboagye Reviewed-by: Jett Rink --- driver/ppc/nx20p3483.c | 9 +++++++++ driver/tcpm/anx7447.c | 4 ++++ driver/tcpm/tcpci.c | 22 ++++++++++++++++++++++ driver/tcpm/tcpci.h | 8 ++++++++ driver/tcpm/tcpm.h | 19 +++++++++++++++++++ include/usb_pd_tcpm.h | 22 ++++++++++++++++++++++ 6 files changed, 84 insertions(+) diff --git a/driver/ppc/nx20p3483.c b/driver/ppc/nx20p3483.c index b9b355441b..6c89fa76d5 100644 --- a/driver/ppc/nx20p3483.c +++ b/driver/ppc/nx20p3483.c @@ -12,6 +12,7 @@ #include "hooks.h" #include "i2c.h" #include "system.h" +#include "tcpm.h" #include "usb_charge.h" #include "usb_pd_tcpm.h" #include "usbc_ppc.h" @@ -129,6 +130,10 @@ static int nx20p3483_vbus_sink_enable(int port, int enable) /* Set SNK mode based on enable */ gpio_set_level(ppc_chips[port].snk_gpio, enable); + } else { + rv = tcpm_set_snk_ctrl(port, enable); + if (rv) + return rv; } /* Verify switch status register */ @@ -158,6 +163,10 @@ static int nx20p3483_vbus_source_enable(int port, int enable) /* Set SRC mode based on enable */ gpio_set_level(ppc_chips[port].src_gpio, enable); + } else { + rv = tcpm_set_src_ctrl(port, enable); + if (rv) + return rv; } /* Verify switch status register */ diff --git a/driver/tcpm/anx7447.c b/driver/tcpm/anx7447.c index 30266a3b6b..f16a5cba0a 100644 --- a/driver/tcpm/anx7447.c +++ b/driver/tcpm/anx7447.c @@ -381,6 +381,10 @@ const struct tcpm_drv anx7447_tcpm_drv = { .drp_toggle = &tcpci_tcpc_drp_toggle, #endif .get_chip_info = &tcpci_get_chip_info, +#ifdef CONFIG_USBC_PPC + .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl, + .set_src_ctrl = &tcpci_tcpm_set_src_ctrl, +#endif }; #ifdef CONFIG_USB_PD_TCPM_MUX diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 6eaf2cd8cd..60083e312c 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -169,6 +169,24 @@ int tcpci_tcpm_set_polarity(int port, int polarity) TCPC_REG_TCPC_CTRL_SET(polarity)); } +#ifdef CONFIG_USBC_PPC +int tcpci_tcpm_set_snk_ctrl(int port, int enable) +{ + int cmd = enable ? TCPC_REG_COMMAND_SNK_CTRL_HIGH : + TCPC_REG_COMMAND_SNK_CTRL_LOW; + + return tcpc_write(port, TCPC_REG_COMMAND, cmd); +} + +int tcpci_tcpm_set_src_ctrl(int port, int enable) +{ + int cmd = enable ? TCPC_REG_COMMAND_SRC_CTRL_HIGH : + TCPC_REG_COMMAND_SRC_CTRL_LOW; + + return tcpc_write(port, TCPC_REG_COMMAND, cmd); +} +#endif + int tcpci_tcpm_set_vconn(int port, int enable) { int reg, rv; @@ -559,4 +577,8 @@ const struct tcpm_drv tcpci_tcpm_drv = { .drp_toggle = &tcpci_tcpc_drp_toggle, #endif .get_chip_info = &tcpci_get_chip_info, +#ifdef CONFIG_USBC_PPC + .set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl, + .set_src_ctrl = &tcpci_tcpm_set_src_ctrl, +#endif }; diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h index cc6fb3c4d1..c7cefc4ba4 100644 --- a/driver/tcpm/tcpci.h +++ b/driver/tcpm/tcpci.h @@ -81,6 +81,10 @@ #define TCPC_REG_FAULT_STATUS 0x1f #define TCPC_REG_COMMAND 0x23 +#define TCPC_REG_COMMAND_SNK_CTRL_LOW 0x44 +#define TCPC_REG_COMMAND_SNK_CTRL_HIGH 0x55 +#define TCPC_REG_COMMAND_SRC_CTRL_LOW 0x66 +#define TCPC_REG_COMMAND_SRC_CTRL_HIGH 0x77 #define TCPC_REG_COMMAND_LOOK4CONNECTION 0x99 #define TCPC_REG_COMMAND_I2CIDLE 0xFF @@ -148,5 +152,9 @@ 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); int tcpci_get_chip_info(int port, int renew, struct ec_response_pd_chip_info **chip_info); +#ifdef CONFIG_USBC_PPC +int tcpci_tcpm_set_snk_ctrl(int port, int enable); +int tcpci_tcpm_set_src_ctrl(int port, int enable); +#endif #endif /* __CROS_EC_USB_PD_TCPM_TCPCI_H */ diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h index 34f1138c57..32ec76bbfc 100644 --- a/driver/tcpm/tcpm.h +++ b/driver/tcpm/tcpm.h @@ -13,6 +13,7 @@ #include "gpio.h" #include "i2c.h" #include "usb_pd_tcpm.h" +#include "util.h" #if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ !defined(CONFIG_USB_PD_DUAL_ROLE) @@ -142,6 +143,24 @@ static inline int tcpm_transmit(int port, enum tcpm_transmit_type type, return tcpc_config[port].drv->transmit(port, type, header, data); } +#ifdef CONFIG_USBC_PPC +static inline int tcpm_set_snk_ctrl(int port, int enable) +{ + if (tcpc_config[port].drv->set_snk_ctrl != NULL) + return tcpc_config[port].drv->set_snk_ctrl(port, enable); + else + return EC_ERROR_UNIMPLEMENTED; +} + +static inline int tcpm_set_src_ctrl(int port, int enable) +{ + if (tcpc_config[port].drv->set_snk_ctrl != NULL) + return tcpc_config[port].drv->set_src_ctrl(port, enable); + else + return EC_ERROR_UNIMPLEMENTED; +} +#endif + static inline void tcpc_alert(int port) { tcpc_config[port].drv->tcpc_alert(port); diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h index d8ad743caa..1b77e40450 100644 --- a/include/usb_pd_tcpm.h +++ b/include/usb_pd_tcpm.h @@ -220,6 +220,28 @@ struct tcpm_drv { */ int (*get_chip_info)(int port, int renew, struct ec_response_pd_chip_info **info); + +#ifdef CONFIG_USBC_PPC + /** + * Send SinkVBUS or DisableSinkVBUS command + * + * @param port Type-C port number + * @enable true for enable, false for disable + * + * @return EC_SUCCESS or error + */ + int (*set_snk_ctrl)(int port, int enable); + + /** + * Send SourceVBUS or DisableSourceVBUS command + * + * @param port Type-C port number + * @enable true for enable, false for disable + * + * @return EC_SUCCESS or error + */ + int (*set_src_ctrl)(int port, int enable); +#endif }; enum tcpc_alert_polarity { -- cgit v1.2.1