summaryrefslogtreecommitdiff
path: root/drivers/phy/m31/phy-m31-dphy-tx0.c
blob: e82e1da50c66e9516e88e3a8bf87dddc798bf78e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Rockchip MIPI Synopsys DPHY RX0 driver
 *
 * Copyright (C) 2019 Collabora, Ltd.
 *
 * Based on:
 *
 * drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
 * in https://chromium.googlesource.com/chromiumos/third_party/kernel,
 * chromeos-4.4 branch.
 *
 * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
 *   Jacob Chen <jacob2.chen@rock-chips.com>
 *   Shunqian Zheng <zhengsq@rock-chips.com>
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-mipi-dphy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

//syscfg registers
#define SCFG_DSI_CSI_SEL	        0x2c
#define SCFG_PHY_RESETB	            0x30
#define SCFG_REFCLK_SEL	            0x34
#define SCFG_DBUS_PW_PLL_SSC_LD0	0x38
#define SCFG_GRS_CDTX_PLL       	0x3c

#define SCFG_RG_CDTX_PLL_FBK_PRE	0x44
#define SCFG_RG_CLANE_DLANE_TIME   	0x58
#define SCFG_RG_CLANE_HS_TIME   	0x58

#define SCFG_RG_EXTD_CYCLE_SEL   	0x5c

#define SCFG_L0N_L0P_HSTX	        0x60
#define SCFG_L1N_L1P_HSTX	        0x64
#define SCFG_L2N_L2P_HSTX	        0x68
#define SCFG_L3N_L3P_HSTX	        0x6c
#define SCFG_L4N_L4P_HSTX	        0x70
#define SCFG_LX_SWAP_SEL	        0x78

#define SCFG_HS_PRE_ZERO_T_D	    0xc4
#define SCFG_TXREADY_SRC_SEL_D	    0xc8
#define SCFG_HS_PRE_ZERO_T_C	    0xd4
#define SCFG_TXREADY_SRC_SEL_C	    0xd8

//reg SCFG_LX_SWAP_SEL
#define	OFFSET_CFG_L0_SWAP_SEL 	0
#define	OFFSET_CFG_L1_SWAP_SEL 	3
#define	OFFSET_CFG_L2_SWAP_SEL 	6
#define	OFFSET_CFG_L3_SWAP_SEL 	9
#define OFFSET_CFG_L4_SWAP_SEL 	12

//reg SCFG_DBUS_PW_PLL_SSC_LD0
#define OFFSET_SCFG_CFG_DATABUD16_SEL    0
#define OFFSET_SCFG_PWRON_READY_N        1
#define OFFSET_RG_CDTX_PLL_FM_EN         2
#define OFFSET_SCFG_PLLSSC_EN            3
#define OFFSET_RG_CDTX_PLL_LDO_STB_X2_EN 4

//reg SCFG_RG_CLANE_DLANE_TIME
#define OFFSET_DHS_PRE_TIME          8
#define OFFSET_DHS_TRIAL_TIME        16
#define OFFSET_DHS_ZERO_TIME         24

//reg SCFG_RG_CLANE_HS_TIME
#define OFFSET_CHS_PRE_TIME          8
#define OFFSET_CHS_TRIAL_TIME        16
#define OFFSET_CHS_ZERO_TIME         24

//dsitx registers
#define  VID_MCTL_MAIN_DATA_CTL	        0x04
#define  VID_MCTL_MAIN_PHY_CTL	        0x08
#define  VID_MCTL_MAIN_EN	            0x0c
#define  VID_MAIN_CTRL_ADDR    0xb0
#define  VID_VSIZE1_ADDR       0xb4
#define  VID_VSIZE2_ADDR       0xb8
#define  VID_HSIZE1_ADDR       0xc0
#define  VID_HSIZE2_ADDR       0xc4
#define  VID_BLKSIZE1_ADDR     0xCC
#define  VID_BLKSIZE2_ADDR     0xd0
#define  VID_PCK_TIME_ADDR     0xd8
#define  VID_DPHY_TIME_ADDR    0xdc
#define  VID_ERR_COLOR1_ADDR   0xe0
#define  VID_ERR_COLOR2_ADDR   0xe4
#define  VID_VPOS_ADDR         0xe8
#define  VID_HPOS_ADDR         0xec
#define  VID_MODE_STAT_ADDR    0xf0
#define  VID_VCA_SET1_ADDR     0xf4
#define  VID_VCA_SET2_ADDR     0xf8


