1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/* 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,
};
|