diff options
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/ps8740.h | 35 | ||||
-rw-r--r-- | driver/usb_mux_ps8740.c | 114 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/usb_mux.h | 1 |
5 files changed, 154 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 97d80521b3..2331badec3 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -67,6 +67,7 @@ driver-$(CONFIG_USBC_SS_MUX)+=usb_mux.o # USB muxes driver-$(CONFIG_USB_MUX_PI3USB30532)+=usb_mux_pi3usb30532.o +driver-$(CONFIG_USB_MUX_PS8740)+=usb_mux_ps8740.o # Firmware Update driver-$(CONFIG_SB_FIRMWARE_UPDATE)+=battery/sb_fw_update.o diff --git a/driver/ps8740.h b/driver/ps8740.h new file mode 100644 index 0000000000..ec27a7bf50 --- /dev/null +++ b/driver/ps8740.h @@ -0,0 +1,35 @@ +/* Copyright 2015 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. + * + * Parade PS8740 USB port switch driver. + */ + +#ifndef __CROS_EC_PS8740_H +#define __CROS_EC_PS8740_H + +/* Mode register for setting mux */ +#define PS8740_REG_MODE 0x00 +#define PS8740_MODE_POLARITY_INVERTED (1 << 4) +#define PS8740_MODE_USB_ENABLED (1 << 5) +#define PS8740_MODE_DP_ENABLED (1 << 6) +#define PS8740_MODE_POWER_DOWN (1 << 7) + +/* Status register for checking mux state */ +#define PS8740_REG_STATUS 0x09 +#define PS8740_STATUS_POLARITY_INVERTED (1 << 2) +#define PS8740_STATUS_USB_ENABLED (1 << 3) +#define PS8740_STATUS_DP_ENABLED (1 << 4) +#define PS8740_STATUS_HPD_ASSERTED (1 << 7) + +/* Chip ID / revision registers and expected fused values */ +#define PS8740_REG_REVISION_ID1 0xf0 +#define PS8740_REVISION_ID1 0x00 +#define PS8740_REG_REVISION_ID2 0xf1 +#define PS8740_REVISION_ID2 0x0a +#define PS8740_REG_CHIP_ID1 0xf2 +#define PS8740_CHIP_ID1 0x40 +#define PS8740_REG_CHIP_ID2 0xf3 +#define PS8740_CHIP_ID2 0x87 + +#endif /* __CROS_EC_PS8740_H */ diff --git a/driver/usb_mux_ps8740.c b/driver/usb_mux_ps8740.c new file mode 100644 index 0000000000..2023c2dea4 --- /dev/null +++ b/driver/usb_mux_ps8740.c @@ -0,0 +1,114 @@ +/* Copyright 2015 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. + * + * Parade PS8740 USB port switch driver. + */ + +#include "common.h" +#include "i2c.h" +#include "ps8740.h" +#include "usb_mux.h" +#include "util.h" + +static int ps8740_read(int i2c_addr, uint8_t reg, uint8_t *val) +{ + int read, res; + + res = i2c_read8(I2C_PORT_USB_MUX, i2c_addr, reg, &read); + if (res) + return res; + + *val = read; + return EC_SUCCESS; +} + +static int ps8740_write(int i2c_addr, uint8_t reg, uint8_t val) +{ + return i2c_write8(I2C_PORT_USB_MUX, i2c_addr, reg, val); +} + +static int ps8740_reset(int i2c_addr) +{ + return ps8740_write(i2c_addr, PS8740_REG_MODE, PS8740_MODE_POWER_DOWN); +} + +static int ps8740_init(int i2c_addr) +{ + uint8_t val; + int res; + + /* Reset chip back to power-on state */ + res = ps8740_reset(i2c_addr); + if (res) + return res; + + /* Verify revision / chip ID registers */ + res = ps8740_read(i2c_addr, PS8740_REG_REVISION_ID1, &val); + if (res) + return res; + if (val != PS8740_REVISION_ID1) + return EC_ERROR_UNKNOWN; + + res = ps8740_read(i2c_addr, PS8740_REG_REVISION_ID2, &val); + if (res) + return res; + if (val != PS8740_REVISION_ID2) + return EC_ERROR_UNKNOWN; + + res = ps8740_read(i2c_addr, PS8740_REG_CHIP_ID1, &val); + if (res) + return res; + if (val != PS8740_CHIP_ID1) + return EC_ERROR_UNKNOWN; + + res = ps8740_read(i2c_addr, PS8740_REG_CHIP_ID2, &val); + if (res) + return res; + if (val != PS8740_CHIP_ID2) + return EC_ERROR_UNKNOWN; + + return EC_SUCCESS; +} + +/* Writes control register to set switch mode */ +static int ps8740_set_mux(int i2c_addr, mux_state_t mux_state) +{ + uint8_t reg = 0; + + if (mux_state & MUX_USB_ENABLED) + reg |= PS8740_MODE_USB_ENABLED; + if (mux_state & MUX_DP_ENABLED) + reg |= PS8740_MODE_DP_ENABLED; + if (mux_state & MUX_POLARITY_INVERTED) + reg |= PS8740_MODE_POLARITY_INVERTED; + + return ps8740_write(i2c_addr, PS8740_REG_MODE, reg); +} + +/* Reads control register and updates mux_state accordingly */ +static int ps8740_get_mux(int i2c_addr, mux_state_t *mux_state) +{ + uint8_t reg; + int res; + + *mux_state = 0; + res = ps8740_read(i2c_addr, PS8740_REG_STATUS, ®); + if (res) + return res; + + if (reg & PS8740_STATUS_USB_ENABLED) + *mux_state |= MUX_USB_ENABLED; + if (reg & PS8740_STATUS_DP_ENABLED) + *mux_state |= MUX_DP_ENABLED; + if (reg & PS8740_STATUS_POLARITY_INVERTED) + *mux_state |= MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +const struct usb_mux_driver ps8740_usb_mux_driver = { + .init = ps8740_init, + .set = ps8740_set_mux, + .get = ps8740_get_mux, +}; diff --git a/include/config.h b/include/config.h index 76436708ca..2699335996 100644 --- a/include/config.h +++ b/include/config.h @@ -1633,6 +1633,9 @@ /* Support the Pericom PI3USB30532 USB3.0/DP1.2 Matrix Switch */ #undef CONFIG_USB_MUX_PI3USB30532 +/* Support the Parade PS8740 Type-C Redriving Switch */ +#undef CONFIG_USB_MUX_PS8740 + /*****************************************************************************/ /* USB GPIO config */ #undef CONFIG_USB_GPIO diff --git a/include/usb_mux.h b/include/usb_mux.h index d451e9cf1c..d94c0c4606 100644 --- a/include/usb_mux.h +++ b/include/usb_mux.h @@ -69,6 +69,7 @@ struct usb_mux { /* Supported USB mux drivers */ extern const struct usb_mux_driver pi3usb30532_usb_mux_driver; +extern const struct usb_mux_driver ps8740_usb_mux_driver; /* USB muxes present in system, ordered by PD port #, defined at board-level */ extern struct usb_mux usb_muxes[]; |