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 0x0000
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 0x0004
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 0x000c
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 0x0010
59 #define FBDIV_LO_MASK GENMASK(7, 0)
60 #define FBDIV_LO(x) UPDATE(x, 7, 0)
61 #define ANALOG_REG_08 0x0020
62 #define PRE_EMPHASIS_ENABLE_MASK BIT(7)
63 #define PRE_EMPHASIS_ENABLE BIT(7)
64 #define PRE_EMPHASIS_DISABLE 0
65 #define PLL_POST_DIV_ENABLE_MASK BIT(5)
66 #define PLL_POST_DIV_ENABLE BIT(5)
67 #define PLL_POST_DIV_DISABLE 0
68 #define DATA_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
69 #define DATA_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
70 #define ANALOG_REG_0B 0x002c
71 #define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
72 #define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
73 #define VOD_MIN_RANGE 0x1
74 #define VOD_MID_RANGE 0x3
75 #define VOD_BIG_RANGE 0x7
76 #define VOD_MAX_RANGE 0xf
77 #define INNO_PHY_DIG_CTRL 0x0080
78 #define DIGITAL_RESET_MASK BIT(0)
79 #define DIGITAL_NORMAL BIT(0)
80 #define DIGITAL_RESET 0
81 #define INNO_PHY_LVDS_CTRL 0x03ac
82 #define LVDS_BGPD BIT(0)
83
84 #define INNO_CLOCK_LANE_REG_BASE 0x0100
85 #define INNO_DATA_LANE_0_REG_BASE 0x0180
86 #define INNO_DATA_LANE_1_REG_BASE 0x0200
87 #define INNO_DATA_LANE_2_REG_BASE 0x0280
88 #define INNO_DATA_LANE_3_REG_BASE 0x0300
89
90 #define T_LPX_OFFSET 0x0014
91 #define T_HS_PREPARE_OFFSET 0x0018
92 #define T_HS_ZERO_OFFSET 0x001c
93 #define T_HS_TRAIL_OFFSET 0x0020
94 #define T_HS_EXIT_OFFSET 0x0024
95 #define T_CLK_POST_OFFSET 0x0028
96 #define T_WAKUP_H_OFFSET 0x0030
97 #define T_WAKUP_L_OFFSET 0x0034
98 #define T_CLK_PRE_OFFSET 0x0038
99 #define T_TA_GO_OFFSET 0x0040
100 #define T_TA_SURE_OFFSET 0x0044
101 #define T_TA_WAIT_OFFSET 0x0048
102
103 #define T_LPX_MASK GENMASK(5, 0)
104 #define T_LPX(x) UPDATE(x, 5, 0)
105 #define T_HS_PREPARE_MASK GENMASK(6, 0)
106 #define T_HS_PREPARE(x) UPDATE(x, 6, 0)
107 #define T_HS_ZERO_MASK GENMASK(5, 0)
108 #define T_HS_ZERO(x) UPDATE(x, 5, 0)
109 #define T_HS_TRAIL_MASK GENMASK(6, 0)
110 #define T_HS_TRAIL(x) UPDATE(x, 6, 0)
111 #define T_HS_EXIT_MASK GENMASK(4, 0)
112 #define T_HS_EXIT(x) UPDATE(x, 4, 0)
113 #define T_CLK_POST_MASK GENMASK(3, 0)
114 #define T_CLK_POST(x) UPDATE(x, 3, 0)
115 #define T_WAKUP_H_MASK GENMASK(1, 0)
116 #define T_WAKUP_H(x) UPDATE(x, 1, 0)
117 #define T_WAKUP_L_MASK GENMASK(7, 0)
118 #define T_WAKUP_L(x) UPDATE(x, 7, 0)
119 #define T_CLK_PRE_MASK GENMASK(3, 0)
120 #define T_CLK_PRE(x) UPDATE(x, 3, 0)
121 #define T_TA_GO_MASK GENMASK(5, 0)
122 #define T_TA_GO(x) UPDATE(x, 5, 0)
123 #define T_TA_SURE_MASK GENMASK(5, 0)
124 #define T_TA_SURE(x) UPDATE(x, 5, 0)
125 #define T_TA_WAIT_MASK GENMASK(5, 0)
126 #define T_TA_WAIT(x) UPDATE(x, 5, 0)
127
128 enum soc_type {
129 RV1108_MIPI_DPHY,
130 RK1808_MIPI_DPHY,
131 };
132
133 enum lane_type {
134 CLOCK_LANE,
135 DATA_LANE_0,
136 DATA_LANE_1,
137 DATA_LANE_2,
138 DATA_LANE_3,
139 };
140
141 struct mipi_dphy_timing {
142 unsigned int clkmiss;
143 unsigned int clkpost;
144 unsigned int clkpre;
145 unsigned int clkprepare;
146 unsigned int clksettle;
147 unsigned int clktermen;
148 unsigned int clktrail;
149 unsigned int clkzero;
150 unsigned int dtermen;
151 unsigned int eot;
152 unsigned int hsexit;
153 unsigned int hsprepare;
154 unsigned int hszero;
155 unsigned int hssettle;
156 unsigned int hsskip;
157 unsigned int hstrail;
158 unsigned int init;
159 unsigned int lpx;
160 unsigned int taget;
161 unsigned int tago;
162 unsigned int tasure;
163 unsigned int wakeup;
164 };
165
166 struct inno_mipi_dphy_timing {
167 u8 lpx;
168 u8 hs_prepare;
169 u8 hs_zero;
170 u8 hs_trail;
171 u8 hs_exit;
172 u8 clk_post;
173 u8 wakup_h;
174 u8 wakup_l;
175 u8 clk_pre;
176 u8 ta_go;
177 u8 ta_sure;
178 u8 ta_wait;
179 };
180
181 struct inno_mipi_dphy {
182 struct udevice *dev;
183 void __iomem *regs;
184 unsigned int lane_mbps;
185 int lanes;
186 };
187
188 static const u32 lane_reg_offset[] = {
189 [CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
190 [DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
191 [DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
192 [DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
193 [DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
194 };
195
196 #define FIXED_PARAM(_freq, _lpx, _prepare, _clk_zero, _data_zero, _trail) \
197 { \
198 .max_freq = _freq, \
199 .lpx = _lpx, \
200 .hs_prepare = _prepare, \
201 .clk_lane = { \
202 .hs_zero = _clk_zero, \
203 }, \
204 .data_lane = { \
205 .hs_zero = _data_zero, \
206 }, \
207 .hs_trail = _trail, \
208 }
209
210 struct fixed_param {
211 unsigned int max_freq;
212 u8 lpx;
213 u8 hs_prepare;
214 struct {
215 u8 hs_zero;
216 } clk_lane;
217 struct {
218 u8 hs_zero;
219 } data_lane;
220 u8 hs_trail;
221 };
222
223 static const struct fixed_param fixed_param_table[] = {
224 FIXED_PARAM(110, 0x0, 0x20, 0x16, 0x02, 0x22),
225 FIXED_PARAM(150, 0x0, 0x06, 0x16, 0x03, 0x45),
226 FIXED_PARAM(200, 0x0, 0x18, 0x17, 0x04, 0x0b),
227 FIXED_PARAM(250, 0x0, 0x05, 0x17, 0x05, 0x16),
228 FIXED_PARAM(300, 0x0, 0x51, 0x18, 0x06, 0x2c),
229 FIXED_PARAM(400, 0x0, 0x64, 0x19, 0x07, 0x33),
230 FIXED_PARAM(500, 0x0, 0x20, 0x1b, 0x07, 0x4e),
231 FIXED_PARAM(600, 0x0, 0x6a, 0x1d, 0x08, 0x3a),
232 FIXED_PARAM(700, 0x0, 0x3e, 0x1e, 0x08, 0x6a),
233 FIXED_PARAM(800, 0x0, 0x21, 0x1f, 0x09, 0x29),
234 FIXED_PARAM(1000, 0x0, 0x09, 0x20, 0x09, 0x27)
235 };
236
237 static const struct fixed_param rk1808_fixed_param_table[] = {
238 FIXED_PARAM(110, 0x02, 0x7f, 0x16, 0x02, 0x02),
239 FIXED_PARAM(150, 0x02, 0x7f, 0x16, 0x03, 0x02),
240 FIXED_PARAM(200, 0x02, 0x7f, 0x17, 0x04, 0x02),
241 FIXED_PARAM(250, 0x02, 0x7f, 0x17, 0x05, 0x04),
242 FIXED_PARAM(300, 0x02, 0x7f, 0x18, 0x06, 0x04),
243 FIXED_PARAM(400, 0x03, 0x7e, 0x19, 0x07, 0x04),
244 FIXED_PARAM(500, 0x03, 0x7c, 0x1b, 0x07, 0x08),
245 FIXED_PARAM(600, 0x03, 0x70, 0x1d, 0x08, 0x10),
246 FIXED_PARAM(700, 0x05, 0x40, 0x1e, 0x08, 0x30),
247 FIXED_PARAM(800, 0x05, 0x02, 0x1f, 0x09, 0x30),
248 FIXED_PARAM(1000, 0x05, 0x08, 0x20, 0x09, 0x30),
249 FIXED_PARAM(1400, 0x09, 0x03, 0x32, 0x14, 0x0f),
250 FIXED_PARAM(1600, 0x0d, 0x42, 0x36, 0x0e, 0x0f),
251 FIXED_PARAM(1800, 0x0e, 0x47, 0x7a, 0x0e, 0x0f),
252 FIXED_PARAM(2000, 0x11, 0x64, 0x7a, 0x0e, 0x0b),
253 };
254
inno_write(struct inno_mipi_dphy * inno,u32 reg,u32 val)255 static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
256 {
257 writel(val, inno->regs + reg);
258 }
259
inno_read(struct inno_mipi_dphy * inno,u32 reg)260 static inline u32 inno_read(struct inno_mipi_dphy *inno, u32 reg)
261 {
262 return readl(inno->regs + reg);
263 }
264
inno_update_bits(struct inno_mipi_dphy * inno,u32 reg,u32 mask,u32 val)265 static inline void inno_update_bits(struct inno_mipi_dphy *inno, u32 reg,
266 u32 mask, u32 val)
267 {
268 u32 tmp, orig;
269
270 orig = inno_read(inno, reg);
271 tmp = orig & ~mask;
272 tmp |= val & mask;
273 inno_write(inno, reg, tmp);
274 }
275
mipi_dphy_timing_get_default(struct mipi_dphy_timing * timing,unsigned long period)276 static void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
277 unsigned long period)
278 {
279 /* Global Operation Timing Parameters */
280 timing->clkmiss = 0;
281 timing->clkpost = 70 + 52 * period;
282 timing->clkpre = 8 * period;
283 timing->clkprepare = 65;
284 timing->clksettle = 95;
285 timing->clktermen = 0;
286 timing->clktrail = 80;
287 timing->clkzero = 260;
288 timing->dtermen = 0;
289 timing->eot = 0;
290 timing->hsexit = 120;
291 timing->hsprepare = 65 + 4 * period;
292 timing->hszero = 145 + 6 * period;
293 timing->hssettle = 85 + 6 * period;
294 timing->hsskip = 40;
295 timing->hstrail = max(8 * period, 60 + 4 * period);
296 timing->init = 100000;
297 timing->lpx = 60;
298 timing->taget = 5 * timing->lpx;
299 timing->tago = 4 * timing->lpx;
300 timing->tasure = 2 * timing->lpx;
301 timing->wakeup = 1000000;
302 }
303
inno_mipi_dphy_timing_update(struct inno_mipi_dphy * inno,enum lane_type lane_type,struct inno_mipi_dphy_timing * t)304 static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
305 enum lane_type lane_type,
306 struct inno_mipi_dphy_timing *t)
307 {
308 u32 base = lane_reg_offset[lane_type];
309 u32 m, v;
310
311 m = T_HS_PREPARE_MASK;
312 v = T_HS_PREPARE(t->hs_prepare);
313 inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, m, v);
314
315 m = T_HS_ZERO_MASK;
316 v = T_HS_ZERO(t->hs_zero);
317 inno_update_bits(inno, base + T_HS_ZERO_OFFSET, m, v);
318
319 m = T_HS_TRAIL_MASK;
320 v = T_HS_TRAIL(t->hs_trail);
321 inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, m, v);
322
323 m = T_HS_EXIT_MASK;
324 v = T_HS_EXIT(t->hs_exit);
325 inno_update_bits(inno, base + T_HS_EXIT_OFFSET, m, v);
326
327 if (lane_type == CLOCK_LANE) {
328 m = T_CLK_POST_MASK;
329 v = T_CLK_POST(t->clk_post);
330 inno_update_bits(inno, base + T_CLK_POST_OFFSET, m, v);
331
332 m = T_CLK_PRE_MASK;
333 v = T_CLK_PRE(t->clk_pre);
334 inno_update_bits(inno, base + T_CLK_PRE_OFFSET, m, v);
335 }
336
337 m = T_WAKUP_H_MASK;
338 v = T_WAKUP_H(t->wakup_h);
339 inno_update_bits(inno, base + T_WAKUP_H_OFFSET, m, v);
340
341 m = T_WAKUP_L_MASK;
342 v = T_WAKUP_L(t->wakup_l);
343 inno_update_bits(inno, base + T_WAKUP_L_OFFSET, m, v);
344
345 m = T_LPX_MASK;
346 v = T_LPX(t->lpx);
347 inno_update_bits(inno, base + T_LPX_OFFSET, m, v);
348
349 m = T_TA_GO_MASK;
350 v = T_TA_GO(t->ta_go);
351 inno_update_bits(inno, base + T_TA_GO_OFFSET, m, v);
352
353 m = T_TA_SURE_MASK;
354 v = T_TA_SURE(t->ta_sure);
355 inno_update_bits(inno, base + T_TA_SURE_OFFSET, m, v);
356
357 m = T_TA_WAIT_MASK;
358 v = T_TA_WAIT(t->ta_wait);
359 inno_update_bits(inno, base + T_TA_WAIT_OFFSET, m, v);
360 }
361
inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing * t,unsigned int freq,enum soc_type soc_type,enum lane_type lane_type)362 static void inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
363 unsigned int freq,
364 enum soc_type soc_type,
365 enum lane_type lane_type)
366 {
367 const struct fixed_param *param, *param_table;
368 int i, param_num;
369
370 if (soc_type == RK1808_MIPI_DPHY) {
371 param_table = rk1808_fixed_param_table;
372 param_num = ARRAY_SIZE(rk1808_fixed_param_table);
373 } else {
374 param_table = fixed_param_table;
375 param_num = ARRAY_SIZE(fixed_param_table);
376 }
377
378 for (i = 0; i < param_num; i++)
379 if (freq <= param_table[i].max_freq)
380 break;
381
382 if (i == param_num)
383 --i;
384
385 param = ¶m_table[i];
386
387 if (lane_type == CLOCK_LANE)
388 t->hs_zero = param->clk_lane.hs_zero;
389 else
390 t->hs_zero = param->data_lane.hs_zero;
391
392 t->hs_prepare = param->hs_prepare;
393 t->hs_trail = param->hs_trail;
394
395 if (soc_type == RK1808_MIPI_DPHY)
396 t->lpx = param->lpx;
397 }
398
inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy * inno,enum lane_type lane_type)399 static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
400 enum lane_type lane_type)
401 {
402 struct rockchip_phy *phy =
403 (struct rockchip_phy *)dev_get_driver_data(inno->dev);
404 struct mipi_dphy_timing timing;
405 struct inno_mipi_dphy_timing data;
406 unsigned long txbyteclk, txclkesc, UI;
407 unsigned int esc_clk_div;
408
409 memset(&timing, 0, sizeof(timing));
410 memset(&data, 0, sizeof(data));
411
412 txbyteclk = inno->lane_mbps * USEC_PER_SEC / 8;
413 esc_clk_div = DIV_ROUND_UP(txbyteclk, 20000000);
414 txclkesc = txbyteclk / esc_clk_div;
415 UI = DIV_ROUND_CLOSEST(NSEC_PER_USEC, inno->lane_mbps);
416
417 debug("txbyteclk=%lu, txclkesc=%lu, esc_clk_div=%u, UI=%lu\n",
418 txbyteclk, txclkesc, esc_clk_div, UI);
419
420 mipi_dphy_timing_get_default(&timing, UI);
421 inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps,
422 phy->soc_type, lane_type);
423
424 /*
425 * Ttxbyteclk * val >= Ths-exit
426 * Ttxbyteclk * val >= Tclk-post
427 * Ttxbyteclk * val >= Tclk-pre
428 * Ttxbyteclk * (2 + val) >= Tlpx
429 */
430 data.hs_exit = DIV_ROUND_UP(timing.hsexit * txbyteclk, NSEC_PER_SEC);
431 data.clk_post = DIV_ROUND_UP(timing.clkpost * txbyteclk, NSEC_PER_SEC);
432 data.clk_pre = DIV_ROUND_UP(timing.clkpre * txbyteclk, NSEC_PER_SEC);
433 data.wakup_h = 0x3;
434 data.wakup_l = 0xff;
435
436 if (phy->soc_type == RV1108_MIPI_DPHY) {
437 data.lpx = DIV_ROUND_UP(txbyteclk * timing.lpx, NSEC_PER_SEC);
438 if (data.lpx > 2)
439 data.lpx -= 2;
440 }
441
442 /*
443 * Ttxclkesc * val >= Tta-go
444 * Ttxclkesc * val >= Tta-sure
445 * Ttxclkesc * val >= Tta-wait
446 */
447 data.ta_go = DIV_ROUND_UP(timing.tago * txclkesc, NSEC_PER_SEC);
448 data.ta_sure = DIV_ROUND_UP(timing.tasure * txclkesc, NSEC_PER_SEC);
449 data.ta_wait = DIV_ROUND_UP(timing.taget * txclkesc, NSEC_PER_SEC);
450
451 inno_mipi_dphy_timing_update(inno, lane_type, &data);
452
453 #define TIMING_NS(x, freq) (((x) * (DIV_ROUND_CLOSEST(NSEC_PER_SEC, freq))))
454 debug("hs-exit=%lu, clk-post=%lu, clk-pre=%lu, lpx=%lu\n",
455 TIMING_NS(data.hs_exit, txbyteclk),
456 TIMING_NS(data.clk_post, txbyteclk),
457 TIMING_NS(data.clk_pre, txbyteclk),
458 TIMING_NS(data.lpx + 2, txbyteclk));
459 debug("ta-go=%lu, ta-sure=%lu, ta-wait=%lu\n",
460 TIMING_NS(data.ta_go, txclkesc),
461 TIMING_NS(data.ta_sure, txclkesc),
462 TIMING_NS(data.ta_wait, txclkesc));
463 }
464
inno_mipi_dphy_pll_round_rate(unsigned long fin,unsigned long fout,u8 * prediv,u16 * fbdiv)465 static unsigned long inno_mipi_dphy_pll_round_rate(unsigned long fin,
466 unsigned long fout,
467 u8 *prediv, u16 *fbdiv)
468 {
469 unsigned long best_freq = 0;
470 u8 min_prediv, max_prediv;
471 u8 _prediv, best_prediv = 0;
472 u16 _fbdiv, best_fbdiv = 0;
473 u32 min_delta = 0xffffffff;
474
475 fout *= 2;
476
477 min_prediv = DIV_ROUND_UP(fin, 40000000);
478 max_prediv = fin / 5000000;
479
480 for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
481 u64 tmp;
482 u32 delta;
483 tmp = (u64)fout * _prediv;
484 do_div(tmp, fin);
485 _fbdiv = tmp;
486 if ((_fbdiv == 15) || (_fbdiv < 12) || (_fbdiv > 511))
487 continue;
488 tmp = (u64)_fbdiv * fin;
489 do_div(tmp, _prediv);
490
491 delta = abs(fout - tmp);
492 if (delta < min_delta) {
493 best_prediv = _prediv;
494 best_fbdiv = _fbdiv;
495 min_delta = delta;
496 best_freq = tmp;
497 }
498 }
499
500 if (best_freq) {
501 *prediv = best_prediv;
502 *fbdiv = best_fbdiv;
503 }
504
505 return best_freq / 2;
506 }
507
inno_mipi_dphy_reset(struct inno_mipi_dphy * inno)508 static inline void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)
509 {
510 /* Reset analog */
511 inno_update_bits(inno, INNO_PHY_POWER_CTRL,
512 ANALOG_RESET_MASK, ANALOG_RESET);
513 udelay(1);
514 inno_update_bits(inno, INNO_PHY_POWER_CTRL,
515 ANALOG_RESET_MASK, ANALOG_NORMAL);
516 /* Reset digital */
517 inno_update_bits(inno, INNO_PHY_DIG_CTRL,
518 DIGITAL_RESET_MASK, DIGITAL_RESET);
519 udelay(1);
520 inno_update_bits(inno, INNO_PHY_DIG_CTRL,
521 DIGITAL_RESET_MASK, DIGITAL_NORMAL);
522 }
523
inno_mipi_dphy_timing_init(struct inno_mipi_dphy * inno)524 static void inno_mipi_dphy_timing_init(struct inno_mipi_dphy *inno)
525 {
526 switch (inno->lanes) {
527 case 4:
528 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_3);
529 /* Fall through */
530 case 3:
531 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_2);
532 /* Fall through */
533 case 2:
534 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_1);
535 /* Fall through */
536 case 1:
537 default:
538 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_0);
539 inno_mipi_dphy_lane_timing_init(inno, CLOCK_LANE);
540 break;
541 }
542 }
543
inno_mipi_dphy_lane_enable(struct inno_mipi_dphy * inno)544 static inline void inno_mipi_dphy_lane_enable(struct inno_mipi_dphy *inno)
545 {
546 u32 m = 0, v = 0;
547
548 switch (inno->lanes) {
549 case 4:
550 m |= DATA_LANE_3_EN_MASK;
551 v |= DATA_LANE_3_EN;
552 /* Fall through */
553 case 3:
554 m |= DATA_LANE_2_EN_MASK;
555 v |= DATA_LANE_2_EN;
556 /* Fall through */
557 case 2:
558 m |= DATA_LANE_1_EN_MASK;
559 v |= DATA_LANE_1_EN;
560 /* Fall through */
561 default:
562 case 1:
563 m |= DATA_LANE_0_EN_MASK | CLK_LANE_EN_MASK;
564 v |= DATA_LANE_0_EN | CLK_LANE_EN;
565 break;
566 }
567
568 inno_update_bits(inno, INNO_PHY_LANE_CTRL, m, v);
569 }
570
inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy * inno)571 static inline void inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy *inno)
572 {
573 inno_update_bits(inno, INNO_PHY_POWER_CTRL,
574 PLL_POWER_MASK | LDO_POWER_MASK,
575 PLL_POWER_DOWN | LDO_POWER_DOWN);
576 }
577
inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy * inno)578 static inline void inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy *inno)
579 {
580 inno_update_bits(inno, INNO_PHY_POWER_CTRL,
581 PLL_POWER_MASK | LDO_POWER_MASK,
582 PLL_POWER_ON | LDO_POWER_ON);
583 }
584
inno_mipi_dphy_da_pwrok_enable(struct inno_mipi_dphy * inno)585 static inline void inno_mipi_dphy_da_pwrok_enable(struct inno_mipi_dphy *inno)
586 {
587 inno_update_bits(inno, INNO_PHY_LANE_CTRL, PWROK_BP | PWROK, PWROK);
588 }
589
inno_mipi_dphy_da_pwrok_disable(struct inno_mipi_dphy * inno)590 static inline void inno_mipi_dphy_da_pwrok_disable(struct inno_mipi_dphy *inno)
591 {
592 inno_update_bits(inno, INNO_PHY_LANE_CTRL, PWROK_BP | PWROK, PWROK_BP);
593 }
594
inno_mipi_dphy_bgpd_enable(struct inno_mipi_dphy * inno)595 static inline void inno_mipi_dphy_bgpd_enable(struct inno_mipi_dphy *inno)
596 {
597 inno_update_bits(inno, INNO_PHY_LANE_CTRL, MIPI_BGPD, 0);
598 }
599
inno_mipi_dphy_bgpd_disable(struct inno_mipi_dphy * inno)600 static inline void inno_mipi_dphy_bgpd_disable(struct inno_mipi_dphy *inno)
601 {
602 inno_update_bits(inno, INNO_PHY_LANE_CTRL, MIPI_BGPD, MIPI_BGPD);
603 inno_update_bits(inno, INNO_PHY_LVDS_CTRL, LVDS_BGPD, LVDS_BGPD);
604 }
605
inno_mipi_dphy_power_on(struct rockchip_phy * phy)606 static int inno_mipi_dphy_power_on(struct rockchip_phy *phy)
607 {
608 struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
609
610 inno_mipi_dphy_bgpd_enable(inno);
611 inno_mipi_dphy_da_pwrok_enable(inno);
612 inno_mipi_dphy_pll_ldo_enable(inno);
613 inno_mipi_dphy_lane_enable(inno);
614 inno_mipi_dphy_reset(inno);
615 inno_mipi_dphy_timing_init(inno);
616 udelay(1);
617
618 return 0;
619 }
620
inno_mipi_dphy_lane_disable(struct inno_mipi_dphy * inno)621 static inline void inno_mipi_dphy_lane_disable(struct inno_mipi_dphy *inno)
622 {
623 inno_update_bits(inno, INNO_PHY_LANE_CTRL, 0x7c, 0x00);
624 }
625
inno_mipi_dphy_power_off(struct rockchip_phy * phy)626 static int inno_mipi_dphy_power_off(struct rockchip_phy *phy)
627 {
628 struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
629
630 inno_mipi_dphy_lane_disable(inno);
631 inno_mipi_dphy_pll_ldo_disable(inno);
632 inno_mipi_dphy_da_pwrok_disable(inno);
633 inno_mipi_dphy_bgpd_disable(inno);
634
635 return 0;
636 }
637
inno_mipi_dphy_set_pll(struct rockchip_phy * phy,unsigned long rate)638 static unsigned long inno_mipi_dphy_set_pll(struct rockchip_phy *phy,
639 unsigned long rate)
640 {
641 struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
642 unsigned long fin, fout;
643 u16 fbdiv = 0;
644 u8 prediv = 0;
645 u32 m, v;
646
647 fin = 24000000;
648 fout = inno_mipi_dphy_pll_round_rate(fin, rate, &prediv, &fbdiv);
649
650 debug("%s: fin=%lu, fout=%lu, prediv=%u, fbdiv=%u\n",
651 __func__, fin, fout, prediv, fbdiv);
652
653 m = FBDIV_HI_MASK | PREDIV_MASK;
654 v = FBDIV_HI(fbdiv >> 8) | PREDIV(prediv);
655 inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, m, v);
656
657 m = FBDIV_LO_MASK;
658 v = FBDIV_LO(fbdiv);
659 inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, m, v);
660
661 if (phy->soc_type == RK1808_MIPI_DPHY) {
662 inno_update_bits(inno, ANALOG_REG_08,
663 PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
664 inno_update_bits(inno, ANALOG_REG_0B,
665 CLOCK_LANE_VOD_RANGE_SET_MASK,
666 CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
667 }
668
669 inno->lane_mbps = fout / USEC_PER_SEC;
670
671 return fout;
672 }
673
inno_mipi_dphy_parse_dt(struct inno_mipi_dphy * inno)674 static int inno_mipi_dphy_parse_dt(struct inno_mipi_dphy *inno)
675 {
676 struct udevice *dev = inno->dev;
677
678 inno->lanes = ofnode_read_u32_default(dev->node, "inno,lanes", 4);
679
680 return 0;
681 }
682
inno_mipi_dphy_init(struct rockchip_phy * phy)683 static int inno_mipi_dphy_init(struct rockchip_phy *phy)
684 {
685 struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
686 int ret;
687
688 ret = inno_mipi_dphy_parse_dt(inno);
689 if (ret) {
690 printf("%s: failed to parse DT\n", __func__);
691 return ret;
692 }
693
694 inno->regs = dev_read_addr_ptr(inno->dev);
695
696 return 0;
697 }
698
699 static const struct rockchip_phy_funcs inno_mipi_dphy_funcs = {
700 .init = inno_mipi_dphy_init,
701 .power_on = inno_mipi_dphy_power_on,
702 .power_off = inno_mipi_dphy_power_off,
703 .set_pll = inno_mipi_dphy_set_pll,
704 };
705
706 static const struct udevice_id inno_mipi_dphy_ids[] = {
707 {
708 .compatible = "rockchip,rv1108-mipi-dphy",
709 },
710 {
711 .compatible = "rockchip,rk1808-mipi-dphy",
712 },
713 {
714 .compatible = "rockchip,rv1126-mipi-dphy",
715 },
716 {}
717 };
718
inno_mipi_dphy_probe(struct udevice * dev)719 static int inno_mipi_dphy_probe(struct udevice *dev)
720 {
721 struct inno_mipi_dphy *inno = dev_get_priv(dev);
722 struct rockchip_phy *phy;
723
724 phy = calloc(1, sizeof(*phy));
725 if (!phy)
726 return -ENOMEM;
727
728 dev->driver_data = (ulong)phy;
729 inno->dev = dev;
730 phy->dev = dev;
731 phy->funcs = &inno_mipi_dphy_funcs;
732
733 #if defined(CONFIG_ROCKCHIP_RV1108)
734 phy->soc_type = RV1108_MIPI_DPHY;
735 #else
736 phy->soc_type = RK1808_MIPI_DPHY;
737 #endif
738
739 return 0;
740 }
741
742 U_BOOT_DRIVER(inno_mipi_dphy) = {
743 .name = "inno_mipi_dphy",
744 .id = UCLASS_PHY,
745 .of_match = inno_mipi_dphy_ids,
746 .probe = inno_mipi_dphy_probe,
747 .priv_auto_alloc_size = sizeof(struct inno_mipi_dphy),
748 };
749