1*a2c81616SWang Jie // SPDX-License-Identifier: GPL-2.0+
2*a2c81616SWang Jie /*
3*a2c81616SWang Jie * Copyright 2015-2017 Google, Inc
4*a2c81616SWang Jie *
5*a2c81616SWang Jie * USB Type-C Port Controller Interface.
6*a2c81616SWang Jie */
7*a2c81616SWang Jie
8*a2c81616SWang Jie #include <dm.h>
9*a2c81616SWang Jie #include <i2c.h>
10*a2c81616SWang Jie #include <asm/gpio.h>
11*a2c81616SWang Jie #include <power/power_delivery/pd.h>
12*a2c81616SWang Jie #include <power/power_delivery/tcpm.h>
13*a2c81616SWang Jie #include <power/power_delivery/typec.h>
14*a2c81616SWang Jie #include <power/power_delivery/power_delivery.h>
15*a2c81616SWang Jie
16*a2c81616SWang Jie #include "tcpci.h"
17*a2c81616SWang Jie
18*a2c81616SWang Jie #define PD_RETRY_COUNT 3
19*a2c81616SWang Jie
20*a2c81616SWang Jie #define tcpc_presenting_cc1_rd(reg) \
21*a2c81616SWang Jie (!(TCPC_ROLE_CTRL_DRP & (reg)) && \
22*a2c81616SWang Jie (((reg) & (TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT)) == \
23*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT)))
24*a2c81616SWang Jie #define tcpc_presenting_cc2_rd(reg) \
25*a2c81616SWang Jie (!(TCPC_ROLE_CTRL_DRP & (reg)) && \
26*a2c81616SWang Jie (((reg) & (TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT)) == \
27*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT)))
28*a2c81616SWang Jie
29*a2c81616SWang Jie struct tcpci {
30*a2c81616SWang Jie struct udevice *dev;
31*a2c81616SWang Jie
32*a2c81616SWang Jie struct tcpm_port *port;
33*a2c81616SWang Jie
34*a2c81616SWang Jie bool controls_vbus;
35*a2c81616SWang Jie bool gpio_cc_int_present;
36*a2c81616SWang Jie
37*a2c81616SWang Jie struct tcpc_dev tcpc;
38*a2c81616SWang Jie struct tcpci_data *data;
39*a2c81616SWang Jie struct gpio_desc gpio_cc_int;
40*a2c81616SWang Jie };
41*a2c81616SWang Jie
42*a2c81616SWang Jie struct tcpci_chip {
43*a2c81616SWang Jie struct udevice *udev;
44*a2c81616SWang Jie struct tcpci *tcpci;
45*a2c81616SWang Jie struct tcpci_data data;
46*a2c81616SWang Jie };
47*a2c81616SWang Jie
tcpc_to_tcpci(struct tcpc_dev * tcpc)48*a2c81616SWang Jie static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
49*a2c81616SWang Jie {
50*a2c81616SWang Jie return container_of(tcpc, struct tcpci, tcpc);
51*a2c81616SWang Jie }
52*a2c81616SWang Jie
tcpci_read16(struct tcpci * tcpci,unsigned int reg,u16 * val)53*a2c81616SWang Jie static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, u16 *val)
54*a2c81616SWang Jie {
55*a2c81616SWang Jie int ret = 0;
56*a2c81616SWang Jie u8 buffer[2];
57*a2c81616SWang Jie
58*a2c81616SWang Jie ret = dm_i2c_read(tcpci->dev, reg, buffer, 2);
59*a2c81616SWang Jie if (ret) {
60*a2c81616SWang Jie printf("%s: cannot read %02x, ret=%d\n",
61*a2c81616SWang Jie __func__, reg, ret);
62*a2c81616SWang Jie return ret;
63*a2c81616SWang Jie }
64*a2c81616SWang Jie
65*a2c81616SWang Jie *val = ((buffer[1] << 8) & 0xFF00) | (buffer[0] & 0xFF);
66*a2c81616SWang Jie
67*a2c81616SWang Jie return ret;
68*a2c81616SWang Jie }
69*a2c81616SWang Jie
tcpci_block_read(struct tcpci * tcpci,unsigned int reg,u8 * data,u8 length)70*a2c81616SWang Jie static int tcpci_block_read(struct tcpci *tcpci, unsigned int reg,
71*a2c81616SWang Jie u8 *data, u8 length)
72*a2c81616SWang Jie {
73*a2c81616SWang Jie int ret = 0;
74*a2c81616SWang Jie
75*a2c81616SWang Jie ret = dm_i2c_read(tcpci->dev, reg, data, length);
76*a2c81616SWang Jie if (ret)
77*a2c81616SWang Jie printf("%s: cannot block read 0x%02x, len=%d, ret=%d\n",
78*a2c81616SWang Jie __func__, reg, length, ret);
79*a2c81616SWang Jie
80*a2c81616SWang Jie return ret;
81*a2c81616SWang Jie }
82*a2c81616SWang Jie
tcpci_write16(struct tcpci * tcpci,unsigned int reg,u16 val)83*a2c81616SWang Jie static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
84*a2c81616SWang Jie {
85*a2c81616SWang Jie int ret = 0;
86*a2c81616SWang Jie u8 buffer[2];
87*a2c81616SWang Jie
88*a2c81616SWang Jie buffer[0] = val & 0xFF;
89*a2c81616SWang Jie buffer[1] = (val >> 8) & 0xFF;
90*a2c81616SWang Jie ret = dm_i2c_write(tcpci->dev, reg, buffer, 2);
91*a2c81616SWang Jie if (ret)
92*a2c81616SWang Jie printf("%s: cannot write 0x%02x, ret=%d\n",
93*a2c81616SWang Jie __func__, reg, ret);
94*a2c81616SWang Jie
95*a2c81616SWang Jie return ret;
96*a2c81616SWang Jie }
97*a2c81616SWang Jie
tcpci_block_write(struct tcpci * tcpci,unsigned int reg,u8 * data,u8 length)98*a2c81616SWang Jie static int tcpci_block_write(struct tcpci *tcpci, unsigned int reg,
99*a2c81616SWang Jie u8 *data, u8 length)
100*a2c81616SWang Jie {
101*a2c81616SWang Jie int ret = 0;
102*a2c81616SWang Jie
103*a2c81616SWang Jie ret = dm_i2c_write(tcpci->dev, reg, data, length);
104*a2c81616SWang Jie if (ret)
105*a2c81616SWang Jie printf("%s: cannot block write 0x%02x, len=%d, ret=%d\n",
106*a2c81616SWang Jie __func__, reg, length, ret);
107*a2c81616SWang Jie
108*a2c81616SWang Jie return ret;
109*a2c81616SWang Jie }
110*a2c81616SWang Jie
tcpci_set_cc(struct tcpc_dev * tcpc,enum typec_cc_status cc)111*a2c81616SWang Jie static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
112*a2c81616SWang Jie {
113*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
114*a2c81616SWang Jie unsigned int reg;
115*a2c81616SWang Jie int ret;
116*a2c81616SWang Jie
117*a2c81616SWang Jie switch (cc) {
118*a2c81616SWang Jie case TYPEC_CC_RA:
119*a2c81616SWang Jie reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
120*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC2_SHIFT);
121*a2c81616SWang Jie break;
122*a2c81616SWang Jie case TYPEC_CC_RD:
123*a2c81616SWang Jie reg = (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
124*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
125*a2c81616SWang Jie break;
126*a2c81616SWang Jie case TYPEC_CC_RP_DEF:
127*a2c81616SWang Jie reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
128*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
129*a2c81616SWang Jie (TCPC_ROLE_CTRL_RP_VAL_DEF <<
130*a2c81616SWang Jie TCPC_ROLE_CTRL_RP_VAL_SHIFT);
131*a2c81616SWang Jie break;
132*a2c81616SWang Jie case TYPEC_CC_RP_1_5:
133*a2c81616SWang Jie reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
134*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
135*a2c81616SWang Jie (TCPC_ROLE_CTRL_RP_VAL_1_5 <<
136*a2c81616SWang Jie TCPC_ROLE_CTRL_RP_VAL_SHIFT);
137*a2c81616SWang Jie break;
138*a2c81616SWang Jie case TYPEC_CC_RP_3_0:
139*a2c81616SWang Jie reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
140*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
141*a2c81616SWang Jie (TCPC_ROLE_CTRL_RP_VAL_3_0 <<
142*a2c81616SWang Jie TCPC_ROLE_CTRL_RP_VAL_SHIFT);
143*a2c81616SWang Jie break;
144*a2c81616SWang Jie case TYPEC_CC_OPEN:
145*a2c81616SWang Jie default:
146*a2c81616SWang Jie reg = (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT) |
147*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
148*a2c81616SWang Jie break;
149*a2c81616SWang Jie }
150*a2c81616SWang Jie
151*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_ROLE_CTRL, reg);
152*a2c81616SWang Jie if (ret)
153*a2c81616SWang Jie return ret;
154*a2c81616SWang Jie
155*a2c81616SWang Jie return 0;
156*a2c81616SWang Jie }
157*a2c81616SWang Jie
tcpci_start_toggling(struct tcpc_dev * tcpc,enum typec_port_type port_type,enum typec_cc_status cc)158*a2c81616SWang Jie static int tcpci_start_toggling(struct tcpc_dev *tcpc,
159*a2c81616SWang Jie enum typec_port_type port_type,
160*a2c81616SWang Jie enum typec_cc_status cc)
161*a2c81616SWang Jie {
162*a2c81616SWang Jie int ret;
163*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
164*a2c81616SWang Jie unsigned int reg = TCPC_ROLE_CTRL_DRP;
165*a2c81616SWang Jie
166*a2c81616SWang Jie if (port_type != TYPEC_PORT_DRP)
167*a2c81616SWang Jie return -EOPNOTSUPP;
168*a2c81616SWang Jie
169*a2c81616SWang Jie /* Handle vendor drp toggling */
170*a2c81616SWang Jie if (tcpci->data->start_drp_toggling) {
171*a2c81616SWang Jie ret = tcpci->data->start_drp_toggling(tcpci, tcpci->data, cc);
172*a2c81616SWang Jie if (ret < 0)
173*a2c81616SWang Jie return ret;
174*a2c81616SWang Jie }
175*a2c81616SWang Jie
176*a2c81616SWang Jie switch (cc) {
177*a2c81616SWang Jie default:
178*a2c81616SWang Jie case TYPEC_CC_RP_DEF:
179*a2c81616SWang Jie reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF <<
180*a2c81616SWang Jie TCPC_ROLE_CTRL_RP_VAL_SHIFT);
181*a2c81616SWang Jie break;
182*a2c81616SWang Jie case TYPEC_CC_RP_1_5:
183*a2c81616SWang Jie reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 <<
184*a2c81616SWang Jie TCPC_ROLE_CTRL_RP_VAL_SHIFT);
185*a2c81616SWang Jie break;
186*a2c81616SWang Jie case TYPEC_CC_RP_3_0:
187*a2c81616SWang Jie reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 <<
188*a2c81616SWang Jie TCPC_ROLE_CTRL_RP_VAL_SHIFT);
189*a2c81616SWang Jie break;
190*a2c81616SWang Jie }
191*a2c81616SWang Jie
192*a2c81616SWang Jie if (cc == TYPEC_CC_RD)
193*a2c81616SWang Jie reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
194*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
195*a2c81616SWang Jie else
196*a2c81616SWang Jie reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
197*a2c81616SWang Jie (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT);
198*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_ROLE_CTRL, reg);
199*a2c81616SWang Jie if (ret < 0)
200*a2c81616SWang Jie return ret;
201*a2c81616SWang Jie return dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
202*a2c81616SWang Jie TCPC_CMD_LOOK4CONNECTION);
203*a2c81616SWang Jie }
204*a2c81616SWang Jie
tcpci_to_typec_cc(unsigned int cc,bool sink)205*a2c81616SWang Jie static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink)
206*a2c81616SWang Jie {
207*a2c81616SWang Jie switch (cc) {
208*a2c81616SWang Jie case 0x1:
209*a2c81616SWang Jie return sink ? TYPEC_CC_RP_DEF : TYPEC_CC_RA;
210*a2c81616SWang Jie case 0x2:
211*a2c81616SWang Jie return sink ? TYPEC_CC_RP_1_5 : TYPEC_CC_RD;
212*a2c81616SWang Jie case 0x3:
213*a2c81616SWang Jie if (sink)
214*a2c81616SWang Jie return TYPEC_CC_RP_3_0;
215*a2c81616SWang Jie /* fall through */
216*a2c81616SWang Jie case 0x0:
217*a2c81616SWang Jie default:
218*a2c81616SWang Jie return TYPEC_CC_OPEN;
219*a2c81616SWang Jie }
220*a2c81616SWang Jie }
221*a2c81616SWang Jie
tcpci_get_cc(struct tcpc_dev * tcpc,enum typec_cc_status * cc1,enum typec_cc_status * cc2)222*a2c81616SWang Jie static int tcpci_get_cc(struct tcpc_dev *tcpc,
223*a2c81616SWang Jie enum typec_cc_status *cc1, enum typec_cc_status *cc2)
224*a2c81616SWang Jie {
225*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
226*a2c81616SWang Jie unsigned int reg, role_control;
227*a2c81616SWang Jie
228*a2c81616SWang Jie role_control = dm_i2c_reg_read(tcpci->dev, TCPC_ROLE_CTRL);
229*a2c81616SWang Jie if (role_control < 0)
230*a2c81616SWang Jie return role_control;
231*a2c81616SWang Jie
232*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_CC_STATUS);
233*a2c81616SWang Jie if (reg < 0)
234*a2c81616SWang Jie return reg;
235*a2c81616SWang Jie
236*a2c81616SWang Jie *cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) &
237*a2c81616SWang Jie TCPC_CC_STATUS_CC1_MASK,
238*a2c81616SWang Jie reg & TCPC_CC_STATUS_TERM ||
239*a2c81616SWang Jie tcpc_presenting_cc1_rd(role_control));
240*a2c81616SWang Jie *cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) &
241*a2c81616SWang Jie TCPC_CC_STATUS_CC2_MASK,
242*a2c81616SWang Jie reg & TCPC_CC_STATUS_TERM ||
243*a2c81616SWang Jie tcpc_presenting_cc2_rd(role_control));
244*a2c81616SWang Jie
245*a2c81616SWang Jie return 0;
246*a2c81616SWang Jie }
247*a2c81616SWang Jie
tcpci_set_polarity(struct tcpc_dev * tcpc,enum typec_cc_polarity polarity)248*a2c81616SWang Jie static int tcpci_set_polarity(struct tcpc_dev *tcpc,
249*a2c81616SWang Jie enum typec_cc_polarity polarity)
250*a2c81616SWang Jie {
251*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
252*a2c81616SWang Jie unsigned int reg;
253*a2c81616SWang Jie int ret;
254*a2c81616SWang Jie enum typec_cc_status cc1, cc2;
255*a2c81616SWang Jie
256*a2c81616SWang Jie /* Obtain Rp setting from role control */
257*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_ROLE_CTRL);
258*a2c81616SWang Jie if (reg < 0)
259*a2c81616SWang Jie return reg;
260*a2c81616SWang Jie
261*a2c81616SWang Jie ret = tcpci_get_cc(tcpc, &cc1, &cc2);
262*a2c81616SWang Jie if (ret < 0)
263*a2c81616SWang Jie return ret;
264*a2c81616SWang Jie
265*a2c81616SWang Jie /*
266*a2c81616SWang Jie * When port has drp toggling enabled, ROLE_CONTROL would only have the initial
267*a2c81616SWang Jie * terminations for the toggling and does not indicate the final cc
268*a2c81616SWang Jie * terminations when ConnectionResult is 0 i.e. drp toggling stops and
269*a2c81616SWang Jie * the connection is resolbed. Infer port role from TCPC_CC_STATUS based on the
270*a2c81616SWang Jie * terminations seen. The port role is then used to set the cc terminations.
271*a2c81616SWang Jie */
272*a2c81616SWang Jie if (reg & TCPC_ROLE_CTRL_DRP) {
273*a2c81616SWang Jie /* Disable DRP for the OPEN setting to take effect */
274*a2c81616SWang Jie reg = reg & ~TCPC_ROLE_CTRL_DRP;
275*a2c81616SWang Jie
276*a2c81616SWang Jie if (polarity == TYPEC_POLARITY_CC2) {
277*a2c81616SWang Jie reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
278*a2c81616SWang Jie /* Local port is source */
279*a2c81616SWang Jie if (cc2 == TYPEC_CC_RD)
280*a2c81616SWang Jie /* Role control would have the Rp setting when DRP was enabled */
281*a2c81616SWang Jie reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT;
282*a2c81616SWang Jie else
283*a2c81616SWang Jie reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT;
284*a2c81616SWang Jie } else {
285*a2c81616SWang Jie reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
286*a2c81616SWang Jie /* Local port is source */
287*a2c81616SWang Jie if (cc1 == TYPEC_CC_RD)
288*a2c81616SWang Jie /* Role control would have the Rp setting when DRP was enabled */
289*a2c81616SWang Jie reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT;
290*a2c81616SWang Jie else
291*a2c81616SWang Jie reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT;
292*a2c81616SWang Jie }
293*a2c81616SWang Jie }
294*a2c81616SWang Jie
295*a2c81616SWang Jie if (polarity == TYPEC_POLARITY_CC2)
296*a2c81616SWang Jie reg |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT;
297*a2c81616SWang Jie else
298*a2c81616SWang Jie reg |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT;
299*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_ROLE_CTRL, reg);
300*a2c81616SWang Jie if (ret < 0)
301*a2c81616SWang Jie return ret;
302*a2c81616SWang Jie
303*a2c81616SWang Jie return dm_i2c_reg_write(tcpci->dev, TCPC_TCPC_CTRL,
304*a2c81616SWang Jie (polarity == TYPEC_POLARITY_CC2) ?
305*a2c81616SWang Jie TCPC_TCPC_CTRL_ORIENTATION : 0);
306*a2c81616SWang Jie }
307*a2c81616SWang Jie
tcpci_set_vconn(struct tcpc_dev * tcpc,bool enable)308*a2c81616SWang Jie static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
309*a2c81616SWang Jie {
310*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
311*a2c81616SWang Jie int ret;
312*a2c81616SWang Jie unsigned int reg;
313*a2c81616SWang Jie
314*a2c81616SWang Jie /* Handle vendor set vconn */
315*a2c81616SWang Jie if (tcpci->data->set_vconn) {
316*a2c81616SWang Jie ret = tcpci->data->set_vconn(tcpci, tcpci->data, enable);
317*a2c81616SWang Jie if (ret < 0)
318*a2c81616SWang Jie return ret;
319*a2c81616SWang Jie }
320*a2c81616SWang Jie
321*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_CTRL);
322*a2c81616SWang Jie if (reg)
323*a2c81616SWang Jie return reg;
324*a2c81616SWang Jie reg &= ~TCPC_POWER_CTRL_VCONN_ENABLE;
325*a2c81616SWang Jie reg |= enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0;
326*a2c81616SWang Jie return dm_i2c_reg_write(tcpci->dev, TCPC_POWER_CTRL, reg);
327*a2c81616SWang Jie }
328*a2c81616SWang Jie
tcpci_set_roles(struct tcpc_dev * tcpc,bool attached,enum typec_role role,enum typec_data_role data)329*a2c81616SWang Jie static int tcpci_set_roles(struct tcpc_dev *tcpc, bool attached,
330*a2c81616SWang Jie enum typec_role role, enum typec_data_role data)
331*a2c81616SWang Jie {
332*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
333*a2c81616SWang Jie unsigned int reg;
334*a2c81616SWang Jie int ret;
335*a2c81616SWang Jie
336*a2c81616SWang Jie reg = PD_REV20 << TCPC_MSG_HDR_INFO_REV_SHIFT;
337*a2c81616SWang Jie if (role == TYPEC_SOURCE)
338*a2c81616SWang Jie reg |= TCPC_MSG_HDR_INFO_PWR_ROLE;
339*a2c81616SWang Jie if (data == TYPEC_HOST)
340*a2c81616SWang Jie reg |= TCPC_MSG_HDR_INFO_DATA_ROLE;
341*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_MSG_HDR_INFO, reg);
342*a2c81616SWang Jie if (ret < 0)
343*a2c81616SWang Jie return ret;
344*a2c81616SWang Jie
345*a2c81616SWang Jie return 0;
346*a2c81616SWang Jie }
347*a2c81616SWang Jie
tcpci_set_pd_rx(struct tcpc_dev * tcpc,bool enable)348*a2c81616SWang Jie static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable)
349*a2c81616SWang Jie {
350*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
351*a2c81616SWang Jie unsigned int reg = 0;
352*a2c81616SWang Jie int ret;
353*a2c81616SWang Jie
354*a2c81616SWang Jie if (enable)
355*a2c81616SWang Jie reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET;
356*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_RX_DETECT, reg);
357*a2c81616SWang Jie if (ret < 0)
358*a2c81616SWang Jie return ret;
359*a2c81616SWang Jie
360*a2c81616SWang Jie return 0;
361*a2c81616SWang Jie }
362*a2c81616SWang Jie
tcpci_get_vbus(struct tcpc_dev * tcpc)363*a2c81616SWang Jie static int tcpci_get_vbus(struct tcpc_dev *tcpc)
364*a2c81616SWang Jie {
365*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
366*a2c81616SWang Jie unsigned int reg;
367*a2c81616SWang Jie
368*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_STATUS);
369*a2c81616SWang Jie if (reg < 0)
370*a2c81616SWang Jie return reg;
371*a2c81616SWang Jie
372*a2c81616SWang Jie return !!(reg & TCPC_POWER_STATUS_VBUS_PRES);
373*a2c81616SWang Jie }
374*a2c81616SWang Jie
tcpci_set_vbus(struct tcpc_dev * tcpc,bool source,bool sink)375*a2c81616SWang Jie static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
376*a2c81616SWang Jie {
377*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
378*a2c81616SWang Jie int ret;
379*a2c81616SWang Jie
380*a2c81616SWang Jie /* Disable both source and sink first before enabling anything */
381*a2c81616SWang Jie
382*a2c81616SWang Jie if (!source) {
383*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
384*a2c81616SWang Jie TCPC_CMD_DISABLE_SRC_VBUS);
385*a2c81616SWang Jie if (ret < 0)
386*a2c81616SWang Jie return ret;
387*a2c81616SWang Jie }
388*a2c81616SWang Jie
389*a2c81616SWang Jie if (!sink) {
390*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
391*a2c81616SWang Jie TCPC_CMD_DISABLE_SINK_VBUS);
392*a2c81616SWang Jie if (ret < 0)
393*a2c81616SWang Jie return ret;
394*a2c81616SWang Jie }
395*a2c81616SWang Jie
396*a2c81616SWang Jie if (source) {
397*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
398*a2c81616SWang Jie TCPC_CMD_SRC_VBUS_DEFAULT);
399*a2c81616SWang Jie if (ret < 0)
400*a2c81616SWang Jie return ret;
401*a2c81616SWang Jie }
402*a2c81616SWang Jie
403*a2c81616SWang Jie if (sink) {
404*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
405*a2c81616SWang Jie TCPC_CMD_SINK_VBUS);
406*a2c81616SWang Jie if (ret < 0)
407*a2c81616SWang Jie return ret;
408*a2c81616SWang Jie }
409*a2c81616SWang Jie
410*a2c81616SWang Jie return 0;
411*a2c81616SWang Jie }
412*a2c81616SWang Jie
tcpci_pd_transmit(struct tcpc_dev * tcpc,enum tcpm_transmit_type type,const struct pd_message * msg,unsigned int negotiated_rev)413*a2c81616SWang Jie static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
414*a2c81616SWang Jie enum tcpm_transmit_type type,
415*a2c81616SWang Jie const struct pd_message *msg,
416*a2c81616SWang Jie unsigned int negotiated_rev)
417*a2c81616SWang Jie {
418*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
419*a2c81616SWang Jie u16 header = msg ? le16_to_cpu(msg->header) : 0;
420*a2c81616SWang Jie unsigned int reg, cnt;
421*a2c81616SWang Jie int ret;
422*a2c81616SWang Jie
423*a2c81616SWang Jie cnt = msg ? pd_header_cnt(header) * 4 : 0;
424*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_TX_BYTE_CNT, cnt + 2);
425*a2c81616SWang Jie if (ret < 0)
426*a2c81616SWang Jie return ret;
427*a2c81616SWang Jie
428*a2c81616SWang Jie ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
429*a2c81616SWang Jie if (ret < 0)
430*a2c81616SWang Jie return ret;
431*a2c81616SWang Jie
432*a2c81616SWang Jie if (cnt > 0) {
433*a2c81616SWang Jie ret = tcpci_block_write(tcpci, TCPC_TX_DATA,
434*a2c81616SWang Jie (u8 *)&msg->payload, cnt);
435*a2c81616SWang Jie if (ret < 0)
436*a2c81616SWang Jie return ret;
437*a2c81616SWang Jie }
438*a2c81616SWang Jie
439*a2c81616SWang Jie reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
440*a2c81616SWang Jie (type << TCPC_TRANSMIT_TYPE_SHIFT);
441*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_TRANSMIT, reg);
442*a2c81616SWang Jie if (ret < 0)
443*a2c81616SWang Jie return ret;
444*a2c81616SWang Jie
445*a2c81616SWang Jie return 0;
446*a2c81616SWang Jie }
447*a2c81616SWang Jie
tcpci_init(struct tcpc_dev * tcpc)448*a2c81616SWang Jie static int tcpci_init(struct tcpc_dev *tcpc)
449*a2c81616SWang Jie {
450*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
451*a2c81616SWang Jie unsigned int timeout = 0; /* XXX */
452*a2c81616SWang Jie unsigned int reg;
453*a2c81616SWang Jie int ret;
454*a2c81616SWang Jie
455*a2c81616SWang Jie while (timeout < 100) {
456*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_STATUS);
457*a2c81616SWang Jie if (reg < 0)
458*a2c81616SWang Jie return reg;
459*a2c81616SWang Jie if (!(reg & TCPC_POWER_STATUS_UNINIT))
460*a2c81616SWang Jie break;
461*a2c81616SWang Jie timeout++;
462*a2c81616SWang Jie udelay(200);
463*a2c81616SWang Jie }
464*a2c81616SWang Jie if (timeout >= 100)
465*a2c81616SWang Jie return -ETIMEDOUT;
466*a2c81616SWang Jie
467*a2c81616SWang Jie /* Handle vendor init */
468*a2c81616SWang Jie if (tcpci->data->init) {
469*a2c81616SWang Jie ret = tcpci->data->init(tcpci, tcpci->data);
470*a2c81616SWang Jie if (ret < 0)
471*a2c81616SWang Jie return ret;
472*a2c81616SWang Jie }
473*a2c81616SWang Jie
474*a2c81616SWang Jie /* Clear all events */
475*a2c81616SWang Jie ret = tcpci_write16(tcpci, TCPC_ALERT, 0xffff);
476*a2c81616SWang Jie if (ret < 0)
477*a2c81616SWang Jie return ret;
478*a2c81616SWang Jie
479*a2c81616SWang Jie if (tcpci->controls_vbus)
480*a2c81616SWang Jie reg = TCPC_POWER_STATUS_VBUS_PRES;
481*a2c81616SWang Jie else
482*a2c81616SWang Jie reg = 0;
483*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_POWER_STATUS_MASK, reg);
484*a2c81616SWang Jie if (ret < 0)
485*a2c81616SWang Jie return ret;
486*a2c81616SWang Jie
487*a2c81616SWang Jie /* Enable Vbus detection */
488*a2c81616SWang Jie ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
489*a2c81616SWang Jie TCPC_CMD_ENABLE_VBUS_DETECT);
490*a2c81616SWang Jie if (ret < 0)
491*a2c81616SWang Jie return ret;
492*a2c81616SWang Jie
493*a2c81616SWang Jie reg = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_FAILED |
494*a2c81616SWang Jie TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_RX_STATUS |
495*a2c81616SWang Jie TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_CC_STATUS;
496*a2c81616SWang Jie if (tcpci->controls_vbus)
497*a2c81616SWang Jie reg |= TCPC_ALERT_POWER_STATUS;
498*a2c81616SWang Jie return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
499*a2c81616SWang Jie }
500*a2c81616SWang Jie
tcpci_poll_event(struct tcpc_dev * tcpc)501*a2c81616SWang Jie static void tcpci_poll_event(struct tcpc_dev *tcpc)
502*a2c81616SWang Jie {
503*a2c81616SWang Jie u16 status;
504*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
505*a2c81616SWang Jie
506*a2c81616SWang Jie if (tcpci->gpio_cc_int_present)
507*a2c81616SWang Jie if (!dm_gpio_get_value(&tcpci->gpio_cc_int))
508*a2c81616SWang Jie return;
509*a2c81616SWang Jie
510*a2c81616SWang Jie tcpci_read16(tcpci, TCPC_ALERT, &status);
511*a2c81616SWang Jie
512*a2c81616SWang Jie /*
513*a2c81616SWang Jie * Clear alert status for everything except RX_STATUS, which shouldn't
514*a2c81616SWang Jie * be cleared until we have successfully retrieved message.
515*a2c81616SWang Jie */
516*a2c81616SWang Jie if (status & ~TCPC_ALERT_RX_STATUS)
517*a2c81616SWang Jie tcpci_write16(tcpci, TCPC_ALERT,
518*a2c81616SWang Jie status & ~TCPC_ALERT_RX_STATUS);
519*a2c81616SWang Jie
520*a2c81616SWang Jie if (status & TCPC_ALERT_CC_STATUS)
521*a2c81616SWang Jie tcpm_cc_change(tcpci->port);
522*a2c81616SWang Jie
523*a2c81616SWang Jie if (status & TCPC_ALERT_POWER_STATUS) {
524*a2c81616SWang Jie unsigned int reg;
525*a2c81616SWang Jie
526*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_STATUS_MASK);
527*a2c81616SWang Jie if (reg < 0)
528*a2c81616SWang Jie return;
529*a2c81616SWang Jie
530*a2c81616SWang Jie /*
531*a2c81616SWang Jie * If power status mask has been reset, then the TCPC
532*a2c81616SWang Jie * has reset.
533*a2c81616SWang Jie */
534*a2c81616SWang Jie if (reg == 0xff)
535*a2c81616SWang Jie tcpm_tcpc_reset(tcpci->port);
536*a2c81616SWang Jie else
537*a2c81616SWang Jie tcpm_vbus_change(tcpci->port);
538*a2c81616SWang Jie }
539*a2c81616SWang Jie
540*a2c81616SWang Jie if (status & TCPC_ALERT_RX_STATUS) {
541*a2c81616SWang Jie struct pd_message msg;
542*a2c81616SWang Jie unsigned int cnt, payload_cnt;
543*a2c81616SWang Jie u16 header;
544*a2c81616SWang Jie
545*a2c81616SWang Jie cnt = dm_i2c_reg_read(tcpci->dev, TCPC_RX_BYTE_CNT);
546*a2c81616SWang Jie if (cnt < 0)
547*a2c81616SWang Jie return;
548*a2c81616SWang Jie /*
549*a2c81616SWang Jie * 'cnt' corresponds to READABLE_BYTE_COUNT in section 4.4.14
550*a2c81616SWang Jie * of the TCPCI spec [Rev 2.0 Ver 1.0 October 2017] and is
551*a2c81616SWang Jie * defined in table 4-36 as one greater than the number of
552*a2c81616SWang Jie * bytes received. And that number includes the header. So:
553*a2c81616SWang Jie */
554*a2c81616SWang Jie if (cnt > 3)
555*a2c81616SWang Jie payload_cnt = cnt - (1 + sizeof(msg.header));
556*a2c81616SWang Jie else
557*a2c81616SWang Jie payload_cnt = 0;
558*a2c81616SWang Jie
559*a2c81616SWang Jie tcpci_read16(tcpci, TCPC_RX_HDR, &header);
560*a2c81616SWang Jie msg.header = cpu_to_le16(header);
561*a2c81616SWang Jie
562*a2c81616SWang Jie if (WARN_ON(payload_cnt > sizeof(msg.payload)))
563*a2c81616SWang Jie payload_cnt = sizeof(msg.payload);
564*a2c81616SWang Jie
565*a2c81616SWang Jie if (payload_cnt > 0)
566*a2c81616SWang Jie tcpci_block_read(tcpci, TCPC_RX_DATA,
567*a2c81616SWang Jie (u8 *)&msg.payload, payload_cnt);
568*a2c81616SWang Jie
569*a2c81616SWang Jie /* Read complete, clear RX status alert bit */
570*a2c81616SWang Jie tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
571*a2c81616SWang Jie
572*a2c81616SWang Jie tcpm_pd_receive(tcpci->port, &msg);
573*a2c81616SWang Jie }
574*a2c81616SWang Jie
575*a2c81616SWang Jie if (status & TCPC_ALERT_RX_HARD_RST)
576*a2c81616SWang Jie tcpm_pd_hard_reset(tcpci->port);
577*a2c81616SWang Jie
578*a2c81616SWang Jie if (status & TCPC_ALERT_TX_SUCCESS)
579*a2c81616SWang Jie tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_SUCCESS);
580*a2c81616SWang Jie else if (status & TCPC_ALERT_TX_DISCARDED)
581*a2c81616SWang Jie tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_DISCARDED);
582*a2c81616SWang Jie else if (status & TCPC_ALERT_TX_FAILED)
583*a2c81616SWang Jie tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_FAILED);
584*a2c81616SWang Jie }
585*a2c81616SWang Jie
tcpci_enter_low_power_mode(struct tcpc_dev * tcpc,bool attached,bool pd_capable)586*a2c81616SWang Jie static int tcpci_enter_low_power_mode(struct tcpc_dev *tcpc,
587*a2c81616SWang Jie bool attached, bool pd_capable)
588*a2c81616SWang Jie {
589*a2c81616SWang Jie int ret;
590*a2c81616SWang Jie struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
591*a2c81616SWang Jie unsigned int reg;
592*a2c81616SWang Jie
593*a2c81616SWang Jie /* Disable chip interrupts before unregistering port */
594*a2c81616SWang Jie ret = tcpci_write16(tcpci, TCPC_ALERT_MASK, 0);
595*a2c81616SWang Jie if (ret < 0)
596*a2c81616SWang Jie return ret;
597*a2c81616SWang Jie
598*a2c81616SWang Jie reg = dm_i2c_reg_read(tcpci->dev, TCPC_BMCIO_CTRL);
599*a2c81616SWang Jie if (reg < 0)
600*a2c81616SWang Jie return reg;
601*a2c81616SWang Jie /*
602*a2c81616SWang Jie * For Type-C devices with PD capability, Only disable VBUS detect,
603*a2c81616SWang Jie * do not diable 24M oscillator for BMC communication. Otherwise,
604*a2c81616SWang Jie * data packets cannot be received.
605*a2c81616SWang Jie */
606*a2c81616SWang Jie if (attached && pd_capable)
607*a2c81616SWang Jie reg &= ~TCPC_BMCIO_VBUS_DETECT_MASK;
608*a2c81616SWang Jie else
609*a2c81616SWang Jie reg &= ~(TCPC_BMCIO_VBUS_DETECT_MASK | TCPC_BMCIO_24M_OSC_MASK);
610*a2c81616SWang Jie return dm_i2c_reg_write(tcpci->dev, TCPC_BMCIO_CTRL, reg);
611*a2c81616SWang Jie }
612*a2c81616SWang Jie
tcpci_parse_config(struct tcpci * tcpci)613*a2c81616SWang Jie static int tcpci_parse_config(struct tcpci *tcpci)
614*a2c81616SWang Jie {
615*a2c81616SWang Jie tcpci->controls_vbus = true; /* XXX */
616*a2c81616SWang Jie
617*a2c81616SWang Jie tcpci->tcpc.connector_node = dev_read_subnode(tcpci->dev, "connector");
618*a2c81616SWang Jie if (!ofnode_valid(tcpci->tcpc.connector_node)) {
619*a2c81616SWang Jie printf("%s: 'connector' node is not found\n", __func__);
620*a2c81616SWang Jie return -EINVAL;
621*a2c81616SWang Jie }
622*a2c81616SWang Jie
623*a2c81616SWang Jie return 0;
624*a2c81616SWang Jie }
625*a2c81616SWang Jie
tcpci_register_port(struct udevice * dev,struct tcpci_data * data)626*a2c81616SWang Jie struct tcpci *tcpci_register_port(struct udevice *dev, struct tcpci_data *data)
627*a2c81616SWang Jie {
628*a2c81616SWang Jie struct tcpci *tcpci;
629*a2c81616SWang Jie int err;
630*a2c81616SWang Jie
631*a2c81616SWang Jie tcpci = devm_kzalloc(dev, sizeof(*tcpci), GFP_KERNEL);
632*a2c81616SWang Jie if (!tcpci)
633*a2c81616SWang Jie return ERR_PTR(-ENOMEM);
634*a2c81616SWang Jie
635*a2c81616SWang Jie err = gpio_request_by_name(dev, "int-n-gpios", 0, &tcpci->gpio_cc_int, GPIOD_IS_IN);
636*a2c81616SWang Jie if (err) {
637*a2c81616SWang Jie printf("%s: fail to get int GPIO: err=%d\n", __func__, err);
638*a2c81616SWang Jie tcpci->gpio_cc_int_present = false;
639*a2c81616SWang Jie } else {
640*a2c81616SWang Jie tcpci->gpio_cc_int_present = true;
641*a2c81616SWang Jie }
642*a2c81616SWang Jie
643*a2c81616SWang Jie tcpci->dev = dev;
644*a2c81616SWang Jie tcpci->data = data;
645*a2c81616SWang Jie
646*a2c81616SWang Jie tcpci->tcpc.init = tcpci_init;
647*a2c81616SWang Jie tcpci->tcpc.get_vbus = tcpci_get_vbus;
648*a2c81616SWang Jie tcpci->tcpc.set_vbus = tcpci_set_vbus;
649*a2c81616SWang Jie tcpci->tcpc.set_cc = tcpci_set_cc;
650*a2c81616SWang Jie tcpci->tcpc.get_cc = tcpci_get_cc;
651*a2c81616SWang Jie tcpci->tcpc.set_polarity = tcpci_set_polarity;
652*a2c81616SWang Jie tcpci->tcpc.set_vconn = tcpci_set_vconn;
653*a2c81616SWang Jie tcpci->tcpc.start_toggling = tcpci_start_toggling;
654*a2c81616SWang Jie
655*a2c81616SWang Jie tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx;
656*a2c81616SWang Jie tcpci->tcpc.set_roles = tcpci_set_roles;
657*a2c81616SWang Jie tcpci->tcpc.pd_transmit = tcpci_pd_transmit;
658*a2c81616SWang Jie tcpci->tcpc.poll_event = tcpci_poll_event;
659*a2c81616SWang Jie tcpci->tcpc.enter_low_power_mode = tcpci_enter_low_power_mode;
660*a2c81616SWang Jie
661*a2c81616SWang Jie err = tcpci_parse_config(tcpci);
662*a2c81616SWang Jie if (err < 0)
663*a2c81616SWang Jie return ERR_PTR(err);
664*a2c81616SWang Jie
665*a2c81616SWang Jie tcpci->port = tcpm_port_init(tcpci->dev, &tcpci->tcpc);
666*a2c81616SWang Jie if (IS_ERR(tcpci->port)) {
667*a2c81616SWang Jie printf("%s: failed to tcpm port init\n", __func__);
668*a2c81616SWang Jie return ERR_CAST(tcpci->port);
669*a2c81616SWang Jie }
670*a2c81616SWang Jie
671*a2c81616SWang Jie tcpm_poll_event(tcpci->port);
672*a2c81616SWang Jie
673*a2c81616SWang Jie return tcpci;
674*a2c81616SWang Jie }
675*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpci_register_port);
676*a2c81616SWang Jie
tcpci_unregister_port(struct tcpci * tcpci)677*a2c81616SWang Jie void tcpci_unregister_port(struct tcpci *tcpci)
678*a2c81616SWang Jie {
679*a2c81616SWang Jie tcpm_uninit_port(tcpci->port);
680*a2c81616SWang Jie }
681*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpci_unregister_port);
682*a2c81616SWang Jie
tcpci_get_voltage_fun(struct tcpci * tcpci)683*a2c81616SWang Jie int tcpci_get_voltage_fun(struct tcpci *tcpci)
684*a2c81616SWang Jie {
685*a2c81616SWang Jie return tcpm_get_voltage(tcpci->port);
686*a2c81616SWang Jie }
687*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpci_get_voltage_fun);
688*a2c81616SWang Jie
tcpci_get_current_fun(struct tcpci * tcpci)689*a2c81616SWang Jie int tcpci_get_current_fun(struct tcpci *tcpci)
690*a2c81616SWang Jie {
691*a2c81616SWang Jie return tcpm_get_current(tcpci->port);
692*a2c81616SWang Jie }
693*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpci_get_current_fun);
694*a2c81616SWang Jie
tcpci_get_online_fun(struct tcpci * tcpci)695*a2c81616SWang Jie int tcpci_get_online_fun(struct tcpci *tcpci)
696*a2c81616SWang Jie {
697*a2c81616SWang Jie return tcpm_get_online(tcpci->port);
698*a2c81616SWang Jie }
699*a2c81616SWang Jie EXPORT_SYMBOL_GPL(tcpci_get_online_fun);
700*a2c81616SWang Jie
tcpci_probe(struct udevice * dev)701*a2c81616SWang Jie static int tcpci_probe(struct udevice *dev)
702*a2c81616SWang Jie {
703*a2c81616SWang Jie struct tcpci_chip *chip = dev_get_priv(dev);
704*a2c81616SWang Jie int err;
705*a2c81616SWang Jie u16 val = 0;
706*a2c81616SWang Jie
707*a2c81616SWang Jie chip->udev = dev;
708*a2c81616SWang Jie
709*a2c81616SWang Jie /* Disable chip interrupts before requesting irq */
710*a2c81616SWang Jie err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, val);
711*a2c81616SWang Jie if (err < 0)
712*a2c81616SWang Jie return err;
713*a2c81616SWang Jie
714*a2c81616SWang Jie chip->tcpci = tcpci_register_port(chip->udev, &chip->data);
715*a2c81616SWang Jie if (IS_ERR(chip->tcpci))
716*a2c81616SWang Jie return PTR_ERR(chip->tcpci);
717*a2c81616SWang Jie
718*a2c81616SWang Jie return 0;
719*a2c81616SWang Jie }
720*a2c81616SWang Jie
tcpci_remove(struct udevice * dev)721*a2c81616SWang Jie static int tcpci_remove(struct udevice *dev)
722*a2c81616SWang Jie {
723*a2c81616SWang Jie struct tcpci_chip *chip = dev_get_priv(dev);
724*a2c81616SWang Jie int err;
725*a2c81616SWang Jie
726*a2c81616SWang Jie /* Disable chip interrupts before unregistering port */
727*a2c81616SWang Jie err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0);
728*a2c81616SWang Jie if (err < 0)
729*a2c81616SWang Jie return err;
730*a2c81616SWang Jie
731*a2c81616SWang Jie tcpci_unregister_port(chip->tcpci);
732*a2c81616SWang Jie
733*a2c81616SWang Jie return 0;
734*a2c81616SWang Jie }
735*a2c81616SWang Jie
tcpci_get_voltage(struct udevice * dev)736*a2c81616SWang Jie static int tcpci_get_voltage(struct udevice *dev)
737*a2c81616SWang Jie {
738*a2c81616SWang Jie struct tcpci_chip *chip = dev_get_priv(dev);
739*a2c81616SWang Jie
740*a2c81616SWang Jie return tcpm_get_voltage(chip->tcpci->port);
741*a2c81616SWang Jie }
742*a2c81616SWang Jie
tcpci_get_current(struct udevice * dev)743*a2c81616SWang Jie static int tcpci_get_current(struct udevice *dev)
744*a2c81616SWang Jie {
745*a2c81616SWang Jie struct tcpci_chip *chip = dev_get_priv(dev);
746*a2c81616SWang Jie
747*a2c81616SWang Jie return tcpm_get_current(chip->tcpci->port);
748*a2c81616SWang Jie }
749*a2c81616SWang Jie
tcpci_get_online(struct udevice * dev)750*a2c81616SWang Jie static int tcpci_get_online(struct udevice *dev)
751*a2c81616SWang Jie {
752*a2c81616SWang Jie struct tcpci_chip *chip = dev_get_priv(dev);
753*a2c81616SWang Jie
754*a2c81616SWang Jie return tcpm_get_online(chip->tcpci->port);
755*a2c81616SWang Jie }
756*a2c81616SWang Jie
757*a2c81616SWang Jie static struct dm_power_delivery_ops tcpci_ops = {
758*a2c81616SWang Jie .get_voltage = tcpci_get_voltage,
759*a2c81616SWang Jie .get_current = tcpci_get_current,
760*a2c81616SWang Jie .get_online = tcpci_get_online,
761*a2c81616SWang Jie };
762*a2c81616SWang Jie
763*a2c81616SWang Jie static const struct udevice_id tcpci_ids[] = {
764*a2c81616SWang Jie { .compatible = "nxp,ptn5110", },
765*a2c81616SWang Jie {},
766*a2c81616SWang Jie };
767*a2c81616SWang Jie
768*a2c81616SWang Jie U_BOOT_DRIVER(tcpci) = {
769*a2c81616SWang Jie .name = "tcpci",
770*a2c81616SWang Jie .id = UCLASS_PD,
771*a2c81616SWang Jie .of_match = tcpci_ids,
772*a2c81616SWang Jie .ops = &tcpci_ops,
773*a2c81616SWang Jie .probe = tcpci_probe,
774*a2c81616SWang Jie .remove = tcpci_remove,
775*a2c81616SWang Jie .priv_auto_alloc_size = sizeof(struct tcpci_chip),
776*a2c81616SWang Jie }
777*a2c81616SWang Jie
778*a2c81616SWang Jie MODULE_DESCRIPTION("USB Type-C Port Controller Interface driver");
779*a2c81616SWang Jie MODULE_LICENSE("GPL");
780