xref: /rk3399_rockchip-uboot/drivers/video/drm/inno_mipi_phy.c (revision 8dd9db5d1cd5826638c3cdb5f681300ff2f29f3b)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <config.h>
8 #include <common.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <asm/unaligned.h>
12 #include <asm/io.h>
13 #include <linux/list.h>
14 #include <div64.h>
15 #include <dm/device.h>
16 #include <dm/read.h>
17 #include <dm/uclass.h>
18 #include <dm/uclass-id.h>
19 
20 #include "rockchip_phy.h"
21 
22 #define NSEC_PER_USEC		1000L
23 #define USEC_PER_SEC		1000000L
24 #define NSEC_PER_SEC		1000000000L
25 
26 #define UPDATE(v, h, l)		(((v) << (l)) & GENMASK((h), (l)))
27 
28 /* Innosilicon MIPI D-PHY registers */
29 #define INNO_PHY_LANE_CTRL	0x00000
30 #define MIPI_BGPD		BIT(7)
31 #define CLK_LANE_EN_MASK	BIT(6)
32 #define DATA_LANE_3_EN_MASK	BIT(5)
33 #define DATA_LANE_2_EN_MASK	BIT(4)
34 #define DATA_LANE_1_EN_MASK	BIT(3)
35 #define DATA_LANE_0_EN_MASK	BIT(2)
36 #define CLK_LANE_EN		BIT(6)
37 #define DATA_LANE_3_EN		BIT(5)
38 #define DATA_LANE_2_EN		BIT(4)
39 #define DATA_LANE_1_EN		BIT(3)
40 #define DATA_LANE_0_EN		BIT(2)
41 #define PWROK_BP		BIT(1)
42 #define PWROK			BIT(0)
43 #define INNO_PHY_POWER_CTRL	0x00004
44 #define ANALOG_RESET_MASK	BIT(2)
45 #define ANALOG_RESET		BIT(2)
46 #define ANALOG_NORMAL		0
47 #define LDO_POWER_MASK		BIT(1)
48 #define LDO_POWER_DOWN		BIT(1)
49 #define LDO_POWER_ON		0
50 #define PLL_POWER_MASK		BIT(0)
51 #define PLL_POWER_DOWN		BIT(0)
52 #define PLL_POWER_ON		0
53 #define INNO_PHY_PLL_CTRL_0	0x0000c
54 #define FBDIV_HI_MASK		BIT(5)
55 #define FBDIV_HI(x)		UPDATE(x, 5, 5)
56 #define PREDIV_MASK		GENMASK(4, 0)
57 #define PREDIV(x)		UPDATE(x, 4, 0)
58 #define INNO_PHY_PLL_CTRL_1	0x00010
59 #define FBDIV_LO_MASK		GENMASK(7, 0)
60 #define FBDIV_LO(x)		UPDATE(x, 7, 0)
61 #define INNO_PHY_DIG_CTRL	0x00080
62 #define DIGITAL_RESET_MASK	BIT(0)
63 #define DIGITAL_NORMAL		BIT(0)
64 #define DIGITAL_RESET		0
65 #define INNO_PHY_LVDS_CTRL	0x003ac
66 #define LVDS_BGPD		BIT(0)
67 
68 #define INNO_CLOCK_LANE_REG_BASE	0x00100
69 #define INNO_DATA_LANE_0_REG_BASE	0x00180
70 #define INNO_DATA_LANE_1_REG_BASE	0x00200
71 #define INNO_DATA_LANE_2_REG_BASE	0x00280
72 #define INNO_DATA_LANE_3_REG_BASE	0x00300
73 
74 #define T_LPX_OFFSET		0x00014
75 #define T_HS_PREPARE_OFFSET	0x00018
76 #define T_HS_ZERO_OFFSET	0x0001c
77 #define T_HS_TRAIL_OFFSET	0x00020
78 #define T_HS_EXIT_OFFSET	0x00024
79 #define T_CLK_POST_OFFSET	0x00028
80 #define T_WAKUP_H_OFFSET	0x00030
81 #define T_WAKUP_L_OFFSET	0x00034
82 #define T_CLK_PRE_OFFSET	0x00038
83 #define T_TA_GO_OFFSET		0x00040
84 #define T_TA_SURE_OFFSET	0x00044
85 #define T_TA_WAIT_OFFSET	0x00048
86 
87 #define T_LPX_MASK		GENMASK(5, 0)
88 #define T_LPX(x)		UPDATE(x, 5, 0)
89 #define T_HS_PREPARE_MASK	GENMASK(6, 0)
90 #define T_HS_PREPARE(x)		UPDATE(x, 6, 0)
91 #define T_HS_ZERO_MASK		GENMASK(5, 0)
92 #define T_HS_ZERO(x)		UPDATE(x, 5, 0)
93 #define T_HS_TRAIL_MASK		GENMASK(6, 0)
94 #define T_HS_TRAIL(x)		UPDATE(x, 6, 0)
95 #define T_HS_EXIT_MASK		GENMASK(4, 0)
96 #define T_HS_EXIT(x)		UPDATE(x, 4, 0)
97 #define T_CLK_POST_MASK		GENMASK(3, 0)
98 #define T_CLK_POST(x)		UPDATE(x, 3, 0)
99 #define T_WAKUP_H_MASK		GENMASK(1, 0)
100 #define T_WAKUP_H(x)		UPDATE(x, 1, 0)
101 #define T_WAKUP_L_MASK		GENMASK(7, 0)
102 #define T_WAKUP_L(x)		UPDATE(x, 7, 0)
103 #define T_CLK_PRE_MASK		GENMASK(3, 0)
104 #define T_CLK_PRE(x)		UPDATE(x, 3, 0)
105 #define T_TA_GO_MASK		GENMASK(5, 0)
106 #define T_TA_GO(x)		UPDATE(x, 5, 0)
107 #define T_TA_SURE_MASK		GENMASK(5, 0)
108 #define T_TA_SURE(x)		UPDATE(x, 5, 0)
109 #define T_TA_WAIT_MASK		GENMASK(5, 0)
110 #define T_TA_WAIT(x)		UPDATE(x, 5, 0)
111 
112 enum lane_type {
113 	CLOCK_LANE,
114 	DATA_LANE_0,
115 	DATA_LANE_1,
116 	DATA_LANE_2,
117 	DATA_LANE_3,
118 };
119 
120 struct mipi_dphy_timing {
121 	unsigned int clkmiss;
122 	unsigned int clkpost;
123 	unsigned int clkpre;
124 	unsigned int clkprepare;
125 	unsigned int clksettle;
126 	unsigned int clktermen;
127 	unsigned int clktrail;
128 	unsigned int clkzero;
129 	unsigned int dtermen;
130 	unsigned int eot;
131 	unsigned int hsexit;
132 	unsigned int hsprepare;
133 	unsigned int hszero;
134 	unsigned int hssettle;
135 	unsigned int hsskip;
136 	unsigned int hstrail;
137 	unsigned int init;
138 	unsigned int lpx;
139 	unsigned int taget;
140 	unsigned int tago;
141 	unsigned int tasure;
142 	unsigned int wakeup;
143 };
144 
145 struct inno_mipi_dphy_timing {
146 	u8 lpx;
147 	u8 hs_prepare;
148 	u8 hs_zero;
149 	u8 hs_trail;
150 	u8 hs_exit;
151 	u8 clk_post;
152 	u8 wakup_h;
153 	u8 wakup_l;
154 	u8 clk_pre;
155 	u8 ta_go;
156 	u8 ta_sure;
157 	u8 ta_wait;
158 };
159 
160 struct inno_mipi_dphy {
161 	struct udevice *dev;
162 	void __iomem *regs;
163 	unsigned int lane_mbps;
164 	int lanes;
165 };
166 
167 static const u32 lane_reg_offset[] = {
168 	[CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
169 	[DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
170 	[DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
171 	[DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
172 	[DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
173 };
174 
175 #define FIXED_PARAM(_freq, _prepare, _clk_zero, _data_zero, _trail)	\
176 {	\
177 	.max_freq = _freq,	\
178 	.hs_prepare = _prepare,	\
179 	.clk_lane = {	\
180 		.hs_zero = _clk_zero,	\
181 	},	\
182 	.data_lane = {	\
183 		.hs_zero = _data_zero,	\
184 	},	\
185 	.hs_trail = _trail,	\
186 }
187 
188 struct fixed_param {
189 	unsigned int max_freq;
190 	u8 hs_prepare;
191 	struct {
192 		u8 hs_zero;
193 	} clk_lane;
194 	struct {
195 		u8 hs_zero;
196 	} data_lane;
197 	u8 hs_trail;
198 };
199 
200 static const struct fixed_param fixed_param_table[] = {
201 	FIXED_PARAM( 110, 0x20, 0x16, 0x02, 0x22),
202 	FIXED_PARAM( 150, 0x06, 0x16, 0x03, 0x45),
203 	FIXED_PARAM( 200, 0x18, 0x17, 0x04, 0x0b),
204 	FIXED_PARAM( 250, 0x05, 0x17, 0x05, 0x16),
205 	FIXED_PARAM( 300, 0x51, 0x18, 0x06, 0x2c),
206 	FIXED_PARAM( 400, 0x64, 0x19, 0x07, 0x33),
207 	FIXED_PARAM( 500, 0x20, 0x1b, 0x07, 0x4e),
208 	FIXED_PARAM( 600, 0x6a, 0x1d, 0x08, 0x3a),
209 	FIXED_PARAM( 700, 0x3e, 0x1e, 0x08, 0x6a),
210 	FIXED_PARAM( 800, 0x21, 0x1f, 0x09, 0x29),
211 	FIXED_PARAM(1000, 0x09, 0x20, 0x09, 0x27)
212 };
213 
214 static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
215 {
216 	writel(val, inno->regs + reg);
217 }
218 
219 static inline u32 inno_read(struct inno_mipi_dphy *inno, u32 reg)
220 {
221 	return readl(inno->regs + reg);
222 }
223 
224 static inline void inno_update_bits(struct inno_mipi_dphy *inno, u32 reg,
225 				    u32 mask, u32 val)
226 {
227 	u32 tmp, orig;
228 
229 	orig = inno_read(inno, reg);
230 	tmp = orig & ~mask;
231 	tmp |= val & mask;
232 	inno_write(inno, reg, tmp);
233 }
234 
235 static void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
236 					 unsigned long period)
237 {
238 	/* Global Operation Timing Parameters */
239 	timing->clkmiss = 0;
240 	timing->clkpost = 70 + 52 * period;
241 	timing->clkpre = 8 * period;
242 	timing->clkprepare = 65;
243 	timing->clksettle = 95;
244 	timing->clktermen = 0;
245 	timing->clktrail = 80;
246 	timing->clkzero = 260;
247 	timing->dtermen = 0;
248 	timing->eot = 0;
249 	timing->hsexit = 120;
250 	timing->hsprepare = 65 + 4 * period;
251 	timing->hszero = 145 + 6 * period;
252 	timing->hssettle = 85 + 6 * period;
253 	timing->hsskip = 40;
254 	timing->hstrail = max(8 * period, 60 + 4 * period);
255 	timing->init = 100000;
256 	timing->lpx = 60;
257 	timing->taget = 5 * timing->lpx;
258 	timing->tago = 4 * timing->lpx;
259 	timing->tasure = 2 * timing->lpx;
260 	timing->wakeup = 1000000;
261 }
262 
263 static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
264 					 enum lane_type lane_type,
265 					 struct inno_mipi_dphy_timing *t)
266 {
267 	u32 base = lane_reg_offset[lane_type];
268 	u32 m, v;
269 
270 	m = T_HS_PREPARE_MASK;
271 	v = T_HS_PREPARE(t->hs_prepare);
272 	inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, m, v);
273 
274 	m = T_HS_ZERO_MASK;
275 	v = T_HS_ZERO(t->hs_zero);
276 	inno_update_bits(inno, base + T_HS_ZERO_OFFSET, m, v);
277 
278 	m = T_HS_TRAIL_MASK;
279 	v = T_HS_TRAIL(t->hs_trail);
280 	inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, m, v);
281 
282 	m = T_HS_EXIT_MASK;
283 	v = T_HS_EXIT(t->hs_exit);
284 	inno_update_bits(inno, base + T_HS_EXIT_OFFSET, m, v);
285 
286 	if (lane_type == CLOCK_LANE) {
287 		m = T_CLK_POST_MASK;
288 		v = T_CLK_POST(t->clk_post);
289 		inno_update_bits(inno, base + T_CLK_POST_OFFSET, m, v);
290 
291 		m = T_CLK_PRE_MASK;
292 		v = T_CLK_PRE(t->clk_pre);
293 		inno_update_bits(inno, base + T_CLK_PRE_OFFSET, m, v);
294 	}
295 
296 	m = T_WAKUP_H_MASK;
297 	v = T_WAKUP_H(t->wakup_h);
298 	inno_update_bits(inno, base + T_WAKUP_H_OFFSET, m, v);
299 
300 	m = T_WAKUP_L_MASK;
301 	v = T_WAKUP_L(t->wakup_l);
302 	inno_update_bits(inno, base + T_WAKUP_L_OFFSET, m, v);
303 
304 	m = T_LPX_MASK;
305 	v = T_LPX(t->lpx);
306 	inno_update_bits(inno, base + T_LPX_OFFSET, m, v);
307 
308 	m = T_TA_GO_MASK;
309 	v = T_TA_GO(t->ta_go);
310 	inno_update_bits(inno, base + T_TA_GO_OFFSET, m, v);
311 
312 	m = T_TA_SURE_MASK;
313 	v = T_TA_SURE(t->ta_sure);
314 	inno_update_bits(inno, base + T_TA_SURE_OFFSET, m, v);
315 
316 	m = T_TA_WAIT_MASK;
317 	v = T_TA_WAIT(t->ta_wait);
318 	inno_update_bits(inno, base + T_TA_WAIT_OFFSET, m, v);
319 }
320 
321 static void inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
322 					   unsigned int freq,
323 					   enum lane_type lane_type)
324 {
325 	const struct fixed_param *param;
326 	int i;
327 
328 	for (i = 0; i < ARRAY_SIZE(fixed_param_table); i++)
329 		if (freq <= fixed_param_table[i].max_freq)
330 			break;
331 
332 	if (i == ARRAY_SIZE(fixed_param_table))
333 		--i;
334 
335 	param = &fixed_param_table[i];
336 
337 	if (lane_type == CLOCK_LANE)
338 		t->hs_zero = param->clk_lane.hs_zero;
339 	else
340 		t->hs_zero = param->data_lane.hs_zero;
341 
342 	t->hs_prepare = param->hs_prepare;
343 	t->hs_trail = param->hs_trail;
344 }
345 
346 static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
347 					    enum lane_type lane_type)
348 {
349 	struct mipi_dphy_timing timing;
350 	struct inno_mipi_dphy_timing data;
351 	unsigned long txbyteclk, txclkesc, UI;
352 	unsigned int esc_clk_div;
353 
354 	memset(&timing, 0, sizeof(timing));
355 	memset(&data, 0, sizeof(data));
356 
357 	txbyteclk = inno->lane_mbps * USEC_PER_SEC / 8;
358 	esc_clk_div = DIV_ROUND_UP(txbyteclk, 20000000);
359 	txclkesc = txbyteclk / esc_clk_div;
360 	UI = DIV_ROUND_CLOSEST(NSEC_PER_USEC, inno->lane_mbps);
361 
362 	debug("txbyteclk=%lu, txclkesc=%lu, esc_clk_div=%u, UI=%lu\n",
363 	      txbyteclk, txclkesc, esc_clk_div, UI);
364 
365 	mipi_dphy_timing_get_default(&timing, UI);
366 	inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps, lane_type);
367 
368 	/*
369 	 * Ttxbyteclk * val >= Ths-exit
370 	 * Ttxbyteclk * val >= Tclk-post
371 	 * Ttxbyteclk * val >= Tclk-pre
372 	 * Ttxbyteclk * (2 + val) >= Tlpx
373 	 */
374 	data.hs_exit = DIV_ROUND_UP(timing.hsexit * txbyteclk, NSEC_PER_SEC);
375 	data.clk_post = DIV_ROUND_UP(timing.clkpost * txbyteclk, NSEC_PER_SEC);
376 	data.clk_pre = DIV_ROUND_UP(timing.clkpre * txbyteclk, NSEC_PER_SEC);
377 	data.wakup_h = 0x3;
378 	data.wakup_l = 0xff;
379 	data.lpx = DIV_ROUND_UP(txbyteclk * timing.lpx, NSEC_PER_SEC);
380 	if (data.lpx > 2)
381 		data.lpx -= 2;
382 
383 	/*
384 	 * Ttxclkesc * val >= Tta-go
385 	 * Ttxclkesc * val >= Tta-sure
386 	 * Ttxclkesc * val >= Tta-wait
387 	 */
388 	data.ta_go = DIV_ROUND_UP(timing.tago * txclkesc, NSEC_PER_SEC);
389 	data.ta_sure = DIV_ROUND_UP(timing.tasure * txclkesc, NSEC_PER_SEC);
390 	data.ta_wait = DIV_ROUND_UP(timing.taget * txclkesc, NSEC_PER_SEC);
391 
392 	inno_mipi_dphy_timing_update(inno, lane_type, &data);
393 
394 #define TIMING_NS(x, freq) (((x) * (DIV_ROUND_CLOSEST(NSEC_PER_SEC, freq))))
395 	debug("hs-exit=%lu, clk-post=%lu, clk-pre=%lu, lpx=%lu\n",
396 	      TIMING_NS(data.hs_exit, txbyteclk),
397 	      TIMING_NS(data.clk_post, txbyteclk),
398 	      TIMING_NS(data.clk_pre, txbyteclk),
399 	      TIMING_NS(data.lpx + 2, txbyteclk));
400 	debug("ta-go=%lu, ta-sure=%lu, ta-wait=%lu\n",
401 	      TIMING_NS(data.ta_go, txclkesc),
402 	      TIMING_NS(data.ta_sure, txclkesc),
403 	      TIMING_NS(data.ta_wait, txclkesc));
404 }
405 
406 static unsigned long inno_mipi_dphy_pll_round_rate(unsigned long fin,
407 						   unsigned long fout,
408 						   u8 *prediv, u16 *fbdiv)
409 {
410 	unsigned long best_freq = 0;
411 	u8 min_prediv, max_prediv;
412 	u8 _prediv, best_prediv = 0;
413 	u16 _fbdiv, best_fbdiv = 0;
414 	u32 min_delta = 0xffffffff;
415 
416 	fout *= 2;
417 
418 	min_prediv = DIV_ROUND_UP(fin, 40000000);
419 	max_prediv = fin / 5000000;
420 
421 	for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
422 		u64 tmp;
423 		u32 delta;
424 		tmp = (u64)fout * _prediv;
425 		do_div(tmp, fin);
426 		_fbdiv = tmp;
427 		if ((_fbdiv == 15) || (_fbdiv < 12) || (_fbdiv > 511))
428 			continue;
429 		tmp = (u64)_fbdiv * fin;
430 		do_div(tmp, _prediv);
431 
432 		delta = abs(fout - tmp);
433 		if (delta < min_delta) {
434 			best_prediv = _prediv;
435 			best_fbdiv = _fbdiv;
436 			min_delta = delta;
437 			best_freq = tmp;
438 		}
439 	}
440 
441 	if (best_freq) {
442 		*prediv = best_prediv;
443 		*fbdiv = best_fbdiv;
444 	}
445 
446 	return best_freq / 2;
447 }
448 
449 static inline void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)
450 {
451 	/* Reset analog */
452 	inno_update_bits(inno, INNO_PHY_POWER_CTRL,
453 			 ANALOG_RESET_MASK, ANALOG_RESET);
454 	udelay(1);
455 	inno_update_bits(inno, INNO_PHY_POWER_CTRL,
456 			 ANALOG_RESET_MASK, ANALOG_NORMAL);
457 	/* Reset digital */
458 	inno_update_bits(inno, INNO_PHY_DIG_CTRL,
459 			 DIGITAL_RESET_MASK, DIGITAL_RESET);
460 	udelay(1);
461 	inno_update_bits(inno, INNO_PHY_DIG_CTRL,
462 			 DIGITAL_RESET_MASK, DIGITAL_NORMAL);
463 }
464 
465 static void inno_mipi_dphy_timing_init(struct inno_mipi_dphy *inno)
466 {
467 	switch (inno->lanes) {
468 	case 4:
469 		inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_3);
470 		/* Fall through */
471 	case 3:
472 		inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_2);
473 		/* Fall through */
474 	case 2:
475 		inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_1);
476 		/* Fall through */
477 	case 1:
478 	default:
479 		inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_0);
480 		inno_mipi_dphy_lane_timing_init(inno, CLOCK_LANE);
481 		break;
482 	}
483 }
484 
485 static inline void inno_mipi_dphy_lane_enable(struct inno_mipi_dphy *inno)
486 {
487 	u32 m = 0, v = 0;
488 
489 	switch (inno->lanes) {
490 	case 4:
491 		m |= DATA_LANE_3_EN_MASK;
492 		v |= DATA_LANE_3_EN;
493 		/* Fall through */
494 	case 3:
495 		m |= DATA_LANE_2_EN_MASK;
496 		v |= DATA_LANE_2_EN;
497 		/* Fall through */
498 	case 2:
499 		m |= DATA_LANE_1_EN_MASK;
500 		v |= DATA_LANE_1_EN;
501 		/* Fall through */
502 	default:
503 	case 1:
504 		m |= DATA_LANE_0_EN_MASK | CLK_LANE_EN_MASK;
505 		v |= DATA_LANE_0_EN | CLK_LANE_EN;
506 		break;
507 	}
508 
509 	inno_update_bits(inno, INNO_PHY_LANE_CTRL, m, v);
510 }
511 
512 static inline void inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy *inno)
513 {
514 	inno_update_bits(inno, INNO_PHY_POWER_CTRL,
515 			 PLL_POWER_MASK | LDO_POWER_MASK,
516 			 PLL_POWER_DOWN | LDO_POWER_DOWN);
517 }
518 
519 static inline void inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy *inno)
520 {
521 	inno_update_bits(inno, INNO_PHY_POWER_CTRL,
522 			 PLL_POWER_MASK | LDO_POWER_MASK,
523 			 PLL_POWER_ON | LDO_POWER_ON);
524 }
525 
526 static inline void inno_mipi_dphy_da_pwrok_enable(struct inno_mipi_dphy *inno)
527 {
528 	inno_update_bits(inno, INNO_PHY_LANE_CTRL, PWROK_BP | PWROK, PWROK);
529 }
530 
531 static inline void inno_mipi_dphy_da_pwrok_disable(struct inno_mipi_dphy *inno)
532 {
533 	inno_update_bits(inno, INNO_PHY_LANE_CTRL, PWROK_BP | PWROK, PWROK_BP);
534 }
535 
536 static inline void inno_mipi_dphy_bgpd_enable(struct inno_mipi_dphy *inno)
537 {
538 	inno_update_bits(inno, INNO_PHY_LANE_CTRL, MIPI_BGPD, 0);
539 }
540 
541 static inline void inno_mipi_dphy_bgpd_disable(struct inno_mipi_dphy *inno)
542 {
543 	inno_update_bits(inno, INNO_PHY_LANE_CTRL, MIPI_BGPD, MIPI_BGPD);
544 	inno_update_bits(inno, INNO_PHY_LVDS_CTRL, LVDS_BGPD, LVDS_BGPD);
545 }
546 
547 static int inno_mipi_dphy_power_on(struct rockchip_phy *phy)
548 {
549 	struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
550 
551 	inno_mipi_dphy_bgpd_enable(inno);
552 	inno_mipi_dphy_da_pwrok_enable(inno);
553 	inno_mipi_dphy_pll_ldo_enable(inno);
554 	inno_mipi_dphy_lane_enable(inno);
555 	inno_mipi_dphy_reset(inno);
556 	inno_mipi_dphy_timing_init(inno);
557 	udelay(1);
558 
559 	return 0;
560 }
561 
562 static inline void inno_mipi_dphy_lane_disable(struct inno_mipi_dphy *inno)
563 {
564 	inno_update_bits(inno, INNO_PHY_LANE_CTRL, 0x7c, 0x00);
565 }
566 
567 static int inno_mipi_dphy_power_off(struct rockchip_phy *phy)
568 {
569 	struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
570 
571 	inno_mipi_dphy_lane_disable(inno);
572 	inno_mipi_dphy_pll_ldo_disable(inno);
573 	inno_mipi_dphy_da_pwrok_disable(inno);
574 	inno_mipi_dphy_bgpd_disable(inno);
575 
576 	return 0;
577 }
578 
579 static unsigned long inno_mipi_dphy_set_pll(struct rockchip_phy *phy,
580 					    unsigned long rate)
581 {
582 	struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
583 	unsigned long fin, fout;
584 	u16 fbdiv = 0;
585 	u8 prediv = 0;
586 	u32 m, v;
587 
588 	fin = 24000000;
589 	fout = inno_mipi_dphy_pll_round_rate(fin, rate, &prediv, &fbdiv);
590 
591 	debug("%s: fin=%lu, fout=%lu, prediv=%u, fbdiv=%u\n",
592 	       __func__, fin, fout, prediv, fbdiv);
593 
594 	m = FBDIV_HI_MASK | PREDIV_MASK;
595 	v = FBDIV_HI(fbdiv >> 8) | PREDIV(prediv);
596 	inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, m, v);
597 
598 	m = FBDIV_LO_MASK;
599 	v = FBDIV_LO(fbdiv);
600 	inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, m, v);
601 
602 	inno->lane_mbps = fout / USEC_PER_SEC;
603 
604 	return fout;
605 }
606 
607 static int inno_mipi_dphy_parse_dt(struct inno_mipi_dphy *inno)
608 {
609 	struct udevice *dev = inno->dev;
610 
611 	inno->lanes = ofnode_read_u32_default(dev->node, "inno,lanes", 4);
612 
613 	return 0;
614 }
615 
616 static int inno_mipi_dphy_init(struct rockchip_phy *phy)
617 {
618 	struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
619 	int ret;
620 
621 	ret = inno_mipi_dphy_parse_dt(inno);
622 	if (ret) {
623 		printf("%s: failed to parse DT\n", __func__);
624 		return ret;
625 	}
626 
627 	inno->regs = dev_read_addr_ptr(inno->dev);
628 
629 	return 0;
630 }
631 
632 static const struct rockchip_phy_funcs inno_mipi_dphy_funcs = {
633 	.init = inno_mipi_dphy_init,
634 	.power_on = inno_mipi_dphy_power_on,
635 	.power_off = inno_mipi_dphy_power_off,
636 	.set_pll = inno_mipi_dphy_set_pll,
637 };
638 
639 static struct rockchip_phy inno_mipi_dphy_driver_data = {
640 	 .funcs = &inno_mipi_dphy_funcs,
641 };
642 
643 static const struct udevice_id inno_mipi_dphy_ids[] = {
644 	{
645 		.compatible = "rockchip,rv1108-mipi-dphy",
646 		.data = (ulong)&inno_mipi_dphy_driver_data,
647 	},
648 	{}
649 };
650 
651 static int inno_mipi_dphy_probe(struct udevice *dev)
652 {
653 	struct inno_mipi_dphy *inno = dev_get_priv(dev);
654 	struct rockchip_phy *phy =
655 		(struct rockchip_phy *)dev_get_driver_data(dev);
656 
657 	inno->dev = dev;
658 	phy->dev = dev;
659 
660 	return 0;
661 }
662 
663 U_BOOT_DRIVER(inno_mipi_dphy) = {
664 	.name = "inno_mipi_dphy",
665 	.id = UCLASS_PHY,
666 	.of_match = inno_mipi_dphy_ids,
667 	.probe = inno_mipi_dphy_probe,
668 	.priv_auto_alloc_size = sizeof(struct inno_mipi_dphy),
669 };
670