#define  VID_MODE_STAT_CLR_ADDR    0x160
#define  VID_MODE_STAT_FLAG_ADDR   0x180

#define  TVG_CTRL_ADDR      0x0fc
#define  TVG_IMG_SIZE_ADDR  0x100
#define  TVG_COLOR1_ADDR    0x104
#define  TVG_COLOR1BIT_ADDR 0x108
#define  TVG_COLOR2_ADDR    0x10c
#define  TVG_COLOR2BIT_ADDR 0x110
#define  TVG_STAT_ADDR      0x114
#define  TVG_STAT_CTRL_ADDR 0x144
#define  TVG_STAT_CLR_ADDR  0x164
#define  TVG_STAT_FLAG_ADDR 0x184

#define  DPI_IRQ_EN_ADDR   0x1a0
#define  DPI_IRQ_CLR_ADDR  0x1a4
#define  DPI_IRQ_STAT_ADDR 0x1a4
#define  DPI_CFG_ADDR      0x1ac


//sysrst registers
#define SRST_ASSERT0	    0x00
#define SRST_STATUS0    	0x04
/* Definition controller bit for syd rst registers */
#define BIT_RST_DSI_DPI_PIX		17

struct sf_dphy {
	struct device *dev;
	void __iomem *topsys;

	struct clk_bulk_data *clks;

	struct phy_configure_opts_mipi_dphy config;

	u8 hsfreq;

	struct phy *phy;
};

static u32 top_sys_read32(struct sf_dphy *priv, u32 reg)
{
	return ioread32(priv->topsys + reg);
}


static inline void top_sys_write32(struct sf_dphy *priv, u32 reg, u32 val)
{
	iowrite32(val, priv->topsys + reg);
}

static void dsi_csi2tx_sel(struct sf_dphy *priv, int sel)
{
  u32 temp = 0;
  temp = top_sys_read32(priv, SCFG_DSI_CSI_SEL);
  temp &= ~(0x1);
  temp |= (sel & 0x1);
  top_sys_write32(priv, SCFG_DSI_CSI_SEL, temp);
}

static void dphy_clane_hs_txready_sel(struct sf_dphy *priv, u32 ready_sel)
{
	top_sys_write32(priv, SCFG_TXREADY_SRC_SEL_D, ready_sel);
	top_sys_write32(priv, SCFG_TXREADY_SRC_SEL_C, ready_sel);
	top_sys_write32(priv, SCFG_HS_PRE_ZERO_T_D, 0x30);
	top_sys_write32(priv, SCFG_HS_PRE_ZERO_T_C, 0x30);
}

static void mipi_tx_lxn_set(struct sf_dphy *priv, u32 reg, u32 n_hstx, u32 p_hstx)
{
	u32 temp = 0;

	temp = n_hstx;
	temp |= p_hstx << 5;
	top_sys_write32(priv, reg, temp);
}

