diff options
author | Aseda Aboagye <aaboagye@google.com> | 2018-01-22 17:46:05 +0800 |
---|---|---|
committer | Daisuke Nojiri <dnojiri@chromium.org> | 2018-02-02 15:37:25 -0800 |
commit | 60c7a51108eeceac39cf9f4e6ffcfe49a8508c37 (patch) | |
tree | 6b7dcca593e3dad6b9030b5a73307281866161cf | |
parent | 9a156dc286f71aad3e7fd25d550f3e476bfce103 (diff) | |
download | chrome-ec-60c7a51108eeceac39cf9f4e6ffcfe49a8508c37.tar.gz |
ppc: Add Vconn and CC polarity settings.
BUG=b:72292985
BRANCH=None
TEST=Flash meowth; Verify with twinkie that Vconn is provided for a sink
that requires it.
Change-Id: I8168d2e4c46e04810dcf5c2898b2c337424eefec
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/888224
Commit-Ready: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Edward Hill <ecgh@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r-- | common/usb_pd_protocol.c | 39 | ||||
-rw-r--r-- | common/usbc_ppc.c | 16 | ||||
-rw-r--r-- | driver/ppc/sn5s330.c | 36 | ||||
-rw-r--r-- | driver/ppc/sn5s330.h | 3 | ||||
-rw-r--r-- | include/usbc_ppc.h | 34 |
5 files changed, 120 insertions, 8 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 78578aaf9f..c7a7bbe6e9 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -317,6 +317,29 @@ static inline int pd_is_vbus_present(int port) } #endif +static void set_polarity(int port, int polarity) +{ + tcpm_set_polarity(port, polarity); +#ifdef CONFIG_USBC_PPC + ppc_set_polarity(port, polarity); +#endif /* defined(CONFIG_USBC_PPC) */ +} + +#ifdef CONFIG_USBC_VCONN +static void set_vconn(int port, int enable) +{ +#ifdef CONFIG_USBC_PPC + /* + * USB-C PPCs can source their own Vconn. No need to tell the TCPC + * to source its own. + */ + ppc_set_vconn(port, enable); +#else /* !defined(CONFIG_USBC_PPC) */ + tcpm_set_vconn(port, enable); +#endif /* defined(CONFIG_USBC_PPC) */ +} +#endif /* defined(CONFIG_USBC_VCONN) */ + static inline void set_state(int port, enum pd_states next_state) { enum pd_states last_state = pd[port].task_state; @@ -355,8 +378,8 @@ static inline void set_state(int port, enum pd_states next_state) CHARGE_CEIL_NONE); #endif #ifdef CONFIG_USBC_VCONN - tcpm_set_vconn(port, 0); -#endif + set_vconn(port, 0); +#endif /* defined(CONFIG_USBC_VCONN) */ #else /* CONFIG_USB_PD_DUAL_ROLE */ if (next_state == PD_STATE_SRC_DISCONNECTED) { #endif @@ -2180,7 +2203,7 @@ void pd_task(void *u) #endif (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE && pd[port].task_state == PD_STATE_SRC_READY))) { - tcpm_set_polarity(port, pd[port].polarity); + set_polarity(port, pd[port].polarity); tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role); tcpm_set_rx_enable(port, 1); @@ -2311,7 +2334,7 @@ void pd_task(void *u) if (new_cc_state == PD_CC_UFP_ATTACHED || new_cc_state == PD_CC_DEBUG_ACC) { pd[port].polarity = (cc1 != TYPEC_CC_VOLT_RD); - tcpm_set_polarity(port, pd[port].polarity); + set_polarity(port, pd[port].polarity); /* initial data role for source is DFP */ pd_set_data_role(port, PD_ROLE_DFP); @@ -2336,7 +2359,7 @@ void pd_task(void *u) tcpm_set_rx_enable(port, 1); #ifdef CONFIG_USBC_VCONN - tcpm_set_vconn(port, 1); + set_vconn(port, 1); pd[port].flags |= PD_FLAGS_VCONN_ON; #endif @@ -2794,7 +2817,7 @@ void pd_task(void *u) /* We are attached */ pd[port].polarity = get_snk_polarity(cc1, cc2); - tcpm_set_polarity(port, pd[port].polarity); + set_polarity(port, pd[port].polarity); /* reset message ID on connection */ pd[port].msg_id = 0; /* initial data role for sink is UFP */ @@ -3128,7 +3151,7 @@ void pd_task(void *u) if (pd[port].last_state != pd[port].task_state) { if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { /* Turn VCONN on and wait for it */ - tcpm_set_vconn(port, 1); + set_vconn(port, 1); set_state_timeout(port, get_time().val + PD_VCONN_SWAP_DELAY, PD_STATE_VCONN_SWAP_READY); @@ -3160,7 +3183,7 @@ void pd_task(void *u) READY_RETURN_STATE(port)); } else { /* Turn VCONN off and wait for it */ - tcpm_set_vconn(port, 0); + set_vconn(port, 0); pd[port].flags &= ~PD_FLAGS_VCONN_ON; set_state_timeout(port, get_time().val + PD_VCONN_SWAP_DELAY, diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c index 4cea6813bc..6ff79a17bf 100644 --- a/common/usbc_ppc.c +++ b/common/usbc_ppc.c @@ -42,6 +42,14 @@ int ppc_is_sourcing_vbus(int port) return ppc_chips[port].drv->is_sourcing_vbus(port); } +int ppc_set_polarity(int port, int polarity) +{ + if ((port < 0) || (port >= ppc_cnt)) + return EC_ERROR_INVAL; + + return ppc_chips[port].drv->set_polarity(port, polarity); +} + int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) { if ((port < 0) || (port >= ppc_cnt)) @@ -58,6 +66,14 @@ int ppc_discharge_vbus(int port, int enable) return ppc_chips[port].drv->discharge_vbus(port, enable); } +int ppc_set_vconn(int port, int enable) +{ + if ((port < 0) || (port >= ppc_cnt)) + return EC_ERROR_INVAL; + + return ppc_chips[port].drv->set_vconn(port, enable); +} + int ppc_vbus_sink_enable(int port, int enable) { if ((port < 0) || (port >= ppc_cnt)) diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c index bdc9d3af7d..90f90528ef 100644 --- a/driver/ppc/sn5s330.c +++ b/driver/ppc/sn5s330.c @@ -455,6 +455,23 @@ static int sn5s330_is_sourcing_vbus(int port) return is_sourcing_vbus; } +static int sn5s330_set_polarity(int port, int polarity) +{ + int regval; + int status; + + status = read_reg(port, SN5S330_FUNC_SET4, ®val); + if (status) + return status; + + if (polarity) + regval |= SN5S330_CC_POLARITY; /* CC2 active. */ + else + regval &= ~SN5S330_CC_POLARITY; /* CC1 active. */ + + return write_reg(port, SN5S330_FUNC_SET4, regval); +} + static int sn5s330_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) { @@ -515,6 +532,23 @@ static int sn5s330_discharge_vbus(int port, int enable) return EC_SUCCESS; } +static int sn5s330_set_vconn(int port, int enable) +{ + int regval; + int status; + + status = read_reg(port, SN5S330_FUNC_SET4, ®val); + if (status) + return status; + + if (enable) + regval |= SN5S330_VCONN_EN; + else + regval &= ~SN5S330_VCONN_EN; + + return write_reg(port, SN5S330_FUNC_SET4, regval); +} + static int sn5s330_vbus_sink_enable(int port, int enable) { return sn5s330_pp_fet_enable(port, SN5S330_PP2, !!enable); @@ -588,6 +622,8 @@ const struct ppc_drv sn5s330_drv = { #ifdef CONFIG_USB_PD_VBUS_DETECT_PPC .is_vbus_present = &sn5s330_is_vbus_present, #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ + .set_polarity = &sn5s330_set_polarity, .set_vbus_source_current_limit = &sn5s330_set_vbus_source_current_limit, .discharge_vbus = &sn5s330_discharge_vbus, + .set_vconn = &sn5s330_set_vconn, }; diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h index e8850faf57..2e4b36cbca 100644 --- a/driver/ppc/sn5s330.h +++ b/driver/ppc/sn5s330.h @@ -95,6 +95,9 @@ enum sn5s330_pp_idx { #define SN5S330_SET_RCP_MODE_PP1 (1 << 5) #define SN5S330_SET_RCP_MODE_PP2 (1 << 6) +/* FUNC_SET_4 */ +#define SN5S330_VCONN_EN (1 << 0) +#define SN5S330_CC_POLARITY (1 << 1) #define SN5S330_CC_EN (1 << 4) /* FUNC_SET_9 */ diff --git a/include/usbc_ppc.h b/include/usbc_ppc.h index eec8362959..54142b2921 100644 --- a/include/usbc_ppc.h +++ b/include/usbc_ppc.h @@ -49,6 +49,15 @@ struct ppc_drv { int (*vbus_source_enable)(int port, int enable); /** + * Inform the PPC of the polarity of the CC pins. + * + * @param port: The Type-C port number. + * @param polarity: 1: CC2 used for comms, 0: CC1 used for comms. + * @return EC_SUCCESS on success, error otherwise. + */ + int (*set_polarity)(int port, int polarity); + + /** * Set the Vbus source path current limit * * @param port: The Type-C port number. @@ -66,6 +75,14 @@ struct ppc_drv { */ int (*discharge_vbus)(int port, int enable); + /** + * Turn on/off the VCONN FET. + * + * @param port: The Type-C port number. + * @param enable: 1: enable VCONN FET 0: disable VCONN FET. + */ + int (*set_vconn)(int port, int enable); + #ifdef CONFIG_CMD_PPC_DUMP /** * Perform a register dump of the PPC. @@ -121,6 +138,15 @@ int ppc_is_vbus_present(int port); int ppc_is_sourcing_vbus(int port); /** + * Inform the PPC of the polarity of the CC pins. + * + * @param port: The Type-C port number. + * @param polarity: 1: CC2 used for comms, 0: CC1 used for comms. + * @return EC_SUCCESS on success, error otherwise. + */ +int ppc_set_polarity(int port, int polarity); + +/** * Set the Vbus source path current limit * * @param port: The Type-C port number. @@ -130,6 +156,14 @@ int ppc_is_sourcing_vbus(int port); int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp); /** + * Turn on/off the VCONN FET. + * + * @param port: The Type-C port number. + * @param enable: 1: enable VCONN FET 0: disable VCONN FET. + */ +int ppc_set_vconn(int port, int enable); + +/** * Discharge PD VBUS on src/sink disconnect & power role swap * * @param port: The Type-C port number. |