xref: /rk3399_rockchip-uboot/drivers/video/drm/display-serdes/serdes-core.c (revision 77c57384925823ac7325dead6d2664651a86d016)
1fb0c3269SLuo Wei // SPDX-License-Identifier: GPL-2.0-or-later
2fb0c3269SLuo Wei /*
3fb0c3269SLuo Wei  * serdes-i2c.c  --  display i2c for different serdes chips
4fb0c3269SLuo Wei  *
5fb0c3269SLuo Wei  * Copyright (c) 2023 Rockchip Electronics Co. Ltd.
6fb0c3269SLuo Wei  *
7fb0c3269SLuo Wei  * Author: luowei <lw@rock-chips.com>
8fb0c3269SLuo Wei  */
9fb0c3269SLuo Wei 
10fb0c3269SLuo Wei #include "core.h"
11fb0c3269SLuo Wei 
dm_i2c_reg_write_u8(struct udevice * dev,u8 reg,u8 val)12fb0c3269SLuo Wei static int dm_i2c_reg_write_u8(struct udevice *dev, u8 reg, u8 val)
13fb0c3269SLuo Wei {
14fb0c3269SLuo Wei 	int ret;
15fb0c3269SLuo Wei 	u8 buf[2];
16fb0c3269SLuo Wei 	struct i2c_msg msg;
17fb0c3269SLuo Wei 	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
18fb0c3269SLuo Wei 
19fb0c3269SLuo Wei 	buf[0] = reg;
20fb0c3269SLuo Wei 	buf[1] = val;
21fb0c3269SLuo Wei 	msg.addr = chip->chip_addr;
22fb0c3269SLuo Wei 	msg.flags = 0;
23fb0c3269SLuo Wei 	msg.len = 2;
24fb0c3269SLuo Wei 	msg.buf = buf;
25fb0c3269SLuo Wei 
26fb0c3269SLuo Wei 	ret = dm_i2c_xfer(dev, &msg, 1);
27fb0c3269SLuo Wei 	if (ret) {
28fb0c3269SLuo Wei 		printf("dm i2c write failed: %d\n", ret);
29fb0c3269SLuo Wei 		return ret;
30fb0c3269SLuo Wei 	}
31fb0c3269SLuo Wei 
32fb0c3269SLuo Wei 	return 0;
33fb0c3269SLuo Wei }
34fb0c3269SLuo Wei 
dm_i2c_reg_read_u8(struct udevice * dev,u8 reg)35fb0c3269SLuo Wei static uint8_t dm_i2c_reg_read_u8(struct udevice *dev, u8 reg)
36fb0c3269SLuo Wei {
37fb0c3269SLuo Wei 	int ret;
38fb0c3269SLuo Wei 	u8 data;
39fb0c3269SLuo Wei 	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
40fb0c3269SLuo Wei 	struct i2c_msg msg[] = {
41fb0c3269SLuo Wei 		{
42fb0c3269SLuo Wei 			.addr = chip->chip_addr,
43fb0c3269SLuo Wei 			.flags = 0,
44fb0c3269SLuo Wei 			.buf = (u8 *)&reg,
45fb0c3269SLuo Wei 			.len = 1,
46fb0c3269SLuo Wei 		}, {
47fb0c3269SLuo Wei 			.addr = chip->chip_addr,
48fb0c3269SLuo Wei 			.flags = I2C_M_RD,
49fb0c3269SLuo Wei 			.buf = (u8 *)&data,
50fb0c3269SLuo Wei 			.len = 1,
51fb0c3269SLuo Wei 		}
52fb0c3269SLuo Wei 	};
53fb0c3269SLuo Wei 
54fb0c3269SLuo Wei 	ret = dm_i2c_xfer(dev, msg, 2);
55fb0c3269SLuo Wei 	if (ret) {
56fb0c3269SLuo Wei 		printf("dm i2c read failed: %d\n", ret);
57fb0c3269SLuo Wei 		return ret;
58fb0c3269SLuo Wei 	}
59fb0c3269SLuo Wei 
60fb0c3269SLuo Wei 	return data;
61fb0c3269SLuo Wei }
62fb0c3269SLuo Wei 
dm_i2c_reg_clrset_u8(struct udevice * dev,u8 offset,u8 clr,u8 set)63fb0c3269SLuo Wei static int dm_i2c_reg_clrset_u8(struct udevice *dev,
64fb0c3269SLuo Wei 				u8 offset,
65fb0c3269SLuo Wei 				u8 clr, u8 set)
66fb0c3269SLuo Wei {
67fb0c3269SLuo Wei 	u8 val;
68fb0c3269SLuo Wei 
69fb0c3269SLuo Wei 	val = dm_i2c_reg_read_u8(dev, offset);
70fb0c3269SLuo Wei 	if (val < 0)
71fb0c3269SLuo Wei 		return val;
72fb0c3269SLuo Wei 
73fb0c3269SLuo Wei 	val &= ~clr;
74fb0c3269SLuo Wei 	val |= set;
75fb0c3269SLuo Wei 
76fb0c3269SLuo Wei 	return dm_i2c_reg_write_u8(dev, offset, val);
77fb0c3269SLuo Wei }
78fb0c3269SLuo Wei 
79fb0c3269SLuo Wei /**
80fb0c3269SLuo Wei  * serdes_reg_read: Read a single serdes register.
81fb0c3269SLuo Wei  *
82fb0c3269SLuo Wei  * @serdes: Device to read from.
83fb0c3269SLuo Wei  * @reg: Register to read.
84fb0c3269SLuo Wei  * @val: Date read from register.
85fb0c3269SLuo Wei  */
serdes_reg_read(struct serdes * serdes,unsigned int reg,unsigned int * val)86fb0c3269SLuo Wei int serdes_reg_read(struct serdes *serdes,
87fb0c3269SLuo Wei 		    unsigned int reg, unsigned int *val)
88fb0c3269SLuo Wei {
89fb0c3269SLuo Wei 	unsigned int value;
90fb0c3269SLuo Wei 
91fb0c3269SLuo Wei 	if (serdes->chip_data->reg_val_type == REG_8BIT_VAL_8IT)
92fb0c3269SLuo Wei 		value = dm_i2c_reg_read_u8(serdes->dev, reg);
93fb0c3269SLuo Wei 	else
94fb0c3269SLuo Wei 		value = dm_i2c_reg_read(serdes->dev, reg);
95fb0c3269SLuo Wei 
96fb0c3269SLuo Wei 	*val = value;
97fb0c3269SLuo Wei 	SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x\n",
98fb0c3269SLuo Wei 		       __func__, serdes->dev->name,
99fb0c3269SLuo Wei 		       serdes->dev->name, reg, *val);
100fb0c3269SLuo Wei 	return 0;
101fb0c3269SLuo Wei }
102fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_reg_read);
103fb0c3269SLuo Wei 
104fb0c3269SLuo Wei /**
105fb0c3269SLuo Wei  * serdes_reg_write: Write a single serdes register.
106fb0c3269SLuo Wei  *
107fb0c3269SLuo Wei  * @serdes: Device to write to.
108fb0c3269SLuo Wei  * @reg: Register to write to.
109fb0c3269SLuo Wei  * @val: Value to write.
110fb0c3269SLuo Wei  */
serdes_reg_write(struct serdes * serdes,unsigned int reg,unsigned int val)111fb0c3269SLuo Wei int serdes_reg_write(struct serdes *serdes, unsigned int reg,
112fb0c3269SLuo Wei 		     unsigned int val)
113fb0c3269SLuo Wei {
114fb0c3269SLuo Wei 	int ret = 0;
115fb0c3269SLuo Wei 
116fb0c3269SLuo Wei 	SERDES_DBG_I2C("%s %s Write Reg%04x %04x) type=%d\n",
117fb0c3269SLuo Wei 		       __func__, serdes->dev->name,
118fb0c3269SLuo Wei 		       reg, val, serdes->chip_data->reg_val_type);
119fb0c3269SLuo Wei 	if (serdes->chip_data->reg_val_type == REG_8BIT_VAL_8IT) {
120fb0c3269SLuo Wei 		ret = dm_i2c_reg_write_u8(serdes->dev, reg, val);
121fb0c3269SLuo Wei 		if (ret != 0)
122fb0c3269SLuo Wei 			return ret;
123fb0c3269SLuo Wei 	} else {
124fb0c3269SLuo Wei 		ret = dm_i2c_reg_write(serdes->dev, reg, val);
125fb0c3269SLuo Wei 		if (ret != 0)
126fb0c3269SLuo Wei 			return ret;
127fb0c3269SLuo Wei 	}
128fb0c3269SLuo Wei 
129fb0c3269SLuo Wei 	return ret;
130fb0c3269SLuo Wei }
131fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_reg_write);
132fb0c3269SLuo Wei 
133fb0c3269SLuo Wei /**
134fb0c3269SLuo Wei  * serdes_multi_reg_write: Write many serdes register.
135fb0c3269SLuo Wei  *
136fb0c3269SLuo Wei  * @serdes: Device to write to.
137fb0c3269SLuo Wei  * @regs: Registers to write to.
138fb0c3269SLuo Wei  * @num_regs: Number of registers to write.
139fb0c3269SLuo Wei  */
serdes_multi_reg_write(struct serdes * serdes,const struct reg_sequence * regs,int num_regs)140fb0c3269SLuo Wei int serdes_multi_reg_write(struct serdes *serdes,
141fb0c3269SLuo Wei 			   const struct reg_sequence *regs,
142fb0c3269SLuo Wei 			   int num_regs)
143fb0c3269SLuo Wei {
144fb0c3269SLuo Wei 	int i, ret = 0;
145fb0c3269SLuo Wei 
146fb0c3269SLuo Wei 	SERDES_DBG_I2C("%s %s %s num=%d\n", __func__, serdes->dev->name,
147fb0c3269SLuo Wei 		       serdes->chip_data->name, num_regs);
148fb0c3269SLuo Wei 
149fb0c3269SLuo Wei 	for (i = 0; i < num_regs; i++) {
150fb0c3269SLuo Wei 		ret = serdes_reg_write(serdes, regs[i].reg, regs[i].def);
151fb0c3269SLuo Wei 		SERDES_DBG_I2C("serdes %s Write Reg%04x %04x ret=%d\n",
152fb0c3269SLuo Wei 			       serdes->chip_data->name,
153fb0c3269SLuo Wei 			       regs[i].reg, regs[i].def, ret);
154fb0c3269SLuo Wei 	}
155fb0c3269SLuo Wei 
156fb0c3269SLuo Wei 	return ret;
157fb0c3269SLuo Wei }
158fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_multi_reg_write);
159fb0c3269SLuo Wei 
160fb0c3269SLuo Wei /**
161fb0c3269SLuo Wei  * serdes_set_bits: Set the value of a bitfield in a serdes register
162fb0c3269SLuo Wei  *
163fb0c3269SLuo Wei  * @serdes: Device to write to.
164fb0c3269SLuo Wei  * @reg: Register to write to.
165fb0c3269SLuo Wei  * @mask: Mask of bits to set.
166fb0c3269SLuo Wei  * @val: Value to set (unshifted)
167fb0c3269SLuo Wei  */
serdes_set_bits(struct serdes * serdes,unsigned int reg,unsigned int mask,unsigned int val)168fb0c3269SLuo Wei int serdes_set_bits(struct serdes *serdes, unsigned int reg,
169fb0c3269SLuo Wei 		    unsigned int mask, unsigned int val)
170fb0c3269SLuo Wei {
171fb0c3269SLuo Wei 	int ret = 0;
172fb0c3269SLuo Wei 
173fb0c3269SLuo Wei 	SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x) mask=%04x\n",
174fb0c3269SLuo Wei 		       __func__,
175fb0c3269SLuo Wei 		       serdes->dev->name,
176fb0c3269SLuo Wei 		       serdes->dev->name, reg, val, mask);
177fb0c3269SLuo Wei 
178fb0c3269SLuo Wei 	if (serdes->chip_data->reg_val_type == REG_8BIT_VAL_8IT)
179fb0c3269SLuo Wei 		ret = dm_i2c_reg_clrset_u8(serdes->dev, reg, mask, val);
180fb0c3269SLuo Wei 	else
181fb0c3269SLuo Wei 		ret = dm_i2c_reg_clrset(serdes->dev, reg, mask, val);
182fb0c3269SLuo Wei 
183fb0c3269SLuo Wei 	return ret;
184fb0c3269SLuo Wei }
185fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_set_bits);
186fb0c3269SLuo Wei 
serdes_i2c_set_sequence(struct serdes * serdes)187fb0c3269SLuo Wei int serdes_i2c_set_sequence(struct serdes *serdes)
188fb0c3269SLuo Wei {
189fb0c3269SLuo Wei 	int i, ret = 0;
190fb0c3269SLuo Wei 	unsigned int def = 0;
191fb0c3269SLuo Wei 
1923fc0646aSZitong Cai 	if (serdes->mcu_enable) {
193*77c57384SZitong Cai 		printf("serdes %s i2c set sequence in MCU\n",
194*77c57384SZitong Cai 		       serdes->dev->name);
1953fc0646aSZitong Cai 		return 0;
1963fc0646aSZitong Cai 	}
1973fc0646aSZitong Cai 
198fb0c3269SLuo Wei 	for (i = 0; i < serdes->serdes_init_seq->reg_seq_cnt; i++) {
199fb0c3269SLuo Wei 		if (serdes->serdes_init_seq->reg_sequence[i].reg == 0xffff) {
200fb0c3269SLuo Wei 			SERDES_DBG_MFD("%s: delay 0x%04x us\n", __func__,
201fb0c3269SLuo Wei 				       serdes->serdes_init_seq->reg_sequence[i].def);
202fb0c3269SLuo Wei 			udelay(serdes->serdes_init_seq->reg_sequence[i].def);
203fb0c3269SLuo Wei 			continue;
204fb0c3269SLuo Wei 		}
205fb0c3269SLuo Wei 
206fb0c3269SLuo Wei 		ret = serdes_reg_write(serdes,
207fb0c3269SLuo Wei 				       serdes->serdes_init_seq->reg_sequence[i].reg,
208fb0c3269SLuo Wei 				       serdes->serdes_init_seq->reg_sequence[i].def);
209fb0c3269SLuo Wei 
210fb0c3269SLuo Wei 		if (ret < 0) {
211fb0c3269SLuo Wei 			SERDES_DBG_MFD("failed to write reg %04x, ret %d\n",
212fb0c3269SLuo Wei 				       serdes->serdes_init_seq->reg_sequence[i].reg, ret);
213fb0c3269SLuo Wei 			ret = serdes_reg_write(serdes,
214fb0c3269SLuo Wei 					       serdes->serdes_init_seq->reg_sequence[i].reg,
215fb0c3269SLuo Wei 					       serdes->serdes_init_seq->reg_sequence[i].def);
216fb0c3269SLuo Wei 		}
217fb0c3269SLuo Wei 		serdes_reg_read(serdes, serdes->serdes_init_seq->reg_sequence[i].reg, &def);
218fb0c3269SLuo Wei 		if ((def != serdes->serdes_init_seq->reg_sequence[i].def) || (ret < 0)) {
219fb0c3269SLuo Wei 			/*if read value != write value then write again*/
220fb0c3269SLuo Wei 			printf("%s read %04x %04x != %04x\n", serdes->dev->name,
221fb0c3269SLuo Wei 			       serdes->serdes_init_seq->reg_sequence[i].reg,
222fb0c3269SLuo Wei 			       def, serdes->serdes_init_seq->reg_sequence[i].def);
223fb0c3269SLuo Wei 			ret = serdes_reg_write(serdes,
224fb0c3269SLuo Wei 					       serdes->serdes_init_seq->reg_sequence[i].reg,
225fb0c3269SLuo Wei 					       serdes->serdes_init_seq->reg_sequence[i].def);
226fb0c3269SLuo Wei 		}
227fb0c3269SLuo Wei 	}
228fb0c3269SLuo Wei 
229d1fd9c74SLuo Wei 	/* workaround */
230d1fd9c74SLuo Wei 	if (serdes->chip_data->serdes_id == MAXIM_ID_MAX96752) {
231d1fd9c74SLuo Wei 		ret = serdes_reg_write(serdes, 0x10, 0x21);
232d1fd9c74SLuo Wei 		mdelay(10);
233d1fd9c74SLuo Wei 		printf("%s reset oneshot max96752\n", serdes->dev->name);
234d1fd9c74SLuo Wei 	}
235d1fd9c74SLuo Wei 
236fb0c3269SLuo Wei 	SERDES_DBG_MFD("serdes %s sequence_init\n", serdes->dev->name);
237fb0c3269SLuo Wei 
238fb0c3269SLuo Wei 	return ret;
239fb0c3269SLuo Wei }
240fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_i2c_set_sequence);
241fb0c3269SLuo Wei 
serdes_parse_init_seq(struct udevice * dev,const u16 * data,int length,struct serdes_init_seq * seq)242fb0c3269SLuo Wei int serdes_parse_init_seq(struct udevice *dev, const u16 *data,
243fb0c3269SLuo Wei 			  int length, struct serdes_init_seq *seq)
244fb0c3269SLuo Wei {
245fb0c3269SLuo Wei 	struct reg_sequence *reg_sequence;
246fb0c3269SLuo Wei 	u16 *buf, *d;
247fb0c3269SLuo Wei 	unsigned int i, cnt;
248fb0c3269SLuo Wei 	int ret;
249fb0c3269SLuo Wei 
250fb0c3269SLuo Wei 	if (!seq)
251fb0c3269SLuo Wei 		return -EINVAL;
252fb0c3269SLuo Wei 
253fb0c3269SLuo Wei 	buf = calloc(1, length);
254fb0c3269SLuo Wei 	if (!buf)
255fb0c3269SLuo Wei 		return -ENOMEM;
256fb0c3269SLuo Wei 
257fb0c3269SLuo Wei 	memcpy(buf, data, length);
258fb0c3269SLuo Wei 
259fb0c3269SLuo Wei 	d = buf;
260fb0c3269SLuo Wei 	cnt = length / 4;
261fb0c3269SLuo Wei 	seq->reg_seq_cnt = cnt;
262fb0c3269SLuo Wei 
263fb0c3269SLuo Wei 	seq->reg_sequence = calloc(cnt, sizeof(struct reg_sequence));
264fb0c3269SLuo Wei 	if (!seq->reg_sequence) {
265fb0c3269SLuo Wei 		ret = -ENOMEM;
266fb0c3269SLuo Wei 		goto free_buf;
267fb0c3269SLuo Wei 	}
268fb0c3269SLuo Wei 
269fb0c3269SLuo Wei 	for (i = 0; i < cnt; i++) {
270fb0c3269SLuo Wei 		reg_sequence = &seq->reg_sequence[i];
271fb0c3269SLuo Wei 		reg_sequence->reg = get_unaligned_be16(&d[0]);
272fb0c3269SLuo Wei 		reg_sequence->def = get_unaligned_be16(&d[1]);
273fb0c3269SLuo Wei 		d += 2;
274fb0c3269SLuo Wei 	}
275fb0c3269SLuo Wei 
276fb0c3269SLuo Wei 	return 0;
277fb0c3269SLuo Wei 
278fb0c3269SLuo Wei free_buf:
279fb0c3269SLuo Wei 	free(buf);
280fb0c3269SLuo Wei 
281fb0c3269SLuo Wei 	return ret;
282fb0c3269SLuo Wei }
283fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_parse_init_seq);
284fb0c3269SLuo Wei 
serdes_get_init_seq(struct serdes * serdes)285fb0c3269SLuo Wei int serdes_get_init_seq(struct serdes *serdes)
286fb0c3269SLuo Wei {
287fb0c3269SLuo Wei 	const void *data = NULL;
288fb0c3269SLuo Wei 	int len, err;
289fb0c3269SLuo Wei 
290fb0c3269SLuo Wei 	data = dev_read_prop(serdes->dev, "serdes-init-sequence", &len);
291fb0c3269SLuo Wei 	if (!data) {
292fb0c3269SLuo Wei 		printf("failed to get serdes-init-sequence\n");
293fb0c3269SLuo Wei 		return -EINVAL;
294fb0c3269SLuo Wei 	}
295fb0c3269SLuo Wei 
296fb0c3269SLuo Wei 	serdes->serdes_init_seq = calloc(1, sizeof(*serdes->serdes_init_seq));
297fb0c3269SLuo Wei 	if (!serdes->serdes_init_seq)
298fb0c3269SLuo Wei 		return -ENOMEM;
299fb0c3269SLuo Wei 
300fb0c3269SLuo Wei 	err = serdes_parse_init_seq(serdes->dev,
301fb0c3269SLuo Wei 				    data, len, serdes->serdes_init_seq);
302fb0c3269SLuo Wei 	if (err) {
303fb0c3269SLuo Wei 		printf("failed to parse serdes-init-sequence\n");
304fb0c3269SLuo Wei 		goto free_init_seq;
305fb0c3269SLuo Wei 	}
306fb0c3269SLuo Wei 
307fb0c3269SLuo Wei 	return 0;
308fb0c3269SLuo Wei 
309fb0c3269SLuo Wei free_init_seq:
310fb0c3269SLuo Wei 	free(serdes->serdes_init_seq);
311fb0c3269SLuo Wei 
312fb0c3269SLuo Wei 	return err;
313fb0c3269SLuo Wei }
314fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_get_init_seq);
315fb0c3269SLuo Wei 
serdes_gpio_register(struct udevice * dev)316*77c57384SZitong Cai int serdes_gpio_register(struct udevice *dev)
317fb0c3269SLuo Wei {
318fb0c3269SLuo Wei 	bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
319fb0c3269SLuo Wei 	struct uclass_driver *drv;
320fb0c3269SLuo Wei 	int ret = -ENODEV;
321fb0c3269SLuo Wei 	const char *name;
322*77c57384SZitong Cai 	const char *status;
323fb0c3269SLuo Wei 	ofnode subnode;
324fb0c3269SLuo Wei 	struct udevice *subdev;
325fb0c3269SLuo Wei 	struct udevice *gpio_dev;
326fb0c3269SLuo Wei 
327fb0c3269SLuo Wei 	SERDES_DBG_MFD("%s node=%s\n",
328fb0c3269SLuo Wei 		       __func__, ofnode_get_name(dev->node));
329fb0c3269SLuo Wei 
330fb0c3269SLuo Wei 	/* Lookup GPIO driver */
331fb0c3269SLuo Wei 	drv = lists_uclass_lookup(UCLASS_GPIO);
332fb0c3269SLuo Wei 	if (!drv) {
333fb0c3269SLuo Wei 		printf("Cannot find GPIO driver\n");
334fb0c3269SLuo Wei 		return -ENOENT;
335fb0c3269SLuo Wei 	}
336fb0c3269SLuo Wei 
337fb0c3269SLuo Wei 	dev_for_each_subnode(subnode, dev) {
338fb0c3269SLuo Wei 		if (pre_reloc_only &&
339fb0c3269SLuo Wei 		    !ofnode_pre_reloc(subnode))
340fb0c3269SLuo Wei 			continue;
341fb0c3269SLuo Wei 
342fb0c3269SLuo Wei 		name = ofnode_get_name(subnode);
343fb0c3269SLuo Wei 		if (!name)
344fb0c3269SLuo Wei 			continue;
345fb0c3269SLuo Wei 
346fb0c3269SLuo Wei 		if (strstr(name, "gpio")) {
347*77c57384SZitong Cai 			status = ofnode_read_string(subnode, "status");
348*77c57384SZitong Cai 			if (status && strcmp(status, "okay") != 0) {
349*77c57384SZitong Cai 				SERDES_DBG_MFD("%s node=%s status=%s, exit\n",
350*77c57384SZitong Cai 					       __func__, name, status);
351*77c57384SZitong Cai 				return 0;
352*77c57384SZitong Cai 			}
353*77c57384SZitong Cai 
354fb0c3269SLuo Wei 			ret = device_bind_driver_to_node(dev,
355fb0c3269SLuo Wei 							 "serdes-gpio", name,
356fb0c3269SLuo Wei 							 subnode, &subdev);
357*77c57384SZitong Cai 			if (ret) {
358*77c57384SZitong Cai 				printf("Cannot find serdes gpio driver\n");
359fb0c3269SLuo Wei 				return ret;
360*77c57384SZitong Cai 			}
361fb0c3269SLuo Wei 
362fb0c3269SLuo Wei 			ret = uclass_get_device_by_ofnode(UCLASS_GPIO,
363fb0c3269SLuo Wei 							  subnode,
364fb0c3269SLuo Wei 							  &gpio_dev);
365fb0c3269SLuo Wei 			if (ret) {
366fb0c3269SLuo Wei 				printf("%s failed to get gpio dev\n", __func__);
367fb0c3269SLuo Wei 				return ret;
368fb0c3269SLuo Wei 			}
369fb0c3269SLuo Wei 
370fb0c3269SLuo Wei 			SERDES_DBG_MFD("%s select %s gpio_dev=%s\n",
371fb0c3269SLuo Wei 				       __func__, name, gpio_dev->name);
372fb0c3269SLuo Wei 			return 0;
373fb0c3269SLuo Wei 		}
374fb0c3269SLuo Wei 	}
375fb0c3269SLuo Wei 
376fb0c3269SLuo Wei 	return ret;
377fb0c3269SLuo Wei }
378fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_gpio_register);
379fb0c3269SLuo Wei 
serdes_pinctrl_register(struct udevice * dev)380*77c57384SZitong Cai int serdes_pinctrl_register(struct udevice *dev)
381fb0c3269SLuo Wei {
382fb0c3269SLuo Wei 	bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
383fb0c3269SLuo Wei 	struct uclass_driver *drv;
384fb0c3269SLuo Wei 	int ret = -ENODEV;
385fb0c3269SLuo Wei 	const char *name;
386*77c57384SZitong Cai 	const char *status;
387fb0c3269SLuo Wei 	ofnode subnode;
388fb0c3269SLuo Wei 	struct udevice *subdev;
389fb0c3269SLuo Wei 	struct udevice *pinctrl_dev;
390*77c57384SZitong Cai 	struct serdes *serdes = dev_get_priv(dev);
391fb0c3269SLuo Wei 
392fb0c3269SLuo Wei 	SERDES_DBG_MFD("%s node=%s\n",
393fb0c3269SLuo Wei 		       __func__, ofnode_get_name(dev->node));
394fb0c3269SLuo Wei 
395fb0c3269SLuo Wei 	/* Lookup PINCTRL driver */
396fb0c3269SLuo Wei 	drv = lists_uclass_lookup(UCLASS_PINCTRL);
397fb0c3269SLuo Wei 	if (!drv) {
398fb0c3269SLuo Wei 		printf("Cannot find PINCTRL driver\n");
399fb0c3269SLuo Wei 		return -ENOENT;
400fb0c3269SLuo Wei 	}
401fb0c3269SLuo Wei 
402fb0c3269SLuo Wei 	dev_for_each_subnode(subnode, dev) {
403fb0c3269SLuo Wei 		if (pre_reloc_only &&
404fb0c3269SLuo Wei 		    !ofnode_pre_reloc(subnode))
405fb0c3269SLuo Wei 			continue;
406fb0c3269SLuo Wei 
407fb0c3269SLuo Wei 		name = ofnode_get_name(subnode);
408fb0c3269SLuo Wei 		if (!name)
409fb0c3269SLuo Wei 			continue;
410fb0c3269SLuo Wei 
411fb0c3269SLuo Wei 		if (strstr(name, "pinctrl")) {
412*77c57384SZitong Cai 			status = ofnode_read_string(subnode, "status");
413*77c57384SZitong Cai 			if (status && strcmp(status, "okay") != 0) {
414*77c57384SZitong Cai 				SERDES_DBG_MFD("%s node=%s status=%s, exit\n",
415*77c57384SZitong Cai 					       __func__, name, status);
416*77c57384SZitong Cai 				return 0;
417*77c57384SZitong Cai 			}
418*77c57384SZitong Cai 
419*77c57384SZitong Cai 			if (serdes->mcu_enable) {
420*77c57384SZitong Cai 				printf("serdes %s iomux init in MCU\n",
421*77c57384SZitong Cai 				       serdes->dev->name);
422*77c57384SZitong Cai 				return 0;
423*77c57384SZitong Cai 			}
424*77c57384SZitong Cai 
425fb0c3269SLuo Wei 			ret = device_bind_driver_to_node(dev,
426fb0c3269SLuo Wei 							 "serdes-pinctrl", name,
427fb0c3269SLuo Wei 							 subnode, &subdev);
428*77c57384SZitong Cai 			if (ret) {
429*77c57384SZitong Cai 				printf("Cannot find serdes pinctrl driver\n");
430fb0c3269SLuo Wei 				return ret;
431*77c57384SZitong Cai 			}
432fb0c3269SLuo Wei 
433fb0c3269SLuo Wei 			ret = uclass_get_device_by_ofnode(UCLASS_PINCTRL,
434fb0c3269SLuo Wei 							  subnode,
435fb0c3269SLuo Wei 							  &pinctrl_dev);
436fb0c3269SLuo Wei 			if (ret) {
437fb0c3269SLuo Wei 				printf("%s failed to get pinctrl\n", __func__);
438fb0c3269SLuo Wei 				return ret;
439fb0c3269SLuo Wei 			}
440fb0c3269SLuo Wei 
441fb0c3269SLuo Wei 			SERDES_DBG_MFD("%s select %s pinctrl_dev=%s\n",
442fb0c3269SLuo Wei 				       __func__, name, pinctrl_dev->name);
443fb0c3269SLuo Wei 			return 0;
444fb0c3269SLuo Wei 		}
445fb0c3269SLuo Wei 	}
446fb0c3269SLuo Wei 
447fb0c3269SLuo Wei 	return ret;
448fb0c3269SLuo Wei }
449fb0c3269SLuo Wei EXPORT_SYMBOL_GPL(serdes_pinctrl_register);
450fb0c3269SLuo Wei 
serdes_i2c_init(struct serdes * serdes)451fb0c3269SLuo Wei static int serdes_i2c_init(struct serdes *serdes)
452fb0c3269SLuo Wei {
453fb0c3269SLuo Wei 	int ret = 0;
454fb0c3269SLuo Wei 	int i = 0;
455fb0c3269SLuo Wei 
456fb0c3269SLuo Wei 	if (serdes->vpower_supply)
457fb0c3269SLuo Wei 		regulator_set_enable(serdes->vpower_supply, true);
458fb0c3269SLuo Wei 
459fb0c3269SLuo Wei 	if (dm_gpio_is_valid(&serdes->enable_gpio))
460fb0c3269SLuo Wei 		dm_gpio_set_value(&serdes->enable_gpio, 1);
461fb0c3269SLuo Wei 
462fb0c3269SLuo Wei 	mdelay(5);
463fb0c3269SLuo Wei 
464fb0c3269SLuo Wei 	for (i = 0; i < 3; i++) {
465fb0c3269SLuo Wei 		ret = serdes_i2c_set_sequence(serdes);
466fb0c3269SLuo Wei 		if (!ret)
467fb0c3269SLuo Wei 			break;
468fb0c3269SLuo Wei 		mdelay(20);
469fb0c3269SLuo Wei 	}
470fb0c3269SLuo Wei 
471fb0c3269SLuo Wei 	SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name,
472fb0c3269SLuo Wei 		       serdes->chip_data->name);
473fb0c3269SLuo Wei 
474fb0c3269SLuo Wei 	return ret;
475fb0c3269SLuo Wei }
476fb0c3269SLuo Wei 
serdes_i2c_probe(struct udevice * dev)477fb0c3269SLuo Wei static int serdes_i2c_probe(struct udevice *dev)
478fb0c3269SLuo Wei {
479fb0c3269SLuo Wei 	struct serdes *serdes = dev_get_priv(dev);
480fb0c3269SLuo Wei 	int ret;
481fb0c3269SLuo Wei 
482fb0c3269SLuo Wei 	ret = i2c_set_chip_offset_len(dev, 2);
483fb0c3269SLuo Wei 	if (ret)
484fb0c3269SLuo Wei 		return ret;
485fb0c3269SLuo Wei 
486fb0c3269SLuo Wei 	serdes->dev = dev;
487fb0c3269SLuo Wei 	serdes->chip_data = (struct serdes_chip_data *)dev_get_driver_data(dev);
488fb0c3269SLuo Wei 	serdes->type = serdes->chip_data->serdes_type;
489fb0c3269SLuo Wei 
490fb0c3269SLuo Wei 	SERDES_DBG_MFD("serdes %s %s probe start\n",
491fb0c3269SLuo Wei 		       serdes->dev->name, serdes->chip_data->name);
492fb0c3269SLuo Wei 
493fb0c3269SLuo Wei 	ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
494fb0c3269SLuo Wei 					   "vpower-supply",
495fb0c3269SLuo Wei 					   &serdes->vpower_supply);
496fb0c3269SLuo Wei 	if (ret && ret != -ENOENT)
497fb0c3269SLuo Wei 		SERDES_DBG_MFD("%s: Cannot get power supply: %d\n",
498fb0c3269SLuo Wei 			       __func__, ret);
499fb0c3269SLuo Wei 
500fb0c3269SLuo Wei 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
501fb0c3269SLuo Wei 				   &serdes->enable_gpio, GPIOD_IS_OUT);
502fb0c3269SLuo Wei 	if (ret)
503fb0c3269SLuo Wei 		SERDES_DBG_MFD("%s: failed to get enable gpio: %d\n",
504fb0c3269SLuo Wei 			       __func__, ret);
505fb0c3269SLuo Wei 
506fb0c3269SLuo Wei 	ret = gpio_request_by_name(dev, "lock-gpios", 0,
507fb0c3269SLuo Wei 				   &serdes->lock_gpio,
508fb0c3269SLuo Wei 				   GPIOD_IS_IN);
509fb0c3269SLuo Wei 	if (ret)
510fb0c3269SLuo Wei 		SERDES_DBG_MFD("%s: failed to get lock gpio: %d\n",
511fb0c3269SLuo Wei 			       __func__, ret);
512fb0c3269SLuo Wei 
513fb0c3269SLuo Wei 	ret = gpio_request_by_name(dev, "err-gpios", 0,
514fb0c3269SLuo Wei 				   &serdes->err_gpio,
515fb0c3269SLuo Wei 				   GPIOD_IS_IN);
516fb0c3269SLuo Wei 	if (ret)
517fb0c3269SLuo Wei 		SERDES_DBG_MFD("%s: failed to err gpio: %d\n",
518fb0c3269SLuo Wei 			       __func__, ret);
519fb0c3269SLuo Wei 
520fb0c3269SLuo Wei 	ret = serdes_get_init_seq(serdes);
521fb0c3269SLuo Wei 	if (ret)
522fb0c3269SLuo Wei 		return ret;
523fb0c3269SLuo Wei 
524fb0c3269SLuo Wei 	serdes_i2c_init(serdes);
525fb0c3269SLuo Wei 
526fb0c3269SLuo Wei 	printf("%s %s successful, version %s\n",
527fb0c3269SLuo Wei 	       __func__,
528fb0c3269SLuo Wei 	       serdes->dev->name,
529fb0c3269SLuo Wei 	       SERDES_UBOOT_DISPLAY_VERSION);
530fb0c3269SLuo Wei 
531fb0c3269SLuo Wei 	return 0;
532fb0c3269SLuo Wei }
533fb0c3269SLuo Wei 
534fb0c3269SLuo Wei static const struct udevice_id serdes_of_match[] = {
535fb0c3269SLuo Wei #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_NOVO_NCA9539)
536fb0c3269SLuo Wei 	{ .compatible = "novo,nca9539", .data = (ulong)&serdes_nca9539_data },
537fb0c3269SLuo Wei #endif
538fb0c3269SLuo Wei 	{ }
539fb0c3269SLuo Wei };
540fb0c3269SLuo Wei 
541fb0c3269SLuo Wei U_BOOT_DRIVER(serdes_misc) = {
542fb0c3269SLuo Wei 	.name = "serdes-misc",
543fb0c3269SLuo Wei 	.id = UCLASS_MISC,
544fb0c3269SLuo Wei 	.of_match = serdes_of_match,
545fb0c3269SLuo Wei 	.probe = serdes_i2c_probe,
546fb0c3269SLuo Wei 	.priv_auto_alloc_size = sizeof(struct serdes),
547fb0c3269SLuo Wei };
548fb0c3269SLuo Wei 
serdes_power_init(void)549fb0c3269SLuo Wei int serdes_power_init(void)
550fb0c3269SLuo Wei {
551fb0c3269SLuo Wei 	struct udevice *dev;
552fb0c3269SLuo Wei 	int ret = 0;
553fb0c3269SLuo Wei 
554fb0c3269SLuo Wei 	ret = uclass_get_device_by_driver(UCLASS_MISC,
555fb0c3269SLuo Wei 					  DM_GET_DRIVER(serdes_misc),
556fb0c3269SLuo Wei 					  &dev);
557fb0c3269SLuo Wei 	if (ret)
558fb0c3269SLuo Wei 		printf("%s failed to get misc device ret=%d\n", __func__, ret);
559fb0c3269SLuo Wei 
560fb0c3269SLuo Wei 	return ret;
561fb0c3269SLuo Wei }
562