/* 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; } /* Tune USB Tx/Rx Equalization */ int ps8740_tune_usb_eq(int i2c_addr, uint8_t tx, uint8_t rx) { int ret = 0; ret |= ps8740_write(i2c_addr, PS8740_REG_USB_EQ_TX, tx); ret |= ps8740_write(i2c_addr, PS8740_REG_USB_EQ_RX, rx); return ret; } const struct usb_mux_driver ps8740_usb_mux_driver = { .init = ps8740_init, .set = ps8740_set_mux, .get = ps8740_get_mux, };