diff options
author | Aseda Aboagye <aaboagye@google.com> | 2020-01-23 19:00:07 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-29 00:57:39 +0000 |
commit | 5f92ac0bde2b6108c4359ea453456d30ef36bdde (patch) | |
tree | 1560209defa8765c334178bc39f9432d0f5151a9 | |
parent | 609366791c55586d051130363cafb0272ceb0800 (diff) | |
download | chrome-ec-5f92ac0bde2b6108c4359ea453456d30ef36bdde.tar.gz |
driver/retimer: Add support for ON Semi NB7V904M
This commit adds support for the ON Semiconductor NB7V904M USB Type-C
Alt Mode Linear Redriver.
BUG=b:147782066
BRANCH=None
TEST=Enable on waddledoo, `make -j BOARD=waddledoo`
Change-Id: Ia6fe76d0ad99bf7a8129e5d453ff12183990a50a
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2018707
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Diana Z <dzigterman@chromium.org>
Commit-Queue: Aseda Aboagye <aaboagye@chromium.org>
Auto-Submit: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/retimer/nb7v904m.c | 143 | ||||
-rw-r--r-- | driver/retimer/nb7v904m.h | 41 | ||||
-rw-r--r-- | include/config.h | 1 |
4 files changed, 186 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 6bd2689e8e..ee2afde542 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -136,6 +136,7 @@ driver-$(CONFIG_USB_PD_TCPM_RAA489000)+=tcpm/raa489000.o # Type-C Retimer drivers driver-$(CONFIG_USBC_RETIMER_INTEL_BB)+=retimer/bb_retimer.o +driver-$(CONFIG_USBC_RETIMER_NB7V904M)+=retimer/nb7v904m.o driver-$(CONFIG_USBC_RETIMER_PI3DPX1207)+=retimer/pi3dpx1207.o driver-$(CONFIG_USBC_RETIMER_PS8802)+=retimer/ps8802.o driver-$(CONFIG_USBC_RETIMER_PS8818)+=retimer/ps8818.o diff --git a/driver/retimer/nb7v904m.c b/driver/retimer/nb7v904m.c new file mode 100644 index 0000000000..81fd5abc93 --- /dev/null +++ b/driver/retimer/nb7v904m.c @@ -0,0 +1,143 @@ +/* Copyright 2020 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. + * + * ON Semiconductor NB7V904M USB Type-C DisplayPort Alt Mode Redriver + */ +#include <stdbool.h> +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "i2c.h" +#include "nb7v904m.h" +#include "usb_mux.h" + +#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) + +static int nb7v904m_write(int port, int offset, int data) +{ + return i2c_write8(usb_retimers[port].i2c_port, + usb_retimers[port].i2c_addr_flags, + offset, data); + +} + +static int nb7v904m_read(int port, int offset, int *regval) +{ + return i2c_read8(usb_retimers[port].i2c_port, + usb_retimers[port].i2c_addr_flags, + offset, regval); + +} + +static int set_low_power_mode(int port, bool enable) +{ + int regval; + int rv; + + rv = nb7v904m_read(port, NB7V904M_REG_GEN_DEV_SETTINGS, ®val); + if (rv) + return rv; + + if (enable) + regval |= NB7V904M_CHIP_EN; + else + regval &= ~NB7V904M_CHIP_EN; + + return nb7v904m_write(port, NB7V904M_REG_GEN_DEV_SETTINGS, regval); +} + +static int nb7v904m_enter_low_power_mode(int port) +{ + int rv = set_low_power_mode(port, 1); + + if (rv) + CPRINTS("C%d: NB7V904M: Failed to enter low power mode!", port); + return rv; +} + +static int nb7v904m_init(int port) +{ + int rv = set_low_power_mode(port, 0); + + if (rv) + CPRINTS("C%d: NB7V904M: init failed!", port); + return rv; +} + +static int nb7v904m_set_mux(int port, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + int regval; + int flipped = !!(mux_state & USB_PD_MUX_POLARITY_INVERTED); + + /* Turn off redriver if it's not needed at all. */ + if (mux_state == USB_PD_MUX_NONE) + return nb7v904m_enter_low_power_mode(port); + + rv = nb7v904m_init(port); + if (rv) + return rv; + + /* Clear operation mode field */ + rv = nb7v904m_read(port, NB7V904M_REG_GEN_DEV_SETTINGS, ®val); + if (rv) { + CPRINTS("C%d %s: Failed to obtain dev settings!", port, + __func__); + return rv; + } + regval &= ~NB7V904M_OP_MODE_MASK; + + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* USB with DP */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + if (flipped) + regval |= NB7V904M_USB_DP_FLIPPED; + else + regval |= NB7V904M_USB_DP_NORMAL; + } else { + /* USB only */ + regval |= NB7V904M_USB_ONLY; + } + + } else if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* 4 lanes DP */ + regval |= NB7V904M_DP_ONLY; + } + + if (mux_state & USB_PD_MUX_DP_ENABLED) { + /* Connect AUX */ + rv = nb7v904m_write(port, NB7V904M_REG_AUX_CH_CTRL, flipped ? + NB7V904M_AUX_CH_FLIPPED : + NB7V904M_AUX_CH_NORMAL); + /* Enable all channels for DP */ + regval |= NB7V904M_CH_EN_MASK; + } else { + /* Disconnect AUX since it's not being used. */ + rv = nb7v904m_write(port, NB7V904M_REG_AUX_CH_CTRL, + NB7V904M_AUX_CH_HI_Z); + + /* Disable the unused channels to save power */ + regval &= ~NB7V904M_CH_EN_MASK; + if (flipped) { + /* Only enable channels A & B */ + regval |= NB7V904M_CH_A_EN | NB7V904M_CH_B_EN; + } else { + /* Only enable channels C & D */ + regval |= NB7V904M_CH_C_EN | NB7V904M_CH_D_EN; + } + } + + rv |= nb7v904m_write(port, NB7V904M_REG_GEN_DEV_SETTINGS, regval); + if (rv) + CPRINTS("C%d: %s failed!", port, __func__); + + return rv; +} + +const struct usb_retimer_driver nb7v904m_usb_redriver_drv = { + .enter_low_power_mode = &nb7v904m_enter_low_power_mode, + .init = &nb7v904m_init, + .set = &nb7v904m_set_mux, +}; diff --git a/driver/retimer/nb7v904m.h b/driver/retimer/nb7v904m.h new file mode 100644 index 0000000000..4306615825 --- /dev/null +++ b/driver/retimer/nb7v904m.h @@ -0,0 +1,41 @@ +/* Copyright 2020 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. + * + * ON Semiconductor NB7V904M USB Type-C DisplayPort Alt Mode Redriver + */ + +#ifndef __CROS_EC_USB_REDRIVER_NB7V904M_H +#define __CROS_EC_USB_REDRIVER_NB7V904M_H + +#include "compile_time_macros.h" +#include "usb_mux.h" + +#define NB7V904M_I2C_ADDR0 0x19 +#define NB7V904M_I2C_ADDR1 0x1A +#define NB7V904M_I2C_ADDR2 0x1C + +/* Registers */ +#define NB7V904M_REG_GEN_DEV_SETTINGS 0x00 +#define NB7V904M_REG_AUX_CH_CTRL 0x09 + +/* 0x00 - General Device Settings */ +#define NB7V904M_CHIP_EN BIT(0) +#define NB7V904M_USB_DP_NORMAL BIT(1) +#define NB7V904M_USB_DP_FLIPPED 0 +#define NB7V904M_DP_ONLY BIT(2) +#define NB7V904M_USB_ONLY (BIT(3) | BIT(1)) +#define NB7V904M_OP_MODE_MASK GENMASK(3, 1) +#define NB7V904M_CH_A_EN BIT(4) +#define NB7V904M_CH_B_EN BIT(5) +#define NB7V904M_CH_C_EN BIT(6) +#define NB7V904M_CH_D_EN BIT(7) +#define NB7V904M_CH_EN_MASK GENMASK(7, 4) + +/* 0x09 - Auxiliary Channel Control */ +#define NB7V904M_AUX_CH_NORMAL 0 +#define NB7V904M_AUX_CH_FLIPPED BIT(0) +#define NB7V904M_AUX_CH_HI_Z BIT(1) + +extern const struct usb_retimer_driver nb7v904m_usb_redriver_drv; +#endif /* __CROS_EC_USB_REDRIVER_NB7V904M_H */ diff --git a/include/config.h b/include/config.h index ae5318d311..7741c807eb 100644 --- a/include/config.h +++ b/include/config.h @@ -3893,6 +3893,7 @@ * Type-C retimer drivers to be used. */ #undef CONFIG_USBC_RETIMER_INTEL_BB +#undef CONFIG_USBC_RETIMER_NB7V904M #undef CONFIG_USBC_RETIMER_PI3DPX1207 #undef CONFIG_USBC_RETIMER_PS8802 #undef CONFIG_USBC_RETIMER_PS8818 |