summaryrefslogtreecommitdiff
path: root/driver/usb_mux
diff options
context:
space:
mode:
authorDivagar Mohandass <divagar.mohandass@intel.com>2019-12-22 23:50:30 +0530
committerCommit Bot <commit-bot@chromium.org>2019-12-24 11:18:27 +0000
commitd479bc2a0c48760f246bb91d2f231abdf45cfe21 (patch)
tree1e8c3c0e4919a9405d4d409296d6d8f9bde6d29c /driver/usb_mux
parent28001a83d226a86f176bd92b699586d6c0858196 (diff)
downloadchrome-ec-d479bc2a0c48760f246bb91d2f231abdf45cfe21.tar.gz
driver/usb_mux: add ANX7440 USB Type-C mux driver
Add support to Analogix ANX7440 USB Type-C USB mux with integrated Re-timers for USB3.1/DisplayPort BRANCH=none BUG=b:146683781 TEST=make buildall -j verify the mux functionality with reference platform Change-Id: I7847e67025385ca6ea044ee72da143c8e52e65cf Signed-off-by: Divagar Mohandass <divagar.mohandass@intel.com> Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1980089 Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Diffstat (limited to 'driver/usb_mux')
-rw-r--r--driver/usb_mux/anx7440.c106
-rw-r--r--driver/usb_mux/anx7440.h40
2 files changed, 146 insertions, 0 deletions
diff --git a/driver/usb_mux/anx7440.c b/driver/usb_mux/anx7440.c
new file mode 100644
index 0000000000..ec02b8f90b
--- /dev/null
+++ b/driver/usb_mux/anx7440.c
@@ -0,0 +1,106 @@
+/* Copyright 2019 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.
+ *
+ * Analogix ANX7440 USB Type-C Active mux with
+ * Integrated Re-timers for USB3.1/DisplayPort.
+ */
+
+#include "anx7440.h"
+#include "common.h"
+#include "console.h"
+#include "i2c.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 anx7440_read(int port, uint8_t reg, int *val)
+{
+ return i2c_read8(I2C_PORT_USB_MUX, MUX_ADDR(port), reg, val);
+}
+
+static inline int anx7440_write(int port, uint8_t reg, uint8_t val)
+{
+ return i2c_write8(I2C_PORT_USB_MUX, MUX_ADDR(port), reg, val);
+}
+
+struct anx7440_id_t {
+ uint8_t val;
+ uint8_t reg;
+};
+
+static const struct anx7440_id_t anx7440_device_ids[] = {
+ { ANX7440_VENDOR_ID_L, ANX7440_REG_VENDOR_ID_L },
+ { ANX7440_VENDOR_ID_H, ANX7440_REG_VENDOR_ID_H },
+ { ANX7440_DEVICE_ID_L, ANX7440_REG_DEVICE_ID_L },
+ { ANX7440_DEVICE_ID_H, ANX7440_REG_DEVICE_ID_H },
+ { ANX7440_DEVICE_VERSION, ANX7440_REG_DEVICE_VERSION },
+};
+
+static int anx7440_init(int port)
+{
+ int i;
+ int val;
+ int res;
+
+ /* Verify device id / version registers */
+ for (i = 0; i < ARRAY_SIZE(anx7440_device_ids); i++) {
+ res = anx7440_read(port, anx7440_device_ids[i].reg, &val);
+ if (res)
+ return res;
+
+ if (val != anx7440_device_ids[i].val)
+ return EC_ERROR_UNKNOWN;
+ }
+
+ return EC_SUCCESS;
+}
+
+/* Writes control register to set switch mode */
+static int anx7440_set_mux(int port, mux_state_t mux_state)
+{
+ int reg, res;
+
+ res = anx7440_read(port, ANX7440_REG_CHIP_CTRL, &reg);
+ if (res)
+ return res;
+
+ reg &= ~ANX7440_CHIP_CTRL_SW_OP_MODE_CLEAR;
+ if (mux_state & MUX_USB_ENABLED)
+ reg |= ANX7440_CHIP_CTRL_SW_OP_MODE_USB;
+ if (mux_state & MUX_DP_ENABLED)
+ reg |= ANX7440_CHIP_CTRL_SW_OP_MODE_DP;
+ if (mux_state & MUX_POLARITY_INVERTED)
+ reg |= ANX7440_CHIP_CTRL_SW_FLIP;
+
+ return anx7440_write(port, ANX7440_REG_CHIP_CTRL, reg);
+}
+
+/* Reads control register and updates mux_state accordingly */
+static int anx7440_get_mux(int port, mux_state_t *mux_state)
+{
+ int reg, res;
+
+ *mux_state = 0;
+ res = anx7440_read(port, ANX7440_REG_CHIP_CTRL, &reg);
+ if (res)
+ return res;
+
+ if (reg & ANX7440_CHIP_CTRL_OP_MODE_FINAL_USB)
+ *mux_state |= MUX_USB_ENABLED;
+ if (reg & ANX7440_CHIP_CTRL_OP_MODE_FINAL_DP)
+ *mux_state |= MUX_DP_ENABLED;
+ if (reg & ANX7440_CHIP_CTRL_FINAL_FLIP)
+ *mux_state |= MUX_POLARITY_INVERTED;
+
+ return EC_SUCCESS;
+}
+
+const struct usb_mux_driver anx7440_usb_mux_driver = {
+ .init = anx7440_init,
+ .set = anx7440_set_mux,
+ .get = anx7440_get_mux,
+ /* TODO(b/146683781): add low power mode */
+};
diff --git a/driver/usb_mux/anx7440.h b/driver/usb_mux/anx7440.h
new file mode 100644
index 0000000000..2147e3146a
--- /dev/null
+++ b/driver/usb_mux/anx7440.h
@@ -0,0 +1,40 @@
+/* Copyright 2019 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.
+ *
+ * Analogix ANX7440 USB Type-C Active mux with
+ * Integrated Re-timers for USB3.1/DisplayPort.
+ */
+
+#ifndef __CROS_EC_USB_MUX_ANX7440_H
+#define __CROS_EC_USB_MUX_ANX7440_H
+
+/* I2C interface address */
+#define ANX7440_I2C_ADDR1_FLAGS 0x10
+#define ANX7440_I2C_ADDR2_FLAGS 0x12
+#define I2C_ADDR_USB_MUX0_FLAGS ANX7440_I2C_ADDR1_FLAGS
+#define I2C_ADDR_USB_MUX1_FLAGS ANX7440_I2C_ADDR2_FLAGS
+
+/* Vendor / Device Id registers and expected fused values */
+#define ANX7440_REG_VENDOR_ID_L 0x00
+#define ANX7440_VENDOR_ID_L 0xaa
+#define ANX7440_REG_VENDOR_ID_H 0x01
+#define ANX7440_VENDOR_ID_H 0xaa
+#define ANX7440_REG_DEVICE_ID_L 0x02
+#define ANX7440_DEVICE_ID_L 0x40
+#define ANX7440_REG_DEVICE_ID_H 0x03
+#define ANX7440_DEVICE_ID_H 0x74
+#define ANX7440_REG_DEVICE_VERSION 0x04
+#define ANX7440_DEVICE_VERSION 0xCB
+
+/* Chip control register for checking mux state */
+#define ANX7440_REG_CHIP_CTRL 0x05
+#define ANX7440_CHIP_CTRL_FINAL_FLIP BIT(6)
+#define ANX7440_CHIP_CTRL_OP_MODE_FINAL_DP BIT(5)
+#define ANX7440_CHIP_CTRL_OP_MODE_FINAL_USB BIT(4)
+#define ANX7440_CHIP_CTRL_SW_FLIP BIT(2)
+#define ANX7440_CHIP_CTRL_SW_OP_MODE_DP BIT(1)
+#define ANX7440_CHIP_CTRL_SW_OP_MODE_USB BIT(0)
+#define ANX7440_CHIP_CTRL_SW_OP_MODE_CLEAR 0x7
+
+#endif /* __CROS_EC_USB_MUX_ANX7440_H */