2 * Copyright (c) 2017 Rockchip Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/phy/phy.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
23 #include <linux/reset.h>
25 #include <drm/drm_mipi_dsi.h>
27 #include <video/mipi_display.h>
28 #include <video/of_videomode.h>
29 #include <video/videomode.h>
31 #define DRV_NAME "inno-mipi-dphy"
33 #define INNO_PHY_LANE_CTRL 0x00000
34 #define INNO_PHY_POWER_CTRL 0x00004
35 #define INNO_PHY_PLL_CTRL_0 0x0000c
36 #define INNO_PHY_PLL_CTRL_1 0x00010
37 #define INNO_PHY_DIG_CTRL 0x00080
38 #define INNO_PHY_PIN_CTRL 0x00084
40 #define INNO_CLOCK_LANE_REG_BASE 0x00100
41 #define INNO_DATA_LANE_0_REG_BASE 0x00180
42 #define INNO_DATA_LANE_1_REG_BASE 0x00200
43 #define INNO_DATA_LANE_2_REG_BASE 0x00280
44 #define INNO_DATA_LANE_3_REG_BASE 0x00300
46 #define T_LPX_OFFSET 0x00014
47 #define T_HS_PREPARE_OFFSET 0x00018
48 #define T_HS_ZERO_OFFSET 0x0001c
49 #define T_HS_TRAIL_OFFSET 0x00020
50 #define T_HS_EXIT_OFFSET 0x00024
51 #define T_CLK_POST_OFFSET 0x00028
52 #define T_WAKUP_H_OFFSET 0x00030
53 #define T_WAKUP_L_OFFSET 0x00034
54 #define T_CLK_PRE_OFFSET 0x00038
55 #define T_TA_GO_OFFSET 0x00040
56 #define T_TA_SURE_OFFSET 0x00044
57 #define T_TA_WAIT_OFFSET 0x00048
59 /* INNO_PHY_LANE_CTRL */
60 #define M_CLK_LANE_EN BIT(6)
61 #define M_DATA_LANE_3_EN BIT(5)
62 #define M_DATA_LANE_2_EN BIT(4)
63 #define M_DATA_LANE_1_EN BIT(3)
64 #define M_DATA_LANE_0_EN BIT(2)
65 #define V_CLK_LANE_EN BIT(6)
66 #define V_DATA_LANE_3_EN BIT(5)
67 #define V_DATA_LANE_2_EN BIT(4)
68 #define V_DATA_LANE_1_EN BIT(3)
69 #define V_DATA_LANE_0_EN BIT(2)
70 /* INNO_PHY_PLL_CTRL_0 */
71 #define M_FBDIV_8 BIT(5)
72 #define M_PREDIV (0x1f << 0)
73 #define V_FBDIV_8(x) ((x) << 5)
74 #define V_PREDIV(x) ((x) << 0)
75 /* INNO_PHY_PLL_CTRL_1 */
76 #define M_FBDIV_7_0 (0xff << 0)
77 #define V_FBDIV_7_0(x) ((x) << 0)
79 #define M_T_LPX (0x3f << 0)
80 #define V_T_LPX(x) ((x) << 0)
81 #define M_T_HS_PREPARE (0x7f << 0)
82 #define V_T_HS_PREPARE(x) ((x) << 0)
83 #define M_T_HS_ZERO (0x3f << 0)
84 #define V_T_HS_ZERO(x) ((x) << 0)
85 #define M_T_HS_TRAIL (0x7f << 0)
86 #define V_T_HS_TRAIL(x) ((x) << 0)
87 #define M_T_HS_EXIT (0x1f << 0)
88 #define V_T_HS_EXIT(x) ((x) << 0)
89 #define M_T_CLK_POST (0xf << 0)
90 #define V_T_CLK_POST(x) ((x) << 0)
91 #define M_T_WAKUP_H (0x3 << 0)
92 #define V_T_WAKUP_H(x) ((x) << 0)
93 #define M_T_WAKUP_L (0xff << 0)
94 #define V_T_WAKUP_L(x) ((x) << 0)
95 #define M_T_CLK_PRE (0xf << 0)
96 #define V_T_CLK_PRE(x) ((x) << 0)
97 #define M_T_TA_GO (0x3f << 0)
98 #define V_T_TA_GO(x) ((x) << 0)
99 #define M_T_TA_SURE (0x3f << 0)
100 #define V_T_TA_SURE(x) ((x) << 0)
101 #define M_T_TA_WAIT (0x3f << 0)
102 #define V_T_TA_WAIT(x) ((x) << 0)
112 static const u32 lane_reg_offset[] = {
113 [CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
114 [DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
115 [DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
116 [DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
117 [DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
121 HS_CLK_RANGE_80_110_MHZ,
122 HS_CLK_RANGE_110_150_MHZ,
123 HS_CLK_RANGE_150_200_MHZ,
124 HS_CLK_RANGE_200_250_MHZ,
125 HS_CLK_RANGE_250_300_MHZ,
126 HS_CLK_RANGE_300_400_MHZ,
127 HS_CLK_RANGE_400_500_MHZ,
128 HS_CLK_RANGE_500_600_MHZ,
129 HS_CLK_RANGE_600_700_MHZ,
130 HS_CLK_RANGE_700_800_MHZ,
131 HS_CLK_RANGE_800_1000_MHZ,
134 static const u8 t_hs_prepare_val[] = {
135 [HS_CLK_RANGE_80_110_MHZ] = 0x20,
136 [HS_CLK_RANGE_110_150_MHZ] = 0x06,
137 [HS_CLK_RANGE_150_200_MHZ] = 0x18,
138 [HS_CLK_RANGE_200_250_MHZ] = 0x05,
139 [HS_CLK_RANGE_250_300_MHZ] = 0x51,
140 [HS_CLK_RANGE_300_400_MHZ] = 0x64,
141 [HS_CLK_RANGE_400_500_MHZ] = 0x20,
142 [HS_CLK_RANGE_500_600_MHZ] = 0x6a,
143 [HS_CLK_RANGE_600_700_MHZ] = 0x3e,
144 [HS_CLK_RANGE_700_800_MHZ] = 0x21,
145 [HS_CLK_RANGE_800_1000_MHZ] = 0x09,
148 static const u8 clock_lane_t_hs_zero_val[] = {
149 [HS_CLK_RANGE_80_110_MHZ] = 0x16,
150 [HS_CLK_RANGE_110_150_MHZ] = 0x16,
151 [HS_CLK_RANGE_150_200_MHZ] = 0x17,
152 [HS_CLK_RANGE_200_250_MHZ] = 0x17,
153 [HS_CLK_RANGE_250_300_MHZ] = 0x18,
154 [HS_CLK_RANGE_300_400_MHZ] = 0x19,
155 [HS_CLK_RANGE_400_500_MHZ] = 0x1b,
156 [HS_CLK_RANGE_500_600_MHZ] = 0x1d,
157 [HS_CLK_RANGE_600_700_MHZ] = 0x1e,
158 [HS_CLK_RANGE_700_800_MHZ] = 0x1f,
159 [HS_CLK_RANGE_800_1000_MHZ] = 0x20,
162 static const u8 data_lane_t_hs_zero_val[] = {
163 [HS_CLK_RANGE_80_110_MHZ] = 2,
164 [HS_CLK_RANGE_110_150_MHZ] = 3,
165 [HS_CLK_RANGE_150_200_MHZ] = 4,
166 [HS_CLK_RANGE_200_250_MHZ] = 5,
167 [HS_CLK_RANGE_250_300_MHZ] = 6,
168 [HS_CLK_RANGE_300_400_MHZ] = 7,
169 [HS_CLK_RANGE_400_500_MHZ] = 7,
170 [HS_CLK_RANGE_500_600_MHZ] = 8,
171 [HS_CLK_RANGE_600_700_MHZ] = 8,
172 [HS_CLK_RANGE_700_800_MHZ] = 9,
173 [HS_CLK_RANGE_800_1000_MHZ] = 9,
176 static const u8 t_hs_trail_val[] = {
177 [HS_CLK_RANGE_80_110_MHZ] = 0x22,
178 [HS_CLK_RANGE_110_150_MHZ] = 0x45,
179 [HS_CLK_RANGE_150_200_MHZ] = 0x0b,
180 [HS_CLK_RANGE_200_250_MHZ] = 0x16,
181 [HS_CLK_RANGE_250_300_MHZ] = 0x2c,
182 [HS_CLK_RANGE_300_400_MHZ] = 0x33,
183 [HS_CLK_RANGE_400_500_MHZ] = 0x4e,
184 [HS_CLK_RANGE_500_600_MHZ] = 0x3a,
185 [HS_CLK_RANGE_600_700_MHZ] = 0x6a,
186 [HS_CLK_RANGE_700_800_MHZ] = 0x29,
187 [HS_CLK_RANGE_800_1000_MHZ] = 0x27,
190 struct mipi_dphy_timing {
191 unsigned int clkmiss;
192 unsigned int clkpost;
194 unsigned int clkprepare;
195 unsigned int clksettle;
196 unsigned int clktermen;
197 unsigned int clktrail;
198 unsigned int clkzero;
199 unsigned int dtermen;
202 unsigned int hsprepare;
204 unsigned int hssettle;
206 unsigned int hstrail;
215 struct inno_mipi_dphy_timing {
235 struct inno_mipi_dphy {
240 struct reset_control *rst;
242 struct dsi_panel *panel;
247 static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
249 writel_relaxed(val, inno->regs + reg);
252 static inline u32 inno_read(struct inno_mipi_dphy *inno, u32 reg)
254 return readl_relaxed(inno->regs + reg);
257 static inline void inno_update_bits(struct inno_mipi_dphy *inno, u32 reg,
262 orig = inno_read(inno, reg);
265 inno_write(inno, reg, tmp);
268 static void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
269 unsigned long period)
271 /* Global Operation Timing Parameters */
273 timing->clkpost = 70000 + 52 * period;
274 timing->clkpre = 8000;
275 timing->clkprepare = 65000;
276 timing->clksettle = 95000;
277 timing->clktermen = 0;
278 timing->clktrail = 80000;
279 timing->clkzero = 260000;
282 timing->hsexit = 120000;
283 timing->hsprepare = 65000 + 5 * period;
284 timing->hszero = 145000 + 5 * period;
285 timing->hssettle = 85000 + 6 * period;
286 timing->hsskip = 40000;
287 timing->hstrail = max(4 * 8 * period, 60000 + 4 * 4 * period);
288 timing->init = 100000000;
290 timing->taget = 5 * timing->lpx;
291 timing->tago = 4 * timing->lpx;
292 timing->tasure = timing->lpx;
293 timing->wakeup = 1000000000;
296 static u32 fre_to_period(u32 fre)
301 integer = 1000000000UL / fre;
302 decimals = 1000000000UL % fre;
303 if (decimals <= 40000000)
304 decimals = (decimals * 100) / (fre / 10);
305 else if (decimals <= 400000000)
306 decimals = (decimals * 10) / (fre / 100);
308 decimals = decimals / (fre / 1000);
309 integer = integer * 1000 + decimals;
314 static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
315 enum lane_type lane_type,
316 struct inno_mipi_dphy_timing *t)
318 u32 base = lane_reg_offset[lane_type];
321 mask = M_T_HS_PREPARE;
322 val = V_T_HS_PREPARE(t->t_hs_prepare);
323 inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, mask, val);
326 val = V_T_HS_ZERO(t->t_hs_zero);
327 inno_update_bits(inno, base + T_HS_ZERO_OFFSET, mask, val);
330 val = V_T_HS_TRAIL(t->t_hs_trail);
331 inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, mask, val);
334 val = V_T_HS_EXIT(t->t_hs_exit);
335 inno_update_bits(inno, base + T_HS_EXIT_OFFSET, mask, val);
337 if (lane_type == CLOCK_LANE) {
339 val = V_T_CLK_POST(t->t_clk_post);
340 inno_update_bits(inno, base + T_CLK_POST_OFFSET, mask, val);
343 val = V_T_CLK_PRE(t->t_clk_pre);
344 inno_update_bits(inno, base + T_CLK_PRE_OFFSET, mask, val);
348 val = V_T_WAKUP_H(t->t_wakup_h);
349 inno_update_bits(inno, base + T_WAKUP_H_OFFSET, mask, val);
352 val = V_T_WAKUP_L(t->t_wakup_l);
353 inno_update_bits(inno, base + T_WAKUP_L_OFFSET, mask, val);
356 val = V_T_LPX(t->t_lpx);
357 inno_update_bits(inno, base + T_LPX_OFFSET, mask, val);
360 val = V_T_TA_GO(t->t_ta_go);
361 inno_update_bits(inno, base + T_TA_GO_OFFSET, mask, val);
364 val = V_T_TA_SURE(t->t_ta_sure);
365 inno_update_bits(inno, base + T_TA_SURE_OFFSET, mask, val);
368 val = V_T_TA_WAIT(t->t_ta_wait);
369 inno_update_bits(inno, base + T_TA_WAIT_OFFSET, mask, val);
372 static enum hs_clk_range inno_mipi_dphy_get_hs_clk_range(u32 lane_rate)
374 u32 range = lane_rate / USEC_PER_SEC;
377 return HS_CLK_RANGE_80_110_MHZ;
378 else if (range < 150)
379 return HS_CLK_RANGE_110_150_MHZ;
380 else if (range < 200)
381 return HS_CLK_RANGE_150_200_MHZ;
382 else if (range < 250)
383 return HS_CLK_RANGE_200_250_MHZ;
384 else if (range < 300)
385 return HS_CLK_RANGE_250_300_MHZ;
386 else if (range < 400)
387 return HS_CLK_RANGE_400_500_MHZ;
388 else if (range < 500)
389 return HS_CLK_RANGE_400_500_MHZ;
390 else if (range < 600)
391 return HS_CLK_RANGE_500_600_MHZ;
392 else if (range < 700)
393 return HS_CLK_RANGE_600_700_MHZ;
394 else if (range < 800)
395 return HS_CLK_RANGE_700_800_MHZ;
397 return HS_CLK_RANGE_800_1000_MHZ;
400 static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
401 enum lane_type lane_type)
403 struct mipi_dphy_timing timing;
404 struct inno_mipi_dphy_timing data;
405 u32 txbyteclkhs = inno->lane_mbps * USEC_PER_SEC / 8;
406 u32 txclkesc = 20000000;
407 u32 UI = fre_to_period(inno->lane_mbps * USEC_PER_SEC);
409 enum hs_clk_range range;
411 memset(&timing, 0, sizeof(timing));
412 memset(&data, 0, sizeof(data));
414 mipi_dphy_timing_get_default(&timing, UI);
416 range = inno_mipi_dphy_get_hs_clk_range(inno->lane_mbps * USEC_PER_SEC);
418 if (lane_type == CLOCK_LANE)
419 data.t_hs_zero = clock_lane_t_hs_zero_val[range];
421 data.t_hs_zero = data_lane_t_hs_zero_val[range];
423 data.t_hs_prepare = t_hs_prepare_val[range];
424 data.t_hs_trail = t_hs_trail_val[range];
426 /* txbyteclkhs domain */
427 unit = fre_to_period(txbyteclkhs);
428 data.t_hs_exit = DIV_ROUND_UP(timing.hsexit, unit);
429 data.t_clk_post = DIV_ROUND_UP(timing.clkpost, unit);
430 data.t_clk_pre = DIV_ROUND_UP(timing.clkpre, unit);
431 data.t_wakup_h = 0x3;
432 data.t_wakup_l = 0xff;
433 data.t_lpx = DIV_ROUND_UP(timing.lpx, unit) - 2;
435 /* txclkesc domain */
436 unit = fre_to_period(txclkesc);
437 data.t_ta_go = DIV_ROUND_UP(timing.tago, unit);
438 data.t_ta_sure = DIV_ROUND_UP(timing.tasure, unit);
439 data.t_ta_wait = DIV_ROUND_UP(timing.taget, unit);
441 inno_mipi_dphy_timing_update(inno, lane_type, &data);
444 static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
446 struct dsi_panel *panel = inno->panel;
448 unsigned long mpclk, pllref, tmp;
449 unsigned int target_mbps = 1000;
450 unsigned int max_mbps = 1000;
451 u32 fbdiv = 1, prediv = 1;
454 mpclk = DIV_ROUND_UP(panel->vm.pixelclock, USEC_PER_SEC);
456 /* take 1 / 0.9, since mbps must big than bandwidth of RGB */
457 tmp = mpclk * (panel->bpp / inno->lanes) * 10 / 9;
461 dev_err(inno->dev, "DPHY clock frequency is out of range\n");
464 pllref = DIV_ROUND_UP(clk_get_rate(inno->ref_clk) / 2, USEC_PER_SEC);
467 for (i = 1; i < 6; i++) {
469 if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
470 tmp = target_mbps % pre;
472 fbdiv = target_mbps / pre;
478 inno->lane_mbps = pllref / prediv * fbdiv;
480 mask = M_FBDIV_8 | M_PREDIV;
481 val = V_FBDIV_8(fbdiv >> 8) | V_PREDIV(prediv);
482 inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, mask, val);
485 val = V_FBDIV_7_0(fbdiv);
486 inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, mask, val);
488 dev_info(inno->dev, "fin=%ld, fout=%d, prediv=%d, fbdiv=%d\n",
489 pllref, inno->lane_mbps, prediv, fbdiv);
492 static void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)
495 inno_write(inno, INNO_PHY_POWER_CTRL, 0xe0);
498 inno_write(inno, INNO_PHY_DIG_CTRL, 0x1e);
500 inno_write(inno, INNO_PHY_DIG_CTRL, 0x1f);
504 static void inno_mipi_dphy_timing_init(struct inno_mipi_dphy *inno)
506 switch (inno->lanes) {
508 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_3);
511 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_2);
514 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_1);
518 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_0);
519 inno_mipi_dphy_lane_timing_init(inno, CLOCK_LANE);
524 static inline void inno_mipi_dphy_lane_enable(struct inno_mipi_dphy *inno)
529 switch (inno->lanes) {
531 mask |= M_DATA_LANE_3_EN;
532 val |= V_DATA_LANE_3_EN;
535 mask |= M_DATA_LANE_2_EN;
536 val |= V_DATA_LANE_2_EN;
539 mask |= M_DATA_LANE_1_EN;
540 val |= V_DATA_LANE_1_EN;
544 mask |= M_DATA_LANE_0_EN | M_CLK_LANE_EN;
545 val |= V_DATA_LANE_0_EN | V_CLK_LANE_EN;
549 inno_update_bits(inno, INNO_PHY_LANE_CTRL, mask, val);
552 static inline void inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy *inno)
554 inno_write(inno, INNO_PHY_POWER_CTRL, 0xe4);
558 static int inno_mipi_dphy_power_on(struct phy *phy)
560 struct inno_mipi_dphy *inno = phy_get_drvdata(phy);
562 clk_prepare_enable(inno->ref_clk);
563 clk_prepare_enable(inno->pclk);
566 /* MIPI DSI PHY APB software reset request. */
567 reset_control_assert(inno->rst);
568 usleep_range(20, 40);
569 reset_control_deassert(inno->rst);
572 inno_mipi_dphy_pll_init(inno);
573 inno_mipi_dphy_pll_ldo_enable(inno);
574 inno_mipi_dphy_lane_enable(inno);
575 inno_mipi_dphy_reset(inno);
576 inno_mipi_dphy_timing_init(inno);
578 dev_info(inno->dev, "Inno MIPI-DPHY Power-On\n");
583 static inline void inno_mipi_dphy_lane_disable(struct inno_mipi_dphy *inno)
585 inno_update_bits(inno, INNO_PHY_LANE_CTRL, 0x7c, 0x00);
588 static inline void inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy *inno)
590 inno_write(inno, INNO_PHY_POWER_CTRL, 0xe3);
594 static int inno_mipi_dphy_power_off(struct phy *phy)
596 struct inno_mipi_dphy *inno = phy_get_drvdata(phy);
598 inno_mipi_dphy_lane_disable(inno);
599 inno_mipi_dphy_pll_ldo_disable(inno);
601 clk_disable_unprepare(inno->pclk);
602 clk_disable_unprepare(inno->ref_clk);
604 dev_info(inno->dev, "Inno MIPI-DPHY Power-Off\n");
609 static const struct phy_ops inno_mipi_dphy_ops = {
610 .power_on = inno_mipi_dphy_power_on,
611 .power_off = inno_mipi_dphy_power_off,
612 .owner = THIS_MODULE,
615 static int get_bpp(struct device_node *np)
619 if (of_property_read_u32(np, "dsi,format", &format))
623 case MIPI_DSI_FMT_RGB666_PACKED:
625 case MIPI_DSI_FMT_RGB565:
627 case MIPI_DSI_FMT_RGB888:
628 case MIPI_DSI_FMT_RGB666:
634 static int inno_mipi_dphy_parse_dt(struct device_node *np,
635 struct inno_mipi_dphy *inno)
637 struct device_node *panel_node;
638 struct dsi_panel *panel;
641 panel_node = of_parse_phandle(np, "rockchip,dsi-panel", 0);
643 dev_err(inno->dev, "Missing 'rockchip,dsi-panel' property");
647 panel = devm_kzalloc(inno->dev, sizeof(*panel), GFP_KERNEL);
653 ret = of_get_videomode(panel_node, &panel->vm, 0);
657 panel->bpp = get_bpp(panel_node);
659 if (of_property_read_u32(panel_node, "dsi,lanes", &inno->lanes))
662 of_node_put(panel_node);
669 of_node_put(panel_node);
673 static int inno_mipi_dphy_probe(struct platform_device *pdev)
675 struct device_node *np = pdev->dev.of_node;
676 struct inno_mipi_dphy *inno;
678 struct phy_provider *phy_provider;
679 struct resource *res;
682 inno = devm_kzalloc(&pdev->dev, sizeof(*inno), GFP_KERNEL);
686 inno->dev = &pdev->dev;
688 ret = inno_mipi_dphy_parse_dt(np, inno);
690 dev_err(&pdev->dev, "failed to parse DT\n");
694 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
695 inno->regs = devm_ioremap_resource(&pdev->dev, res);
696 if (IS_ERR(inno->regs))
697 return PTR_ERR(inno->regs);
699 inno->ref_clk = devm_clk_get(&pdev->dev, "ref");
700 if (IS_ERR(inno->ref_clk)) {
701 dev_err(&pdev->dev, "failed to get mipi dphy ref clk\n");
702 return PTR_ERR(inno->ref_clk);
705 clk_set_rate(inno->ref_clk, 24000000);
707 inno->pclk = devm_clk_get(&pdev->dev, "pclk");
708 if (IS_ERR(inno->pclk)) {
709 dev_err(&pdev->dev, "failed to get mipi dphy pclk\n");
710 return PTR_ERR(inno->pclk);
713 inno->rst = devm_reset_control_get_optional(&pdev->dev, "apb");
714 if (IS_ERR(inno->rst)) {
715 dev_info(&pdev->dev, "No reset control specified\n");
719 phy = devm_phy_create(&pdev->dev, NULL, &inno_mipi_dphy_ops);
721 dev_err(&pdev->dev, "failed to create MIPI D-PHY\n");
725 phy_set_drvdata(phy, inno);
727 phy_provider = devm_of_phy_provider_register(&pdev->dev,
728 of_phy_simple_xlate);
729 if (IS_ERR(phy_provider)) {
730 dev_err(&pdev->dev, "failed to register phy provider\n");
731 return PTR_ERR(phy_provider);
734 dev_info(&pdev->dev, "Inno MIPI-DPHY Driver Probe\n");
739 static const struct of_device_id inno_mipi_dphy_of_match[] = {
740 { .compatible = "rockchip,rk3368-mipi-dphy", },
743 MODULE_DEVICE_TABLE(of, inno_mipi_dphy_of_match);
745 static struct platform_driver inno_mipi_dphy_driver = {
746 .probe = inno_mipi_dphy_probe,
749 .of_match_table = inno_mipi_dphy_of_match,
753 module_platform_driver(inno_mipi_dphy_driver);
755 MODULE_DESCRIPTION("Innosilicon MIPI D-PHY Driver");
756 MODULE_LICENSE("GPL v2");