xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/rockchip/rk628/rk628_combtxphy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4  *
5  * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6  */
7 
8 #include <asm/bitsperlong.h>
9 #include <linux/kernel.h>
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/platform_device.h>
16 #include <linux/reset.h>
17 #include <linux/mfd/rk628.h>
18 
19 #include "rk628_combtxphy.h"
20 
21 #define REG(x)			((x) + 0x90000)
22 
23 #define COMBTXPHY_CON0		REG(0x0000)
24 #define SW_TX_IDLE_MASK		GENMASK(29, 20)
25 #define SW_TX_IDLE(x)		UPDATE(x, 29, 20)
26 #define SW_TX_PD_MASK		GENMASK(17, 8)
27 #define SW_TX_PD(x)		UPDATE(x, 17, 8)
28 #define SW_BUS_WIDTH_MASK	GENMASK(6, 5)
29 #define SW_BUS_WIDTH_7BIT	UPDATE(0x3, 6, 5)
30 #define SW_BUS_WIDTH_8BIT	UPDATE(0x2, 6, 5)
31 #define SW_BUS_WIDTH_9BIT	UPDATE(0x1, 6, 5)
32 #define SW_BUS_WIDTH_10BIT	UPDATE(0x0, 6, 5)
33 #define SW_PD_PLL_MASK		BIT(4)
34 #define SW_PD_PLL		BIT(4)
35 #define SW_GVI_LVDS_EN_MASK	BIT(3)
36 #define SW_GVI_LVDS_EN		BIT(3)
37 #define SW_MIPI_DSI_EN_MASK	BIT(2)
38 #define SW_MIPI_DSI_EN		BIT(2)
39 #define SW_MODULEB_EN_MASK	BIT(1)
40 #define SW_MODULEB_EN		BIT(1)
41 #define SW_MODULEA_EN_MASK	BIT(0)
42 #define SW_MODULEA_EN		BIT(0)
43 #define COMBTXPHY_CON1		REG(0x0004)
44 #define COMBTXPHY_CON2		REG(0x0008)
45 #define COMBTXPHY_CON3		REG(0x000c)
46 #define COMBTXPHY_CON4		REG(0x0010)
47 #define COMBTXPHY_CON5		REG(0x0014)
48 #define SW_RATE(x)		UPDATE(x, 26, 24)
49 #define SW_REF_DIV(x)		UPDATE(x, 20, 16)
50 #define SW_PLL_FB_DIV(x)	UPDATE(x, 14, 10)
51 #define SW_PLL_FRAC_DIV(x)	UPDATE(x, 9, 0)
52 #define COMBTXPHY_CON6		REG(0x0018)
53 #define COMBTXPHY_CON7		REG(0x001c)
54 #define SW_TX_RTERM_MASK	GENMASK(22, 20)
55 #define SW_TX_RTERM(x)		UPDATE(x, 22, 20)
56 #define SW_TX_MODE_MASK		GENMASK(17, 16)
57 #define SW_TX_MODE(x)		UPDATE(x, 17, 16)
58 #define SW_TX_CTL_CON5_MASK	BIT(10)
59 #define SW_TX_CTL_CON5(x)	UPDATE(x, 10, 10)
60 #define SW_TX_CTL_CON4_MASK	GENMASK(9, 8)
61 #define SW_TX_CTL_CON4(x)	UPDATE(x, 9, 8)
62 #define BYPASS_095V_LDO_MASK	BIT(3)
63 #define BYPASS_095V_LDO(x)	UPDATE(x, 3, 3)
64 #define TX_COM_VOLT_ADJ_MASK	GENMASK(2, 0)
65 #define TX_COM_VOLT_ADJ(x)	UPDATE(x, 2, 0)
66 #define COMBTXPHY_CON8		REG(0x0020)
67 #define COMBTXPHY_CON9		REG(0x0024)
68 #define SW_DSI_FSET_EN_MASK	BIT(29)
69 #define SW_DSI_FSET_EN		BIT(29)
70 #define SW_DSI_RCAL_EN_MASK	BIT(28)
71 #define SW_DSI_RCAL_EN		BIT(28)
72 #define COMBTXPHY_CON10		REG(0x0028)
73 #define TX9_CKDRV_EN		BIT(9)
74 #define TX8_CKDRV_EN		BIT(8)
75 #define TX7_CKDRV_EN		BIT(7)
76 #define TX6_CKDRV_EN		BIT(6)
77 #define TX5_CKDRV_EN		BIT(5)
78 #define TX4_CKDRV_EN		BIT(4)
79 #define TX3_CKDRV_EN		BIT(3)
80 #define TX2_CKDRV_EN		BIT(2)
81 #define TX1_CKDRV_EN		BIT(1)
82 #define TX0_CKDRV_EN		BIT(0)
83 #define COMBTXPHY_MAX_REGISTER	COMBTXPHY_CON10
84 
85 struct rk628_combtxphy {
86 	struct device *dev;
87 	struct rk628 *parent;
88 	struct regmap *grf;
89 	struct regmap *regmap;
90 	struct clk *pclk;
91 	struct clk *ref_clk;
92 	struct reset_control *rstc;
93 	unsigned int flags;
94 
95 	u16 frac_div;
96 	u8 ref_div;
97 	u8 fb_div;
98 	u8 rate_div;
99 	u8 division_mode;
100 };
101 
rk628_combtxphy_dsi_power_on(struct rk628_combtxphy * combtxphy)102 static int rk628_combtxphy_dsi_power_on(struct rk628_combtxphy *combtxphy)
103 {
104 	u32 val;
105 	int ret;
106 
107 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
108 			   SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
109 			   SW_MIPI_DSI_EN_MASK,
110 			   SW_BUS_WIDTH_8BIT | SW_MIPI_DSI_EN);
111 
112 	if (combtxphy->flags & COMBTXPHY_MODULEA_EN)
113 		regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
114 				   SW_MODULEA_EN_MASK, SW_MODULEA_EN);
115 	if (combtxphy->flags & COMBTXPHY_MODULEB_EN)
116 		regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
117 				   SW_MODULEB_EN_MASK, SW_MODULEB_EN);
118 
119 	regmap_write(combtxphy->regmap, COMBTXPHY_CON5,
120 		     SW_REF_DIV(combtxphy->ref_div - 1) |
121 		     SW_PLL_FB_DIV(combtxphy->fb_div) |
122 		     SW_PLL_FRAC_DIV(combtxphy->frac_div) |
123 		     SW_RATE(combtxphy->rate_div / 2));
124 
125 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
126 			   SW_PD_PLL, 0);
127 
128 	ret = regmap_read_poll_timeout(combtxphy->grf, GRF_DPHY0_STATUS,
129 				       val, val & DPHY_PHYLOCK, 0, 1000);
130 	if (ret < 0) {
131 		dev_err(combtxphy->dev, "phy is not lock\n");
132 		return ret;
133 	}
134 
135 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON9,
136 			   SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK,
137 			   SW_DSI_FSET_EN | SW_DSI_RCAL_EN);
138 
139 	usleep_range(200, 400);
140 
141 	return 0;
142 }
143 
rk628_combtxphy_lvds_power_on(struct rk628_combtxphy * combtxphy)144 static int rk628_combtxphy_lvds_power_on(struct rk628_combtxphy *combtxphy)
145 {
146 	u32 val;
147 	int ret;
148 
149 	/* Adjust terminal resistance 133 ohm, bypass 0.95v ldo for driver. */
150 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON7,
151 			   SW_TX_RTERM_MASK | SW_TX_MODE_MASK |
152 			   BYPASS_095V_LDO_MASK | TX_COM_VOLT_ADJ_MASK,
153 			   SW_TX_RTERM(6) | SW_TX_MODE(3) |
154 			   BYPASS_095V_LDO(1) | TX_COM_VOLT_ADJ(0));
155 
156 	regmap_write(combtxphy->regmap, COMBTXPHY_CON10,
157 		     TX7_CKDRV_EN | TX2_CKDRV_EN);
158 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
159 			   SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
160 			   SW_MIPI_DSI_EN_MASK,
161 			   SW_BUS_WIDTH_7BIT | SW_GVI_LVDS_EN);
162 
163 	if (combtxphy->flags & COMBTXPHY_MODULEA_EN)
164 		regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
165 				   SW_MODULEA_EN_MASK, SW_MODULEA_EN);
166 	if (combtxphy->flags & COMBTXPHY_MODULEB_EN)
167 		regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
168 				   SW_MODULEB_EN_MASK, SW_MODULEB_EN);
169 
170 	regmap_write(combtxphy->regmap, COMBTXPHY_CON5,
171 		     SW_REF_DIV(combtxphy->ref_div - 1) |
172 		     SW_PLL_FB_DIV(combtxphy->fb_div) |
173 		     SW_PLL_FRAC_DIV(combtxphy->frac_div) |
174 		     SW_RATE(combtxphy->rate_div / 2));
175 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
176 			   SW_PD_PLL, 0);
177 
178 	ret = regmap_read_poll_timeout(combtxphy->grf, GRF_DPHY0_STATUS,
179 				       val, val & DPHY_PHYLOCK, 0, 1000);
180 	if (ret < 0) {
181 		dev_info(combtxphy->dev, "phy is not lock\n");
182 		return ret;
183 	}
184 
185 	usleep_range(100, 200);
186 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
187 			   SW_TX_IDLE_MASK | SW_TX_PD_MASK, 0);
188 
189 	return 0;
190 }
191 
rk628_combtxphy_gvi_power_on(struct rk628_combtxphy * combtxphy)192 static int rk628_combtxphy_gvi_power_on(struct rk628_combtxphy *combtxphy)
193 {
194 	int ref_div = 0;
195 
196 	if (combtxphy->ref_div % 2) {
197 		ref_div = combtxphy->ref_div - 1;
198 	} else {
199 		ref_div = BIT(4);
200 		ref_div |= combtxphy->ref_div / 2 - 1;
201 	}
202 	regmap_write(combtxphy->regmap, COMBTXPHY_CON5,
203 		     SW_REF_DIV(ref_div) |
204 		     SW_PLL_FB_DIV(combtxphy->fb_div) |
205 		     SW_PLL_FRAC_DIV(combtxphy->frac_div) |
206 		     SW_RATE(combtxphy->rate_div / 2));
207 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
208 			   SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
209 			   SW_MIPI_DSI_EN_MASK |
210 			   SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK,
211 			   SW_BUS_WIDTH_10BIT | SW_GVI_LVDS_EN |
212 			   SW_MODULEB_EN | SW_MODULEA_EN);
213 
214 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
215 			   SW_PD_PLL | SW_TX_PD_MASK, 0);
216 	usleep_range(100, 200);
217 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
218 			   SW_TX_IDLE_MASK, 0);
219 
220 	return 0;
221 }
222 
rk628_combtxphy_set_gvi_division_mode(struct phy * phy,u8 mode)223 int rk628_combtxphy_set_gvi_division_mode(struct phy *phy, u8 mode)
224 {
225 	struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
226 
227 	combtxphy->division_mode = mode;
228 
229 	return 0;
230 }
231 EXPORT_SYMBOL(rk628_combtxphy_set_gvi_division_mode);
232 
rk628_combtxphy_power_on(struct phy * phy)233 static int rk628_combtxphy_power_on(struct phy *phy)
234 {
235 	struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
236 	enum phy_mode mode = phy_get_mode(phy);
237 
238 	clk_prepare_enable(combtxphy->pclk);
239 	reset_control_assert(combtxphy->rstc);
240 	udelay(10);
241 	reset_control_deassert(combtxphy->rstc);
242 	udelay(10);
243 
244 	regcache_mark_dirty(combtxphy->regmap);
245 	regcache_sync(combtxphy->regmap);
246 
247 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
248 			   SW_TX_IDLE_MASK | SW_TX_PD_MASK | SW_PD_PLL_MASK,
249 			   SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL);
250 
251 	switch (mode) {
252 	case PHY_MODE_MIPI_DPHY:
253 		regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON,
254 				   SW_TXPHY_REFCLK_SEL_MASK,
255 				   SW_TXPHY_REFCLK_SEL(0));
256 		return rk628_combtxphy_dsi_power_on(combtxphy);
257 	case PHY_MODE_LVDS:
258 		regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON,
259 				   SW_TXPHY_REFCLK_SEL_MASK,
260 				   SW_TXPHY_REFCLK_SEL(1));
261 		return rk628_combtxphy_lvds_power_on(combtxphy);
262 	default:
263 		regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON,
264 				   SW_TXPHY_REFCLK_SEL_MASK,
265 				   SW_TXPHY_REFCLK_SEL(2));
266 		return rk628_combtxphy_gvi_power_on(combtxphy);
267 	}
268 
269 	return 0;
270 }
271 
rk628_combtxphy_power_off(struct phy * phy)272 static int rk628_combtxphy_power_off(struct phy *phy)
273 {
274 	struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
275 
276 	regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
277 			   SW_TX_IDLE_MASK | SW_TX_PD_MASK | SW_PD_PLL_MASK |
278 			   SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK,
279 			   SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL);
280 
281 	clk_disable_unprepare(combtxphy->pclk);
282 
283 	return 0;
284 }
285 
rk628_combtxphy_set_mode(struct phy * phy,enum phy_mode mode,int submode)286 static int rk628_combtxphy_set_mode(struct phy *phy, enum phy_mode mode,
287 				    int submode)
288 {
289 	struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
290 	unsigned int bus_width = phy_get_bus_width(phy);
291 	unsigned int frac_rate, fin = 24;
292 	unsigned long fvco, fpfd;
293 
294 	switch (mode) {
295 	case PHY_MODE_MIPI_DPHY:
296 	{
297 		unsigned int fhsc = bus_width >> 8;
298 		unsigned int flags = bus_width & 0xff;
299 
300 		fhsc = fin * (fhsc / fin);
301 
302 		if (fhsc < 80 || fhsc > 1500)
303 			return -EINVAL;
304 		else if (fhsc < 375)
305 			combtxphy->rate_div = 4;
306 		else if (fhsc < 750)
307 			combtxphy->rate_div = 2;
308 		else
309 			combtxphy->rate_div = 1;
310 
311 		combtxphy->flags = flags;
312 
313 		fvco = fhsc * 2 * combtxphy->rate_div;
314 		combtxphy->ref_div = 1;
315 		combtxphy->fb_div = fvco / 8 / fin;
316 		frac_rate = fvco - (fin * 8 * combtxphy->fb_div);
317 
318 		if (frac_rate) {
319 			frac_rate <<= 10;
320 			frac_rate /= fin * 8;
321 			combtxphy->frac_div = frac_rate;
322 		} else {
323 			combtxphy->frac_div = 0;
324 		}
325 
326 		fvco = fin * (1024 * combtxphy->fb_div + combtxphy->frac_div);
327 		fvco *= 8;
328 		fvco = DIV_ROUND_UP(fvco, 1024 * combtxphy->ref_div);
329 		fhsc = fvco / 2 / combtxphy->rate_div;
330 		phy_set_bus_width(phy, fhsc);
331 		break;
332 	}
333 	case PHY_MODE_LVDS:
334 	{
335 		unsigned int flags = bus_width & 0xff;
336 		unsigned int rate = (bus_width >> 8) * 7;
337 
338 		combtxphy->flags = flags;
339 		combtxphy->ref_div = 1;
340 		combtxphy->fb_div = 14;
341 		combtxphy->frac_div = 0;
342 
343 		if (rate < 500)
344 			combtxphy->rate_div = 4;
345 		else if (rate < 1000)
346 			combtxphy->rate_div = 2;
347 		else
348 			combtxphy->rate_div = 1;
349 		break;
350 	}
351 	default:
352 	{
353 		unsigned int i, delta_freq, best_delta_freq, fb_div;
354 		unsigned long ref_clk;
355 		unsigned long long pre_clk;
356 
357 		if (bus_width < 500000 || bus_width > 4000000)
358 			return -EINVAL;
359 		else if (bus_width < 1000000)
360 			combtxphy->rate_div = 4;
361 		else if (bus_width < 2000000)
362 			combtxphy->rate_div = 2;
363 		else
364 			combtxphy->rate_div = 1;
365 		fvco = bus_width * combtxphy->rate_div;
366 		ref_clk = clk_get_rate(combtxphy->ref_clk) / 1000; /* khz */
367 		if (combtxphy->division_mode)
368 			ref_clk /= 2;
369 		/*
370 		 * the reference clock at PFD(FPFD = ref_clk / ref_div) about
371 		 * 25MHz is recommende, FPFD must range from 16MHz to 35MHz,
372 		 * here to find the best rev_div.
373 		 */
374 		best_delta_freq = ref_clk;
375 		for (i = 1; i <= 32; i++) {
376 			fpfd = ref_clk / i;
377 			delta_freq = abs(fpfd - 25000);
378 			if (delta_freq < best_delta_freq) {
379 				best_delta_freq = delta_freq;
380 				combtxphy->ref_div = i;
381 			}
382 		}
383 
384 		/*
385 		 * ref_clk / ref_div * 8 * fb_div = FVCO
386 		 */
387 		pre_clk = (unsigned long long)fvco / 8 * combtxphy->ref_div * 1024;
388 		do_div(pre_clk, ref_clk);
389 		fb_div = pre_clk / 1024;
390 
391 		/*
392 		 * get the actually frequence
393 		 */
394 		bus_width = ref_clk / combtxphy->ref_div * 8;
395 		bus_width *= fb_div;
396 		bus_width /= combtxphy->rate_div;
397 
398 		combtxphy->frac_div = 0;
399 		combtxphy->fb_div = fb_div;
400 
401 		phy_set_bus_width(phy, bus_width);
402 		break;
403 	}
404 	}
405 
406 	return 0;
407 }
408 
409 static const struct phy_ops rk628_combtxphy_ops = {
410 	.set_mode = rk628_combtxphy_set_mode,
411 	.power_on = rk628_combtxphy_power_on,
412 	.power_off = rk628_combtxphy_power_off,
413 	.owner = THIS_MODULE,
414 };
415 
416 static const struct regmap_range rk628_combtxphy_readable_ranges[] = {
417 	regmap_reg_range(COMBTXPHY_CON0, COMBTXPHY_CON10),
418 };
419 
420 static const struct regmap_access_table rk628_combtxphy_readable_table = {
421 	.yes_ranges     = rk628_combtxphy_readable_ranges,
422 	.n_yes_ranges   = ARRAY_SIZE(rk628_combtxphy_readable_ranges),
423 };
424 
425 static const struct regmap_config rk628_combtxphy_regmap_cfg = {
426 	.name = "combtxphy",
427 	.reg_bits = 32,
428 	.val_bits = 32,
429 	.reg_stride = 4,
430 	.cache_type = REGCACHE_RBTREE,
431 	.max_register = COMBTXPHY_MAX_REGISTER,
432 	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
433 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
434 	.rd_table = &rk628_combtxphy_readable_table,
435 };
436 
rk628_combtxphy_probe(struct platform_device * pdev)437 static int rk628_combtxphy_probe(struct platform_device *pdev)
438 {
439 	struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
440 	struct device *dev = &pdev->dev;
441 	struct rk628_combtxphy *combtxphy;
442 	struct phy_provider *phy_provider;
443 	struct phy *phy;
444 	int ret;
445 
446 	combtxphy = devm_kzalloc(dev, sizeof(*combtxphy), GFP_KERNEL);
447 	if (!combtxphy)
448 		return -ENOMEM;
449 
450 	combtxphy->dev = dev;
451 	combtxphy->parent = rk628;
452 	combtxphy->grf = rk628->grf;
453 	platform_set_drvdata(pdev, combtxphy);
454 
455 	combtxphy->pclk = devm_clk_get(dev, "pclk");
456 	if (IS_ERR(combtxphy->pclk))
457 		return PTR_ERR(combtxphy->pclk);
458 
459 	combtxphy->ref_clk = devm_clk_get(dev, "ref_clk");
460 	if (IS_ERR(combtxphy->ref_clk)) {
461 		dev_err(dev, "fail to get ref clk\n");
462 		return PTR_ERR(combtxphy->ref_clk);
463 	}
464 
465 	combtxphy->rstc = of_reset_control_get(dev->of_node, NULL);
466 	if (IS_ERR(combtxphy->rstc)) {
467 		ret = PTR_ERR(combtxphy->rstc);
468 		dev_err(dev, "failed to get reset control: %d\n", ret);
469 		return ret;
470 	}
471 
472 	combtxphy->regmap = devm_regmap_init_i2c(rk628->client,
473 						 &rk628_combtxphy_regmap_cfg);
474 	if (IS_ERR(combtxphy->regmap)) {
475 		ret = PTR_ERR(combtxphy->regmap);
476 		dev_err(dev, "failed to allocate register map: %d\n", ret);
477 		return ret;
478 	}
479 
480 	phy = devm_phy_create(dev, NULL, &rk628_combtxphy_ops);
481 	if (IS_ERR(phy)) {
482 		ret = PTR_ERR(phy);
483 		dev_err(dev, "failed to create phy: %d\n", ret);
484 		return ret;
485 	}
486 
487 	phy_set_drvdata(phy, combtxphy);
488 
489 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
490 	if (IS_ERR(phy_provider)) {
491 		ret = PTR_ERR(phy_provider);
492 		dev_err(dev, "failed to register phy provider: %d\n", ret);
493 		return ret;
494 	}
495 
496 	return 0;
497 }
498 
499 static const struct of_device_id rk628_combtxphy_of_match[] = {
500 	{ .compatible = "rockchip,rk628-combtxphy", },
501 	{}
502 };
503 MODULE_DEVICE_TABLE(of, rk628_combtxphy_of_match);
504 
505 static struct platform_driver rk628_combtxphy_driver = {
506 	.driver = {
507 		.name = "rk628-combtxphy",
508 		.of_match_table	= of_match_ptr(rk628_combtxphy_of_match),
509 	},
510 	.probe = rk628_combtxphy_probe,
511 };
512 module_platform_driver(rk628_combtxphy_driver);
513 
514 MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
515 MODULE_DESCRIPTION("Rockchip RK628 GVI/LVDS/MIPI Combo TX PHY driver");
516 MODULE_LICENSE("GPL v2");
517