File Index
Files and directories
Sign in
FILE

dsi_phy_28nm_8960.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  4 */
  5
  6#include <dt-bindings/clock/qcom,dsi-phy-28nm.h>
  7#include <linux/clk-provider.h>
  8#include <linux/delay.h>
  9
 10#include "dsi_phy.h"
 11#include "dsi.xml.h"
 12#include "dsi_phy_28nm_8960.xml.h"
 13
 14/*
 15 * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):
 16 *
 17 *
 18 *                        +------+
 19 *  dsi1vco_clk ----o-----| DIV1 |---dsi1pllbit (not exposed as clock)
 20 *  F * byte_clk    |     +------+
 21 *                  | bit clock divider (F / 8)
 22 *                  |
 23 *                  |     +------+
 24 *                  o-----| DIV2 |---dsi0pllbyte---o---> To byte RCG
 25 *                  |     +------+                 | (sets parent rate)
 26 *                  | byte clock divider (F)       |
 27 *                  |                              |
 28 *                  |                              o---> To esc RCG
 29 *                  |                                (doesn't set parent rate)
 30 *                  |
 31 *                  |     +------+
 32 *                  o-----| DIV3 |----dsi0pll------o---> To dsi RCG
 33 *                        +------+                 | (sets parent rate)
 34 *                  dsi clock divider (F * magic)  |
 35 *                                                 |
 36 *                                                 o---> To pixel rcg
 37 *                                                  (doesn't set parent rate)
 38 */
 39
 40#define POLL_MAX_READS		8000
 41#define POLL_TIMEOUT_US		1
 42
 43#define VCO_REF_CLK_RATE	27000000
 44#define VCO_MIN_RATE		600000000
 45#define VCO_MAX_RATE		1200000000
 46
 47#define VCO_PREF_DIV_RATIO	27
 48
 49struct pll_28nm_cached_state {
 50	unsigned long vco_rate;
 51	u8 postdiv3;
 52	u8 postdiv2;
 53	u8 postdiv1;
 54};
 55
 56struct clk_bytediv {
 57	struct clk_hw hw;
 58	void __iomem *reg;
 59};
 60
 61struct dsi_pll_28nm {
 62	struct clk_hw clk_hw;
 63
 64	struct msm_dsi_phy *phy;
 65
 66	struct pll_28nm_cached_state cached_state;
 67};
 68
 69#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, clk_hw)
 70
 71static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
 72				    int nb_tries, int timeout_us)
 73{
 74	bool pll_locked = false;
 75	u32 val;
 76
 77	while (nb_tries--) {
 78		val = readl(pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_RDY);
 79		pll_locked = !!(val & DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY);
 80
 81		if (pll_locked)
 82			break;
 83
 84		udelay(timeout_us);
 85	}
 86	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
 87
 88	return pll_locked;
 89}
 90
 91/*
 92 * Clock Callbacks
 93 */
 94static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 95				     unsigned long parent_rate)
 96{
 97	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
 98	void __iomem *base = pll_28nm->phy->pll_base;
 99	u32 val, temp, fb_divider;
100
101	DBG("rate=%lu, parent's=%lu", rate, parent_rate);
102
103	temp = rate / 10;
104	val = VCO_REF_CLK_RATE / 10;
105	fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
106	fb_divider = fb_divider / 2 - 1;
107	writel(fb_divider & 0xff, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
108
109	val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
110
111	val |= (fb_divider >> 8) & 0x07;
112
113	writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2);
114
115	val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
116
117	val |= (VCO_PREF_DIV_RATIO - 1) & 0x3f;
118
119	writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
120
121	writel(0xf, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_6);
122
123	val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
124	val |= 0x7 << 4;
125	writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
126
127	return 0;
128}
129
130static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
131{
132	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
133
134	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
135					POLL_TIMEOUT_US);
136}
137
138static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
139						  unsigned long parent_rate)
140{
141	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
142	void __iomem *base = pll_28nm->phy->pll_base;
143	unsigned long vco_rate;
144	u32 status, fb_divider, temp, ref_divider;
145
146	VERB("parent_rate=%lu", parent_rate);
147
148	status = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
149
150	if (status & DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE) {
151		fb_divider = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_1);
152		fb_divider &= 0xff;
153		temp = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_2) & 0x07;
154		fb_divider = (temp << 8) | fb_divider;
155		fb_divider += 1;
156
157		ref_divider = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_3);
158		ref_divider &= 0x3f;
159		ref_divider += 1;
160
161		/* multiply by 2 */
162		vco_rate = (parent_rate / ref_divider) * fb_divider * 2;
163	} else {
164		vco_rate = 0;
165	}
166
167	DBG("returning vco rate = %lu", vco_rate);
168
169	return vco_rate;
170}
171
172static int dsi_pll_28nm_vco_prepare(struct clk_hw *hw)
173{
174	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
175	struct device *dev = &pll_28nm->phy->pdev->dev;
176	void __iomem *base = pll_28nm->phy->pll_base;
177	bool locked;
178	unsigned int bit_div, byte_div;
179	int max_reads = 1000, timeout_us = 100;
180	u32 val;
181
182	DBG("id=%d", pll_28nm->phy->id);
183
184	if (unlikely(pll_28nm->phy->pll_on))
185		return 0;
186
187	/*
188	 * before enabling the PLL, configure the bit clock divider since we
189	 * don't expose it as a clock to the outside world
190	 * 1: read back the byte clock divider that should already be set
191	 * 2: divide by 8 to get bit clock divider
192	 * 3: write it to POSTDIV1
193	 */
194	val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
195	byte_div = val + 1;
196	bit_div = byte_div / 8;
197
198	val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
199	val &= ~0xf;
200	val |= (bit_div - 1);
201	writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
202
203	/* enable the PLL */
204	writel(DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE,
205	       base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
206
207	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
208
209	if (unlikely(!locked)) {
210		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");
211		return -EINVAL;
212	}
213
214	DBG("DSI PLL lock success");
215	pll_28nm->phy->pll_on = true;
216
217	return 0;
218}
219
220static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)
221{
222	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
223
224	DBG("id=%d", pll_28nm->phy->id);
225
226	if (unlikely(!pll_28nm->phy->pll_on))
227		return;
228
229	writel(0x00, pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
230
231	pll_28nm->phy->pll_on = false;
232}
233
234static int dsi_pll_28nm_clk_determine_rate(struct clk_hw *hw,
235					   struct clk_rate_request *req)
236{
237	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
238
239	req->rate = clamp_t(unsigned long, req->rate,
240			    pll_28nm->phy->cfg->min_pll_rate, pll_28nm->phy->cfg->max_pll_rate);
241
242	return 0;
243}
244
245static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
246	.determine_rate = dsi_pll_28nm_clk_determine_rate,
247	.set_rate = dsi_pll_28nm_clk_set_rate,
248	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
249	.prepare = dsi_pll_28nm_vco_prepare,
250	.unprepare = dsi_pll_28nm_vco_unprepare,
251	.is_enabled = dsi_pll_28nm_clk_is_enabled,
252};
253
254/*
255 * Custom byte clock divier clk_ops
256 *
257 * This clock is the entry point to configuring the PLL. The user (dsi host)
258 * will set this clock's rate to the desired byte clock rate. The VCO lock
259 * frequency is a multiple of the byte clock rate. The multiplication factor
260 * (shown as F in the diagram above) is a function of the byte clock rate.
261 *
262 * This custom divider clock ensures that its parent (VCO) is set to the
263 * desired rate, and that the byte clock postdivider (POSTDIV2) is configured
264 * accordingly
265 */
266#define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)
267
268static unsigned long clk_bytediv_recalc_rate(struct clk_hw *hw,
269		unsigned long parent_rate)
270{
271	struct clk_bytediv *bytediv = to_clk_bytediv(hw);
272	unsigned int div;
273
274	div = readl(bytediv->reg) & 0xff;
275
276	return parent_rate / (div + 1);
277}
278
279/* find multiplication factor(wrt byte clock) at which the VCO should be set */
280static unsigned int get_vco_mul_factor(unsigned long byte_clk_rate)
281{
282	unsigned long bit_mhz;
283
284	/* convert to bit clock in Mhz */
285	bit_mhz = (byte_clk_rate * 8) / 1000000;
286
287	if (bit_mhz < 125)
288		return 64;
289	else if (bit_mhz < 250)
290		return 32;
291	else if (bit_mhz < 600)
292		return 16;
293	else
294		return 8;
295}
296
297static int clk_bytediv_determine_rate(struct clk_hw *hw,
298				      struct clk_rate_request *req)
299{
300	unsigned long best_parent;
301	unsigned int factor;
302
303	factor = get_vco_mul_factor(req->rate);
304
305	best_parent = req->rate * factor;
306	req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
307
308	req->rate = req->best_parent_rate / factor;
309
310	return 0;
311}
312
313static int clk_bytediv_set_rate(struct clk_hw *hw, unsigned long rate,
314				unsigned long parent_rate)
315{
316	struct clk_bytediv *bytediv = to_clk_bytediv(hw);
317	u32 val;
318	unsigned int factor;
319
320	factor = get_vco_mul_factor(rate);
321
322	val = readl(bytediv->reg);
323	val |= (factor - 1) & 0xff;
324	writel(val, bytediv->reg);
325
326	return 0;
327}
328
329/* Our special byte clock divider ops */
330static const struct clk_ops clk_bytediv_ops = {
331	.determine_rate = clk_bytediv_determine_rate,
332	.set_rate = clk_bytediv_set_rate,
333	.recalc_rate = clk_bytediv_recalc_rate,
334};
335
336/*
337 * PLL Callbacks
338 */
339static void dsi_28nm_pll_save_state(struct msm_dsi_phy *phy)
340{
341	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(phy->vco_hw);
342	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
343	void __iomem *base = pll_28nm->phy->pll_base;
344
345	cached_state->postdiv3 =
346			readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
347	cached_state->postdiv2 =
348			readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
349	cached_state->postdiv1 =
350			readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
351
352	cached_state->vco_rate = clk_hw_get_rate(phy->vco_hw);
353}
354
355static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy)
356{
357	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(phy->vco_hw);
358	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
359	void __iomem *base = pll_28nm->phy->pll_base;
360	int ret;
361
362	ret = dsi_pll_28nm_clk_set_rate(phy->vco_hw,
363					cached_state->vco_rate, 0);
364	if (ret) {
365		DRM_DEV_ERROR(&pll_28nm->phy->pdev->dev,
366			      "restore vco rate failed. ret=%d\n", ret);
367		return ret;
368	}
369
370	writel(cached_state->postdiv3, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
371	writel(cached_state->postdiv2, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
372	writel(cached_state->postdiv1, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
373
374	return 0;
375}
376
377static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **provided_clocks)
378{
379	char clk_name[32];
380	struct clk_init_data vco_init = {
381		.parent_data = &(const struct clk_parent_data) {
382			.fw_name = "ref",
383		},
384		.num_parents = 1,
385		.flags = CLK_IGNORE_UNUSED,
386		.ops = &clk_ops_dsi_pll_28nm_vco,
387	};
388	struct device *dev = &pll_28nm->phy->pdev->dev;
389	struct clk_hw *hw;
390	struct clk_bytediv *bytediv;
391	struct clk_init_data bytediv_init = { };
392	int ret;
393
394	DBG("%d", pll_28nm->phy->id);
395
396	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);
397	if (!bytediv)
398		return -ENOMEM;
399
400	snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_28nm->phy->id);
401	vco_init.name = clk_name;
402
403	pll_28nm->clk_hw.init = &vco_init;
404
405	ret = devm_clk_hw_register(dev, &pll_28nm->clk_hw);
406	if (ret)
407		return ret;
408
409	/* prepare and register bytediv */
410	bytediv->hw.init = &bytediv_init;
411	bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
412
413	snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_28nm->phy->id + 1);
414
415	bytediv_init.name = clk_name;
416	bytediv_init.ops = &clk_bytediv_ops;
417	bytediv_init.flags = CLK_SET_RATE_PARENT;
418	bytediv_init.parent_hws = (const struct clk_hw*[]){
419		&pll_28nm->clk_hw,
420	};
421	bytediv_init.num_parents = 1;
422
423	/* DIV2 */
424	ret = devm_clk_hw_register(dev, &bytediv->hw);
425	if (ret)
426		return ret;
427	provided_clocks[DSI_BYTE_PLL_CLK] = &bytediv->hw;
428
429	snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_28nm->phy->id + 1);
430	/* DIV3 */
431	hw = devm_clk_hw_register_divider_parent_hw(dev, clk_name,
432			&pll_28nm->clk_hw, 0, pll_28nm->phy->pll_base +
433				REG_DSI_28nm_8960_PHY_PLL_CTRL_10,
434			0, 8, 0, NULL);
435	if (IS_ERR(hw))
436		return PTR_ERR(hw);
437	provided_clocks[DSI_PIXEL_PLL_CLK] = hw;
438
439	return 0;
440}
441
442static int dsi_pll_28nm_8960_init(struct msm_dsi_phy *phy)
443{
444	struct platform_device *pdev = phy->pdev;
445	struct dsi_pll_28nm *pll_28nm;
446	int ret;
447
448	if (!pdev)
449		return -ENODEV;
450
451	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
452	if (!pll_28nm)
453		return -ENOMEM;
454
455	pll_28nm->phy = phy;
456
457	ret = pll_28nm_register(pll_28nm, phy->provided_clocks->hws);
458	if (ret) {
459		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);
460		return ret;
461	}
462
463	phy->vco_hw = &pll_28nm->clk_hw;
464
465	return 0;
466}
467
468static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
469		struct msm_dsi_dphy_timing *timing)
470{
471	void __iomem *base = phy->base;
472
473	writel(DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero),
474	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0);
475	writel(DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail),
476	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1);
477	writel(DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare),
478	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2);
479	writel(0, base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3);
480	writel(DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),
481	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4);
482	writel(DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero),
483	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5);
484	writel(DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare),
485	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6);
486	writel(DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail),
487	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7);
488	writel(DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst),
489	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8);
490	writel(DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
491	       DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure),
492	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9);
493	writel(DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get),
494	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10);
495	writel(DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0),
496	       base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11);
497}
498
499static void dsi_28nm_phy_regulator_init(struct msm_dsi_phy *phy)
500{
501	void __iomem *base = phy->reg_base;
502
503	writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0);
504	writel(1, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1);
505	writel(1, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2);
506	writel(0, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3);
507	writel(0x100, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4);
508}
509
510static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy)
511{
512	void __iomem *base = phy->reg_base;
513
514	writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0);
515	writel(0xa, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1);
516	writel(0x4, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2);
517	writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3);
518	writel(0x20, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4);
519}
520
521static void dsi_28nm_phy_calibration(struct msm_dsi_phy *phy)
522{
523	void __iomem *base = phy->reg_base;
524	u32 status;
525	int i = 5000;
526
527	writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG);
528
529	writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2);
530	writel(0x5a, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1);
531	writel(0x10, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3);
532	writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4);
533	writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0);
534
535	writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER);
536	usleep_range(5000, 6000);
537	writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER);
538
539	do {
540		status = readl(base +
541				REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS);
542
543		if (!(status & DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY))
544			break;
545
546		udelay(1);
547	} while (--i > 0);
548}
549
550static void dsi_28nm_phy_lane_config(struct msm_dsi_phy *phy)
551{
552	void __iomem *base = phy->base;
553	int i;
554
555	for (i = 0; i < 4; i++) {
556		writel(0x80, base + REG_DSI_28nm_8960_PHY_LN_CFG_0(i));
557		writel(0x45, base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i));
558		writel(0x00, base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i));
559		writel(0x00, base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i));
560		writel(0x01, base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i));
561		writel(0x66, base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i));
562	}
563
564	writel(0x40, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0);
565	writel(0x67, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_1);
566	writel(0x0, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_2);
567	writel(0x0, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH);
568	writel(0x1, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0);
569	writel(0x88, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1);
570}
571
572static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,
573				struct msm_dsi_phy_clk_request *clk_req)
574{
575	struct msm_dsi_dphy_timing *timing = &phy->timing;
576	void __iomem *base = phy->base;
577
578	DBG("");
579
580	if (msm_dsi_dphy_timing_calc(timing, clk_req)) {
581		DRM_DEV_ERROR(&phy->pdev->dev,
582			      "%s: D-PHY timing calculation failed\n",
583			      __func__);
584		return -EINVAL;
585	}
586
587	dsi_28nm_phy_regulator_init(phy);
588
589	writel(0x04, base + REG_DSI_28nm_8960_PHY_LDO_CTRL);
590
591	/* strength control */
592	writel(0xff, base + REG_DSI_28nm_8960_PHY_STRENGTH_0);
593	writel(0x00, base + REG_DSI_28nm_8960_PHY_STRENGTH_1);
594	writel(0x06, base + REG_DSI_28nm_8960_PHY_STRENGTH_2);
595
596	/* phy ctrl */
597	writel(0x5f, base + REG_DSI_28nm_8960_PHY_CTRL_0);
598	writel(0x00, base + REG_DSI_28nm_8960_PHY_CTRL_1);
599	writel(0x00, base + REG_DSI_28nm_8960_PHY_CTRL_2);
600	writel(0x10, base + REG_DSI_28nm_8960_PHY_CTRL_3);
601
602	dsi_28nm_phy_regulator_ctrl(phy);
603
604	dsi_28nm_phy_calibration(phy);
605
606	dsi_28nm_phy_lane_config(phy);
607
608	writel(0x0f, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4);
609	writel(0x03, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_1);
610	writel(0x03, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_0);
611	writel(0x0, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4);
612
613	dsi_28nm_dphy_set_timing(phy, timing);
614
615	return 0;
616}
617
618static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
619{
620	writel(0x0, phy->base + REG_DSI_28nm_8960_PHY_CTRL_0);
621
622	/*
623	 * Wait for the registers writes to complete in order to
624	 * ensure that the phy is completely disabled
625	 */
626	wmb();
627}
628
629static const struct regulator_bulk_data dsi_phy_28nm_8960_regulators[] = {
630	{ .supply = "vddio", .init_load_uA = 100000 },	/* 1.8 V */
631};
632
633const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs = {
634	.has_phy_regulator = true,
635	.regulator_data = dsi_phy_28nm_8960_regulators,
636	.num_regulators = ARRAY_SIZE(dsi_phy_28nm_8960_regulators),
637	.ops = {
638		.enable = dsi_28nm_phy_enable,
639		.disable = dsi_28nm_phy_disable,
640		.pll_init = dsi_pll_28nm_8960_init,
641		.save_pll_state = dsi_28nm_pll_save_state,
642		.restore_pll_state = dsi_28nm_pll_restore_state,
643	},
644	.min_pll_rate = VCO_MIN_RATE,
645	.max_pll_rate = VCO_MAX_RATE,
646	.io_start = { 0x4700300, 0x5800300 },
647	.num_dsi_phy = 2,
648};
~/ Read-only file preview.