1 // SPDX-License-Identifier: GPL-2.0
3 * ITE IT5205 Type-C USB alternate mode passive mux
5 * Copyright (c) 2020 MediaTek Inc.
6 * Copyright (c) 2024 Collabora Ltd.
7 * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
11 #include <linux/delay.h>
12 #include <linux/i2c.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of_platform.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/usb/tcpm.h>
20 #include <linux/usb/typec.h>
21 #include <linux/usb/typec_dp.h>
22 #include <linux/usb/typec_mux.h>
24 #define IT5205_REG_CHIP_ID(x) (0x4 + (x))
25 #define IT5205FN_CHIP_ID 0x35323035 /* "5205" */
27 /* MUX power down register */
28 #define IT5205_REG_MUXPDR 0x10
29 #define IT5205_MUX_POWER_DOWN BIT(0)
31 /* MUX control register */
32 #define IT5205_REG_MUXCR 0x11
33 #define IT5205_POLARITY_INVERTED BIT(4)
34 #define IT5205_DP_USB_CTRL_MASK GENMASK(3, 0)
35 #define IT5205_DP 0x0f
36 #define IT5205_DP_USB 0x03
37 #define IT5205_USB 0x07
39 /* Vref Select Register */
40 #define IT5205_REG_VSR 0x10
41 #define IT5205_VREF_SELECT_MASK GENMASK(5, 4)
42 #define IT5205_VREF_SELECT_3_3V 0x00
43 #define IT5205_VREF_SELECT_OFF 0x20
45 /* CSBU Over Voltage Protection Register */
46 #define IT5205_REG_CSBUOVPSR 0x1e
47 #define IT5205_OVP_SELECT_MASK GENMASK(5, 4)
48 #define IT5205_OVP_3_90V 0x00
49 #define IT5205_OVP_3_68V 0x10
50 #define IT5205_OVP_3_62V 0x20
51 #define IT5205_OVP_3_57V 0x30
53 /* CSBU Switch Register */
54 #define IT5205_REG_CSBUSR 0x22
55 #define IT5205_CSBUSR_SWITCH BIT(0)
57 /* Interrupt Switch Register */
58 #define IT5205_REG_ISR 0x25
59 #define IT5205_ISR_CSBU_MASK BIT(4)
60 #define IT5205_ISR_CSBU_OVP BIT(0)
63 struct i2c_client
*client
;
64 struct regmap
*regmap
;
65 struct typec_switch_dev
*sw
;
66 struct typec_mux_dev
*mux
;
69 static int it5205_switch_set(struct typec_switch_dev
*sw
, enum typec_orientation orientation
)
71 struct it5205
*it
= typec_switch_get_drvdata(sw
);
73 switch (orientation
) {
74 case TYPEC_ORIENTATION_NORMAL
:
75 regmap_update_bits(it
->regmap
, IT5205_REG_MUXCR
,
76 IT5205_POLARITY_INVERTED
, 0);
78 case TYPEC_ORIENTATION_REVERSE
:
79 regmap_update_bits(it
->regmap
, IT5205_REG_MUXCR
,
80 IT5205_POLARITY_INVERTED
, IT5205_POLARITY_INVERTED
);
82 case TYPEC_ORIENTATION_NONE
:
85 regmap_write(it
->regmap
, IT5205_REG_MUXCR
, 0);
92 static int it5205_mux_set(struct typec_mux_dev
*mux
, struct typec_mux_state
*state
)
94 struct it5205
*it
= typec_mux_get_drvdata(mux
);
97 if (state
->mode
>= TYPEC_STATE_MODAL
&&
98 state
->alt
->svid
!= USB_TYPEC_DP_SID
)
101 switch (state
->mode
) {
102 case TYPEC_STATE_USB
:
105 case TYPEC_DP_STATE_C
:
107 case TYPEC_DP_STATE_E
:
110 case TYPEC_DP_STATE_D
:
113 case TYPEC_STATE_SAFE
:
120 return regmap_update_bits(it
->regmap
, IT5205_REG_MUXCR
,
121 IT5205_DP_USB_CTRL_MASK
, val
);
124 static irqreturn_t
it5205_irq_handler(int irq
, void *data
)
126 struct it5205
*it
= data
;
130 ret
= regmap_read(it
->regmap
, IT5205_REG_ISR
, &val
);
134 if (val
& IT5205_ISR_CSBU_OVP
) {
135 dev_warn(&it
->client
->dev
, "Overvoltage detected!\n");
138 regmap_update_bits(it
->regmap
, IT5205_REG_CSBUSR
,
139 IT5205_CSBUSR_SWITCH
, 0);
140 regmap_update_bits(it
->regmap
, IT5205_REG_CSBUSR
,
141 IT5205_CSBUSR_SWITCH
, IT5205_CSBUSR_SWITCH
);
147 static void it5205_enable_ovp(struct it5205
*it
)
149 /* Select Vref 3.3v */
150 regmap_update_bits(it
->regmap
, IT5205_REG_VSR
,
151 IT5205_VREF_SELECT_MASK
, IT5205_VREF_SELECT_3_3V
);
153 /* Trigger OVP at 3.68V */
154 regmap_update_bits(it
->regmap
, IT5205_REG_CSBUOVPSR
,
155 IT5205_OVP_SELECT_MASK
, IT5205_OVP_3_68V
);
157 /* Unmask OVP interrupt */
158 regmap_update_bits(it
->regmap
, IT5205_REG_ISR
,
159 IT5205_ISR_CSBU_MASK
, 0);
161 /* Enable CSBU Interrupt */
162 regmap_update_bits(it
->regmap
, IT5205_REG_CSBUSR
,
163 IT5205_CSBUSR_SWITCH
, IT5205_CSBUSR_SWITCH
);
166 static const struct regmap_config it5205_regmap
= {
167 .max_register
= 0x2f,
172 static int it5205_probe(struct i2c_client
*client
)
174 struct typec_switch_desc sw_desc
= { };
175 struct typec_mux_desc mux_desc
= { };
176 struct device
*dev
= &client
->dev
;
181 it
= devm_kzalloc(dev
, sizeof(*it
), GFP_KERNEL
);
185 ret
= devm_regulator_get_enable(dev
, "vcc");
187 return dev_err_probe(dev
, ret
, "Failed to get regulator\n");
191 it
->regmap
= devm_regmap_init_i2c(client
, &it5205_regmap
);
192 if (IS_ERR(it
->regmap
))
193 return dev_err_probe(dev
, PTR_ERR(it
->regmap
),
194 "Failed to init regmap\n");
196 /* IT5205 needs a long time to power up after enabling regulator */
199 /* Unset poweroff bit */
200 ret
= regmap_write(it
->regmap
, IT5205_REG_MUXPDR
, 0);
202 return dev_err_probe(dev
, ret
, "Failed to set power on\n");
204 /* Read the 32 bits ChipID */
205 for (i
= 3; i
>= 0; i
--) {
206 ret
= regmap_read(it
->regmap
, IT5205_REG_CHIP_ID(i
), &val
);
210 chipid
|= val
<< (i
* 8);
213 if (chipid
!= IT5205FN_CHIP_ID
)
214 return dev_err_probe(dev
, -EINVAL
,
215 "Unknown ChipID 0x%x\n", chipid
);
217 /* Initialize as USB mode with default (non-inverted) polarity */
218 ret
= regmap_write(it
->regmap
, IT5205_REG_MUXCR
, IT5205_USB
);
220 return dev_err_probe(dev
, ret
, "Cannot set mode to USB\n");
222 sw_desc
.drvdata
= it
;
223 sw_desc
.fwnode
= dev_fwnode(dev
);
224 sw_desc
.set
= it5205_switch_set
;
226 it
->sw
= typec_switch_register(dev
, &sw_desc
);
228 return dev_err_probe(dev
, PTR_ERR(it
->sw
),
229 "failed to register typec switch\n");
231 mux_desc
.drvdata
= it
;
232 mux_desc
.fwnode
= dev_fwnode(dev
);
233 mux_desc
.set
= it5205_mux_set
;
235 it
->mux
= typec_mux_register(dev
, &mux_desc
);
236 if (IS_ERR(it
->mux
)) {
237 typec_switch_unregister(it
->sw
);
238 return dev_err_probe(dev
, PTR_ERR(it
->mux
),
239 "failed to register typec mux\n");
242 i2c_set_clientdata(client
, it
);
244 if (of_property_read_bool(dev
->of_node
, "ite,ovp-enable") && client
->irq
) {
245 it5205_enable_ovp(it
);
247 ret
= devm_request_threaded_irq(dev
, client
->irq
, NULL
,
249 IRQF_ONESHOT
, dev_name(dev
), it
);
251 typec_mux_unregister(it
->mux
);
252 typec_switch_unregister(it
->sw
);
253 return dev_err_probe(dev
, ret
, "Failed to request irq\n");
260 static void it5205_remove(struct i2c_client
*client
)
262 struct it5205
*it
= i2c_get_clientdata(client
);
264 typec_mux_unregister(it
->mux
);
265 typec_switch_unregister(it
->sw
);
268 static const struct i2c_device_id it5205_table
[] = {
272 MODULE_DEVICE_TABLE(i2c
, it5205_table
);
274 static const struct of_device_id it5205_of_table
[] = {
275 { .compatible
= "ite,it5205" },
278 MODULE_DEVICE_TABLE(of
, it5205_of_table
);
280 static struct i2c_driver it5205_driver
= {
283 .of_match_table
= it5205_of_table
,
285 .probe
= it5205_probe
,
286 .remove
= it5205_remove
,
287 .id_table
= it5205_table
,
289 module_i2c_driver(it5205_driver
);
291 MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
292 MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
293 MODULE_DESCRIPTION("ITE IT5205 alternate mode passive MUX driver");
294 MODULE_LICENSE("GPL");