static void dphy_config(struct sf_dphy *priv, int bit_rate)
{
	int pre_div,      fbk_int,       extd_cycle_sel;
	int dhs_pre_time, dhs_zero_time, dhs_trial_time;
	int chs_pre_time, chs_zero_time, chs_trial_time;
	int chs_clk_pre_time, chs_clk_post_time;
	u32 set_val = 0;

	mipi_tx_lxn_set(priv, SCFG_L0N_L0P_HSTX, 0x10, 0x10);
	mipi_tx_lxn_set(priv, SCFG_L1N_L1P_HSTX, 0x10, 0x10);
	mipi_tx_lxn_set(priv, SCFG_L2N_L2P_HSTX, 0x10, 0x10);
	mipi_tx_lxn_set(priv, SCFG_L3N_L3P_HSTX, 0x10, 0x10);
	mipi_tx_lxn_set(priv, SCFG_L4N_L4P_HSTX, 0x10, 0x10);

	if(bit_rate == 80) {
		pre_div=0x1,		fbk_int=2*0x33,		extd_cycle_sel=0x4,
		dhs_pre_time=0xe,	dhs_zero_time=0x1d,	dhs_trial_time=0x15,
		chs_pre_time=0x5,	chs_zero_time=0x2b,	chs_trial_time=0xd,
		chs_clk_pre_time=0xf,
		chs_clk_post_time=0x71;
	} else if (bit_rate == 100) {
		pre_div=0x1,		fbk_int=2*0x40,		extd_cycle_sel=0x4,
		dhs_pre_time=0x10,	dhs_zero_time=0x21,	dhs_trial_time=0x17,
		chs_pre_time=0x7,	chs_zero_time=0x35,	chs_trial_time=0xf,
		chs_clk_pre_time=0xf,
		chs_clk_post_time=0x73;
	} else if (bit_rate == 200) {
		pre_div=0x1,		fbk_int=2*0x40,		extd_cycle_sel=0x3;
		dhs_pre_time=0xc,	dhs_zero_time=0x1b,	dhs_trial_time=0x13;
		chs_pre_time=0x7,	chs_zero_time=0x35,	chs_trial_time=0xf,
		chs_clk_pre_time=0x7,
		chs_clk_post_time=0x3f;
	} else if(bit_rate == 300) {
		pre_div=0x1,		fbk_int=2*0x60, 	extd_cycle_sel=0x3,
		dhs_pre_time=0x11,	dhs_zero_time=0x25, dhs_trial_time=0x19,
		chs_pre_time=0xa, 	chs_zero_time=0x50, chs_trial_time=0x15,
		chs_clk_pre_time=0x7,
		chs_clk_post_time=0x45;
    } else if(bit_rate == 400) {
		pre_div=0x1,      	fbk_int=2*0x40,		extd_cycle_sel=0x2,
		dhs_pre_time=0xa, 	dhs_zero_time=0x18,	dhs_trial_time=0x11,
		chs_pre_time=0x7, 	chs_zero_time=0x35, chs_trial_time=0xf,
		chs_clk_pre_time=0x3,
		chs_clk_post_time=0x25;
    } else if(bit_rate == 500 ) {
		pre_div=0x1,      fbk_int=2*0x50,       extd_cycle_sel=0x2,
		dhs_pre_time=0xc, dhs_zero_time=0x1d,	dhs_trial_time=0x14,
		chs_pre_time=0x9, chs_zero_time=0x42,	chs_trial_time=0x12,
		chs_clk_pre_time=0x3,
		chs_clk_post_time=0x28;
    } else if(bit_rate == 600 ) {
		pre_div=0x1,      fbk_int=2*0x60,       extd_cycle_sel=0x2,
		dhs_pre_time=0xe, dhs_zero_time=0x23,	dhs_trial_time=0x17,
		chs_pre_time=0xa, chs_zero_time=0x50,	chs_trial_time=0x15,
		chs_clk_pre_time=0x3,
		chs_clk_post_time=0x2b;
    } else if(bit_rate == 700) {
		pre_div=0x1,      fbk_int=2*0x38,       extd_cycle_sel=0x1,
		dhs_pre_time=0x8, dhs_zero_time=0x14,	dhs_trial_time=0xf,
		chs_pre_time=0x6, chs_zero_time=0x2f,	chs_trial_time=0xe,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x16;
    } else if(bit_rate == 800 ) {
		pre_div=0x1,      fbk_int=2*0x40,       extd_cycle_sel=0x1,
		dhs_pre_time=0x9, dhs_zero_time=0x17,	dhs_trial_time=0x10,
		chs_pre_time=0x7, chs_zero_time=0x35,	chs_trial_time=0xf,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x18;
    } else if(bit_rate == 900 ) {
		pre_div=0x1,      fbk_int=2*0x48,       extd_cycle_sel=0x1,
		dhs_pre_time=0xa, dhs_zero_time=0x19, 	dhs_trial_time=0x12,
		chs_pre_time=0x8, chs_zero_time=0x3c, 	chs_trial_time=0x10,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x19;
    } else if(bit_rate == 1000) {
		pre_div=0x1,      fbk_int=2*0x50,       extd_cycle_sel=0x1,
		dhs_pre_time=0xb, dhs_zero_time=0x1c,	dhs_trial_time=0x13,
		chs_pre_time=0x9, chs_zero_time=0x42,	chs_trial_time=0x12,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x1b;
    } else if(bit_rate == 1100) {
		pre_div=0x1,      fbk_int=2*0x58,       extd_cycle_sel=0x1,
		dhs_pre_time=0xc, dhs_zero_time=0x1e,	dhs_trial_time=0x15,
		chs_pre_time=0x9, chs_zero_time=0x4a,	chs_trial_time=0x14,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x1d;
    } else if(bit_rate == 1200) {
		pre_div=0x1,      fbk_int=2*0x60,       extd_cycle_sel=0x1,
		dhs_pre_time=0xe, dhs_zero_time=0x20,	dhs_trial_time=0x16,
		chs_pre_time=0xa, chs_zero_time=0x50,	chs_trial_time=0x15,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x1e;
    } else if(bit_rate == 1300) {
		pre_div=0x1,      fbk_int=2*0x34,       extd_cycle_sel=0x0,
		dhs_pre_time=0x7, dhs_zero_time=0x12,	dhs_trial_time=0xd,
		chs_pre_time=0x5, chs_zero_time=0x2c,	chs_trial_time=0xd,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0xf;
    } else if(bit_rate == 1400) {
		pre_div=0x1,      fbk_int=2*0x38,       extd_cycle_sel=0x0,
		dhs_pre_time=0x7, dhs_zero_time=0x14,	dhs_trial_time=0xe,
		chs_pre_time=0x6, chs_zero_time=0x2f,	chs_trial_time=0xe,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x10;
    } else if(bit_rate == 1500) {
		pre_div=0x1,      fbk_int=2*0x3c,       extd_cycle_sel=0x0,
		dhs_pre_time=0x8, dhs_zero_time=0x14,	dhs_trial_time=0xf,
		chs_pre_time=0x6, chs_zero_time=0x32,	chs_trial_time=0xe,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x11;
    } else if(bit_rate == 1600) {
		pre_div=0x1,      fbk_int=2*0x40,       extd_cycle_sel=0x0,
		dhs_pre_time=0x9, dhs_zero_time=0x15,	dhs_trial_time=0x10,
		chs_pre_time=0x7, chs_zero_time=0x35,	chs_trial_time=0xf,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x12;
    } else if(bit_rate == 1700) {
		pre_div=0x1,      fbk_int=2*0x44,       extd_cycle_sel=0x0,
		dhs_pre_time=0x9, dhs_zero_time=0x17,	dhs_trial_time=0x10,
		chs_pre_time=0x7, chs_zero_time=0x39,	chs_trial_time=0x10,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x12;
    } else if(bit_rate == 1800) {
		pre_div=0x1,      fbk_int=2*0x48,       extd_cycle_sel=0x0,
		dhs_pre_time=0xa, dhs_zero_time=0x18,	dhs_trial_time=0x11,
		chs_pre_time=0x8, chs_zero_time=0x3c,	chs_trial_time=0x10,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x13;
    } else if(bit_rate == 1900) {
		pre_div=0x1,      fbk_int=2*0x4c,       extd_cycle_sel=0x0,
		dhs_pre_time=0xa, dhs_zero_time=0x1a,	dhs_trial_time=0x12,
		chs_pre_time=0x8, chs_zero_time=0x3f,	chs_trial_time=0x11,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x14;
    } else if(bit_rate == 2000) {
		pre_div=0x1,      fbk_int=2*0x50,       extd_cycle_sel=0x0,
		dhs_pre_time=0xb, dhs_zero_time=0x1b,	dhs_trial_time=0x13,
		chs_pre_time=0x9, chs_zero_time=0x42,	chs_trial_time=0x12,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x15;
    } else if(bit_rate == 2100) {
		pre_div=0x1,      fbk_int=2*0x54,       extd_cycle_sel=0x0,
		dhs_pre_time=0xb, dhs_zero_time=0x1c,	dhs_trial_time=0x13,
		chs_pre_time=0x9, chs_zero_time=0x46,	chs_trial_time=0x13,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x15;
    } else if(bit_rate == 2200) {
		pre_div=0x1,      fbk_int=2*0x5b,       extd_cycle_sel=0x0,
		dhs_pre_time=0xc, dhs_zero_time=0x1d,	dhs_trial_time=0x14,
		chs_pre_time=0x9, chs_zero_time=0x4a,	chs_trial_time=0x14,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x16;
    } else if(bit_rate == 2300) {
		pre_div=0x1,      fbk_int=2*0x5c,       extd_cycle_sel=0x0,
		dhs_pre_time=0xc, dhs_zero_time=0x1f,	dhs_trial_time=0x15,
		chs_pre_time=0xa, chs_zero_time=0x4c,	chs_trial_time=0x14,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x17;
    } else if(bit_rate == 2400) {
		pre_div=0x1,      fbk_int=2*0x60,       extd_cycle_sel=0x0,
		dhs_pre_time=0xd, dhs_zero_time=0x20,	dhs_trial_time=0x16,
		chs_pre_time=0xa, chs_zero_time=0x50,	chs_trial_time=0x15,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x18;
    } else if(bit_rate == 2500) {
		pre_div=0x1,      fbk_int=2*0x64,       extd_cycle_sel=0x0,
		dhs_pre_time=0xe, dhs_zero_time=0x21,	dhs_trial_time=0x16,
		chs_pre_time=0xb, chs_zero_time=0x53,	chs_trial_time=0x16,
		chs_clk_pre_time=0x0,
		chs_clk_post_time=0x18;
    } else {
		//default bit_rate == 700
		pre_div=0x1,      fbk_int=2*0x38,       extd_cycle_sel=0x1,
		dhs_pre_time=0x8, dhs_zero_time=0x14,	dhs_trial_time=0xf,
		chs_pre_time=0x6, chs_zero_time=0x2f,	chs_trial_time=0xe,
		chs_clk_pre_time=0x1,
		chs_clk_post_time=0x16;
    }
	top_sys_write32(priv, SCFG_REFCLK_SEL, 0x3);

	set_val = 0
			| (1 << OFFSET_CFG_L1_SWAP_SEL)
			| (4 << OFFSET_CFG_L2_SWAP_SEL)
			| (2 << OFFSET_CFG_L3_SWAP_SEL)
			| (3 << OFFSET_CFG_L4_SWAP_SEL);
	top_sys_write32(priv, SCFG_LX_SWAP_SEL, set_val);

	set_val = 0
			| (0 << OFFSET_SCFG_PWRON_READY_N)
			| (1 << OFFSET_RG_CDTX_PLL_FM_EN)
			| (0 << OFFSET_SCFG_PLLSSC_EN)
			| (1 << OFFSET_RG_CDTX_PLL_LDO_STB_X2_EN);
	top_sys_write32(priv, SCFG_DBUS_PW_PLL_SSC_LD0, set_val);

	set_val = fbk_int
			| (pre_div << 9);
	top_sys_write32(priv, SCFG_RG_CDTX_PLL_FBK_PRE, set_val);

	top_sys_write32(priv, SCFG_RG_EXTD_CYCLE_SEL, extd_cycle_sel);

	set_val = chs_zero_time
			| (dhs_pre_time << OFFSET_DHS_PRE_TIME)
			| (dhs_trial_time << OFFSET_DHS_TRIAL_TIME)
			| (dhs_zero_time << OFFSET_DHS_ZERO_TIME);
	top_sys_write32(priv, SCFG_RG_CLANE_DLANE_TIME, set_val);

	set_val = chs_clk_post_time
			| (chs_clk_pre_time << OFFSET_CHS_PRE_TIME)
			| (chs_pre_time << OFFSET_CHS_TRIAL_TIME)
			| (chs_trial_time << OFFSET_CHS_ZERO_TIME);
	top_sys_write32(priv, SCFG_RG_CLANE_HS_TIME, set_val);

}

