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
|
// 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;
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");
|