xref: /rk3399_rockchip-uboot/drivers/power/power_delivery/fusb302.c (revision 65f336e51a72d35e9c0012ad88016d8bea9f23e1)
1a2c81616SWang Jie // SPDX-License-Identifier: GPL-2.0+
2a2c81616SWang Jie /*
3a2c81616SWang Jie  * Copyright 2016-2017 Google, Inc
4a2c81616SWang Jie  *
5a2c81616SWang Jie  * Fairchild FUSB302 Type-C Chip Driver
6a2c81616SWang Jie  */
7a2c81616SWang Jie 
8a2c81616SWang Jie #include <dm.h>
9a2c81616SWang Jie #include <i2c.h>
10a2c81616SWang Jie #include <asm/gpio.h>
11a2c81616SWang Jie #include <power/power_delivery/tcpm.h>
12a2c81616SWang Jie #include <power/power_delivery/power_delivery.h>
13a2c81616SWang Jie #include "fusb302_reg.h"
14a2c81616SWang Jie 
15a2c81616SWang Jie /*
16a2c81616SWang Jie  * When the device is SNK, BC_LVL interrupt is used to monitor cc pins
17a2c81616SWang Jie  * for the current capability offered by the SRC. As FUSB302 chip fires
18a2c81616SWang Jie  * the BC_LVL interrupt on PD signalings, cc lvl should be handled after
19a2c81616SWang Jie  * a delay to avoid measuring on PD activities. The delay is slightly
20a2c81616SWang Jie  * longer than PD_T_PD_DEBPUNCE (10-20ms).
21a2c81616SWang Jie  */
22a2c81616SWang Jie #define T_BC_LVL_DEBOUNCE_DELAY_MS 30
23a2c81616SWang Jie #define msleep(a)	udelay(a * 1000)
24a2c81616SWang Jie #define usleep_range(a, b) udelay((b))
25a2c81616SWang Jie 
26a2c81616SWang Jie enum toggling_mode {
27a2c81616SWang Jie 	TOGGLING_MODE_OFF,
28a2c81616SWang Jie 	TOGGLING_MODE_DRP,
29a2c81616SWang Jie 	TOGGLING_MODE_SNK,
30a2c81616SWang Jie 	TOGGLING_MODE_SRC,
31a2c81616SWang Jie };
32a2c81616SWang Jie 
33a2c81616SWang Jie enum src_current_status {
34a2c81616SWang Jie 	SRC_CURRENT_DEFAULT,
35a2c81616SWang Jie 	SRC_CURRENT_MEDIUM,
36a2c81616SWang Jie 	SRC_CURRENT_HIGH,
37a2c81616SWang Jie };
38a2c81616SWang Jie 
39a2c81616SWang Jie static const u8 ra_mda_value[] = {
40a2c81616SWang Jie 	[SRC_CURRENT_DEFAULT] = 4,	/* 210mV */
41a2c81616SWang Jie 	[SRC_CURRENT_MEDIUM] = 9,	/* 420mV */
42a2c81616SWang Jie 	[SRC_CURRENT_HIGH] = 18,	/* 798mV */
43a2c81616SWang Jie };
44a2c81616SWang Jie 
45a2c81616SWang Jie static const u8 rd_mda_value[] = {
46a2c81616SWang Jie 	[SRC_CURRENT_DEFAULT] = 38,	/* 1638mV */
47a2c81616SWang Jie 	[SRC_CURRENT_MEDIUM] = 38,	/* 1638mV */
48a2c81616SWang Jie 	[SRC_CURRENT_HIGH] = 61,	/* 2604mV */
49a2c81616SWang Jie };
50a2c81616SWang Jie 
51a2c81616SWang Jie #define LOG_BUFFER_ENTRIES	1024
52a2c81616SWang Jie #define LOG_BUFFER_ENTRY_SIZE	128
53a2c81616SWang Jie 
54a2c81616SWang Jie struct fusb302_chip {
55a2c81616SWang Jie 	struct udevice *udev;
56a2c81616SWang Jie 	struct udevice *vbus_regulator;
57a2c81616SWang Jie 	struct ofnode *child_node;
58a2c81616SWang Jie 	struct tcpm_port *tcpm_port;
59a2c81616SWang Jie 	struct tcpc_dev tcpc_dev;
60a2c81616SWang Jie 	struct gpio_desc gpio_cc_int;
61a2c81616SWang Jie 
62a2c81616SWang Jie 	int irq;
63a2c81616SWang Jie 
64a2c81616SWang Jie 	enum toggling_mode toggling_mode;
65a2c81616SWang Jie 	enum src_current_status src_current_status;
66a2c81616SWang Jie 	bool intr_togdone;
67a2c81616SWang Jie 	bool intr_bc_lvl;
68a2c81616SWang Jie 	bool intr_comp_chng;
69a2c81616SWang Jie 
70a2c81616SWang Jie 	/* port status */
71a2c81616SWang Jie 	bool vconn_on;
72a2c81616SWang Jie 	bool vbus_on;
73a2c81616SWang Jie 	bool charge_on;
74a2c81616SWang Jie 	bool vbus_present;
75a2c81616SWang Jie 	bool gpio_cc_int_present;
76a2c81616SWang Jie 	enum typec_cc_polarity cc_polarity;
77a2c81616SWang Jie 	enum typec_cc_status cc1;
78a2c81616SWang Jie 	enum typec_cc_status cc2;
79a2c81616SWang Jie };
80a2c81616SWang Jie 
fusb302_i2c_write(struct fusb302_chip * chip,u8 address,u8 data)81a2c81616SWang Jie static int fusb302_i2c_write(struct fusb302_chip *chip,
82a2c81616SWang Jie 			     u8 address, u8 data)
83a2c81616SWang Jie {
84a2c81616SWang Jie 	int ret = 0;
85a2c81616SWang Jie 
86a2c81616SWang Jie 	ret = dm_i2c_write(chip->udev, address, &data, 1);
87a2c81616SWang Jie 	if (ret)
88a2c81616SWang Jie 		printf("%s: cannot write 0x%02x to 0x%02x, ret=%d\n",
89a2c81616SWang Jie 			__func__, data, address, ret);
90a2c81616SWang Jie 
91a2c81616SWang Jie 	return ret;
92a2c81616SWang Jie }
93a2c81616SWang Jie 
fusb302_i2c_block_write(struct fusb302_chip * chip,u8 address,u8 length,const u8 * data)94a2c81616SWang Jie static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
95a2c81616SWang Jie 				   u8 length, const u8 *data)
96a2c81616SWang Jie {
97a2c81616SWang Jie 	int ret = 0;
98a2c81616SWang Jie 
99a2c81616SWang Jie 	if (length <= 0)
100a2c81616SWang Jie 		return ret;
101a2c81616SWang Jie 
102a2c81616SWang Jie 	ret = dm_i2c_write(chip->udev, address, data, length);
103a2c81616SWang Jie 	if (ret)
104a2c81616SWang Jie 		printf("%s: cannot block write 0x%02x, len=%d, ret=%d\n",
105a2c81616SWang Jie 			__func__, address, length, ret);
106a2c81616SWang Jie 
107a2c81616SWang Jie 	return ret;
108a2c81616SWang Jie }
109a2c81616SWang Jie 
fusb302_i2c_read(struct fusb302_chip * chip,u8 address,u8 * data)110a2c81616SWang Jie static int fusb302_i2c_read(struct fusb302_chip *chip,
111a2c81616SWang Jie 			    u8 address, u8 *data)
112a2c81616SWang Jie {
113a2c81616SWang Jie 	int ret = 0;
114a2c81616SWang Jie 
115a2c81616SWang Jie 	ret = dm_i2c_read(chip->udev, address, data, 1);
116a2c81616SWang Jie 	if (ret)
117a2c81616SWang Jie 		printf("%s: cannot read %02x, ret=%d\n",
118a2c81616SWang Jie 			__func__, address, ret);
119a2c81616SWang Jie 
120a2c81616SWang Jie 	return ret;
121a2c81616SWang Jie }
122a2c81616SWang Jie 
fusb302_i2c_block_read(struct fusb302_chip * chip,u8 address,u8 length,u8 * data)123a2c81616SWang Jie static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address,
124a2c81616SWang Jie 				  u8 length, u8 *data)
125a2c81616SWang Jie {
126a2c81616SWang Jie 	int ret = 0;
127a2c81616SWang Jie 
128a2c81616SWang Jie 	if (length <= 0)
129a2c81616SWang Jie 		return ret;
130a2c81616SWang Jie 
131a2c81616SWang Jie 	ret = dm_i2c_read(chip->udev, address, data, length);
132a2c81616SWang Jie 	if (ret)
133a2c81616SWang Jie 		printf("%s: cannot block read 0x%02x, len=%d, ret=%d\n",
134a2c81616SWang Jie 			__func__, address, length, ret);
135a2c81616SWang Jie 	return ret;
136a2c81616SWang Jie }
137a2c81616SWang Jie 
fusb302_i2c_mask_write(struct fusb302_chip * chip,u8 address,u8 mask,u8 value)138a2c81616SWang Jie static int fusb302_i2c_mask_write(struct fusb302_chip *chip, u8 address,
139a2c81616SWang Jie 				  u8 mask, u8 value)
140a2c81616SWang Jie {
141a2c81616SWang Jie 	int ret = 0;
142a2c81616SWang Jie 	u8 data;
143a2c81616SWang Jie 
144a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, address, &data);
145a2c81616SWang Jie 	if (ret)
146a2c81616SWang Jie 		return ret;
147a2c81616SWang Jie 	data &= ~mask;
148a2c81616SWang Jie 	data |= value;
149a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, address, data);
150a2c81616SWang Jie 	if (ret)
151a2c81616SWang Jie 		return ret;
152a2c81616SWang Jie 
153a2c81616SWang Jie 	return ret;
154a2c81616SWang Jie }
155a2c81616SWang Jie 
fusb302_i2c_set_bits(struct fusb302_chip * chip,u8 address,u8 set_bits)156a2c81616SWang Jie static int fusb302_i2c_set_bits(struct fusb302_chip *chip, u8 address,
157a2c81616SWang Jie 				u8 set_bits)
158a2c81616SWang Jie {
159a2c81616SWang Jie 	return fusb302_i2c_mask_write(chip, address, 0x00, set_bits);
160a2c81616SWang Jie }
161a2c81616SWang Jie 
fusb302_i2c_clear_bits(struct fusb302_chip * chip,u8 address,u8 clear_bits)162a2c81616SWang Jie static int fusb302_i2c_clear_bits(struct fusb302_chip *chip, u8 address,
163a2c81616SWang Jie 				  u8 clear_bits)
164a2c81616SWang Jie {
165a2c81616SWang Jie 	return fusb302_i2c_mask_write(chip, address, clear_bits, 0x00);
166a2c81616SWang Jie }
167a2c81616SWang Jie 
fusb302_sw_reset(struct fusb302_chip * chip)168a2c81616SWang Jie static int fusb302_sw_reset(struct fusb302_chip *chip)
169a2c81616SWang Jie {
170a2c81616SWang Jie 	int ret = 0;
171a2c81616SWang Jie 
172a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_RESET,
173a2c81616SWang Jie 				FUSB_REG_RESET_SW_RESET);
174a2c81616SWang Jie 	if (ret)
175a2c81616SWang Jie 		printf("cannot sw reset the fusb302(%d)\n", ret);
176a2c81616SWang Jie 	else
177a2c81616SWang Jie 		debug("fusb302 sw reset finished\n");
178a2c81616SWang Jie 
179a2c81616SWang Jie 	return ret;
180a2c81616SWang Jie }
181a2c81616SWang Jie 
fusb302_enable_tx_auto_retries(struct fusb302_chip * chip,u8 retry_count)182a2c81616SWang Jie static int fusb302_enable_tx_auto_retries(struct fusb302_chip *chip, u8 retry_count)
183a2c81616SWang Jie {
184a2c81616SWang Jie 	int ret = 0;
185a2c81616SWang Jie 
186a2c81616SWang Jie 	ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL3, retry_count |
187a2c81616SWang Jie 				   FUSB_REG_CONTROL3_AUTO_RETRY);
188a2c81616SWang Jie 
189a2c81616SWang Jie 	return ret;
190a2c81616SWang Jie }
191a2c81616SWang Jie 
192a2c81616SWang Jie /*
193a2c81616SWang Jie  * mask all interrupt on the chip
194a2c81616SWang Jie  */
fusb302_mask_interrupt(struct fusb302_chip * chip)195a2c81616SWang Jie static int fusb302_mask_interrupt(struct fusb302_chip *chip)
196a2c81616SWang Jie {
197a2c81616SWang Jie 	int ret = 0;
198a2c81616SWang Jie 
199a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MASK, 0xFF);
200a2c81616SWang Jie 	if (ret)
201a2c81616SWang Jie 		return ret;
202a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MASKA, 0xFF);
203a2c81616SWang Jie 	if (ret)
204a2c81616SWang Jie 		return ret;
205a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MASKB, 0xFF);
206a2c81616SWang Jie 	if (ret)
207a2c81616SWang Jie 		return ret;
208a2c81616SWang Jie 	ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL0,
209a2c81616SWang Jie 				   FUSB_REG_CONTROL0_INT_MASK);
210a2c81616SWang Jie 		return ret;
211a2c81616SWang Jie }
212a2c81616SWang Jie 
213a2c81616SWang Jie /*
214a2c81616SWang Jie  * initialize interrupt on the chip
215a2c81616SWang Jie  * - unmasked interrupt: VBUS_OK
216a2c81616SWang Jie  */
fusb302_init_interrupt(struct fusb302_chip * chip)217a2c81616SWang Jie static int fusb302_init_interrupt(struct fusb302_chip *chip)
218a2c81616SWang Jie {
219a2c81616SWang Jie 	int ret = 0;
220a2c81616SWang Jie 
221a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MASK,
222a2c81616SWang Jie 				0xFF & ~FUSB_REG_MASK_VBUSOK);
223a2c81616SWang Jie 	if (ret)
224a2c81616SWang Jie 		return ret;
225a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MASKA, 0xFF);
226a2c81616SWang Jie 	if (ret)
227a2c81616SWang Jie 		return ret;
228a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MASKB, 0xFF);
229a2c81616SWang Jie 	if (ret)
230a2c81616SWang Jie 		return ret;
231a2c81616SWang Jie 	ret = fusb302_i2c_clear_bits(chip, FUSB_REG_CONTROL0,
232a2c81616SWang Jie 				     FUSB_REG_CONTROL0_INT_MASK);
233a2c81616SWang Jie 	return ret;
234a2c81616SWang Jie }
235a2c81616SWang Jie 
fusb302_set_power_mode(struct fusb302_chip * chip,u8 power_mode)236a2c81616SWang Jie static int fusb302_set_power_mode(struct fusb302_chip *chip, u8 power_mode)
237a2c81616SWang Jie {
238a2c81616SWang Jie 	int ret = 0;
239a2c81616SWang Jie 
240a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_POWER, power_mode);
241a2c81616SWang Jie 
242a2c81616SWang Jie 	return ret;
243a2c81616SWang Jie }
244a2c81616SWang Jie 
tcpm_init(struct tcpc_dev * dev)245a2c81616SWang Jie static int tcpm_init(struct tcpc_dev *dev)
246a2c81616SWang Jie {
247a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
248a2c81616SWang Jie 						 tcpc_dev);
249a2c81616SWang Jie 	int ret = 0;
250a2c81616SWang Jie 	u8 data;
251a2c81616SWang Jie 
252a2c81616SWang Jie 	ret = fusb302_sw_reset(chip);
253a2c81616SWang Jie 	if (ret)
254a2c81616SWang Jie 		return ret;
255a2c81616SWang Jie 	ret = fusb302_enable_tx_auto_retries(chip, FUSB_REG_CONTROL3_N_RETRIES_3);
256a2c81616SWang Jie 	if (ret)
257a2c81616SWang Jie 		return ret;
258a2c81616SWang Jie 	ret = fusb302_init_interrupt(chip);
259a2c81616SWang Jie 	if (ret)
260a2c81616SWang Jie 		return ret;
261a2c81616SWang Jie 	ret = fusb302_set_power_mode(chip, FUSB_REG_POWER_PWR_ALL);
262a2c81616SWang Jie 	if (ret)
263a2c81616SWang Jie 		return ret;
264a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data);
265a2c81616SWang Jie 	if (ret)
266a2c81616SWang Jie 		return ret;
267a2c81616SWang Jie 	chip->vbus_present = !!(data & FUSB_REG_STATUS0_VBUSOK);
268a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data);
269a2c81616SWang Jie 	if (ret)
270a2c81616SWang Jie 		return ret;
271a2c81616SWang Jie 	printf("fusb302 device ID: 0x%02x\n", data);
272a2c81616SWang Jie 
273a2c81616SWang Jie 	return ret;
274a2c81616SWang Jie }
275a2c81616SWang Jie 
tcpm_get_vbus(struct tcpc_dev * dev)276a2c81616SWang Jie static int tcpm_get_vbus(struct tcpc_dev *dev)
277a2c81616SWang Jie {
278a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
279a2c81616SWang Jie 						 tcpc_dev);
280a2c81616SWang Jie 	return chip->vbus_present ? 1 : 0;
281a2c81616SWang Jie }
282a2c81616SWang Jie 
283a2c81616SWang Jie #if 0
284a2c81616SWang Jie static int tcpm_get_current_limit(struct tcpc_dev *dev)
285a2c81616SWang Jie {
286a2c81616SWang Jie 
287a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
288a2c81616SWang Jie 						 tcpc_dev);
289a2c81616SWang Jie 	int current_limit = 0;
290a2c81616SWang Jie 	unsigned long timeout;
291a2c81616SWang Jie 
292a2c81616SWang Jie 	if (!chip->extcon)
293a2c81616SWang Jie 		return 0;
294a2c81616SWang Jie 
295a2c81616SWang Jie 	/*
296a2c81616SWang Jie 	 * USB2 Charger detection may still be in progress when we get here,
297a2c81616SWang Jie 	 * this can take upto 600ms, wait 800ms max.
298a2c81616SWang Jie 	 */
299a2c81616SWang Jie 	timeout = jiffies + msecs_to_jiffies(800);
300a2c81616SWang Jie 	do {
301a2c81616SWang Jie 		if (extcon_get_state(chip->extcon, EXTCON_CHG_USB_SDP) == 1)
302a2c81616SWang Jie 			current_limit = 500;
303a2c81616SWang Jie 
304a2c81616SWang Jie 		if (extcon_get_state(chip->extcon, EXTCON_CHG_USB_CDP) == 1 ||
305a2c81616SWang Jie 		    extcon_get_state(chip->extcon, EXTCON_CHG_USB_ACA) == 1)
306a2c81616SWang Jie 			current_limit = 1500;
307a2c81616SWang Jie 
308a2c81616SWang Jie 		if (extcon_get_state(chip->extcon, EXTCON_CHG_USB_DCP) == 1)
309a2c81616SWang Jie 			current_limit = 2000;
310a2c81616SWang Jie 
311a2c81616SWang Jie 		msleep(50);
312a2c81616SWang Jie 	} while (current_limit == 0 && time_before(jiffies, timeout));
313a2c81616SWang Jie 
314a2c81616SWang Jie 	return current_limit;
315a2c81616SWang Jie }
316a2c81616SWang Jie #endif
317a2c81616SWang Jie 
fusb302_set_src_current(struct fusb302_chip * chip,enum src_current_status status)318a2c81616SWang Jie static int fusb302_set_src_current(struct fusb302_chip *chip,
319a2c81616SWang Jie 				   enum src_current_status status)
320a2c81616SWang Jie {
321a2c81616SWang Jie 	int ret = 0;
322a2c81616SWang Jie 
323a2c81616SWang Jie 	chip->src_current_status = status;
324a2c81616SWang Jie 	switch (status) {
325a2c81616SWang Jie 	case SRC_CURRENT_DEFAULT:
326a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL0,
327a2c81616SWang Jie 					     FUSB_REG_CONTROL0_HOST_CUR_MASK,
328a2c81616SWang Jie 					     FUSB_REG_CONTROL0_HOST_CUR_DEF);
329a2c81616SWang Jie 		break;
330a2c81616SWang Jie 	case SRC_CURRENT_MEDIUM:
331a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL0,
332a2c81616SWang Jie 					     FUSB_REG_CONTROL0_HOST_CUR_MASK,
333a2c81616SWang Jie 					     FUSB_REG_CONTROL0_HOST_CUR_MED);
334a2c81616SWang Jie 		break;
335a2c81616SWang Jie 	case SRC_CURRENT_HIGH:
336a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL0,
337a2c81616SWang Jie 					     FUSB_REG_CONTROL0_HOST_CUR_MASK,
338a2c81616SWang Jie 					     FUSB_REG_CONTROL0_HOST_CUR_HIGH);
339a2c81616SWang Jie 		break;
340a2c81616SWang Jie 	default:
341a2c81616SWang Jie 		break;
342a2c81616SWang Jie 	}
343a2c81616SWang Jie 
344a2c81616SWang Jie 	return ret;
345a2c81616SWang Jie }
346a2c81616SWang Jie 
fusb302_set_toggling(struct fusb302_chip * chip,enum toggling_mode mode)347a2c81616SWang Jie static int fusb302_set_toggling(struct fusb302_chip *chip,
348a2c81616SWang Jie 				enum toggling_mode mode)
349a2c81616SWang Jie {
350a2c81616SWang Jie 	int ret = 0;
351a2c81616SWang Jie 
352a2c81616SWang Jie 	/* first disable toggling */
353a2c81616SWang Jie 	ret = fusb302_i2c_clear_bits(chip, FUSB_REG_CONTROL2,
354a2c81616SWang Jie 				     FUSB_REG_CONTROL2_TOGGLE);
355a2c81616SWang Jie 	if (ret)
356a2c81616SWang Jie 		return ret;
357a2c81616SWang Jie 	/* mask interrupts for SRC or SNK */
358a2c81616SWang Jie 	ret = fusb302_i2c_set_bits(chip, FUSB_REG_MASK,
359a2c81616SWang Jie 				   FUSB_REG_MASK_BC_LVL |
360a2c81616SWang Jie 				   FUSB_REG_MASK_COMP_CHNG);
361a2c81616SWang Jie 	if (ret)
362a2c81616SWang Jie 		return ret;
363a2c81616SWang Jie 	chip->intr_bc_lvl = false;
364a2c81616SWang Jie 	chip->intr_comp_chng = false;
365a2c81616SWang Jie 	/* configure toggling mode: none/snk/src/drp */
366a2c81616SWang Jie 	switch (mode) {
367a2c81616SWang Jie 	case TOGGLING_MODE_OFF:
368a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2,
369a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_MASK,
370a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_NONE);
371a2c81616SWang Jie 		break;
372a2c81616SWang Jie 	case TOGGLING_MODE_SNK:
373a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2,
374a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_MASK,
375a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_UFP);
376a2c81616SWang Jie 		break;
377a2c81616SWang Jie 	case TOGGLING_MODE_SRC:
378a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2,
379a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_MASK,
380a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_DFP);
381a2c81616SWang Jie 		break;
382a2c81616SWang Jie 	case TOGGLING_MODE_DRP:
383a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2,
384a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_MASK,
385a2c81616SWang Jie 					     FUSB_REG_CONTROL2_MODE_DRP);
386a2c81616SWang Jie 		break;
387a2c81616SWang Jie 	default:
388a2c81616SWang Jie 		break;
389a2c81616SWang Jie 	}
390a2c81616SWang Jie 
391a2c81616SWang Jie 	if (ret)
392a2c81616SWang Jie 		return ret;
393a2c81616SWang Jie 
394a2c81616SWang Jie 	if (mode == TOGGLING_MODE_OFF) {
395a2c81616SWang Jie 		/* mask TOGDONE interrupt */
396a2c81616SWang Jie 		ret = fusb302_i2c_set_bits(chip, FUSB_REG_MASKA,
397a2c81616SWang Jie 					   FUSB_REG_MASKA_TOGDONE);
398a2c81616SWang Jie 		if (ret)
399a2c81616SWang Jie 			return ret;
400a2c81616SWang Jie 		chip->intr_togdone = false;
401a2c81616SWang Jie 	} else {
402a2c81616SWang Jie 		/* Datasheet says vconn MUST be off when toggling */
403a2c81616SWang Jie 		if (chip->vconn_on)
404a2c81616SWang Jie 			printf("%s: Vconn is on during toggle start\n", __func__);
405a2c81616SWang Jie 		/* unmask TOGDONE interrupt */
406a2c81616SWang Jie 		ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA,
407a2c81616SWang Jie 					     FUSB_REG_MASKA_TOGDONE);
408a2c81616SWang Jie 		if (ret)
409a2c81616SWang Jie 			return ret;
410a2c81616SWang Jie 		chip->intr_togdone = true;
411a2c81616SWang Jie 		/* start toggling */
412a2c81616SWang Jie 		ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL2,
413a2c81616SWang Jie 					   FUSB_REG_CONTROL2_TOGGLE);
414a2c81616SWang Jie 		if (ret)
415a2c81616SWang Jie 			return ret;
416a2c81616SWang Jie 		/* during toggling, consider cc as Open */
417a2c81616SWang Jie 		chip->cc1 = TYPEC_CC_OPEN;
418a2c81616SWang Jie 		chip->cc2 = TYPEC_CC_OPEN;
419a2c81616SWang Jie 	}
420a2c81616SWang Jie 	chip->toggling_mode = mode;
421a2c81616SWang Jie 
422a2c81616SWang Jie 	return ret;
423a2c81616SWang Jie }
424a2c81616SWang Jie 
425a2c81616SWang Jie static const char * const typec_cc_status_name[] = {
426a2c81616SWang Jie 	[TYPEC_CC_OPEN]		= "Open",
427a2c81616SWang Jie 	[TYPEC_CC_RA]		= "Ra",
428a2c81616SWang Jie 	[TYPEC_CC_RD]		= "Rd",
429a2c81616SWang Jie 	[TYPEC_CC_RP_DEF]	= "Rp-def",
430a2c81616SWang Jie 	[TYPEC_CC_RP_1_5]	= "Rp-1.5",
431a2c81616SWang Jie 	[TYPEC_CC_RP_3_0]	= "Rp-3.0",
432a2c81616SWang Jie };
433a2c81616SWang Jie 
434a2c81616SWang Jie static const enum src_current_status cc_src_current[] = {
435a2c81616SWang Jie 	[TYPEC_CC_OPEN]		= SRC_CURRENT_DEFAULT,
436a2c81616SWang Jie 	[TYPEC_CC_RA]		= SRC_CURRENT_DEFAULT,
437a2c81616SWang Jie 	[TYPEC_CC_RD]		= SRC_CURRENT_DEFAULT,
438a2c81616SWang Jie 	[TYPEC_CC_RP_DEF]	= SRC_CURRENT_DEFAULT,
439a2c81616SWang Jie 	[TYPEC_CC_RP_1_5]	= SRC_CURRENT_MEDIUM,
440a2c81616SWang Jie 	[TYPEC_CC_RP_3_0]	= SRC_CURRENT_HIGH,
441a2c81616SWang Jie };
442a2c81616SWang Jie 
tcpm_set_cc(struct tcpc_dev * dev,enum typec_cc_status cc)443a2c81616SWang Jie static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
444a2c81616SWang Jie {
445a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
446a2c81616SWang Jie 						 tcpc_dev);
447a2c81616SWang Jie 	u8 switches0_mask = FUSB_REG_SWITCHES0_CC1_PU_EN |
448a2c81616SWang Jie 			    FUSB_REG_SWITCHES0_CC2_PU_EN |
449a2c81616SWang Jie 			    FUSB_REG_SWITCHES0_CC1_PD_EN |
450a2c81616SWang Jie 			    FUSB_REG_SWITCHES0_CC2_PD_EN;
451a2c81616SWang Jie 	u8 rd_mda, switches0_data = 0x00;
452a2c81616SWang Jie 	int ret = 0;
453a2c81616SWang Jie 
454a2c81616SWang Jie 	switch (cc) {
455a2c81616SWang Jie 	case TYPEC_CC_OPEN:
456a2c81616SWang Jie 		break;
457a2c81616SWang Jie 	case TYPEC_CC_RD:
458a2c81616SWang Jie 		switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN |
459a2c81616SWang Jie 				  FUSB_REG_SWITCHES0_CC2_PD_EN;
460a2c81616SWang Jie 		break;
461a2c81616SWang Jie 	case TYPEC_CC_RP_DEF:
462a2c81616SWang Jie 	case TYPEC_CC_RP_1_5:
463a2c81616SWang Jie 	case TYPEC_CC_RP_3_0:
464a2c81616SWang Jie 		switches0_data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ?
465a2c81616SWang Jie 				  FUSB_REG_SWITCHES0_CC1_PU_EN :
466a2c81616SWang Jie 				  FUSB_REG_SWITCHES0_CC2_PU_EN;
467a2c81616SWang Jie 		break;
468a2c81616SWang Jie 	default:
469a2c81616SWang Jie 		printf("%s: unsupported cc value %s\n",
470a2c81616SWang Jie 			__func__, typec_cc_status_name[cc]);
471a2c81616SWang Jie 		ret = -EINVAL;
472a2c81616SWang Jie 		goto done;
473a2c81616SWang Jie 	}
474a2c81616SWang Jie 
475a2c81616SWang Jie 	ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF);
476a2c81616SWang Jie 	if (ret) {
477a2c81616SWang Jie 		printf("%s: cannot set toggling mode(%d)\n", __func__, ret);
478a2c81616SWang Jie 		goto done;
479a2c81616SWang Jie 	}
480a2c81616SWang Jie 
481a2c81616SWang Jie 	ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0,
482a2c81616SWang Jie 				     switches0_mask, switches0_data);
483a2c81616SWang Jie 	if (ret) {
484a2c81616SWang Jie 		printf("%s: cannot set pull-up/-down(%d)\n", __func__, ret);
485a2c81616SWang Jie 		goto done;
486a2c81616SWang Jie 	}
487a2c81616SWang Jie 	/* reset the cc status */
488a2c81616SWang Jie 	chip->cc1 = TYPEC_CC_OPEN;
489a2c81616SWang Jie 	chip->cc2 = TYPEC_CC_OPEN;
490a2c81616SWang Jie 
491a2c81616SWang Jie 	/* adjust current for SRC */
492a2c81616SWang Jie 	ret = fusb302_set_src_current(chip, cc_src_current[cc]);
493a2c81616SWang Jie 	if (ret) {
494a2c81616SWang Jie 		printf("%s: cannot set src current %s(%d)\n",
495a2c81616SWang Jie 			__func__, typec_cc_status_name[cc], ret);
496a2c81616SWang Jie 		goto done;
497a2c81616SWang Jie 	}
498a2c81616SWang Jie 
499a2c81616SWang Jie 	/* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */
500a2c81616SWang Jie 	switch (cc) {
501a2c81616SWang Jie 	case TYPEC_CC_RP_DEF:
502a2c81616SWang Jie 	case TYPEC_CC_RP_1_5:
503a2c81616SWang Jie 	case TYPEC_CC_RP_3_0:
504a2c81616SWang Jie 		rd_mda = rd_mda_value[cc_src_current[cc]];
505a2c81616SWang Jie 		ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda);
506a2c81616SWang Jie 		if (ret) {
507a2c81616SWang Jie 			printf("%s: cannot set SRC measure value(%d)\n",
508a2c81616SWang Jie 				__func__, ret);
509a2c81616SWang Jie 			goto done;
510a2c81616SWang Jie 		}
511a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
512a2c81616SWang Jie 					     FUSB_REG_MASK_BC_LVL |
513a2c81616SWang Jie 					     FUSB_REG_MASK_COMP_CHNG,
514a2c81616SWang Jie 					     FUSB_REG_MASK_BC_LVL);
515a2c81616SWang Jie 		if (ret) {
516a2c81616SWang Jie 			printf("%s: cannot set SRC interrupt(%d)\n",
517a2c81616SWang Jie 				__func__, ret);
518a2c81616SWang Jie 			goto done;
519a2c81616SWang Jie 		}
520a2c81616SWang Jie 		chip->intr_comp_chng = true;
521a2c81616SWang Jie 		break;
522a2c81616SWang Jie 	case TYPEC_CC_RD:
523a2c81616SWang Jie 		ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK,
524a2c81616SWang Jie 					     FUSB_REG_MASK_BC_LVL |
525a2c81616SWang Jie 					     FUSB_REG_MASK_COMP_CHNG,
526a2c81616SWang Jie 					     FUSB_REG_MASK_COMP_CHNG);
527a2c81616SWang Jie 		if (ret) {
528a2c81616SWang Jie 			printf("%s: cannot set SRC interrupt(%d)\n",
529a2c81616SWang Jie 				__func__, ret);
530a2c81616SWang Jie 			goto done;
531a2c81616SWang Jie 		}
532a2c81616SWang Jie 		chip->intr_bc_lvl = true;
533a2c81616SWang Jie 		break;
534a2c81616SWang Jie 	default:
535a2c81616SWang Jie 		break;
536a2c81616SWang Jie 	}
537a2c81616SWang Jie done:
538a2c81616SWang Jie 	return ret;
539a2c81616SWang Jie }
540a2c81616SWang Jie 
tcpm_get_cc(struct tcpc_dev * dev,enum typec_cc_status * cc1,enum typec_cc_status * cc2)541a2c81616SWang Jie static int tcpm_get_cc(struct tcpc_dev *dev, enum typec_cc_status *cc1,
542a2c81616SWang Jie 		       enum typec_cc_status *cc2)
543a2c81616SWang Jie {
544a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
545a2c81616SWang Jie 						 tcpc_dev);
546a2c81616SWang Jie 
547a2c81616SWang Jie 	*cc1 = chip->cc1;
548a2c81616SWang Jie 	*cc2 = chip->cc2;
549a2c81616SWang Jie 	debug("get cc1 = %s, cc2 = %s\n", typec_cc_status_name[*cc1],
550a2c81616SWang Jie 	       typec_cc_status_name[*cc2]);
551a2c81616SWang Jie 
552a2c81616SWang Jie 	return 0;
553a2c81616SWang Jie }
554a2c81616SWang Jie 
tcpm_set_polarity(struct tcpc_dev * dev,enum typec_cc_polarity polarity)555a2c81616SWang Jie static int tcpm_set_polarity(struct tcpc_dev *dev,
556a2c81616SWang Jie 			     enum typec_cc_polarity polarity)
557a2c81616SWang Jie {
558a2c81616SWang Jie 	return 0;
559a2c81616SWang Jie }
560a2c81616SWang Jie 
tcpm_set_vconn(struct tcpc_dev * dev,bool on)561a2c81616SWang Jie static int tcpm_set_vconn(struct tcpc_dev *dev, bool on)
562a2c81616SWang Jie {
563a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
564a2c81616SWang Jie 						 tcpc_dev);
565a2c81616SWang Jie 	int ret = 0;
566a2c81616SWang Jie 	u8 switches0_data = 0x00;
567a2c81616SWang Jie 	u8 switches0_mask = FUSB_REG_SWITCHES0_VCONN_CC1 |
568a2c81616SWang Jie 			    FUSB_REG_SWITCHES0_VCONN_CC2;
569a2c81616SWang Jie 
570a2c81616SWang Jie 	if (chip->vconn_on == on) {
571a2c81616SWang Jie 		printf("vconn is already %s\n", on ? "On" : "Off");
572a2c81616SWang Jie 		goto done;
573a2c81616SWang Jie 	}
574a2c81616SWang Jie 	if (on) {
575a2c81616SWang Jie 		switches0_data = (chip->cc_polarity == TYPEC_POLARITY_CC1) ?
576a2c81616SWang Jie 				 FUSB_REG_SWITCHES0_VCONN_CC2 :
577a2c81616SWang Jie 				 FUSB_REG_SWITCHES0_VCONN_CC1;
578a2c81616SWang Jie 	}
579a2c81616SWang Jie 	ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0,
580a2c81616SWang Jie 				     switches0_mask, switches0_data);
581a2c81616SWang Jie 	if (ret)
582a2c81616SWang Jie 		goto done;
583a2c81616SWang Jie 	debug("%s: vconn := %s\n", __func__, on ? "On" : "Off");
584a2c81616SWang Jie done:
585a2c81616SWang Jie 	return ret;
586a2c81616SWang Jie }
587a2c81616SWang Jie 
tcpm_set_vbus(struct tcpc_dev * dev,bool on,bool charge)588a2c81616SWang Jie static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge)
589a2c81616SWang Jie {
590a2c81616SWang Jie #if 0
591a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
592a2c81616SWang Jie 						 tcpc_dev);
593a2c81616SWang Jie 	int ret = 0;
594a2c81616SWang Jie 
595a2c81616SWang Jie 	mutex_lock(&chip->lock);
596a2c81616SWang Jie 	if (chip->vbus_on == on) {
597a2c81616SWang Jie 		printf("%s: vbus is already %s\n", __func__, on ? "On" : "Off");
598a2c81616SWang Jie 	} else {
599a2c81616SWang Jie 		if (on)
600a2c81616SWang Jie 			ret = regulator_enable(chip->vbus);
601a2c81616SWang Jie 		else
602a2c81616SWang Jie 			ret = regulator_disable(chip->vbus);
603a2c81616SWang Jie 		if (ret < 0) {
604a2c81616SWang Jie 			printf("%s: cannot %s vbus regulator(%d)\n",
605a2c81616SWang Jie 				__func__, on ? "enable" : "disable", ret);
606a2c81616SWang Jie 			goto done;
607a2c81616SWang Jie 		}
608a2c81616SWang Jie 		chip->vbus_on = on;
609a2c81616SWang Jie 		debug("%s: vbus := %s\n", __func__, on ? "On" : "Off");
610a2c81616SWang Jie 	}
611a2c81616SWang Jie 	if (chip->charge_on == charge)
612a2c81616SWang Jie 		debug("%s: charge is already %s\n",
613a2c81616SWang Jie 			__func__, charge ? "On" : "Off");
614a2c81616SWang Jie 	else
615a2c81616SWang Jie 		chip->charge_on = charge;
616a2c81616SWang Jie 
617a2c81616SWang Jie done:
618a2c81616SWang Jie 	mutex_unlock(&chip->lock);
619a2c81616SWang Jie #endif
620a2c81616SWang Jie 
621a2c81616SWang Jie 	return 0;
622a2c81616SWang Jie }
623a2c81616SWang Jie 
fusb302_pd_tx_flush(struct fusb302_chip * chip)624a2c81616SWang Jie static int fusb302_pd_tx_flush(struct fusb302_chip *chip)
625a2c81616SWang Jie {
626a2c81616SWang Jie 	return fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL0,
627a2c81616SWang Jie 				    FUSB_REG_CONTROL0_TX_FLUSH);
628a2c81616SWang Jie }
629a2c81616SWang Jie 
fusb302_pd_rx_flush(struct fusb302_chip * chip)630a2c81616SWang Jie static int fusb302_pd_rx_flush(struct fusb302_chip *chip)
631a2c81616SWang Jie {
632a2c81616SWang Jie 	return fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL1,
633a2c81616SWang Jie 				    FUSB_REG_CONTROL1_RX_FLUSH);
634a2c81616SWang Jie }
635a2c81616SWang Jie 
fusb302_pd_set_auto_goodcrc(struct fusb302_chip * chip,bool on)636a2c81616SWang Jie static int fusb302_pd_set_auto_goodcrc(struct fusb302_chip *chip, bool on)
637a2c81616SWang Jie {
638a2c81616SWang Jie 	if (on)
639a2c81616SWang Jie 		return fusb302_i2c_set_bits(chip, FUSB_REG_SWITCHES1,
640a2c81616SWang Jie 					    FUSB_REG_SWITCHES1_AUTO_GCRC);
641a2c81616SWang Jie 	return fusb302_i2c_clear_bits(chip, FUSB_REG_SWITCHES1,
642a2c81616SWang Jie 					    FUSB_REG_SWITCHES1_AUTO_GCRC);
643a2c81616SWang Jie }
644a2c81616SWang Jie 
fusb302_pd_set_interrupts(struct fusb302_chip * chip,bool on)645a2c81616SWang Jie static int fusb302_pd_set_interrupts(struct fusb302_chip *chip, bool on)
646a2c81616SWang Jie {
647a2c81616SWang Jie 	int ret = 0;
648a2c81616SWang Jie 	u8 mask_interrupts = FUSB_REG_MASK_COLLISION;
649a2c81616SWang Jie 	u8 maska_interrupts = FUSB_REG_MASKA_RETRYFAIL |
650a2c81616SWang Jie 			      FUSB_REG_MASKA_HARDSENT |
651a2c81616SWang Jie 			      FUSB_REG_MASKA_TX_SUCCESS |
652a2c81616SWang Jie 			      FUSB_REG_MASKA_HARDRESET;
653a2c81616SWang Jie 	u8 maskb_interrupts = FUSB_REG_MASKB_GCRCSENT;
654a2c81616SWang Jie 
655a2c81616SWang Jie 	ret = on ?
656a2c81616SWang Jie 		fusb302_i2c_clear_bits(chip, FUSB_REG_MASK, mask_interrupts) :
657a2c81616SWang Jie 		fusb302_i2c_set_bits(chip, FUSB_REG_MASK, mask_interrupts);
658a2c81616SWang Jie 	if (ret)
659a2c81616SWang Jie 		return ret;
660a2c81616SWang Jie 	ret = on ?
661a2c81616SWang Jie 		fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA, maska_interrupts) :
662a2c81616SWang Jie 		fusb302_i2c_set_bits(chip, FUSB_REG_MASKA, maska_interrupts);
663a2c81616SWang Jie 	if (ret)
664a2c81616SWang Jie 		return ret;
665a2c81616SWang Jie 	ret = on ?
666a2c81616SWang Jie 		fusb302_i2c_clear_bits(chip, FUSB_REG_MASKB, maskb_interrupts) :
667a2c81616SWang Jie 		fusb302_i2c_set_bits(chip, FUSB_REG_MASKB, maskb_interrupts);
668a2c81616SWang Jie 	return ret;
669a2c81616SWang Jie }
670a2c81616SWang Jie 
tcpm_set_pd_rx(struct tcpc_dev * dev,bool on)671a2c81616SWang Jie static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on)
672a2c81616SWang Jie {
673a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
674a2c81616SWang Jie 						 tcpc_dev);
675a2c81616SWang Jie 	int ret = 0;
676a2c81616SWang Jie 
677a2c81616SWang Jie 	ret = fusb302_pd_rx_flush(chip);
678a2c81616SWang Jie 	if (ret) {
679a2c81616SWang Jie 		printf("%s: cannot flush pd rx buffer(%d)\n", __func__, ret);
680a2c81616SWang Jie 		goto done;
681a2c81616SWang Jie 	}
682a2c81616SWang Jie 	ret = fusb302_pd_tx_flush(chip);
683a2c81616SWang Jie 	if (ret) {
684a2c81616SWang Jie 		printf("%s: cannot flush pd tx buffer(%d)\n", __func__, ret);
685a2c81616SWang Jie 		goto done;
686a2c81616SWang Jie 	}
687a2c81616SWang Jie 	ret = fusb302_pd_set_auto_goodcrc(chip, on);
688a2c81616SWang Jie 	if (ret) {
689a2c81616SWang Jie 		printf("%s: cannot turn %s auto GCRC(%d)\n",
690a2c81616SWang Jie 			__func__, on ? "on" : "off", ret);
691a2c81616SWang Jie 		goto done;
692a2c81616SWang Jie 	}
693a2c81616SWang Jie 	ret = fusb302_pd_set_interrupts(chip, on);
694a2c81616SWang Jie 	if (ret) {
695a2c81616SWang Jie 		printf("%s: cannot turn %s pd interrupts(%d)\n",
696a2c81616SWang Jie 			__func__, on ? "on" : "off", ret);
697a2c81616SWang Jie 		goto done;
698a2c81616SWang Jie 	}
699a2c81616SWang Jie 	debug("%s: pd := %s\n", __func__, on ? "on" : "off");
700a2c81616SWang Jie done:
701a2c81616SWang Jie 	return ret;
702a2c81616SWang Jie }
703a2c81616SWang Jie 
704a2c81616SWang Jie static const char * const typec_role_name[] = {
705a2c81616SWang Jie 	[TYPEC_SINK]		= "Sink",
706a2c81616SWang Jie 	[TYPEC_SOURCE]		= "Source",
707a2c81616SWang Jie };
708a2c81616SWang Jie 
709a2c81616SWang Jie static const char * const typec_data_role_name[] = {
710a2c81616SWang Jie 	[TYPEC_DEVICE]		= "Device",
711a2c81616SWang Jie 	[TYPEC_HOST]		= "Host",
712a2c81616SWang Jie };
713a2c81616SWang Jie 
tcpm_set_roles(struct tcpc_dev * dev,bool attached,enum typec_role pwr,enum typec_data_role data)714a2c81616SWang Jie static int tcpm_set_roles(struct tcpc_dev *dev, bool attached,
715a2c81616SWang Jie 			  enum typec_role pwr, enum typec_data_role data)
716a2c81616SWang Jie {
717a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
718a2c81616SWang Jie 						 tcpc_dev);
719a2c81616SWang Jie 	int ret = 0;
720a2c81616SWang Jie 	u8 switches1_mask = FUSB_REG_SWITCHES1_POWERROLE |
721a2c81616SWang Jie 			    FUSB_REG_SWITCHES1_DATAROLE;
722a2c81616SWang Jie 	u8 switches1_data = 0x00;
723a2c81616SWang Jie 
724a2c81616SWang Jie 	if (pwr == TYPEC_SOURCE)
725a2c81616SWang Jie 		switches1_data |= FUSB_REG_SWITCHES1_POWERROLE;
726a2c81616SWang Jie 	if (data == TYPEC_HOST)
727a2c81616SWang Jie 		switches1_data |= FUSB_REG_SWITCHES1_DATAROLE;
728a2c81616SWang Jie 	ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES1,
729a2c81616SWang Jie 				     switches1_mask, switches1_data);
730a2c81616SWang Jie 	if (ret) {
731a2c81616SWang Jie 		printf("unable to set pd header %s, %s, ret= %d\n",
732a2c81616SWang Jie 			typec_role_name[pwr], typec_data_role_name[data], ret);
733a2c81616SWang Jie 		goto done;
734a2c81616SWang Jie 	}
735a2c81616SWang Jie 	debug("%s: pd header : %s, %s\n", __func__, typec_role_name[pwr],
736a2c81616SWang Jie 		typec_data_role_name[data]);
737a2c81616SWang Jie done:
738a2c81616SWang Jie 
739a2c81616SWang Jie 	return ret;
740a2c81616SWang Jie }
741a2c81616SWang Jie 
tcpm_start_toggling(struct tcpc_dev * dev,enum typec_port_type port_type,enum typec_cc_status cc)742a2c81616SWang Jie static int tcpm_start_toggling(struct tcpc_dev *dev,
743a2c81616SWang Jie 			       enum typec_port_type port_type,
744a2c81616SWang Jie 			       enum typec_cc_status cc)
745a2c81616SWang Jie {
746a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
747a2c81616SWang Jie 						 tcpc_dev);
748a2c81616SWang Jie 	enum toggling_mode mode = TOGGLING_MODE_OFF;
749a2c81616SWang Jie 	int ret = 0;
750a2c81616SWang Jie 
751a2c81616SWang Jie 	switch (port_type) {
752a2c81616SWang Jie 	case TYPEC_PORT_SRC:
753a2c81616SWang Jie 		mode = TOGGLING_MODE_SRC;
754a2c81616SWang Jie 		break;
755a2c81616SWang Jie 	case TYPEC_PORT_SNK:
756a2c81616SWang Jie 		mode = TOGGLING_MODE_SNK;
757a2c81616SWang Jie 		break;
758a2c81616SWang Jie 	case TYPEC_PORT_DRP:
759a2c81616SWang Jie 		mode = TOGGLING_MODE_DRP;
760a2c81616SWang Jie 		break;
761a2c81616SWang Jie 	}
762a2c81616SWang Jie 
763a2c81616SWang Jie 	ret = fusb302_set_src_current(chip, cc_src_current[cc]);
764a2c81616SWang Jie 	if (ret) {
765a2c81616SWang Jie 		printf("%s: unable to set src current %s, ret=%d",
766a2c81616SWang Jie 			__func__, typec_cc_status_name[cc], ret);
767a2c81616SWang Jie 		goto done;
768a2c81616SWang Jie 	}
769a2c81616SWang Jie 	ret = fusb302_set_toggling(chip, mode);
770a2c81616SWang Jie 	if (ret) {
771a2c81616SWang Jie 		printf("%s: unable to start drp toggling(%d)\n", __func__, ret);
772a2c81616SWang Jie 		goto done;
773a2c81616SWang Jie 	}
774a2c81616SWang Jie 	printf("fusb302 start drp toggling\n");
775a2c81616SWang Jie done:
776a2c81616SWang Jie 
777a2c81616SWang Jie 	return ret;
778a2c81616SWang Jie }
779a2c81616SWang Jie 
fusb302_pd_send_message(struct fusb302_chip * chip,const struct pd_message * msg)780a2c81616SWang Jie static int fusb302_pd_send_message(struct fusb302_chip *chip,
781a2c81616SWang Jie 				   const struct pd_message *msg)
782a2c81616SWang Jie {
783a2c81616SWang Jie 	int ret = 0;
784a2c81616SWang Jie 	u8 buf[40];
785a2c81616SWang Jie 	u8 pos = 0;
786a2c81616SWang Jie 	int len;
787a2c81616SWang Jie 
788a2c81616SWang Jie 	/* SOP tokens */
789a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_SYNC1;
790a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_SYNC1;
791a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_SYNC1;
792a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_SYNC2;
793a2c81616SWang Jie 
794a2c81616SWang Jie 	len = pd_header_cnt_le(msg->header) * 4;
795a2c81616SWang Jie 	/* plug 2 for header */
796a2c81616SWang Jie 	len += 2;
797a2c81616SWang Jie 	if (len > 0x1F) {
798a2c81616SWang Jie 		printf("PD message too long %d (incl. header)", len);
799a2c81616SWang Jie 		return -EINVAL;
800a2c81616SWang Jie 	}
801a2c81616SWang Jie 	/* packsym tells the FUSB302 chip that the next X bytes are payload */
802a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_PACKSYM | (len & 0x1F);
803a2c81616SWang Jie 	memcpy(&buf[pos], &msg->header, sizeof(msg->header));
804a2c81616SWang Jie 	pos += sizeof(msg->header);
805a2c81616SWang Jie 
806a2c81616SWang Jie 	len -= 2;
807a2c81616SWang Jie 	memcpy(&buf[pos], msg->payload, len);
808a2c81616SWang Jie 	pos += len;
809a2c81616SWang Jie 
810a2c81616SWang Jie 	/* CRC */
811a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_JAMCRC;
812a2c81616SWang Jie 	/* EOP */
813a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_EOP;
814a2c81616SWang Jie 	/* turn tx off after sending message */
815a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_TXOFF;
816a2c81616SWang Jie 	/* start transmission */
817a2c81616SWang Jie 	buf[pos++] = FUSB302_TKN_TXON;
818a2c81616SWang Jie 
819a2c81616SWang Jie 	ret = fusb302_i2c_block_write(chip, FUSB_REG_FIFOS, pos, buf);
820a2c81616SWang Jie 	if (ret)
821a2c81616SWang Jie 		return ret;
822a2c81616SWang Jie 	debug("sending PD message header: %x\n", msg->header);
823a2c81616SWang Jie 	debug("sending PD message len: %d\n", len);
824a2c81616SWang Jie 
825a2c81616SWang Jie 	return ret;
826a2c81616SWang Jie }
827a2c81616SWang Jie 
fusb302_pd_send_hardreset(struct fusb302_chip * chip)828a2c81616SWang Jie static int fusb302_pd_send_hardreset(struct fusb302_chip *chip)
829a2c81616SWang Jie {
830a2c81616SWang Jie 	return fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL3,
831a2c81616SWang Jie 				    FUSB_REG_CONTROL3_SEND_HARDRESET);
832a2c81616SWang Jie }
833a2c81616SWang Jie 
834a2c81616SWang Jie static const char * const transmit_type_name[] = {
835a2c81616SWang Jie 	[TCPC_TX_SOP]			= "SOP",
836a2c81616SWang Jie 	[TCPC_TX_SOP_PRIME]		= "SOP'",
837a2c81616SWang Jie 	[TCPC_TX_SOP_PRIME_PRIME]	= "SOP''",
838a2c81616SWang Jie 	[TCPC_TX_SOP_DEBUG_PRIME]	= "DEBUG'",
839a2c81616SWang Jie 	[TCPC_TX_SOP_DEBUG_PRIME_PRIME]	= "DEBUG''",
840a2c81616SWang Jie 	[TCPC_TX_HARD_RESET]		= "HARD_RESET",
841a2c81616SWang Jie 	[TCPC_TX_CABLE_RESET]		= "CABLE_RESET",
842a2c81616SWang Jie 	[TCPC_TX_BIST_MODE_2]		= "BIST_MODE_2",
843a2c81616SWang Jie };
844a2c81616SWang Jie 
tcpm_pd_transmit(struct tcpc_dev * dev,enum tcpm_transmit_type type,const struct pd_message * msg,unsigned int negotiated_rev)845a2c81616SWang Jie static int tcpm_pd_transmit(struct tcpc_dev *dev, enum tcpm_transmit_type type,
846a2c81616SWang Jie 			    const struct pd_message *msg, unsigned int negotiated_rev)
847a2c81616SWang Jie {
848a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
849a2c81616SWang Jie 						 tcpc_dev);
850a2c81616SWang Jie 	int ret = 0;
851a2c81616SWang Jie 
852a2c81616SWang Jie 	switch (type) {
853a2c81616SWang Jie 	case TCPC_TX_SOP:
854a2c81616SWang Jie 		/* nRetryCount 3 in P2.0 spec, whereas 2 in PD3.0 spec */
855a2c81616SWang Jie 		ret = fusb302_enable_tx_auto_retries(chip, negotiated_rev > PD_REV20 ?
856a2c81616SWang Jie 						     FUSB_REG_CONTROL3_N_RETRIES_2 :
857a2c81616SWang Jie 						     FUSB_REG_CONTROL3_N_RETRIES_3);
858a2c81616SWang Jie 		if (ret)
859a2c81616SWang Jie 			printf("%s: Cannot update retry count(%d)\n",
860a2c81616SWang Jie 				__func__, ret);
861a2c81616SWang Jie 
862a2c81616SWang Jie 		ret = fusb302_pd_send_message(chip, msg);
863a2c81616SWang Jie 		if (ret)
864a2c81616SWang Jie 			printf("%s: cannot send PD message(%d)\n",
865a2c81616SWang Jie 				__func__, ret);
866a2c81616SWang Jie 		break;
867a2c81616SWang Jie 	case TCPC_TX_HARD_RESET:
868a2c81616SWang Jie 		ret = fusb302_pd_send_hardreset(chip);
869a2c81616SWang Jie 		if (ret)
870a2c81616SWang Jie 			printf("%s: cannot send hardreset(%d)\n",
871a2c81616SWang Jie 				__func__, ret);
872a2c81616SWang Jie 		break;
873a2c81616SWang Jie 	default:
874a2c81616SWang Jie 		printf("%s: type %s not supported",
875a2c81616SWang Jie 			__func__, transmit_type_name[type]);
876a2c81616SWang Jie 		ret = -EINVAL;
877a2c81616SWang Jie 	}
878a2c81616SWang Jie 
879a2c81616SWang Jie 	return ret;
880a2c81616SWang Jie }
881a2c81616SWang Jie 
fusb302_bc_lvl_to_cc(u8 bc_lvl)882a2c81616SWang Jie static enum typec_cc_status fusb302_bc_lvl_to_cc(u8 bc_lvl)
883a2c81616SWang Jie {
884a2c81616SWang Jie 	if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_1230_MAX)
885a2c81616SWang Jie 		return TYPEC_CC_RP_3_0;
886a2c81616SWang Jie 	if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_600_1230)
887a2c81616SWang Jie 		return TYPEC_CC_RP_1_5;
888a2c81616SWang Jie 	if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_200_600)
889a2c81616SWang Jie 		return TYPEC_CC_RP_DEF;
890a2c81616SWang Jie 	return TYPEC_CC_OPEN;
891a2c81616SWang Jie }
892a2c81616SWang Jie 
fusb302_bc_lvl_handler(struct fusb302_chip * chip)893a2c81616SWang Jie static void fusb302_bc_lvl_handler(struct fusb302_chip *chip)
894a2c81616SWang Jie {
895a2c81616SWang Jie 	int ret = 0;
896a2c81616SWang Jie 	u8 status0;
897a2c81616SWang Jie 	u8 bc_lvl;
898a2c81616SWang Jie 	enum typec_cc_status cc_status;
899a2c81616SWang Jie 
900a2c81616SWang Jie 	if (!chip->intr_bc_lvl) {
901a2c81616SWang Jie 		printf("BC_LVL interrupt is turned off, abort\n");
902a2c81616SWang Jie 		goto done;
903a2c81616SWang Jie 	}
904a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
905a2c81616SWang Jie 	if (ret)
906a2c81616SWang Jie 		goto done;
907a2c81616SWang Jie 
908a2c81616SWang Jie 	debug("BC_LVL handler, status0 = 0x%02x\n", status0);
909a2c81616SWang Jie 	if (status0 & FUSB_REG_STATUS0_ACTIVITY)
910a2c81616SWang Jie 		printf("CC activities detected, delay handling\n");
911a2c81616SWang Jie 	bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK;
912a2c81616SWang Jie 	cc_status = fusb302_bc_lvl_to_cc(bc_lvl);
913a2c81616SWang Jie 	if (chip->cc_polarity == TYPEC_POLARITY_CC1) {
914a2c81616SWang Jie 		if (chip->cc1 != cc_status) {
915a2c81616SWang Jie 			debug("cc1: %s -> %s\n",
916a2c81616SWang Jie 				typec_cc_status_name[chip->cc1],
917a2c81616SWang Jie 				typec_cc_status_name[cc_status]);
918a2c81616SWang Jie 			chip->cc1 = cc_status;
919a2c81616SWang Jie 			tcpm_cc_change(chip->tcpm_port);
920a2c81616SWang Jie 		}
921a2c81616SWang Jie 	} else {
922a2c81616SWang Jie 		if (chip->cc2 != cc_status) {
923a2c81616SWang Jie 			debug("cc2: %s -> %s\n",
924a2c81616SWang Jie 				typec_cc_status_name[chip->cc2],
925a2c81616SWang Jie 				typec_cc_status_name[cc_status]);
926a2c81616SWang Jie 			chip->cc2 = cc_status;
927a2c81616SWang Jie 			tcpm_cc_change(chip->tcpm_port);
928a2c81616SWang Jie 		}
929a2c81616SWang Jie 	}
930a2c81616SWang Jie 
931a2c81616SWang Jie done:
932a2c81616SWang Jie 	return;
933a2c81616SWang Jie }
934a2c81616SWang Jie 
935a2c81616SWang Jie static void fusb302_interrupt_handle(struct fusb302_chip *chip);
fusb302_poll_event(struct tcpc_dev * dev)936a2c81616SWang Jie static void fusb302_poll_event(struct tcpc_dev *dev)
937a2c81616SWang Jie {
938a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
939a2c81616SWang Jie 						 tcpc_dev);
940a2c81616SWang Jie 
941a2c81616SWang Jie 	fusb302_interrupt_handle(chip);
942a2c81616SWang Jie }
943a2c81616SWang Jie 
fusb302_enter_low_power_mode(struct tcpc_dev * dev,bool attached,bool pd_capable)944a2c81616SWang Jie static int fusb302_enter_low_power_mode(struct tcpc_dev *dev,
945a2c81616SWang Jie 					bool attached, bool pd_capable)
946a2c81616SWang Jie {
947a2c81616SWang Jie 	struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
948a2c81616SWang Jie 						 tcpc_dev);
949a2c81616SWang Jie 	int ret = 0;
950a2c81616SWang Jie 	unsigned int reg;
951a2c81616SWang Jie 
952a2c81616SWang Jie 	ret = fusb302_mask_interrupt(chip);
953a2c81616SWang Jie 	if (ret)
954a2c81616SWang Jie 		return ret;
955a2c81616SWang Jie 	if (attached && pd_capable)
956a2c81616SWang Jie 		reg = FUSB_REG_POWER_PWR_MEDIUM;
957a2c81616SWang Jie 	else if (attached)
958a2c81616SWang Jie 		reg = FUSB_REG_POWER_PWR_LOW;
959a2c81616SWang Jie 	else
960a2c81616SWang Jie 		reg = 0;
961a2c81616SWang Jie 
962a2c81616SWang Jie 	return fusb302_set_power_mode(chip, reg);
963a2c81616SWang Jie }
964a2c81616SWang Jie 
init_tcpc_dev(struct tcpc_dev * fusb302_tcpc_dev)965a2c81616SWang Jie static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev)
966a2c81616SWang Jie {
967a2c81616SWang Jie 	fusb302_tcpc_dev->init = tcpm_init;
968a2c81616SWang Jie 	fusb302_tcpc_dev->get_vbus = tcpm_get_vbus;
969a2c81616SWang Jie 	//fusb302_tcpc_dev->get_current_limit = tcpm_get_current_limit;
970a2c81616SWang Jie 	fusb302_tcpc_dev->set_cc = tcpm_set_cc;
971a2c81616SWang Jie 	fusb302_tcpc_dev->get_cc = tcpm_get_cc;
972a2c81616SWang Jie 	fusb302_tcpc_dev->set_polarity = tcpm_set_polarity;
973a2c81616SWang Jie 	fusb302_tcpc_dev->set_vconn = tcpm_set_vconn;
974a2c81616SWang Jie 	fusb302_tcpc_dev->set_vbus = tcpm_set_vbus;
975a2c81616SWang Jie 	fusb302_tcpc_dev->set_pd_rx = tcpm_set_pd_rx;
976a2c81616SWang Jie 	fusb302_tcpc_dev->set_roles = tcpm_set_roles;
977a2c81616SWang Jie 	fusb302_tcpc_dev->start_toggling = tcpm_start_toggling;
978a2c81616SWang Jie 	fusb302_tcpc_dev->pd_transmit = tcpm_pd_transmit;
979a2c81616SWang Jie 	fusb302_tcpc_dev->poll_event = fusb302_poll_event;
980a2c81616SWang Jie 	fusb302_tcpc_dev->enter_low_power_mode = fusb302_enter_low_power_mode;
981a2c81616SWang Jie }
982a2c81616SWang Jie 
983a2c81616SWang Jie static const char * const cc_polarity_name[] = {
984a2c81616SWang Jie 	[TYPEC_POLARITY_CC1]	= "Polarity_CC1",
985a2c81616SWang Jie 	[TYPEC_POLARITY_CC2]	= "Polarity_CC2",
986a2c81616SWang Jie };
987a2c81616SWang Jie 
fusb302_set_cc_polarity_and_pull(struct fusb302_chip * chip,enum typec_cc_polarity cc_polarity,bool pull_up,bool pull_down)988a2c81616SWang Jie static int fusb302_set_cc_polarity_and_pull(struct fusb302_chip *chip,
989a2c81616SWang Jie 					    enum typec_cc_polarity cc_polarity,
990a2c81616SWang Jie 					    bool pull_up, bool pull_down)
991a2c81616SWang Jie {
992a2c81616SWang Jie 	int ret = 0;
993a2c81616SWang Jie 	u8 switches0_data = 0x00;
994a2c81616SWang Jie 	u8 switches1_mask = FUSB_REG_SWITCHES1_TXCC1_EN |
995a2c81616SWang Jie 			    FUSB_REG_SWITCHES1_TXCC2_EN;
996a2c81616SWang Jie 	u8 switches1_data = 0x00;
997a2c81616SWang Jie 
998a2c81616SWang Jie 	if (pull_down)
999a2c81616SWang Jie 		switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN |
1000a2c81616SWang Jie 				  FUSB_REG_SWITCHES0_CC2_PD_EN;
1001a2c81616SWang Jie 
1002a2c81616SWang Jie 	if (cc_polarity == TYPEC_POLARITY_CC1) {
1003a2c81616SWang Jie 		switches0_data |= FUSB_REG_SWITCHES0_MEAS_CC1;
1004a2c81616SWang Jie 		if (chip->vconn_on)
1005a2c81616SWang Jie 			switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC2;
1006a2c81616SWang Jie 		if (pull_up)
1007a2c81616SWang Jie 			switches0_data |= FUSB_REG_SWITCHES0_CC1_PU_EN;
1008a2c81616SWang Jie 		switches1_data = FUSB_REG_SWITCHES1_TXCC1_EN;
1009a2c81616SWang Jie 	} else {
1010a2c81616SWang Jie 		switches0_data |= FUSB_REG_SWITCHES0_MEAS_CC2;
1011a2c81616SWang Jie 		if (chip->vconn_on)
1012a2c81616SWang Jie 			switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC1;
1013a2c81616SWang Jie 		if (pull_up)
1014a2c81616SWang Jie 			switches0_data |= FUSB_REG_SWITCHES0_CC2_PU_EN;
1015a2c81616SWang Jie 		switches1_data = FUSB_REG_SWITCHES1_TXCC2_EN;
1016a2c81616SWang Jie 	}
1017a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_SWITCHES0, switches0_data);
1018a2c81616SWang Jie 	if (ret)
1019a2c81616SWang Jie 		return ret;
1020a2c81616SWang Jie 	ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES1,
1021a2c81616SWang Jie 				     switches1_mask, switches1_data);
1022a2c81616SWang Jie 	if (ret)
1023a2c81616SWang Jie 		return ret;
1024a2c81616SWang Jie 	chip->cc_polarity = cc_polarity;
1025a2c81616SWang Jie 
1026a2c81616SWang Jie 	return ret;
1027a2c81616SWang Jie }
1028a2c81616SWang Jie 
fusb302_handle_togdone_snk(struct fusb302_chip * chip,u8 togdone_result)1029a2c81616SWang Jie static int fusb302_handle_togdone_snk(struct fusb302_chip *chip,
1030a2c81616SWang Jie 				      u8 togdone_result)
1031a2c81616SWang Jie {
1032a2c81616SWang Jie 	int ret = 0;
1033a2c81616SWang Jie 	u8 status0;
1034a2c81616SWang Jie 	u8 bc_lvl;
1035a2c81616SWang Jie 	enum typec_cc_polarity cc_polarity;
1036a2c81616SWang Jie 	enum typec_cc_status cc_status_active, cc1, cc2;
1037a2c81616SWang Jie 
1038a2c81616SWang Jie 	/* set polarity and pull_up, pull_down */
1039a2c81616SWang Jie 	cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SNK1) ?
1040a2c81616SWang Jie 		      TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2;
1041a2c81616SWang Jie 	ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, false, true);
1042a2c81616SWang Jie 	if (ret) {
1043a2c81616SWang Jie 		printf("cannot set cc polarity %s, ret = %d\n",
1044a2c81616SWang Jie 			cc_polarity_name[cc_polarity], ret);
1045a2c81616SWang Jie 		return ret;
1046a2c81616SWang Jie 	}
1047a2c81616SWang Jie 	/* fusb302_set_cc_polarity() has set the correct measure block */
1048a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
1049a2c81616SWang Jie 	if (ret < 0)
1050a2c81616SWang Jie 		return ret;
1051a2c81616SWang Jie 	bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK;
1052a2c81616SWang Jie 	cc_status_active = fusb302_bc_lvl_to_cc(bc_lvl);
1053a2c81616SWang Jie 	/* restart toggling if the cc status on the active line is OPEN */
1054a2c81616SWang Jie 	if (cc_status_active == TYPEC_CC_OPEN) {
1055a2c81616SWang Jie 		printf("restart toggling as CC_OPEN detected\n");
1056a2c81616SWang Jie 		ret = fusb302_set_toggling(chip, chip->toggling_mode);
1057a2c81616SWang Jie 		return ret;
1058a2c81616SWang Jie 	}
1059a2c81616SWang Jie 	/* update tcpm with the new cc value */
1060a2c81616SWang Jie 	cc1 = (cc_polarity == TYPEC_POLARITY_CC1) ?
1061a2c81616SWang Jie 	      cc_status_active : TYPEC_CC_OPEN;
1062a2c81616SWang Jie 	cc2 = (cc_polarity == TYPEC_POLARITY_CC2) ?
1063a2c81616SWang Jie 	      cc_status_active : TYPEC_CC_OPEN;
1064a2c81616SWang Jie 	if ((chip->cc1 != cc1) || (chip->cc2 != cc2)) {
1065a2c81616SWang Jie 		chip->cc1 = cc1;
1066a2c81616SWang Jie 		chip->cc2 = cc2;
1067a2c81616SWang Jie 		tcpm_cc_change(chip->tcpm_port);
1068a2c81616SWang Jie 	}
1069a2c81616SWang Jie 	/* turn off toggling */
1070a2c81616SWang Jie 	ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF);
1071a2c81616SWang Jie 	if (ret) {
1072a2c81616SWang Jie 		printf("cannot set toggling mode off, ret=%d\n", ret);
1073a2c81616SWang Jie 		return ret;
1074a2c81616SWang Jie 	}
1075a2c81616SWang Jie 	/* unmask bc_lvl interrupt */
1076a2c81616SWang Jie 	ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASK, FUSB_REG_MASK_BC_LVL);
1077a2c81616SWang Jie 	if (ret) {
1078a2c81616SWang Jie 		printf("cannot unmask bc_lcl interrupt, ret=%d\n", ret);
1079a2c81616SWang Jie 		return ret;
1080a2c81616SWang Jie 	}
1081a2c81616SWang Jie 	chip->intr_bc_lvl = true;
1082a2c81616SWang Jie 	debug("detected cc1=%s, cc2=%s\n",
1083a2c81616SWang Jie 		typec_cc_status_name[cc1],
1084a2c81616SWang Jie 		typec_cc_status_name[cc2]);
1085a2c81616SWang Jie 
1086a2c81616SWang Jie 	return ret;
1087a2c81616SWang Jie }
1088a2c81616SWang Jie 
1089a2c81616SWang Jie /* On error returns < 0, otherwise a typec_cc_status value */
fusb302_get_src_cc_status(struct fusb302_chip * chip,enum typec_cc_polarity cc_polarity,enum typec_cc_status * cc)1090a2c81616SWang Jie static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
1091a2c81616SWang Jie 				     enum typec_cc_polarity cc_polarity,
1092a2c81616SWang Jie 				     enum typec_cc_status *cc)
1093a2c81616SWang Jie {
1094a2c81616SWang Jie 	u8 ra_mda = ra_mda_value[chip->src_current_status];
1095a2c81616SWang Jie 	u8 rd_mda = rd_mda_value[chip->src_current_status];
1096a2c81616SWang Jie 	u8 switches0_data, status0;
1097a2c81616SWang Jie 	int ret;
1098a2c81616SWang Jie 
1099a2c81616SWang Jie 	/* Step 1: Set switches so that we measure the right CC pin */
1100a2c81616SWang Jie 	switches0_data = (cc_polarity == TYPEC_POLARITY_CC1) ?
1101a2c81616SWang Jie 		FUSB_REG_SWITCHES0_CC1_PU_EN | FUSB_REG_SWITCHES0_MEAS_CC1 :
1102a2c81616SWang Jie 		FUSB_REG_SWITCHES0_CC2_PU_EN | FUSB_REG_SWITCHES0_MEAS_CC2;
1103a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_SWITCHES0, switches0_data);
1104a2c81616SWang Jie 	if (ret < 0)
1105a2c81616SWang Jie 		return ret;
1106a2c81616SWang Jie 
1107a2c81616SWang Jie 	fusb302_i2c_read(chip, FUSB_REG_SWITCHES0, &status0);
1108a2c81616SWang Jie 	debug("get_src_cc_status switches: 0x%0x", status0);
1109a2c81616SWang Jie 
1110a2c81616SWang Jie 	/* Step 2: Set compararator volt to differentiate between Open and Rd */
1111a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda);
1112a2c81616SWang Jie 	if (ret)
1113a2c81616SWang Jie 		return ret;
1114a2c81616SWang Jie 
1115a2c81616SWang Jie 	usleep_range(50, 100);
1116a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
1117a2c81616SWang Jie 	if (ret)
1118a2c81616SWang Jie 		return ret;
1119a2c81616SWang Jie 
1120a2c81616SWang Jie 	debug("get_src_cc_status rd_mda status0: 0x%0x", status0);
1121a2c81616SWang Jie 	if (status0 & FUSB_REG_STATUS0_COMP) {
1122a2c81616SWang Jie 		*cc = TYPEC_CC_OPEN;
1123a2c81616SWang Jie 		return 0;
1124a2c81616SWang Jie 	}
1125a2c81616SWang Jie 
1126a2c81616SWang Jie 	/* Step 3: Set compararator input to differentiate between Rd and Ra. */
1127a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, ra_mda);
1128a2c81616SWang Jie 	if (ret)
1129a2c81616SWang Jie 		return ret;
1130a2c81616SWang Jie 
1131a2c81616SWang Jie 	usleep_range(50, 100);
1132a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
1133a2c81616SWang Jie 	if (ret)
1134a2c81616SWang Jie 		return ret;
1135a2c81616SWang Jie 
1136a2c81616SWang Jie 	debug("get_src_cc_status ra_mda status0: 0x%0x", status0);
1137a2c81616SWang Jie 	if (status0 & FUSB_REG_STATUS0_COMP)
1138a2c81616SWang Jie 		*cc = TYPEC_CC_RD;
1139a2c81616SWang Jie 	else
1140a2c81616SWang Jie 		*cc = TYPEC_CC_RA;
1141a2c81616SWang Jie 
1142a2c81616SWang Jie 	return 0;
1143a2c81616SWang Jie }
1144a2c81616SWang Jie 
fusb302_handle_togdone_src(struct fusb302_chip * chip,u8 togdone_result)1145a2c81616SWang Jie static int fusb302_handle_togdone_src(struct fusb302_chip *chip,
1146a2c81616SWang Jie 				      u8 togdone_result)
1147a2c81616SWang Jie {
1148a2c81616SWang Jie 	/*
1149a2c81616SWang Jie 	 * - set polarity (measure cc, vconn, tx)
1150a2c81616SWang Jie 	 * - set pull_up, pull_down
1151a2c81616SWang Jie 	 * - set cc1, cc2, and update to tcpm_port
1152a2c81616SWang Jie 	 * - set I_COMP interrupt on
1153a2c81616SWang Jie 	 */
1154a2c81616SWang Jie 	int ret = 0;
1155a2c81616SWang Jie 	u8 rd_mda = rd_mda_value[chip->src_current_status];
1156a2c81616SWang Jie 	enum toggling_mode toggling_mode = chip->toggling_mode;
1157a2c81616SWang Jie 	enum typec_cc_polarity cc_polarity;
1158a2c81616SWang Jie 	enum typec_cc_status cc1, cc2;
1159a2c81616SWang Jie 
1160a2c81616SWang Jie 	/*
1161a2c81616SWang Jie 	 * The toggle-engine will stop in a src state if it sees either Ra or
1162a2c81616SWang Jie 	 * Rd. Determine the status for both CC pins, starting with the one
1163a2c81616SWang Jie 	 * where toggling stopped, as that is where the switches point now.
1164a2c81616SWang Jie 	 */
1165a2c81616SWang Jie 	if (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1)
1166a2c81616SWang Jie 		ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC1, &cc1);
1167a2c81616SWang Jie 	else
1168a2c81616SWang Jie 		ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC2, &cc2);
1169a2c81616SWang Jie 	if (ret)
1170a2c81616SWang Jie 		return ret;
1171a2c81616SWang Jie 	/* we must turn off toggling before we can measure the other pin */
1172a2c81616SWang Jie 	ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF);
1173a2c81616SWang Jie 	if (ret) {
1174a2c81616SWang Jie 		printf("cannot set toggling mode off, ret=%d\n", ret);
1175a2c81616SWang Jie 		return ret;
1176a2c81616SWang Jie 	}
1177a2c81616SWang Jie 	/* get the status of the other pin */
1178a2c81616SWang Jie 	if (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1)
1179a2c81616SWang Jie 		ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC2, &cc2);
1180a2c81616SWang Jie 	else
1181a2c81616SWang Jie 		ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC1, &cc1);
1182a2c81616SWang Jie 	if (ret)
1183a2c81616SWang Jie 		return ret;
1184a2c81616SWang Jie 
1185a2c81616SWang Jie 	/* determine polarity based on the status of both pins */
1186a2c81616SWang Jie 	if (cc1 == TYPEC_CC_RD &&
1187a2c81616SWang Jie 			(cc2 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_RA)) {
1188a2c81616SWang Jie 		cc_polarity = TYPEC_POLARITY_CC1;
1189a2c81616SWang Jie 	} else if (cc2 == TYPEC_CC_RD &&
1190a2c81616SWang Jie 		    (cc1 == TYPEC_CC_OPEN || cc1 == TYPEC_CC_RA)) {
1191a2c81616SWang Jie 		cc_polarity = TYPEC_POLARITY_CC2;
1192a2c81616SWang Jie 	} else {
1193a2c81616SWang Jie 		printf("unexpected CC status cc1=%s, cc2=%s, restarting toggling\n",
1194a2c81616SWang Jie 			typec_cc_status_name[cc1],
1195a2c81616SWang Jie 			typec_cc_status_name[cc2]);
1196a2c81616SWang Jie 		return fusb302_set_toggling(chip, toggling_mode);
1197a2c81616SWang Jie 	}
1198a2c81616SWang Jie 	/* set polarity and pull_up, pull_down */
1199a2c81616SWang Jie 	ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, true, false);
1200a2c81616SWang Jie 	if (ret < 0) {
1201a2c81616SWang Jie 		printf("cannot set cc polarity %s, ret=%d\n",
1202a2c81616SWang Jie 			cc_polarity_name[cc_polarity], ret);
1203a2c81616SWang Jie 		return ret;
1204a2c81616SWang Jie 	}
1205a2c81616SWang Jie 	/* update tcpm with the new cc value */
1206a2c81616SWang Jie 	if ((chip->cc1 != cc1) || (chip->cc2 != cc2)) {
1207a2c81616SWang Jie 		chip->cc1 = cc1;
1208a2c81616SWang Jie 		chip->cc2 = cc2;
1209a2c81616SWang Jie 		tcpm_cc_change(chip->tcpm_port);
1210a2c81616SWang Jie 	}
1211a2c81616SWang Jie 	/* set MDAC to Rd threshold, and unmask I_COMP for unplug detection */
1212a2c81616SWang Jie 	ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda);
1213a2c81616SWang Jie 	if (ret)
1214a2c81616SWang Jie 		return ret;
1215a2c81616SWang Jie 	/* unmask comp_chng interrupt */
1216a2c81616SWang Jie 	ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASK,
1217a2c81616SWang Jie 				     FUSB_REG_MASK_COMP_CHNG);
1218a2c81616SWang Jie 	if (ret) {
1219a2c81616SWang Jie 		printf("cannot unmask comp_chng interrupt, ret=%d\n", ret);
1220a2c81616SWang Jie 		return ret;
1221a2c81616SWang Jie 	}
1222a2c81616SWang Jie 	chip->intr_comp_chng = true;
1223a2c81616SWang Jie 	debug("detected cc1=%s, cc2=%s\n",
1224a2c81616SWang Jie 		typec_cc_status_name[cc1],
1225a2c81616SWang Jie 		typec_cc_status_name[cc2]);
1226a2c81616SWang Jie 
1227a2c81616SWang Jie 	return ret;
1228a2c81616SWang Jie }
1229a2c81616SWang Jie 
fusb302_handle_togdone(struct fusb302_chip * chip)1230a2c81616SWang Jie static int fusb302_handle_togdone(struct fusb302_chip *chip)
1231a2c81616SWang Jie {
1232a2c81616SWang Jie 	int ret = 0;
1233a2c81616SWang Jie 	u8 status1a;
1234a2c81616SWang Jie 	u8 togdone_result;
1235a2c81616SWang Jie 
1236a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS1A, &status1a);
1237a2c81616SWang Jie 	if (ret < 0)
1238a2c81616SWang Jie 		return ret;
1239a2c81616SWang Jie 	togdone_result = (status1a >> FUSB_REG_STATUS1A_TOGSS_POS) &
1240a2c81616SWang Jie 			 FUSB_REG_STATUS1A_TOGSS_MASK;
1241a2c81616SWang Jie 	switch (togdone_result) {
1242a2c81616SWang Jie 	case FUSB_REG_STATUS1A_TOGSS_SNK1:
1243a2c81616SWang Jie 	case FUSB_REG_STATUS1A_TOGSS_SNK2:
1244a2c81616SWang Jie 		return fusb302_handle_togdone_snk(chip, togdone_result);
1245a2c81616SWang Jie 	case FUSB_REG_STATUS1A_TOGSS_SRC1:
1246a2c81616SWang Jie 	case FUSB_REG_STATUS1A_TOGSS_SRC2:
1247a2c81616SWang Jie 		return fusb302_handle_togdone_src(chip, togdone_result);
1248a2c81616SWang Jie 	case FUSB_REG_STATUS1A_TOGSS_AA:
1249a2c81616SWang Jie 		/* doesn't support */
1250a2c81616SWang Jie 		printf("AudioAccessory not supported\n");
1251a2c81616SWang Jie 		fusb302_set_toggling(chip, chip->toggling_mode);
1252a2c81616SWang Jie 		break;
1253a2c81616SWang Jie 	default:
1254a2c81616SWang Jie 		printf("TOGDONE with an invalid state: %d\n", togdone_result);
1255a2c81616SWang Jie 		fusb302_set_toggling(chip, chip->toggling_mode);
1256a2c81616SWang Jie 		break;
1257a2c81616SWang Jie 	}
1258a2c81616SWang Jie 	return ret;
1259a2c81616SWang Jie }
1260a2c81616SWang Jie 
fusb302_pd_reset(struct fusb302_chip * chip)1261a2c81616SWang Jie static int fusb302_pd_reset(struct fusb302_chip *chip)
1262a2c81616SWang Jie {
1263a2c81616SWang Jie 	return fusb302_i2c_set_bits(chip, FUSB_REG_RESET,
1264a2c81616SWang Jie 				    FUSB_REG_RESET_PD_RESET);
1265a2c81616SWang Jie }
1266a2c81616SWang Jie 
fusb302_pd_read_message(struct fusb302_chip * chip,struct pd_message * msg)1267a2c81616SWang Jie static int fusb302_pd_read_message(struct fusb302_chip *chip,
1268a2c81616SWang Jie 				   struct pd_message *msg)
1269a2c81616SWang Jie {
1270a2c81616SWang Jie 	int ret = 0;
1271a2c81616SWang Jie 	u8 token;
1272a2c81616SWang Jie 	u8 crc[4];
1273a2c81616SWang Jie 	int len;
1274a2c81616SWang Jie 
1275a2c81616SWang Jie 	/* first SOP token */
1276a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_FIFOS, &token);
1277a2c81616SWang Jie 	if (ret)
1278a2c81616SWang Jie 		return ret;
1279a2c81616SWang Jie 	ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, 2,
1280a2c81616SWang Jie 				     (u8 *)&msg->header);
1281a2c81616SWang Jie 	if (ret)
1282a2c81616SWang Jie 		return ret;
1283a2c81616SWang Jie 	len = pd_header_cnt_le(msg->header) * 4;
1284a2c81616SWang Jie 	/* add 4 to length to include the CRC */
1285a2c81616SWang Jie 	if (len > PD_MAX_PAYLOAD * 4) {
1286a2c81616SWang Jie 		printf("%s: PD message too long %d\n", __func__, len);
1287a2c81616SWang Jie 		return -EINVAL;
1288a2c81616SWang Jie 	}
1289a2c81616SWang Jie 	if (len > 0) {
1290a2c81616SWang Jie 		ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, len,
1291a2c81616SWang Jie 					     (u8 *)msg->payload);
1292a2c81616SWang Jie 		if (ret)
1293a2c81616SWang Jie 			return ret;
1294a2c81616SWang Jie 	}
1295a2c81616SWang Jie 	/* another 4 bytes to read CRC out */
1296a2c81616SWang Jie 	ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, 4, crc);
1297a2c81616SWang Jie 	if (ret)
1298a2c81616SWang Jie 		return ret;
1299a2c81616SWang Jie 	debug("%s: PD message header: %x\n", __func__, msg->header);
1300a2c81616SWang Jie 	debug("%s: PD message len: %d\n", __func__, len);
1301a2c81616SWang Jie 
1302a2c81616SWang Jie 	/*
1303a2c81616SWang Jie 	 * Check if we've read off a GoodCRC message. If so then indicate to
1304a2c81616SWang Jie 	 * TCPM that the previous transmission has completed. Otherwise we pass
1305a2c81616SWang Jie 	 * the received message over to TCPM for processing.
1306a2c81616SWang Jie 	 *
1307a2c81616SWang Jie 	 * We make this check here instead of basing the reporting decision on
1308a2c81616SWang Jie 	 * the IRQ event type, as it's possible for the chip to report the
1309a2c81616SWang Jie 	 * TX_SUCCESS and GCRCSENT events out of order on occasion, so we need
1310a2c81616SWang Jie 	 * to check the message type to ensure correct reporting to TCPM.
1311a2c81616SWang Jie 	 */
1312a2c81616SWang Jie 	if ((!len) && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC))
1313a2c81616SWang Jie 		tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS);
1314a2c81616SWang Jie 	else
1315a2c81616SWang Jie 		tcpm_pd_receive(chip->tcpm_port, msg);
1316a2c81616SWang Jie 
1317a2c81616SWang Jie 	return ret;
1318a2c81616SWang Jie }
1319a2c81616SWang Jie 
fusb302_interrupt_handle(struct fusb302_chip * chip)1320a2c81616SWang Jie static void fusb302_interrupt_handle(struct fusb302_chip *chip)
1321a2c81616SWang Jie {
1322a2c81616SWang Jie 	int ret = 0;
1323a2c81616SWang Jie 	u8 interrupt;
1324a2c81616SWang Jie 	u8 interrupta;
1325a2c81616SWang Jie 	u8 interruptb;
1326a2c81616SWang Jie 	u8 status0;
1327a2c81616SWang Jie 	bool vbus_present;
1328a2c81616SWang Jie 	bool comp_result;
1329a2c81616SWang Jie 	bool intr_togdone;
1330a2c81616SWang Jie 	bool intr_bc_lvl;
1331a2c81616SWang Jie 	bool intr_comp_chng;
1332a2c81616SWang Jie 	struct pd_message pd_msg;
1333a2c81616SWang Jie 
1334a2c81616SWang Jie 	/* grab a snapshot of intr flags */
1335a2c81616SWang Jie 	intr_togdone = chip->intr_togdone;
1336a2c81616SWang Jie 	intr_bc_lvl = chip->intr_bc_lvl;
1337a2c81616SWang Jie 	intr_comp_chng = chip->intr_comp_chng;
1338a2c81616SWang Jie 
1339a2c81616SWang Jie 	if (chip->gpio_cc_int_present)
1340a2c81616SWang Jie 		if (!dm_gpio_get_value(&chip->gpio_cc_int))
1341a2c81616SWang Jie 			return;
1342a2c81616SWang Jie 
1343a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPT, &interrupt);
1344a2c81616SWang Jie 	if (ret)
1345a2c81616SWang Jie 		return;
1346a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPTA, &interrupta);
1347a2c81616SWang Jie 	if (ret)
1348a2c81616SWang Jie 		return;
1349a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPTB, &interruptb);
1350a2c81616SWang Jie 	if (ret)
1351a2c81616SWang Jie 		return;
1352a2c81616SWang Jie 	ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
1353a2c81616SWang Jie 	if (ret)
1354a2c81616SWang Jie 		return;
1355a2c81616SWang Jie 	debug("IRQ: 0x%02x, a: 0x%02x, b: 0x%02x, status0: 0x%02x\n",
1356a2c81616SWang Jie 		interrupt, interrupta, interruptb, status0);
1357a2c81616SWang Jie 
1358a2c81616SWang Jie 	if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) {
1359a2c81616SWang Jie 		vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK);
1360a2c81616SWang Jie 		debug("IRQ: VBUS_OK, vbus=%s\n", vbus_present ? "On" : "Off");
1361a2c81616SWang Jie 		if (vbus_present != chip->vbus_present) {
1362a2c81616SWang Jie 			chip->vbus_present = vbus_present;
1363a2c81616SWang Jie 			tcpm_vbus_change(chip->tcpm_port);
1364a2c81616SWang Jie 		}
1365a2c81616SWang Jie 	}
1366a2c81616SWang Jie 
1367a2c81616SWang Jie 	if ((interrupta & FUSB_REG_INTERRUPTA_TOGDONE) && intr_togdone) {
1368a2c81616SWang Jie 		debug("IRQ: TOGDONE\n");
1369a2c81616SWang Jie 		ret = fusb302_handle_togdone(chip);
1370a2c81616SWang Jie 		if (ret) {
1371a2c81616SWang Jie 			printf("%s: handle togdone error(%d)\n", __func__, ret);
1372a2c81616SWang Jie 			return;
1373a2c81616SWang Jie 		}
1374a2c81616SWang Jie 	}
1375a2c81616SWang Jie 
1376a2c81616SWang Jie 	if ((interrupt & FUSB_REG_INTERRUPT_BC_LVL) && intr_bc_lvl) {
1377a2c81616SWang Jie 		debug("IRQ: BC_LVL, handler pending\n");
1378a2c81616SWang Jie 		/*
1379a2c81616SWang Jie 		 * as BC_LVL interrupt can be affected by PD activity,
1380a2c81616SWang Jie 		 * apply delay to for the handler to wait for the PD
1381a2c81616SWang Jie 		 * signaling to finish.
1382a2c81616SWang Jie 		 */
1383a2c81616SWang Jie 		//msleep(T_BC_LVL_DEBOUNCE_DELAY_MS);
1384a2c81616SWang Jie 		fusb302_bc_lvl_handler(chip);
1385a2c81616SWang Jie 	}
1386a2c81616SWang Jie 
1387a2c81616SWang Jie 	if ((interrupt & FUSB_REG_INTERRUPT_COMP_CHNG) && intr_comp_chng) {
1388a2c81616SWang Jie 		comp_result = !!(status0 & FUSB_REG_STATUS0_COMP);
1389a2c81616SWang Jie 		debug("IRQ: COMP_CHNG, comp=%s\n", comp_result ? "true" : "false");
1390a2c81616SWang Jie 		if (comp_result) {
1391a2c81616SWang Jie 			/* cc level > Rd_threshold, detach */
1392a2c81616SWang Jie 			chip->cc1 = TYPEC_CC_OPEN;
1393a2c81616SWang Jie 			chip->cc2 = TYPEC_CC_OPEN;
1394a2c81616SWang Jie 			tcpm_cc_change(chip->tcpm_port);
1395a2c81616SWang Jie 		}
1396a2c81616SWang Jie 	}
1397a2c81616SWang Jie 
1398a2c81616SWang Jie 	if (interrupt & FUSB_REG_INTERRUPT_COLLISION) {
1399a2c81616SWang Jie 		debug("IRQ: PD collision\n");
1400a2c81616SWang Jie 		tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_FAILED);
1401a2c81616SWang Jie 	}
1402a2c81616SWang Jie 
1403a2c81616SWang Jie 	if (interrupta & FUSB_REG_INTERRUPTA_RETRYFAIL) {
1404a2c81616SWang Jie 		debug("IRQ: PD retry failed\n");
1405a2c81616SWang Jie 		tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_FAILED);
1406a2c81616SWang Jie 	}
1407a2c81616SWang Jie 
1408a2c81616SWang Jie 	if (interrupta & FUSB_REG_INTERRUPTA_HARDSENT) {
1409a2c81616SWang Jie 		debug("IRQ: PD hardreset sent\n");
1410a2c81616SWang Jie 		ret = fusb302_pd_reset(chip);
1411a2c81616SWang Jie 		if (ret) {
1412a2c81616SWang Jie 			printf("cannot PD reset, ret=%d\n", ret);
1413a2c81616SWang Jie 			return;
1414a2c81616SWang Jie 		}
1415a2c81616SWang Jie 		tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS);
1416a2c81616SWang Jie 	}
1417a2c81616SWang Jie 
1418a2c81616SWang Jie 	if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) {
1419a2c81616SWang Jie 		debug("IRQ: PD tx success\n");
1420a2c81616SWang Jie 		ret = fusb302_pd_read_message(chip, &pd_msg);
1421a2c81616SWang Jie 		if (ret) {
1422a2c81616SWang Jie 			printf("cannot read in PD message, ret=%d\n", ret);
1423a2c81616SWang Jie 			return;
1424a2c81616SWang Jie 		}
1425a2c81616SWang Jie 	}
1426a2c81616SWang Jie 
1427a2c81616SWang Jie 	if (interrupta & FUSB_REG_INTERRUPTA_HARDRESET) {
1428a2c81616SWang Jie 		debug("IRQ: PD received hardreset\n");
1429a2c81616SWang Jie 		ret = fusb302_pd_reset(chip);
1430a2c81616SWang Jie 		if (ret) {
1431a2c81616SWang Jie 			printf("cannot PD reset, ret=%d\n", ret);
1432a2c81616SWang Jie 			return;
1433a2c81616SWang Jie 		}
1434a2c81616SWang Jie 		tcpm_pd_hard_reset(chip->tcpm_port);
1435a2c81616SWang Jie 	}
1436a2c81616SWang Jie 
1437a2c81616SWang Jie 	if (interruptb & FUSB_REG_INTERRUPTB_GCRCSENT) {
1438a2c81616SWang Jie 		debug("IRQ: PD sent good CRC\n");
1439a2c81616SWang Jie 		ret = fusb302_pd_read_message(chip, &pd_msg);
1440a2c81616SWang Jie 		if (ret) {
1441a2c81616SWang Jie 			printf("cannot read in PD message, ret=%d\n", ret);
1442a2c81616SWang Jie 			return;
1443a2c81616SWang Jie 		}
1444a2c81616SWang Jie 	}
1445a2c81616SWang Jie }
1446a2c81616SWang Jie 
fusb302_probe(struct udevice * dev)1447a2c81616SWang Jie static int fusb302_probe(struct udevice *dev)
1448a2c81616SWang Jie {
1449a2c81616SWang Jie 	struct fusb302_chip *chip = dev_get_priv(dev);
1450a2c81616SWang Jie 	int ret = 0;
1451a2c81616SWang Jie 
1452a2c81616SWang Jie 	chip->udev = dev;
1453a2c81616SWang Jie 
1454a2c81616SWang Jie #if 0
1455a2c81616SWang Jie 	/* get vbus regulator */
1456a2c81616SWang Jie 	ret = regulator_get_by_platname("vbus5v0_typec", chip->vbus_regulator);
1457a2c81616SWang Jie 	if (ret) {
1458a2c81616SWang Jie 		printf("Can get the regulator: vbus5v0_typec (err=%d)\n", ret);
1459a2c81616SWang Jie 		chip->vbus_regulator = NULL;
1460a2c81616SWang Jie 	}
1461a2c81616SWang Jie #endif
1462a2c81616SWang Jie 
1463a2c81616SWang Jie 	chip->tcpc_dev.connector_node = dev_read_subnode(dev, "connector");
1464a2c81616SWang Jie 	if (!ofnode_valid(chip->tcpc_dev.connector_node)) {
1465a2c81616SWang Jie 		printf("%s: 'connector' node is not found\n", __func__);
1466a2c81616SWang Jie 		return -ENODEV;
1467a2c81616SWang Jie 	}
1468a2c81616SWang Jie 
1469a2c81616SWang Jie 	init_tcpc_dev(&chip->tcpc_dev);
1470a2c81616SWang Jie 
1471a2c81616SWang Jie 	ret = gpio_request_by_name(dev, "int-n-gpios", 0,
1472a2c81616SWang Jie 				   &chip->gpio_cc_int, GPIOD_IS_IN);
1473a2c81616SWang Jie 	if (ret) {
1474a2c81616SWang Jie 		printf("%s: fail to get int GPIO: ret=%d\n", __func__, ret);
1475a2c81616SWang Jie 		chip->gpio_cc_int_present = false;
1476a2c81616SWang Jie 	} else {
1477a2c81616SWang Jie 		chip->gpio_cc_int_present = true;
1478a2c81616SWang Jie 	}
1479a2c81616SWang Jie 
1480a2c81616SWang Jie 	chip->tcpm_port = tcpm_port_init(dev, &chip->tcpc_dev);
1481a2c81616SWang Jie 	if (IS_ERR(chip->tcpm_port)) {
1482a2c81616SWang Jie 		printf("%s: failed to tcpm port init\n", __func__);
1483a2c81616SWang Jie 		return PTR_ERR(chip->tcpm_port);
1484a2c81616SWang Jie 	}
1485a2c81616SWang Jie 
1486a2c81616SWang Jie 	tcpm_poll_event(chip->tcpm_port);
1487a2c81616SWang Jie 
1488a2c81616SWang Jie 	return 0;
1489a2c81616SWang Jie }
1490a2c81616SWang Jie 
1491a2c81616SWang Jie 
fusb302_get_voltage(struct udevice * dev)1492a2c81616SWang Jie static int fusb302_get_voltage(struct udevice *dev)
1493a2c81616SWang Jie {
1494a2c81616SWang Jie 	struct fusb302_chip *chip = dev_get_priv(dev);
1495a2c81616SWang Jie 
1496a2c81616SWang Jie 	return tcpm_get_voltage(chip->tcpm_port);
1497a2c81616SWang Jie }
1498a2c81616SWang Jie 
fusb302_get_current(struct udevice * dev)1499a2c81616SWang Jie static int fusb302_get_current(struct udevice *dev)
1500a2c81616SWang Jie {
1501a2c81616SWang Jie 	struct fusb302_chip *chip = dev_get_priv(dev);
1502a2c81616SWang Jie 
1503a2c81616SWang Jie 	return tcpm_get_current(chip->tcpm_port);
1504a2c81616SWang Jie }
1505a2c81616SWang Jie 
fusb302_get_online(struct udevice * dev)1506a2c81616SWang Jie static int fusb302_get_online(struct udevice *dev)
1507a2c81616SWang Jie {
1508a2c81616SWang Jie 	struct fusb302_chip *chip = dev_get_priv(dev);
1509a2c81616SWang Jie 
1510a2c81616SWang Jie 	return tcpm_get_online(chip->tcpm_port);
1511a2c81616SWang Jie }
1512a2c81616SWang Jie 
1513a2c81616SWang Jie static struct dm_power_delivery_ops fusb302_ops = {
1514a2c81616SWang Jie 	.get_voltage = fusb302_get_voltage,
1515a2c81616SWang Jie 	.get_current = fusb302_get_current,
1516a2c81616SWang Jie 	.get_online = fusb302_get_online,
1517a2c81616SWang Jie };
1518a2c81616SWang Jie 
1519a2c81616SWang Jie static const struct udevice_id fusb302_ids[] = {
1520a2c81616SWang Jie 	{ .compatible = "fcs,fusb302" },
1521a2c81616SWang Jie 	{ }
1522a2c81616SWang Jie };
1523a2c81616SWang Jie 
1524a2c81616SWang Jie U_BOOT_DRIVER(fusb302) = {
1525a2c81616SWang Jie 	.name = "fusb302",
1526a2c81616SWang Jie 	.id = UCLASS_PD,
1527a2c81616SWang Jie 	.of_match = fusb302_ids,
1528a2c81616SWang Jie 	.ops = &fusb302_ops,
1529a2c81616SWang Jie 	.probe = fusb302_probe,
1530a2c81616SWang Jie 	.priv_auto_alloc_size = sizeof(struct fusb302_chip),
1531a2c81616SWang Jie };
1532*65f336e5SZain Wang 
do_pd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])1533*65f336e5SZain Wang static int do_pd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1534*65f336e5SZain Wang {
1535*65f336e5SZain Wang 	struct power_delivery_data power_data;
1536*65f336e5SZain Wang 	struct udevice *dev;
1537*65f336e5SZain Wang 	int ret;
1538*65f336e5SZain Wang 
1539*65f336e5SZain Wang 	ret = uclass_get_device(UCLASS_PD, 0, &dev);
1540*65f336e5SZain Wang 	if (ret)
1541*65f336e5SZain Wang 		return ret;
1542*65f336e5SZain Wang 
1543*65f336e5SZain Wang 	ret = power_delivery_get_data(dev, &power_data);
1544*65f336e5SZain Wang 	if (ret)
1545*65f336e5SZain Wang 		return ret;
1546*65f336e5SZain Wang 
1547*65f336e5SZain Wang 	if (power_data.online && power_data.current)
1548*65f336e5SZain Wang 		printf("Found Type-C PD, Set Power %dmV, %dmA\n",
1549*65f336e5SZain Wang 		       power_data.voltage, power_data.current);
1550*65f336e5SZain Wang 	else
1551*65f336e5SZain Wang 		printf("No Type-C PD found\n");
1552*65f336e5SZain Wang 
1553*65f336e5SZain Wang 	return 0;
1554*65f336e5SZain Wang }
1555*65f336e5SZain Wang 
1556*65f336e5SZain Wang U_BOOT_CMD(pd, 1, 0, do_pd, "pd default, select power from dtb", "pd");
1557