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 *)®,
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