static void reset_dphy(struct sf_dphy *priv, int resetb)
{
	u32 cfg_dsc_enable = 0x01;//bit0

	u32 precfg = top_sys_read32(priv, SCFG_PHY_RESETB);
	precfg &= ~(cfg_dsc_enable);
	precfg |= (resetb&cfg_dsc_enable);
	top_sys_write32(priv, SCFG_PHY_RESETB, precfg);
}

static void polling_dphy_lock(struct sf_dphy *priv)
{
	int pll_unlock;

	udelay(10);

	do {
		pll_unlock = top_sys_read32(priv, SCFG_GRS_CDTX_PLL) >> 3;
		pll_unlock &= 0x1;
	} while(pll_unlock == 0x1);
}

static int sf_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
{
	struct sf_dphy *dphy = phy_get_drvdata(phy);
	uint32_t bit_rate = 800000000/1000000UL;//new mipi panel clock setting


	dphy_config(dphy, bit_rate);
	reset_dphy(dphy, 1);
	mdelay(10);
	polling_dphy_lock(dphy);

	return 0;
}

static int sf_dphy_power_on(struct phy *phy)
{
	return 0;
}

static int sf_dphy_power_off(struct phy *phy)
{
	return 0;
}

static int sf_dphy_init(struct phy *phy)
{
	struct sf_dphy *dphy = phy_get_drvdata(phy);

	dsi_csi2tx_sel(dphy, 0);
	dphy_clane_hs_txready_sel(dphy, 0x1);

	return 0;
}

