mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-08 00:21:46 +00:00
tcpm: anx74xx: Only connect aux to sbu when DP mode is selected
The anx74xx tcpm driver for the usb_mux_set() function is always connecting the DP aux lines to the SBU signals regardless of whether the bit flag MUX_DP_ENABLED was set or not. For CCD opertation the sbu lines are used to establish a USB connection to H1. This means that if a PD port ever attaches to a sink debug accessory, usb_mux_set would result in interrupting the USB connection being used for CCD. In addition, the anx74xx_tcpm_mux_exit() function had a bug where the value read from ANALOG_CTRL_5 was being masked by 0x09 and then written to ANALOG_CTRL_2. Added functions anx74xx_tcpm_mux_enter_safe_mode() and anx74xx_tcpm_mux_exit_safe_mode() so that writes to the 3 CTRL registers that are used to configure ALT_DP mode can be easily bookended. BUG=b:36007652 BRANCH=reef TEST=Connected servo_v4 to port 0 of electro, verified that H1 console access worked. Then initiated a data role swap so that port 0 on electro was in DFP mode and the H1 console stayed connected. - Tested with dingdong that could connect to a 4k monitor. - Tested with USB3 flash drive. - Tested Anker USBC -> USBA hub Change-Id: I2d045134fbdd21b6b492bbeabc85ab23aef73b9a Signed-off-by: Scott <scollyer@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/451837 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: S Wang <swang@analogix.corp-partner.google.com> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
@@ -41,8 +41,6 @@ struct anx_state {
|
||||
|
||||
static struct anx_state anx[CONFIG_USB_PD_PORT_COUNT];
|
||||
|
||||
static int anx74xx_set_mux(int port, int polarity);
|
||||
|
||||
/* Save the selected rp value */
|
||||
static int selected_rp[CONFIG_USB_PD_PORT_COUNT];
|
||||
|
||||
@@ -151,56 +149,108 @@ static int anx74xx_tcpm_mux_init(int i2c_addr)
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int anx74xx_tcpm_mux_enter_safe_mode(int port)
|
||||
{
|
||||
int reg;
|
||||
|
||||
if (tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
if (tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg |
|
||||
ANX74XX_REG_MODE_TRANS))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int anx74xx_tcpm_mux_exit_safe_mode(int port)
|
||||
{
|
||||
int reg;
|
||||
|
||||
if (tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
if (tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg &
|
||||
~ANX74XX_REG_MODE_TRANS))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int anx74xx_tcpm_mux_exit(int port)
|
||||
{
|
||||
int rv = EC_SUCCESS;
|
||||
int reg = 0x0;
|
||||
int reg;
|
||||
|
||||
rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®);
|
||||
if (rv)
|
||||
/*
|
||||
* Safe mode must be entered before any changes are made to the mux
|
||||
* settings used to enable ALT_DP mode. This funciton is called either
|
||||
* from anx74xx_tcpm_mux_set when TYPEC_MUX_NONE is selected as the new
|
||||
* mux state, or when both cc lines are determined to be
|
||||
* TYPEC_CC_VOLT_OPEN. Therefore, safe mode must be entered and exited
|
||||
* here so that both entry paths are handled.
|
||||
*/
|
||||
if (anx74xx_tcpm_mux_enter_safe_mode(port))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Disconnect aux from sbu */
|
||||
if (tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
if (tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg & 0xf))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg | ANX74XX_REG_MODE_TRANS);
|
||||
|
||||
/* Clear Bit[7:0] R_SWITCH */
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, 0x0);
|
||||
|
||||
if (tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, 0x0))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
/* Clear Bit[7:4] R_SWITCH_H */
|
||||
rv |= tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_5, ®);
|
||||
if (rv)
|
||||
if (tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_5, ®))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, (reg & 0x0f));
|
||||
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg & 0x09);
|
||||
if (rv)
|
||||
if (tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, reg & 0x0f))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
return rv;
|
||||
/* Exit safe mode */
|
||||
if (anx74xx_tcpm_mux_exit_safe_mode(port))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int anx74xx_set_mux(int port, int polarity)
|
||||
static int anx74xx_mux_aux_to_sbu(int port, int polarity, int enabled)
|
||||
{
|
||||
int reg, rv = EC_SUCCESS;
|
||||
int reg;
|
||||
const int aux_mask = ANX74XX_REG_AUX_SWAP_SET_CC2 |
|
||||
ANX74XX_REG_AUX_SWAP_SET_CC1;
|
||||
|
||||
rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®);
|
||||
if (rv)
|
||||
/*
|
||||
* Get the current value of analog_ctrl_2 register. Note, that safe mode
|
||||
* is enabled and exited by the calling function, so only have to worry
|
||||
* about setting the correct value for the upper 4 bits of analog_ctrl_2
|
||||
* here.
|
||||
*/
|
||||
if (tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, ®))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
if (polarity) {
|
||||
reg |= ANX74XX_REG_AUX_SWAP_SET_CC2;
|
||||
reg &= ~ANX74XX_REG_AUX_SWAP_SET_CC1;
|
||||
} else {
|
||||
reg |= ANX74XX_REG_AUX_SWAP_SET_CC1;
|
||||
reg &= ~ANX74XX_REG_AUX_SWAP_SET_CC2;
|
||||
}
|
||||
rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg);
|
||||
|
||||
return rv;
|
||||
/* Assume aux_p/n lines are not connected */
|
||||
reg &= ~aux_mask;
|
||||
|
||||
if (enabled) {
|
||||
/* If enabled, connect aux to sbu based on desired polarity */
|
||||
if (polarity)
|
||||
reg |= ANX74XX_REG_AUX_SWAP_SET_CC2;
|
||||
else
|
||||
reg |= ANX74XX_REG_AUX_SWAP_SET_CC1;
|
||||
}
|
||||
/* Write new aux <-> sbu settings */
|
||||
if (tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int anx74xx_tcpm_mux_set(int i2c_addr, mux_state_t mux_state)
|
||||
{
|
||||
int reg = 0, val = 0;
|
||||
int reg;
|
||||
int pin_cfg = 0;
|
||||
int rv;
|
||||
int port = i2c_addr;
|
||||
|
||||
@@ -217,37 +267,54 @@ static int anx74xx_tcpm_mux_set(int i2c_addr, mux_state_t mux_state)
|
||||
if (mux_state & MUX_USB_ENABLED) {
|
||||
/* Set pin assignment D */
|
||||
if (mux_state & MUX_POLARITY_INVERTED) {
|
||||
val = ANX74XX_REG_MUX_DP_MODE_BDF_CC2;
|
||||
pin_cfg = ANX74XX_REG_MUX_DP_MODE_BDF_CC2;
|
||||
reg |= ANX74XX_REG_MUX_SSTX_B;
|
||||
} else {
|
||||
val = ANX74XX_REG_MUX_DP_MODE_BDF_CC1;
|
||||
pin_cfg = ANX74XX_REG_MUX_DP_MODE_BDF_CC1;
|
||||
reg |= ANX74XX_REG_MUX_SSTX_A;
|
||||
}
|
||||
} else if (mux_state & MUX_DP_ENABLED) {
|
||||
/* Set pin assignment C */
|
||||
if (mux_state & MUX_POLARITY_INVERTED) {
|
||||
val = ANX74XX_REG_MUX_DP_MODE_ACE_CC2;
|
||||
pin_cfg = ANX74XX_REG_MUX_DP_MODE_ACE_CC2;
|
||||
reg |= ANX74XX_REG_MUX_ML2_B;
|
||||
} else {
|
||||
val = ANX74XX_REG_MUX_DP_MODE_ACE_CC1;
|
||||
pin_cfg = ANX74XX_REG_MUX_DP_MODE_ACE_CC1;
|
||||
reg |= ANX74XX_REG_MUX_ML2_A;
|
||||
}
|
||||
/* FIXME: disabling DP mode should disable SBU muxes */
|
||||
rv |= anx74xx_set_mux(port, mux_state & MUX_POLARITY_INVERTED);
|
||||
} else if (!mux_state) {
|
||||
return anx74xx_tcpm_mux_exit(port);
|
||||
} else {
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, val);
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, reg);
|
||||
/*
|
||||
* Safe mode must be entererd prior to any changes to the mux related to
|
||||
* ALT_DP mode. Therefore, first enable safe mode prior to updating the
|
||||
* values for analog_ctrl_1, analog_ctrl_5, and analog_ctrl_2.
|
||||
*/
|
||||
if (anx74xx_tcpm_mux_enter_safe_mode(port))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
anx74xx_set_mux(port, mux_state & MUX_POLARITY_INVERTED ? 1 : 0);
|
||||
/* Write updated pin assignment */
|
||||
rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, pin_cfg);
|
||||
/* Write Rswitch config bits */
|
||||
rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, reg);
|
||||
if (rv)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Configure DP aux to sbu settings */
|
||||
if (anx74xx_mux_aux_to_sbu(port, mux_state & MUX_POLARITY_INVERTED,
|
||||
mux_state & MUX_DP_ENABLED))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Exit safe mode */
|
||||
if (anx74xx_tcpm_mux_exit_safe_mode(port))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
anx[port].mux_state = mux_state;
|
||||
|
||||
return rv;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/* current mux state */
|
||||
|
||||
Reference in New Issue
Block a user