blob: 52b463e51202e3ad45a15003115484dcec1bde13 [file] [log] [blame]
Hai Lia6895542015-03-31 14:36:33 -04001/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 *
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 and
6 * only version 2 as published by the Free Software Foundation.
7 *
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.
12 */
13
Hai Liec31abf2015-05-15 13:04:06 -040014#include <linux/platform_device.h>
15#include <linux/regulator/consumer.h>
16
Hai Lia6895542015-03-31 14:36:33 -040017#include "dsi.h"
18#include "dsi.xml.h"
19
20#define dsi_phy_read(offset) msm_readl((offset))
21#define dsi_phy_write(offset, data) msm_writel((data), (offset))
22
Hai Liec31abf2015-05-15 13:04:06 -040023struct dsi_phy_ops {
Hai Li13351cd2015-06-10 13:18:17 -040024 int (*enable)(struct msm_dsi_phy *phy, int src_pll_id,
Hai Liec31abf2015-05-15 13:04:06 -040025 const unsigned long bit_rate, const unsigned long esc_rate);
26 int (*disable)(struct msm_dsi_phy *phy);
27};
28
29struct dsi_phy_cfg {
30 enum msm_dsi_phy_type type;
31 struct dsi_reg_config reg_cfg;
32 struct dsi_phy_ops ops;
Hai Li13351cd2015-06-10 13:18:17 -040033
34 /* Each cell {phy_id, pll_id} of the truth table indicates
35 * if the source PLL is on the right side of the PHY.
36 * Fill default H/W values in illegal cells, eg. cell {0, 1}.
37 */
38 bool src_pll_truthtable[DSI_MAX][DSI_MAX];
Hai Liec31abf2015-05-15 13:04:06 -040039};
40
Hai Lia6895542015-03-31 14:36:33 -040041struct dsi_dphy_timing {
42 u32 clk_pre;
43 u32 clk_post;
44 u32 clk_zero;
45 u32 clk_trail;
46 u32 clk_prepare;
47 u32 hs_exit;
48 u32 hs_zero;
49 u32 hs_prepare;
50 u32 hs_trail;
51 u32 hs_rqst;
52 u32 ta_go;
53 u32 ta_sure;
54 u32 ta_get;
55};
56
57struct msm_dsi_phy {
Hai Li9d32c4982015-05-15 13:04:05 -040058 struct platform_device *pdev;
Hai Lia6895542015-03-31 14:36:33 -040059 void __iomem *base;
60 void __iomem *reg_base;
61 int id;
Hai Li9d32c4982015-05-15 13:04:05 -040062
63 struct clk *ahb_clk;
Hai Liec31abf2015-05-15 13:04:06 -040064 struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
Hai Li9d32c4982015-05-15 13:04:05 -040065
Hai Lia6895542015-03-31 14:36:33 -040066 struct dsi_dphy_timing timing;
Hai Liec31abf2015-05-15 13:04:06 -040067 const struct dsi_phy_cfg *cfg;
Hai Li9d32c4982015-05-15 13:04:05 -040068
69 struct msm_dsi_pll *pll;
Hai Lia6895542015-03-31 14:36:33 -040070};
71
Hai Liec31abf2015-05-15 13:04:06 -040072static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
73{
74 struct regulator_bulk_data *s = phy->supplies;
75 const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
76 struct device *dev = &phy->pdev->dev;
77 int num = phy->cfg->reg_cfg.num;
78 int i, ret;
79
80 for (i = 0; i < num; i++)
81 s[i].supply = regs[i].name;
82
83 ret = devm_regulator_bulk_get(&phy->pdev->dev, num, s);
84 if (ret < 0) {
85 dev_err(dev, "%s: failed to init regulator, ret=%d\n",
86 __func__, ret);
87 return ret;
88 }
89
90 for (i = 0; i < num; i++) {
91 if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
92 ret = regulator_set_voltage(s[i].consumer,
93 regs[i].min_voltage, regs[i].max_voltage);
94 if (ret < 0) {
95 dev_err(dev,
96 "regulator %d set voltage failed, %d\n",
97 i, ret);
98 return ret;
99 }
100 }
101 }
102
103 return 0;
104}
105
106static void dsi_phy_regulator_disable(struct msm_dsi_phy *phy)
107{
108 struct regulator_bulk_data *s = phy->supplies;
109 const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
110 int num = phy->cfg->reg_cfg.num;
111 int i;
112
113 DBG("");
114 for (i = num - 1; i >= 0; i--)
115 if (regs[i].disable_load >= 0)
116 regulator_set_load(s[i].consumer,
117 regs[i].disable_load);
118
119 regulator_bulk_disable(num, s);
120}
121
122static int dsi_phy_regulator_enable(struct msm_dsi_phy *phy)
123{
124 struct regulator_bulk_data *s = phy->supplies;
125 const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
126 struct device *dev = &phy->pdev->dev;
127 int num = phy->cfg->reg_cfg.num;
128 int ret, i;
129
130 DBG("");
131 for (i = 0; i < num; i++) {
132 if (regs[i].enable_load >= 0) {
133 ret = regulator_set_load(s[i].consumer,
134 regs[i].enable_load);
135 if (ret < 0) {
136 dev_err(dev,
137 "regulator %d set op mode failed, %d\n",
138 i, ret);
139 goto fail;
140 }
141 }
142 }
143
144 ret = regulator_bulk_enable(num, s);
145 if (ret < 0) {
146 dev_err(dev, "regulator enable failed, %d\n", ret);
147 goto fail;
148 }
149
150 return 0;
151
152fail:
153 for (i--; i >= 0; i--)
154 regulator_set_load(s[i].consumer, regs[i].disable_load);
155 return ret;
156}
157
Hai Li13351cd2015-06-10 13:18:17 -0400158static void dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg)
159{
160 int phy_id = phy->id;
161
162 if ((phy_id >= DSI_MAX) || (pll_id >= DSI_MAX))
163 return;
164
165 if (phy->cfg->src_pll_truthtable[phy_id][pll_id])
166 dsi_phy_write(phy->base + reg, 0x01);
167 else
168 dsi_phy_write(phy->base + reg, 0x00);
169}
170
Hai Lia6895542015-03-31 14:36:33 -0400171#define S_DIV_ROUND_UP(n, d) \
172 (((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d)))
173
174static inline s32 linear_inter(s32 tmax, s32 tmin, s32 percent,
175 s32 min_result, bool even)
176{
177 s32 v;
178 v = (tmax - tmin) * percent;
179 v = S_DIV_ROUND_UP(v, 100) + tmin;
180 if (even && (v & 0x1))
181 return max_t(s32, min_result, v - 1);
182 else
183 return max_t(s32, min_result, v);
184}
185
186static void dsi_dphy_timing_calc_clk_zero(struct dsi_dphy_timing *timing,
187 s32 ui, s32 coeff, s32 pcnt)
188{
189 s32 tmax, tmin, clk_z;
190 s32 temp;
191
192 /* reset */
193 temp = 300 * coeff - ((timing->clk_prepare >> 1) + 1) * 2 * ui;
194 tmin = S_DIV_ROUND_UP(temp, ui) - 2;
195 if (tmin > 255) {
196 tmax = 511;
197 clk_z = linear_inter(2 * tmin, tmin, pcnt, 0, true);
198 } else {
199 tmax = 255;
200 clk_z = linear_inter(tmax, tmin, pcnt, 0, true);
201 }
202
203 /* adjust */
204 temp = (timing->hs_rqst + timing->clk_prepare + clk_z) & 0x7;
205 timing->clk_zero = clk_z + 8 - temp;
206}
207
208static int dsi_dphy_timing_calc(struct dsi_dphy_timing *timing,
209 const unsigned long bit_rate, const unsigned long esc_rate)
210{
211 s32 ui, lpx;
212 s32 tmax, tmin;
213 s32 pcnt0 = 10;
214 s32 pcnt1 = (bit_rate > 1200000000) ? 15 : 10;
215 s32 pcnt2 = 10;
216 s32 pcnt3 = (bit_rate > 180000000) ? 10 : 40;
217 s32 coeff = 1000; /* Precision, should avoid overflow */
218 s32 temp;
219
220 if (!bit_rate || !esc_rate)
221 return -EINVAL;
222
223 ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
224 lpx = mult_frac(NSEC_PER_MSEC, coeff, esc_rate / 1000);
225
226 tmax = S_DIV_ROUND_UP(95 * coeff, ui) - 2;
227 tmin = S_DIV_ROUND_UP(38 * coeff, ui) - 2;
228 timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, true);
229
230 temp = lpx / ui;
231 if (temp & 0x1)
232 timing->hs_rqst = temp;
233 else
234 timing->hs_rqst = max_t(s32, 0, temp - 2);
235
236 /* Calculate clk_zero after clk_prepare and hs_rqst */
237 dsi_dphy_timing_calc_clk_zero(timing, ui, coeff, pcnt2);
238
239 temp = 105 * coeff + 12 * ui - 20 * coeff;
240 tmax = S_DIV_ROUND_UP(temp, ui) - 2;
241 tmin = S_DIV_ROUND_UP(60 * coeff, ui) - 2;
242 timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, true);
243
244 temp = 85 * coeff + 6 * ui;
245 tmax = S_DIV_ROUND_UP(temp, ui) - 2;
246 temp = 40 * coeff + 4 * ui;
247 tmin = S_DIV_ROUND_UP(temp, ui) - 2;
248 timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, true);
249
250 tmax = 255;
251 temp = ((timing->hs_prepare >> 1) + 1) * 2 * ui + 2 * ui;
252 temp = 145 * coeff + 10 * ui - temp;
253 tmin = S_DIV_ROUND_UP(temp, ui) - 2;
254 timing->hs_zero = linear_inter(tmax, tmin, pcnt2, 24, true);
255
256 temp = 105 * coeff + 12 * ui - 20 * coeff;
257 tmax = S_DIV_ROUND_UP(temp, ui) - 2;
258 temp = 60 * coeff + 4 * ui;
259 tmin = DIV_ROUND_UP(temp, ui) - 2;
260 timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, true);
261
262 tmax = 255;
263 tmin = S_DIV_ROUND_UP(100 * coeff, ui) - 2;
264 timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, true);
265
266 tmax = 63;
267 temp = ((timing->hs_exit >> 1) + 1) * 2 * ui;
268 temp = 60 * coeff + 52 * ui - 24 * ui - temp;
269 tmin = S_DIV_ROUND_UP(temp, 8 * ui) - 1;
270 timing->clk_post = linear_inter(tmax, tmin, pcnt2, 0, false);
271
272 tmax = 63;
273 temp = ((timing->clk_prepare >> 1) + 1) * 2 * ui;
274 temp += ((timing->clk_zero >> 1) + 1) * 2 * ui;
275 temp += 8 * ui + lpx;
276 tmin = S_DIV_ROUND_UP(temp, 8 * ui) - 1;
277 if (tmin > tmax) {
278 temp = linear_inter(2 * tmax, tmin, pcnt2, 0, false) >> 1;
279 timing->clk_pre = temp >> 1;
280 temp = (2 * tmax - tmin) * pcnt2;
281 } else {
282 timing->clk_pre = linear_inter(tmax, tmin, pcnt2, 0, false);
283 }
284
285 timing->ta_go = 3;
286 timing->ta_sure = 0;
287 timing->ta_get = 4;
288
289 DBG("PHY timings: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
290 timing->clk_pre, timing->clk_post, timing->clk_zero,
291 timing->clk_trail, timing->clk_prepare, timing->hs_exit,
292 timing->hs_zero, timing->hs_prepare, timing->hs_trail,
293 timing->hs_rqst);
294
295 return 0;
296}
297
298static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
299{
300 void __iomem *base = phy->reg_base;
301
302 if (!enable) {
303 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG, 0);
304 return;
305 }
306
307 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0, 0x0);
308 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG, 1);
309 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5, 0);
310 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3, 0);
311 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2, 0x3);
312 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1, 0x9);
313 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0, 0x7);
314 dsi_phy_write(base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4, 0x20);
315}
316
Hai Li13351cd2015-06-10 13:18:17 -0400317static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
Hai Lia6895542015-03-31 14:36:33 -0400318 const unsigned long bit_rate, const unsigned long esc_rate)
319{
320 struct dsi_dphy_timing *timing = &phy->timing;
321 int i;
322 void __iomem *base = phy->base;
323
324 DBG("");
325
326 if (dsi_dphy_timing_calc(timing, bit_rate, esc_rate)) {
327 pr_err("%s: D-PHY timing calculation failed\n", __func__);
328 return -EINVAL;
329 }
330
331 dsi_phy_write(base + REG_DSI_28nm_PHY_STRENGTH_0, 0xff);
332
333 dsi_28nm_phy_regulator_ctrl(phy, true);
334
335 dsi_phy_write(base + REG_DSI_28nm_PHY_LDO_CNTRL, 0x00);
336
337 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_0,
338 DSI_28nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
339 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_1,
340 DSI_28nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
341 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_2,
342 DSI_28nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
343 if (timing->clk_zero & BIT(8))
344 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_3,
345 DSI_28nm_PHY_TIMING_CTRL_3_CLK_ZERO_8);
346 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_4,
347 DSI_28nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
348 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_5,
349 DSI_28nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
350 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_6,
351 DSI_28nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
352 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_7,
353 DSI_28nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
354 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_8,
355 DSI_28nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
356 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_9,
357 DSI_28nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
358 DSI_28nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
359 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_10,
360 DSI_28nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
361 dsi_phy_write(base + REG_DSI_28nm_PHY_TIMING_CTRL_11,
362 DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
363
364 dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_1, 0x00);
365 dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_0, 0x5f);
366
367 dsi_phy_write(base + REG_DSI_28nm_PHY_STRENGTH_1, 0x6);
368
369 for (i = 0; i < 4; i++) {
370 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_0(i), 0);
371 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_1(i), 0);
372 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_2(i), 0);
373 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_3(i), 0);
374 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i), 0);
375 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i), 0);
376 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i), 0x1);
377 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i), 0x97);
378 }
379 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(0), 0);
380 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(1), 0x5);
381 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(2), 0xa);
382 dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(3), 0xf);
383
384 dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_1, 0xc0);
385 dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR0, 0x1);
386 dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR1, 0xbb);
387
388 dsi_phy_write(base + REG_DSI_28nm_PHY_CTRL_0, 0x5f);
389
Hai Li13351cd2015-06-10 13:18:17 -0400390 dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_28nm_PHY_GLBL_TEST_CTRL);
Hai Lia6895542015-03-31 14:36:33 -0400391
392 return 0;
393}
394
395static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
396{
397 dsi_phy_write(phy->base + REG_DSI_28nm_PHY_CTRL_0, 0);
398 dsi_28nm_phy_regulator_ctrl(phy, false);
399
400 /*
401 * Wait for the registers writes to complete in order to
402 * ensure that the phy is completely disabled
403 */
404 wmb();
405
406 return 0;
407}
408
Hai Li9d32c4982015-05-15 13:04:05 -0400409static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
410{
411 int ret;
412
413 pm_runtime_get_sync(&phy->pdev->dev);
414
415 ret = clk_prepare_enable(phy->ahb_clk);
416 if (ret) {
417 pr_err("%s: can't enable ahb clk, %d\n", __func__, ret);
418 pm_runtime_put_sync(&phy->pdev->dev);
419 }
420
421 return ret;
422}
423
424static void dsi_phy_disable_resource(struct msm_dsi_phy *phy)
425{
426 clk_disable_unprepare(phy->ahb_clk);
427 pm_runtime_put_sync(&phy->pdev->dev);
428}
429
Hai Liec31abf2015-05-15 13:04:06 -0400430static const struct dsi_phy_cfg dsi_phy_cfgs[MSM_DSI_PHY_MAX] = {
431 [MSM_DSI_PHY_28NM_HPM] = {
432 .type = MSM_DSI_PHY_28NM_HPM,
Hai Li13351cd2015-06-10 13:18:17 -0400433 .src_pll_truthtable = { {true, true}, {false, true} },
Hai Liec31abf2015-05-15 13:04:06 -0400434 .reg_cfg = {
435 .num = 1,
436 .regs = {
437 {"vddio", 1800000, 1800000, 100000, 100},
438 },
439 },
440 .ops = {
441 .enable = dsi_28nm_phy_enable,
442 .disable = dsi_28nm_phy_disable,
443 }
444 },
445 [MSM_DSI_PHY_28NM_LP] = {
446 .type = MSM_DSI_PHY_28NM_LP,
Hai Li13351cd2015-06-10 13:18:17 -0400447 .src_pll_truthtable = { {true, true}, {true, true} },
Hai Liec31abf2015-05-15 13:04:06 -0400448 .reg_cfg = {
449 .num = 1,
450 .regs = {
451 {"vddio", 1800000, 1800000, 100000, 100},
452 },
453 },
454 .ops = {
455 .enable = dsi_28nm_phy_enable,
456 .disable = dsi_28nm_phy_disable,
457 }
458 },
459};
Hai Lia6895542015-03-31 14:36:33 -0400460
Hai Liec31abf2015-05-15 13:04:06 -0400461static const struct of_device_id dsi_phy_dt_match[] = {
462 { .compatible = "qcom,dsi-phy-28nm-hpm",
463 .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],},
464 { .compatible = "qcom,dsi-phy-28nm-lp",
465 .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],},
466 {}
467};
468
469static int dsi_phy_driver_probe(struct platform_device *pdev)
Hai Lia6895542015-03-31 14:36:33 -0400470{
471 struct msm_dsi_phy *phy;
Hai Liec31abf2015-05-15 13:04:06 -0400472 const struct of_device_id *match;
Hai Li9d32c4982015-05-15 13:04:05 -0400473 int ret;
Hai Lia6895542015-03-31 14:36:33 -0400474
475 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
476 if (!phy)
Hai Liec31abf2015-05-15 13:04:06 -0400477 return -ENOMEM;
478
479 match = of_match_node(dsi_phy_dt_match, pdev->dev.of_node);
480 if (!match)
481 return -ENODEV;
482
483 phy->cfg = match->data;
484 phy->pdev = pdev;
485
486 ret = of_property_read_u32(pdev->dev.of_node,
487 "qcom,dsi-phy-index", &phy->id);
488 if (ret) {
489 dev_err(&pdev->dev,
490 "%s: PHY index not specified, ret=%d\n",
491 __func__, ret);
492 goto fail;
493 }
Hai Lia6895542015-03-31 14:36:33 -0400494
495 phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
Fabian Frederick73dbf692015-05-04 19:03:54 +0200496 if (IS_ERR(phy->base)) {
Hai Liec31abf2015-05-15 13:04:06 -0400497 dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__);
498 ret = -ENOMEM;
499 goto fail;
Hai Lia6895542015-03-31 14:36:33 -0400500 }
501 phy->reg_base = msm_ioremap(pdev, "dsi_phy_regulator", "DSI_PHY_REG");
Fabian Frederick73dbf692015-05-04 19:03:54 +0200502 if (IS_ERR(phy->reg_base)) {
Hai Liec31abf2015-05-15 13:04:06 -0400503 dev_err(&pdev->dev,
504 "%s: failed to map phy regulator base\n", __func__);
505 ret = -ENOMEM;
506 goto fail;
Hai Lia6895542015-03-31 14:36:33 -0400507 }
508
Hai Liec31abf2015-05-15 13:04:06 -0400509 ret = dsi_phy_regulator_init(phy);
510 if (ret) {
511 dev_err(&pdev->dev, "%s: failed to init regulator\n", __func__);
512 goto fail;
Hai Lia6895542015-03-31 14:36:33 -0400513 }
514
Hai Li9d32c4982015-05-15 13:04:05 -0400515 phy->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
516 if (IS_ERR(phy->ahb_clk)) {
517 pr_err("%s: Unable to get ahb clk\n", __func__);
Hai Liec31abf2015-05-15 13:04:06 -0400518 ret = PTR_ERR(phy->ahb_clk);
519 goto fail;
Hai Li9d32c4982015-05-15 13:04:05 -0400520 }
521
522 /* PLL init will call into clk_register which requires
523 * register access, so we need to enable power and ahb clock.
524 */
525 ret = dsi_phy_enable_resource(phy);
526 if (ret)
Hai Liec31abf2015-05-15 13:04:06 -0400527 goto fail;
Hai Li9d32c4982015-05-15 13:04:05 -0400528
Hai Liec31abf2015-05-15 13:04:06 -0400529 phy->pll = msm_dsi_pll_init(pdev, phy->cfg->type, phy->id);
Hai Li9d32c4982015-05-15 13:04:05 -0400530 if (!phy->pll)
Hai Liec31abf2015-05-15 13:04:06 -0400531 dev_info(&pdev->dev,
532 "%s: pll init failed, need separate pll clk driver\n",
Hai Li9d32c4982015-05-15 13:04:05 -0400533 __func__);
534
535 dsi_phy_disable_resource(phy);
Hai Lia6895542015-03-31 14:36:33 -0400536
Hai Liec31abf2015-05-15 13:04:06 -0400537 platform_set_drvdata(pdev, phy);
538
539 return 0;
540
541fail:
542 return ret;
Hai Lia6895542015-03-31 14:36:33 -0400543}
544
Hai Liec31abf2015-05-15 13:04:06 -0400545static int dsi_phy_driver_remove(struct platform_device *pdev)
Hai Li9d32c4982015-05-15 13:04:05 -0400546{
Hai Liec31abf2015-05-15 13:04:06 -0400547 struct msm_dsi_phy *phy = platform_get_drvdata(pdev);
548
549 if (phy && phy->pll) {
Hai Li9d32c4982015-05-15 13:04:05 -0400550 msm_dsi_pll_destroy(phy->pll);
551 phy->pll = NULL;
552 }
Hai Liec31abf2015-05-15 13:04:06 -0400553
554 platform_set_drvdata(pdev, NULL);
555
556 return 0;
557}
558
559static struct platform_driver dsi_phy_platform_driver = {
560 .probe = dsi_phy_driver_probe,
561 .remove = dsi_phy_driver_remove,
562 .driver = {
563 .name = "msm_dsi_phy",
564 .of_match_table = dsi_phy_dt_match,
565 },
566};
567
568void __init msm_dsi_phy_driver_register(void)
569{
570 platform_driver_register(&dsi_phy_platform_driver);
571}
572
573void __exit msm_dsi_phy_driver_unregister(void)
574{
575 platform_driver_unregister(&dsi_phy_platform_driver);
Hai Li9d32c4982015-05-15 13:04:05 -0400576}
577
Hai Li13351cd2015-06-10 13:18:17 -0400578int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
Hai Lia6895542015-03-31 14:36:33 -0400579 const unsigned long bit_rate, const unsigned long esc_rate)
580{
Hai Liec31abf2015-05-15 13:04:06 -0400581 int ret;
582
583 if (!phy || !phy->cfg->ops.enable)
Hai Lia6895542015-03-31 14:36:33 -0400584 return -EINVAL;
Hai Liec31abf2015-05-15 13:04:06 -0400585
586 ret = dsi_phy_regulator_enable(phy);
587 if (ret) {
588 dev_err(&phy->pdev->dev, "%s: regulator enable failed, %d\n",
589 __func__, ret);
590 return ret;
591 }
592
Hai Li13351cd2015-06-10 13:18:17 -0400593 return phy->cfg->ops.enable(phy, src_pll_id, bit_rate, esc_rate);
Hai Lia6895542015-03-31 14:36:33 -0400594}
595
596int msm_dsi_phy_disable(struct msm_dsi_phy *phy)
597{
Hai Liec31abf2015-05-15 13:04:06 -0400598 if (!phy || !phy->cfg->ops.disable)
Hai Lia6895542015-03-31 14:36:33 -0400599 return -EINVAL;
Hai Liec31abf2015-05-15 13:04:06 -0400600
601 phy->cfg->ops.disable(phy);
602 dsi_phy_regulator_disable(phy);
603
604 return 0;
Hai Lia6895542015-03-31 14:36:33 -0400605}
606
607void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
608 u32 *clk_pre, u32 *clk_post)
609{
610 if (!phy)
611 return;
612 if (clk_pre)
613 *clk_pre = phy->timing.clk_pre;
614 if (clk_post)
615 *clk_post = phy->timing.clk_post;
616}
617
Hai Li9d32c4982015-05-15 13:04:05 -0400618struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
619{
620 if (!phy)
621 return NULL;
622
623 return phy->pll;
624}
625