summaryrefslogtreecommitdiff
path: root/driver/retimer/ps8802.c
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@chromium.org>2020-01-29 09:30:33 -0700
committerCommit Bot <commit-bot@chromium.org>2020-01-31 19:49:22 +0000
commita0d6b40c49c7615cddded5e6811a550468eba7b2 (patch)
tree366c24995d70676a58aa1668d121016588649889 /driver/retimer/ps8802.c
parentd1824490d69fb45ad00856496e06d8f253778a71 (diff)
downloadchrome-ec-a0d6b40c49c7615cddded5e6811a550468eba7b2.tar.gz
ps8802: 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 display lane control NOTE: PS8802 has reserved register bits that are being used internally, so be cautious just hitting these with 0, i.e. use field update to set a value to retain the old reserved fields BUG=b:146394157 BRANCH=none TEST=verify USB-C1 DP and USB connections Change-Id: I0b539df15fade509058492d6ab73a7b3ca9181df Signed-off-by: Denis Brockus <dbrockus@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2031646 Reviewed-by: Edward Hill <ecgh@chromium.org>
Diffstat (limited to 'driver/retimer/ps8802.c')
-rw-r--r--driver/retimer/ps8802.c145
1 files changed, 134 insertions, 11 deletions
diff --git a/driver/retimer/ps8802.c b/driver/retimer/ps8802.c
index cb8b179bc0..6c7f2b5244 100644
--- a/driver/retimer/ps8802.c
+++ b/driver/retimer/ps8802.c
@@ -13,22 +13,84 @@
#include "timer.h"
#include "usb_mux.h"
+#define PS8802_DEBUG 0
#define PS8802_I2C_WAKE_DELAY 500
-static int ps8802_i2c_read(int port, int offset, int *data)
+int ps8802_i2c_read(int port, int page, int offset, int *data)
{
- return i2c_read8(usb_retimers[port].i2c_port,
- usb_retimers[port].i2c_addr_flags,
- offset, data);
+ int rv;
+
+ rv = i2c_read8(usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset, data);
+
+ if (PS8802_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 rv;
}
-static int ps8802_i2c_write(int port, int offset, int data)
+int ps8802_i2c_write(int port, int page, int offset, int data)
{
+ if (PS8802_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,
+ usb_retimers[port].i2c_addr_flags + page,
offset, data);
}
+int ps8802_i2c_write16(int port, int page, int offset, int data)
+{
+ if (PS8802_DEBUG)
+ ccprintf("%s(%d:0x%02X, 0x%02X, 0x%04X)\n", __func__,
+ usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset, data);
+
+ return i2c_write16(usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset, data);
+}
+
+int ps8802_i2c_field_update8(int port, int page, int offset,
+ uint8_t field_mask, uint8_t set_value)
+{
+ if (PS8802_DEBUG)
+ ccprintf("%s(%d:0x%02X, 0x%02X, 0x%02X, 0x%02X)\n", __func__,
+ usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset, field_mask, set_value);
+
+ return i2c_field_update8(usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset,
+ field_mask,
+ set_value);
+}
+
+int ps8802_i2c_field_update16(int port, int page, int offset,
+ uint16_t field_mask, uint16_t set_value)
+{
+ if (PS8802_DEBUG)
+ ccprintf("%s(%d:0x%02X, 0x%02X, 0x%04X, 0x%04X)\n", __func__,
+ usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset, field_mask, set_value);
+
+ return i2c_field_update16(usb_retimers[port].i2c_port,
+ usb_retimers[port].i2c_addr_flags + page,
+ offset,
+ field_mask,
+ set_value);
+}
+
/*
* If PS8802 is in I2C standby mode, wake it up by reading PS8802_REG_MODE.
* From Application Note: 1) Activate by reading any Page 2 register. 2) Wait
@@ -41,7 +103,10 @@ static int ps8802_i2c_wake(int port)
/* If in standby, first read will fail, second should succeed. */
for (int i = 0; i < 2; i++) {
- rv = ps8802_i2c_read(port, PS8802_REG_MODE, &data);
+ rv = ps8802_i2c_read(port,
+ PS8802_REG_PAGE2,
+ PS8802_REG2_MODE,
+ &data);
if (rv == EC_SUCCESS)
return rv;
@@ -71,25 +136,80 @@ static int ps8802_set_mux(int port, mux_state_t mux_state)
{
int val = (PS8802_MODE_DP_REG_CONTROL
| PS8802_MODE_USB_REG_CONTROL
- | PS8802_MODE_FLIP_REG_CONTROL);
+ | PS8802_MODE_FLIP_REG_CONTROL
+ | PS8802_MODE_IN_HPD_REG_CONTROL);
int rv;
if (chipset_in_state(CHIPSET_STATE_HARD_OFF))
return (mux_state == USB_PD_MUX_NONE) ? EC_SUCCESS
: EC_ERROR_NOT_POWERED;
+ /* Make sure the PS8802 is awake */
rv = ps8802_i2c_wake(port);
if (rv)
return rv;
+ if (PS8802_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 and flip */
if (mux_state & USB_PD_MUX_USB_ENABLED)
val |= PS8802_MODE_USB_ENABLE;
if (mux_state & USB_PD_MUX_DP_ENABLED)
- val |= PS8802_MODE_DP_ENABLE;
+ val |= PS8802_MODE_DP_ENABLE | PS8802_MODE_IN_HPD_ENABLE;
if (mux_state & USB_PD_MUX_POLARITY_INVERTED)
val |= PS8802_MODE_FLIP_ENABLE;
- return ps8802_i2c_write(port, PS8802_REG_MODE, val);
+ rv = ps8802_i2c_write(port,
+ PS8802_REG_PAGE2,
+ PS8802_REG2_MODE,
+ 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 (PS8802_DEBUG) {
+ int tx_status;
+ int rx_status;
+
+ rv = ps8802_i2c_read(port,
+ PS8802_REG_PAGE0,
+ PS8802_REG0_TX_STATUS,
+ &tx_status);
+ if (rv)
+ return rv;
+
+ rv = ps8802_i2c_read(port,
+ PS8802_REG_PAGE0,
+ PS8802_REG0_RX_STATUS,
+ &rx_status);
+ if (rv)
+ return rv;
+
+ ccprintf("%s: tx:channel %snormal %s10Gbps\n",
+ __func__,
+ (tx_status & PS8802_STATUS_NORMAL_OPERATION)
+ ? "" : "NOT-",
+ (tx_status & PS8802_STATUS_10_GBPS) ? "" : "NON-");
+ ccprintf("%s: rx:channel %snormal %s10Gbps\n",
+ __func__,
+ (rx_status & PS8802_STATUS_NORMAL_OPERATION)
+ ? "" : "NOT-",
+ (rx_status & PS8802_STATUS_10_GBPS) ? "" : "NON-");
+ }
+
+ return rv;
}
static int ps8802_get_mux(int port, mux_state_t *mux_state)
@@ -106,7 +226,10 @@ static int ps8802_get_mux(int port, mux_state_t *mux_state)
if (rv)
return rv;
- rv = ps8802_i2c_read(port, PS8802_REG_MODE, &val);
+ rv = ps8802_i2c_read(port,
+ PS8802_REG_PAGE2,
+ PS8802_REG2_MODE,
+ &val);
if (rv)
return rv;