1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * serdes-bridge.c -- display bridge 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
12 static struct serdes *g_serdes_ser_split[MAX_NUM_SERDES_SPLIT];
13
serdes_i2c_init(struct serdes * serdes)14 static void serdes_i2c_init(struct serdes *serdes)
15 {
16 if (serdes->vpower_supply)
17 regulator_set_enable(serdes->vpower_supply, true);
18
19 if (dm_gpio_is_valid(&serdes->enable_gpio))
20 dm_gpio_set_value(&serdes->enable_gpio, 1);
21
22 //mdelay(5);
23
24 //video_bridge_set_active(serdes->dev, true);
25
26 if (serdes->chip_data->bridge_ops->init)
27 serdes->chip_data->bridge_ops->init(serdes);
28
29 serdes_i2c_set_sequence(serdes);
30
31 SERDES_DBG_MFD("%s: %s %s\n", __func__,
32 serdes->dev->name,
33 serdes->chip_data->name);
34 }
35
serdes_set_i2c_address(struct serdes * serdes,u32 reg_hw,u32 reg_use,int link)36 static int serdes_set_i2c_address(struct serdes *serdes,
37 u32 reg_hw, u32 reg_use, int link)
38 {
39 int ret = 0;
40 struct dm_i2c_chip *chip_split;
41 struct serdes *serdes_split = serdes->g_serdes_bridge_split;
42
43 if (!serdes_split) {
44 pr_info("%s: serdes_split is null\n", __func__);
45 return -1;
46 }
47
48 chip_split = dev_get_parent_platdata(serdes->dev);
49 SERDES_DBG_MFD("%s: %s addr=0x%x reg_hw=0x%x, reg_use=0x%x split=0x%p\n",
50 __func__, serdes_split->dev->name,
51 chip_split->chip_addr, serdes->reg_hw,
52 serdes->reg_use, serdes_split);
53
54 chip_split->chip_addr = serdes->reg_hw;
55
56 if (serdes_split && serdes_split->chip_data->split_ops &&
57 serdes_split->chip_data->split_ops->select)
58 ret = serdes_split->chip_data->split_ops->select(serdes_split, link);
59
60 if (serdes->chip_data->split_ops &&
61 serdes->chip_data->split_ops->set_i2c_addr)
62 serdes->chip_data->split_ops->set_i2c_addr(serdes,
63 reg_use, link);
64
65 if (serdes_split && serdes_split->chip_data->split_ops &&
66 serdes_split->chip_data->split_ops->select)
67 ret = serdes_split->chip_data->split_ops->select(serdes_split,
68 SER_SPLITTER_MODE);
69
70 chip_split->chip_addr = serdes->reg_use;
71
72 serdes_i2c_set_sequence(serdes);
73
74 return ret;
75 }
76
serdes_i2c_probe(struct udevice * dev)77 static int serdes_i2c_probe(struct udevice *dev)
78 {
79 struct serdes *serdes = dev_get_priv(dev);
80 struct serdes_bridge *serdes_bridge = NULL;
81 struct serdes_bridge_split *serdes_bridge_split = NULL;
82
83 int ret;
84
85 ret = i2c_set_chip_offset_len(dev, 2);
86 if (ret)
87 return ret;
88
89 serdes->dev = dev;
90 serdes->chip_data = (struct serdes_chip_data *)dev_get_driver_data(dev);
91 serdes->type = serdes->chip_data->serdes_type;
92
93 SERDES_DBG_MFD("serdes %s %s probe start serdes=%p\n",
94 serdes->dev->name, serdes->chip_data->name, serdes);
95
96 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
97 "vpower-supply",
98 &serdes->vpower_supply);
99 if (ret && ret != -ENOENT)
100 SERDES_DBG_MFD("%s: Cannot get power supply: %d\n",
101 __func__, ret);
102
103 ret = gpio_request_by_name(dev, "enable-gpios", 0,
104 &serdes->enable_gpio, GPIOD_IS_OUT);
105 if (ret)
106 SERDES_DBG_MFD("%s: failed to get enable gpio: %d\n",
107 __func__, ret);
108
109 ret = gpio_request_by_name(dev, "lock-gpios", 0, &serdes->lock_gpio,
110 GPIOD_IS_IN);
111 if (ret)
112 SERDES_DBG_MFD("%s: failed to get lock gpio: %d\n",
113 __func__, ret);
114
115 ret = gpio_request_by_name(dev, "err-gpios", 0, &serdes->err_gpio,
116 GPIOD_IS_IN);
117 if (ret)
118 SERDES_DBG_MFD("%s: failed to err gpio: %d\n",
119 __func__, ret);
120
121 serdes->mcu_enable = dev_read_bool(dev, "mcu-enable");
122
123 if (serdes->chip_data->serdes_type == TYPE_OTHER) {
124 SERDES_DBG_MFD("TYPE_OTHER just need only init i2c\n");
125 serdes_i2c_init(serdes);
126 return 0;
127 }
128
129 ret = serdes_get_init_seq(serdes);
130 if (ret)
131 return ret;
132
133 if (serdes->chip_data->serdes_type == TYPE_SER)
134 serdes_i2c_init(serdes);
135
136 if (serdes->chip_data->bridge_ops) {
137 serdes_bridge = calloc(1, sizeof(*serdes_bridge));
138 if (!serdes_bridge)
139 return -ENOMEM;
140 serdes->serdes_bridge = serdes_bridge;
141
142 serdes_bridge_split = calloc(1, sizeof(*serdes_bridge_split));
143 if (!serdes_bridge_split)
144 return -ENOMEM;
145 serdes->serdes_bridge_split = serdes_bridge_split;
146 }
147
148 ret = serdes_pinctrl_register(dev);
149 if (ret)
150 return ret;
151
152 serdes->id_serdes_bridge_split = dev_read_u32_default(dev, "id-serdes-bridge-split", 0);
153 if ((serdes->id_serdes_bridge_split < MAX_NUM_SERDES_SPLIT) && (serdes->type == TYPE_SER)) {
154 g_serdes_ser_split[serdes->id_serdes_bridge_split] = serdes;
155 SERDES_DBG_MFD("%s: %s-%s g_serdes_split[%d]=0x%p\n", __func__,
156 serdes->dev->name, serdes->chip_data->name,
157 serdes->id_serdes_bridge_split, serdes);
158 }
159
160 serdes->reg_hw = dev_read_u32_default(dev, "reg-hw", 0);
161 serdes->reg_use = dev_read_u32_default(dev, "reg", 0);
162 serdes->link_use = dev_read_u32_default(dev, "link", 0);
163 serdes->id_serdes_panel_split = dev_read_u32_default(dev, "id-serdes-panel-split", 0);
164
165 if ((serdes->id_serdes_panel_split) && (serdes->type == TYPE_DES)) {
166 serdes->g_serdes_bridge_split = g_serdes_ser_split[serdes->id_serdes_panel_split];
167 SERDES_DBG_MFD("%s: id=%d p=0x%p\n", __func__,
168 serdes->id_serdes_panel_split,
169 serdes->g_serdes_bridge_split);
170 }
171
172 if (serdes->reg_hw) {
173 SERDES_DBG_MFD("%s: %s change i2c addr from 0x%x to 0x%x\n",
174 __func__, dev->name,
175 serdes->reg_hw, serdes->reg_use);
176 serdes_set_i2c_address(serdes, serdes->reg_hw,
177 serdes->reg_use, serdes->link_use);
178 }
179
180 printf("%s %s %s successful\n",
181 __func__,
182 serdes->dev->name,
183 serdes->chip_data->name);
184
185 return 0;
186 }
187
188 static const struct udevice_id serdes_of_match[] = {
189 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82)
190 { .compatible = "rohm,bu18tl82",
191 .data = (ulong)&serdes_bu18tl82_data },
192 #endif
193 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82)
194 { .compatible = "rohm,bu18rl82",
195 .data = (ulong)&serdes_bu18rl82_data },
196 #endif
197 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745)
198 { .compatible = "maxim,max96745",
199 .data = (ulong)&serdes_max96745_data },
200 #endif
201 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755)
202 { .compatible = "maxim,max96755",
203 .data = (ulong)&serdes_max96755_data },
204 #endif
205 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789)
206 { .compatible = "maxim,max96789",
207 .data = (ulong)&serdes_max96789_data },
208 #endif
209 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111)
210 { .compatible = "rockchip,rkx111",
211 .data = (ulong)&serdes_rkx111_data },
212 #endif
213 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752)
214 { .compatible = "maxim,max96752",
215 .data = (ulong)&serdes_max96752_data },
216 #endif
217 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772)
218 { .compatible = "maxim,max96772",
219 .data = (ulong)&serdes_max96772_data },
220 #endif
221 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121)
222 { .compatible = "rockchip,rkx121",
223 .data = (ulong)&serdes_rkx121_data },
224 #endif
225 { }
226 };
227
228 U_BOOT_DRIVER(serdes_i2c) = {
229 .name = "serdes-i2c",
230 .id = UCLASS_MISC,
231 .of_match = serdes_of_match,
232 .probe = serdes_i2c_probe,
233 .bind = dm_scan_fdt_dev,
234 .priv_auto_alloc_size = sizeof(struct serdes),
235 };
236