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 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 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 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 struct serdes_pinctrl *serdes_pinctrl = NULL; 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 if (serdes->chip_data->serdes_type == TYPE_OTHER) { 122 SERDES_DBG_MFD("TYPE_OTHER just need only init i2c\n"); 123 serdes_i2c_init(serdes); 124 return 0; 125 } 126 127 ret = serdes_get_init_seq(serdes); 128 if (ret) 129 return ret; 130 131 if (serdes->chip_data->serdes_type == TYPE_SER) 132 serdes_i2c_init(serdes); 133 134 if (serdes->chip_data->bridge_ops) { 135 serdes_bridge = calloc(1, sizeof(*serdes_bridge)); 136 if (!serdes_bridge) 137 return -ENOMEM; 138 serdes->serdes_bridge = serdes_bridge; 139 140 serdes_bridge_split = calloc(1, sizeof(*serdes_bridge_split)); 141 if (!serdes_bridge_split) 142 return -ENOMEM; 143 serdes->serdes_bridge_split = serdes_bridge_split; 144 } 145 146 serdes_pinctrl = calloc(1, sizeof(*serdes_pinctrl)); 147 if (!serdes_pinctrl) 148 return -ENOMEM; 149 150 serdes->serdes_pinctrl = serdes_pinctrl; 151 ret = serdes_pinctrl_register(dev, serdes); 152 if (ret) 153 return ret; 154 155 serdes->id_serdes_bridge_split = dev_read_u32_default(dev, "id-serdes-bridge-split", 0); 156 if ((serdes->id_serdes_bridge_split < MAX_NUM_SERDES_SPLIT) && (serdes->type == TYPE_SER)) { 157 g_serdes_ser_split[serdes->id_serdes_bridge_split] = serdes; 158 SERDES_DBG_MFD("%s: %s-%s g_serdes_split[%d]=0x%p\n", __func__, 159 serdes->dev->name, serdes->chip_data->name, 160 serdes->id_serdes_bridge_split, serdes); 161 } 162 163 serdes->reg_hw = dev_read_u32_default(dev, "reg-hw", 0); 164 serdes->reg_use = dev_read_u32_default(dev, "reg", 0); 165 serdes->link_use = dev_read_u32_default(dev, "link", 0); 166 serdes->id_serdes_panel_split = dev_read_u32_default(dev, "id-serdes-panel-split", 0); 167 168 if ((serdes->id_serdes_panel_split) && (serdes->type == TYPE_DES)) { 169 serdes->g_serdes_bridge_split = g_serdes_ser_split[serdes->id_serdes_panel_split]; 170 SERDES_DBG_MFD("%s: id=%d p=0x%p\n", __func__, 171 serdes->id_serdes_panel_split, 172 serdes->g_serdes_bridge_split); 173 } 174 175 if (serdes->reg_hw) { 176 SERDES_DBG_MFD("%s: %s change i2c addr from 0x%x to 0x%x\n", 177 __func__, dev->name, 178 serdes->reg_hw, serdes->reg_use); 179 serdes_set_i2c_address(serdes, serdes->reg_hw, 180 serdes->reg_use, serdes->link_use); 181 } 182 183 printf("%s %s %s successful\n", 184 __func__, 185 serdes->dev->name, 186 serdes->chip_data->name); 187 188 return 0; 189 } 190 191 static const struct udevice_id serdes_of_match[] = { 192 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) 193 { .compatible = "rohm,bu18tl82", 194 .data = (ulong)&serdes_bu18tl82_data }, 195 #endif 196 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) 197 { .compatible = "rohm,bu18rl82", 198 .data = (ulong)&serdes_bu18rl82_data }, 199 #endif 200 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) 201 { .compatible = "maxim,max96745", 202 .data = (ulong)&serdes_max96745_data }, 203 #endif 204 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) 205 { .compatible = "maxim,max96755", 206 .data = (ulong)&serdes_max96755_data }, 207 #endif 208 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789) 209 { .compatible = "maxim,max96789", 210 .data = (ulong)&serdes_max96789_data }, 211 #endif 212 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) 213 { .compatible = "rockchip,rkx111", 214 .data = (ulong)&serdes_rkx111_data }, 215 #endif 216 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) 217 { .compatible = "maxim,max96752", 218 .data = (ulong)&serdes_max96752_data }, 219 #endif 220 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) 221 { .compatible = "maxim,max96772", 222 .data = (ulong)&serdes_max96772_data }, 223 #endif 224 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121) 225 { .compatible = "rockchip,rkx121", 226 .data = (ulong)&serdes_rkx121_data }, 227 #endif 228 { } 229 }; 230 231 U_BOOT_DRIVER(serdes_i2c) = { 232 .name = "serdes-i2c", 233 .id = UCLASS_MISC, 234 .of_match = serdes_of_match, 235 .probe = serdes_i2c_probe, 236 .bind = dm_scan_fdt_dev, 237 .priv_auto_alloc_size = sizeof(struct serdes), 238 }; 239