static int sf_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
			union phy_configure_opts *opts)
{
	return 0;
}

static int sf_dphy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
{
	return 0;
}


static int sf_dphy_exit(struct phy *phy)
{
	return 0;
}

static const struct phy_ops sf_dphy_ops = {
	.power_on	= sf_dphy_power_on,
	.power_off	= sf_dphy_power_off,
	.init		= sf_dphy_init,
	.exit		= sf_dphy_exit,
	.configure	= sf_dphy_configure,
	.validate  = sf_dphy_validate,
	.set_mode  = sf_dphy_set_mode,
	.owner		= THIS_MODULE,
};

static const struct of_device_id sf_dphy_dt_ids[] = {
	{
		.compatible = "starfive,jh7100-mipi-dphy-tx",
	},
	{}
};
MODULE_DEVICE_TABLE(of, sf_dphy_dt_ids);

static int sf_dphy_probe(struct platform_device *pdev)
{
	struct phy_provider *phy_provider;
	struct sf_dphy *dphy;
	struct resource *res;
	int ret;
	dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
	if (!dphy)
		return -ENOMEM;
	dev_set_drvdata(&pdev->dev, dphy);

	dev_info(&pdev->dev,"===> %s enter, %d \n", __func__, __LINE__);

	dphy->topsys = ioremap(0x12260000, 0x10000);

	dphy->phy = devm_phy_create(&pdev->dev, NULL, &sf_dphy_ops);
	if (IS_ERR(dphy->phy)) {
		dev_err(&pdev->dev, "failed to create phy\n");
		return PTR_ERR(dphy->phy);
	}
	phy_set_drvdata(dphy->phy, dphy);

	phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);

	return PTR_ERR_OR_ZERO(phy_provider);
}

static struct platform_driver sf_dphy_driver = {
	.probe = sf_dphy_probe,
	.driver = {
		.name	= "sf-mipi-dphy-tx",
		.of_match_table = sf_dphy_dt_ids,
	},
};
module_platform_driver(sf_dphy_driver);

MODULE_AUTHOR("Ezequiel Garcia <ezequiel@collabora.com>");
MODULE_DESCRIPTION("sf MIPI  DPHY TX0 driver");
MODULE_LICENSE("Dual MIT/GPL");