/* Copyright 2017 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. * * ITE IT5205 Type-C USB alternate mode mux. */ #include "common.h" #include "console.h" #include "i2c.h" #include "usb_mux.h" #include "usb_mux_it5205.h" #include "util.h" #define MUX_STATE_DP_USB_MASK (MUX_USB_ENABLED | MUX_DP_ENABLED) static int it5205_read(int i2c_addr, uint8_t reg, int *val) { return i2c_read8(I2C_PORT_USB_MUX, i2c_addr, reg, val); } static int it5205_write(int i2c_addr, uint8_t reg, uint8_t val) { return i2c_write8(I2C_PORT_USB_MUX, i2c_addr, reg, val); } struct mux_chip_id_t { uint8_t chip_id; uint8_t reg; }; static const struct mux_chip_id_t mux_chip_id_verify[] = { { '5', IT5205_REG_CHIP_ID3}, { '2', IT5205_REG_CHIP_ID2}, { '0', IT5205_REG_CHIP_ID1}, { '5', IT5205_REG_CHIP_ID0}, }; static int it5205_init(int i2c_addr) { int i, val, ret; /* bit[0]: mux power on, bit[7-1]: reserved. */ ret = it5205_write(i2c_addr, IT5205_REG_MUXPDR, 0); if (ret) return ret; /* Verify chip ID registers. */ for (i = 0; i < ARRAY_SIZE(mux_chip_id_verify); i++) { ret = it5205_read(i2c_addr, mux_chip_id_verify[i].reg, &val); if (ret) return ret; if (val != mux_chip_id_verify[i].chip_id) return EC_ERROR_UNKNOWN; } return EC_SUCCESS; } /* Writes control register to set switch mode */ static int it5205_set_mux(int i2c_addr, mux_state_t mux_state) { uint8_t reg; switch (mux_state & MUX_STATE_DP_USB_MASK) { case MUX_USB_ENABLED: reg = IT5205_USB; break; case MUX_DP_ENABLED: reg = IT5205_DP; break; case MUX_STATE_DP_USB_MASK: reg = IT5205_DP_USB; break; default: reg = 0; break; } if (mux_state & MUX_POLARITY_INVERTED) reg |= IT5205_POLARITY_INVERTED; return it5205_write(i2c_addr, IT5205_REG_MUXCR, reg); } /* Reads control register and updates mux_state accordingly */ static int it5205_get_mux(int i2c_addr, mux_state_t *mux_state) { int reg, ret; ret = it5205_read(i2c_addr, IT5205_REG_MUXCR, ®); if (ret) return ret; switch (reg & IT5205_DP_USB_CTRL_MASK) { case IT5205_USB: *mux_state = MUX_USB_ENABLED; break; case IT5205_DP: *mux_state = MUX_DP_ENABLED; break; case IT5205_DP_USB: *mux_state = MUX_STATE_DP_USB_MASK; break; default: *mux_state = 0; break; } if (reg & IT5205_POLARITY_INVERTED) *mux_state |= MUX_POLARITY_INVERTED; return EC_SUCCESS; } const struct usb_mux_driver it5205_usb_mux_driver = { .init = it5205_init, .set = it5205_set_mux, .get = it5205_get_mux, };