diff options
-rw-r--r-- | baseboard/guybrush/baseboard.h | 2 | ||||
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/usb_mux/anx7451.c | 92 | ||||
-rw-r--r-- | driver/usb_mux/anx7451.h | 37 | ||||
-rw-r--r-- | include/config.h | 6 |
5 files changed, 137 insertions, 1 deletions
diff --git a/baseboard/guybrush/baseboard.h b/baseboard/guybrush/baseboard.h index d4999acd88..fc6b43f74a 100644 --- a/baseboard/guybrush/baseboard.h +++ b/baseboard/guybrush/baseboard.h @@ -162,7 +162,7 @@ #define CONFIG_USBC_SS_MUX_DFP_ONLY #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP -#define CONFIG_USB_MUX_ANX7440 +#define CONFIG_USB_MUX_ANX7451 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USBC_PPC_NX20P3483 #define CONFIG_USBC_RETIMER_PS8818 diff --git a/driver/build.mk b/driver/build.mk index fb9525f4dc..6281247fd8 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -168,6 +168,7 @@ driver-$(CONFIG_USBC_SS_MUX)+=usb_mux/usb_mux.o driver-$(CONFIG_USB_MUX_AMD_FP5)+=usb_mux/amd_fp5.o driver-$(CONFIG_USB_MUX_AMD_FP6)+=usb_mux/amd_fp6.o driver-$(CONFIG_USB_MUX_ANX7440)+=usb_mux/anx7440.o +driver-$(CONFIG_USB_MUX_ANX7451)+=usb_mux/anx7451.o driver-$(CONFIG_USB_MUX_IT5205)+=usb_mux/it5205.o driver-$(CONFIG_USB_MUX_PI3USB30532)+=usb_mux/pi3usb3x532.o driver-$(CONFIG_USB_MUX_PI3USB31532)+=usb_mux/pi3usb3x532.o diff --git a/driver/usb_mux/anx7451.c b/driver/usb_mux/anx7451.c new file mode 100644 index 0000000000..8af46f6388 --- /dev/null +++ b/driver/usb_mux/anx7451.c @@ -0,0 +1,92 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * ANX7451: 10G Active Mux (4x4) with + * Integrated Re-timers for USB3.2/DisplayPort + */ + +#include "anx7451.h" +#include "common.h" +#include "console.h" +#include "i2c.h" +#include "time.h" +#include "usb_mux.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) + +static inline int anx7451_read(const struct usb_mux *me, + uint8_t reg, int *val) +{ + return i2c_read8(me->i2c_port, me->i2c_addr_flags, reg, val); +} + +static inline int anx7451_write(const struct usb_mux *me, + uint8_t reg, uint8_t val) +{ + return i2c_write8(me->i2c_port, me->i2c_addr_flags, reg, val); +} + +static int anx7451_set_mux(const struct usb_mux *me, mux_state_t mux_state) +{ + int reg; + + /* ULP_CFG_MODE_EN overrides pin control. Always set it */ + reg = ANX7451_ULP_CFG_MODE_EN; + if (mux_state & USB_PD_MUX_USB_ENABLED) + reg |= ANX7451_ULP_CFG_MODE_USB_EN; + if (mux_state & USB_PD_MUX_DP_ENABLED) + reg |= ANX7451_ULP_CFG_MODE_DP_EN; + if (mux_state & USB_PD_MUX_POLARITY_INVERTED) + reg |= ANX7451_ULP_CFG_MODE_FLIP; + + return anx7451_write(me, ANX7451_REG_ULP_CFG_MODE, reg); +} + +static int anx7451_get_mux(const struct usb_mux *me, mux_state_t *mux_state) +{ + int reg; + + *mux_state = 0; + RETURN_ERROR(anx7451_read(me, ANX7451_REG_ULP_CFG_MODE, ®)); + + if (reg & ANX7451_ULP_CFG_MODE_USB_EN) + *mux_state |= USB_PD_MUX_USB_ENABLED; + if (reg & ANX7451_ULP_CFG_MODE_DP_EN) + *mux_state |= USB_PD_MUX_DP_ENABLED; + if (reg & ANX7451_ULP_CFG_MODE_FLIP) + *mux_state |= USB_PD_MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +static int anx7451_init(const struct usb_mux *me) +{ + uint64_t now; + + /* + * ANX7451 requires 30ms to power on. EC and ANX7451 are on the same + * power rail, so just wait 30ms since EC boot. + */ + now = get_time().val; + if (now < ANX7451_I2C_READY_DELAY_MS*MSEC) + usleep(ANX7451_I2C_READY_DELAY_MS*MSEC - now); + + /* ULTRA_LOW_POWER must always be disabled (Fig 2-2) */ + RETURN_ERROR(anx7451_write(me, ANX7451_REG_ULTRA_LOW_POWER, + ANX7451_ULTRA_LOW_POWER_DIS)); + + /* Start mux in safe mode */ + RETURN_ERROR(anx7451_set_mux(me, USB_PD_MUX_NONE)); + + return EC_SUCCESS; +} + +const struct usb_mux_driver anx7451_usb_mux_driver = { + .init = anx7451_init, + .set = anx7451_set_mux, + .get = anx7451_get_mux + /* Low power mode is not supported on ANX7451 */ +}; diff --git a/driver/usb_mux/anx7451.h b/driver/usb_mux/anx7451.h new file mode 100644 index 0000000000..21e5d66bf9 --- /dev/null +++ b/driver/usb_mux/anx7451.h @@ -0,0 +1,37 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * ANX7451: 10G Active Mux (4x4) with + * Integrated Re-timers for USB3.2/DisplayPort + */ + +#ifndef __CROS_EC_USB_MUX_ANX7451_H +#define __CROS_EC_USB_MUX_ANX7451_H + +#define ANX7451_I2C_READY_DELAY_MS 30 + +/* I2C interface addresses */ +#define ANX7451_I2C_ADDR0_FLAGS 0x10 +#define ANX7451_I2C_ADDR1_FLAGS 0x14 +#define ANX7451_I2C_ADDR2_FLAGS 0x16 +#define ANX7451_I2C_ADDR3_FLAGS 0x11 + +/* + * Ultra low power control register. + * On ANX7451, this register should always be 0 (disabled). + * See figure 2-2 in family programming guide. + */ +#define ANX7451_REG_ULTRA_LOW_POWER 0xE6 +/* #define ANX7451_ULTRA_LOW_POWER_EN 0x06 */ +#define ANX7451_ULTRA_LOW_POWER_DIS 0x00 + +/* Mux control register */ +#define ANX7451_REG_ULP_CFG_MODE 0xF8 +#define ANX7451_ULP_CFG_MODE_EN BIT(4) +#define ANX7451_ULP_CFG_MODE_SWAP BIT(3) +#define ANX7451_ULP_CFG_MODE_FLIP BIT(2) +#define ANX7451_ULP_CFG_MODE_DP_EN BIT(1) +#define ANX7451_ULP_CFG_MODE_USB_EN BIT(0) + +#endif /* __CROS_EC_USB_MUX_ANX7451_H */ diff --git a/include/config.h b/include/config.h index eb1b178a25..4b7a0bedbd 100644 --- a/include/config.h +++ b/include/config.h @@ -4756,6 +4756,12 @@ */ #undef CONFIG_USB_MUX_ANX7440 +/* + * Support the Analogix ANX7451 10G Active Mux (4x4) with + * Integrated Re-timers for USB3.2/DisplayPort + */ +#undef CONFIG_USB_MUX_ANX7451 + /* Support the ITE IT5205 Type-C USB alternate mode mux. */ #undef CONFIG_USB_MUX_IT5205 |