diff options
author | Denis Brockus <dbrockus@chromium.org> | 2020-01-29 09:33:08 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-31 14:48:08 +0000 |
commit | b56a56eaba32f4d7d06750ffb3aed3f6e69b0d42 (patch) | |
tree | b5c790ebdb658e057a9d05b49d6e05d467fd4637 | |
parent | e600975e068dc2b2706eac2a11eb2d62564c1b4a (diff) | |
download | chrome-ec-b56a56eaba32f4d7d06750ffb3aed3f6e69b0d42.tar.gz |
ps8818: fix redriver configuration
in driver
Added software IN_HPD control
Added compile time optional debug
in board specific tune function in usb_retimer
Added gain control
Added DP lane control
BUG=b:146394157
BRANCH=none
TEST=verify USB-C1 DP and USB connections
Change-Id: Ida0cc243413b8fa469d3edb706040535e4a3f0e0
Signed-off-by: Denis Brockus <dbrockus@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2031645
Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r-- | baseboard/zork/baseboard.c | 97 | ||||
-rw-r--r-- | driver/retimer/ps8818.c | 99 | ||||
-rw-r--r-- | driver/retimer/ps8818.h | 4 | ||||
-rw-r--r-- | include/usb_mux.h | 9 |
4 files changed, 200 insertions, 9 deletions
diff --git a/baseboard/zork/baseboard.c b/baseboard/zork/baseboard.c index 3dcbd96560..ef55d12138 100644 --- a/baseboard/zork/baseboard.c +++ b/baseboard/zork/baseboard.c @@ -467,6 +467,102 @@ void bc12_interrupt(enum gpio_signal signal) */ /* + * PS8818 set mux tuning. + * Adds in board specific gain and DP lane count configuration + */ +static int ps8818_tune_mux(int port, mux_state_t mux_state) +{ + int rv = EC_SUCCESS; + + /* USB specific config */ + if (mux_state & USB_PD_MUX_USB_ENABLED) { + /* Boost the USB gain */ + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_APTX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_APTX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_CRX1EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_CRX2EQ_10G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_CRX1EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_CRX2EQ_5G_LEVEL, + PS8818_EQ_LEVEL_UP_21DB); + if (rv) + return rv; + } + + /* DP specific config */ + if (mux_state & USB_PD_MUX_DP_ENABLED) { + int val; + + /* Boost the DP gain */ + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE1, + PS8818_REG1_DPEQ_LEVEL, + PS8818_DPEQ_LEVEL_UP_21DB); + if (rv) + return rv; + + /* Set DP lane count */ + val = (mux_state & USB_PD_MUX_USB_ENABLED) + ? PS8818_LANE_COUNT_SET_2_LANE + : PS8818_LANE_COUNT_SET_4_LANE; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE2, + PS8818_REG2_LANE_COUNT_SET, + val); + if (rv) + return rv; + } + + return rv; +} + +/* * FP5 is a true MUX but being used as a secondary MUX. Don't want to * send FLIP or this will cause a double flip */ @@ -532,6 +628,7 @@ static int zork_c1_detect(int port, int err_if_power_off) /* Main MUX is FP5, secondary MUX is PS8818 */ usb_muxes[USBC_PORT_C1].driver = &amd_fp5_usb_mux_driver; usb_retimers[USBC_PORT_C1].driver = &ps8818_usb_retimer; + usb_retimers[USBC_PORT_C1].tune = &ps8818_tune_mux; return rv; } diff --git a/driver/retimer/ps8818.c b/driver/retimer/ps8818.c index d9c89ef7e4..6059f7f0d4 100644 --- a/driver/retimer/ps8818.c +++ b/driver/retimer/ps8818.c @@ -14,15 +14,33 @@ #include "ps8818.h" #include "usb_mux.h" -static int ps8818_i2c_read(int port, int page, int offset, int *data) +#define PS8818_DEBUG 0 + +int ps8818_i2c_read(int port, int page, int offset, int *data) { - return i2c_read8(usb_retimers[port].i2c_port, + int rv; + + rv = i2c_read8(usb_retimers[port].i2c_port, + usb_retimers[port].i2c_addr_flags + page, + offset, data); + + if (PS8818_DEBUG) + ccprintf("%s(%d:0x%02X, 0x%02X) => 0x%02X\n", __func__, + usb_retimers[port].i2c_port, usb_retimers[port].i2c_addr_flags + page, - offset, data); + offset, *data); + + return rv; } -static int ps8818_i2c_write(int port, int page, int offset, int data) +int ps8818_i2c_write(int port, int page, int offset, int data) { + if (PS8818_DEBUG) + ccprintf("%s(%d:0x%02X, 0x%02X, 0x%02X)\n", __func__, + usb_retimers[port].i2c_port, + usb_retimers[port].i2c_addr_flags + page, + offset, data); + return i2c_write8(usb_retimers[port].i2c_port, usb_retimers[port].i2c_addr_flags + page, offset, data); @@ -50,8 +68,17 @@ static int ps8818_set_mux(int port, mux_state_t mux_state) if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) return (mux_state == USB_PD_MUX_NONE) ? EC_SUCCESS - : EC_ERROR_NOT_POWERED; + : EC_ERROR_NOT_POWERED; + + if (PS8818_DEBUG) + ccprintf("%s(%d, 0x%02X) %s %s %s\n", + __func__, port, mux_state, + (mux_state & USB_PD_MUX_USB_ENABLED) ? "USB" : "", + (mux_state & USB_PD_MUX_DP_ENABLED) ? "DP" : "", + (mux_state & USB_PD_MUX_POLARITY_INVERTED) + ? "FLIP" : ""); + /* Set the mode */ if (mux_state & USB_PD_MUX_USB_ENABLED) val |= PS8818_MODE_USB_ENABLE; if (mux_state & USB_PD_MUX_DP_ENABLED) @@ -64,14 +91,68 @@ static int ps8818_set_mux(int port, mux_state_t mux_state) if (rv) return rv; + /* Set the flip */ val = 0; if (mux_state & USB_PD_MUX_POLARITY_INVERTED) val |= PS8818_FLIP_CONFIG; - return ps8818_i2c_write(port, - PS8818_REG_PAGE0, - PS8818_REG0_FLIP, - val); + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE0, + PS8818_REG0_FLIP, + val); + if (rv) + return rv; + + /* Set the IN_HPD */ + val = PS8818_DPHPD_CONFIG_INHPD_DISABLE; + if (mux_state & USB_PD_MUX_DP_ENABLED) + val |= PS8818_DPHPD_PLUGGED; + + rv = ps8818_i2c_write(port, + PS8818_REG_PAGE0, + PS8818_REG0_DPHPD_CONFIG, + val); + if (rv) + return rv; + + /* Board specific retimer mux tuning */ + if (usb_retimers[port].tune) { + rv = usb_retimers[port].tune(port, mux_state); + if (rv) + return rv; + } + + if (PS8818_DEBUG) { + int tx_status; + int rx_status; + + rv = ps8818_i2c_read(port, + PS8818_REG_PAGE2, + PS8818_REG2_TX_STATUS, + &tx_status); + if (rv) + return rv; + + rv = ps8818_i2c_read(port, + PS8818_REG_PAGE2, + PS8818_REG2_RX_STATUS, + &rx_status); + if (rv) + return rv; + + ccprintf("%s: tx:channel %snormal %s10Gbps\n", + __func__, + (tx_status & PS8818_STATUS_NORMAL_OPERATION) + ? "" : "NOT-", + (tx_status & PS8818_STATUS_10_GBPS) ? "" : "NON-"); + ccprintf("%s: rx:channel %snormal %s10Gbps\n", + __func__, + (rx_status & PS8818_STATUS_NORMAL_OPERATION) + ? "" : "NOT-", + (rx_status & PS8818_STATUS_10_GBPS) ? "" : "NON-"); + } + + return rv; } const struct usb_retimer_driver ps8818_usb_retimer = { diff --git a/driver/retimer/ps8818.h b/driver/retimer/ps8818.h index a42605229e..0b5c3dfe83 100644 --- a/driver/retimer/ps8818.h +++ b/driver/retimer/ps8818.h @@ -24,6 +24,7 @@ #define PS8818_REG0_DPHPD_CONFIG 0x02 #define PS8818_DPHPD_CONFIG_INHPD_DISABLE BIT(7) +#define PS8818_DPHPD_PLUGGED BIT(6) /* * PAGE 1 Register Definitions @@ -93,4 +94,7 @@ extern const struct usb_retimer_driver ps8818_usb_retimer; int ps8818_detect(int port); +int ps8818_i2c_read(int port, int page, int offset, int *data); +int ps8818_i2c_write(int port, int page, int offset, int data); + #endif /* __CROS_EC_USB_RETIMER_PS8818_H */ diff --git a/include/usb_mux.h b/include/usb_mux.h index 152b240fa0..35350222f0 100644 --- a/include/usb_mux.h +++ b/include/usb_mux.h @@ -174,6 +174,15 @@ struct usb_retimer { /* Driver interfaces for this retimer */ const struct usb_retimer_driver *driver; + + /* + * USB retimer board specific tune on set mux_state. + * + * @param port usb port of retimer (not port_addr) + * @param mux_state State to set retimer mode to. + * @return EC_SUCCESS on success, non-zero error code on failure. + */ + int (*tune)(int port, mux_state_t mux_state); }; /* |