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