summaryrefslogtreecommitdiff
path: root/driver/usb_mux
diff options
context:
space:
mode:
authorRob Barnes <robbarnes@google.com>2021-02-16 19:29:19 -0700
committerCommit Bot <commit-bot@chromium.org>2021-02-23 16:51:14 +0000
commit1039ba163b0d3287f08736e0f8b87805db6f21f1 (patch)
tree4488773491cfbc0582e83ee7d397eae34b7e8c79 /driver/usb_mux
parent136b94b135c584c63673a1f3806ddd9ea5dbf8ac (diff)
downloadchrome-ec-1039ba163b0d3287f08736e0f8b87805db6f21f1.tar.gz
guybrush: Add ANX7451 mux/retimer driver
Add basic support for ANX7451. Datasheets available in bug. Support for tuning can be added later if needed. BUG=b:179065240 BRANCH=None TEST=Build Change-Id: Ifafdec4412b73b0fd3f7de2131a8617bbfde6426 Signed-off-by: Rob Barnes <robbarnes@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2699667 Reviewed-by: Diana Z <dzigterman@chromium.org>
Diffstat (limited to 'driver/usb_mux')
-rw-r--r--driver/usb_mux/anx7451.c92
-rw-r--r--driver/usb_mux/anx7451.h37
2 files changed, 129 insertions, 0 deletions
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, &reg));
+
+ 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 */