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