1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/delay.h>
8
9#include "hdmi.h"
10
11#define HDMI_VCO_MAX_FREQ			12000000000UL
12#define HDMI_VCO_MIN_FREQ			8000000000UL
13
14#define HDMI_PCLK_MAX_FREQ			600000000
15#define HDMI_PCLK_MIN_FREQ			25000000
16
17#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD	3400000000UL
18#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD		1500000000UL
19#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD		750000000UL
20#define HDMI_CORECLK_DIV			5
21#define HDMI_DEFAULT_REF_CLOCK			19200000
22#define HDMI_PLL_CMP_CNT			1024
23
24#define HDMI_PLL_POLL_MAX_READS			100
25#define HDMI_PLL_POLL_TIMEOUT_US		150
26
27#define HDMI_NUM_TX_CHANNEL			4
28
29struct hdmi_pll_8996 {
30	struct platform_device *pdev;
31	struct clk_hw clk_hw;
32
33	/* pll mmio base */
34	void __iomem *mmio_qserdes_com;
35	/* tx channel base */
36	void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
37};
38
39#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8996, clk_hw)
40
41struct hdmi_8996_phy_pll_reg_cfg {
42	u32 tx_lx_lane_mode[HDMI_NUM_TX_CHANNEL];
43	u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
44	u32 com_svs_mode_clk_sel;
45	u32 com_hsclk_sel;
46	u32 com_pll_cctrl_mode0;
47	u32 com_pll_rctrl_mode0;
48	u32 com_cp_ctrl_mode0;
49	u32 com_dec_start_mode0;
50	u32 com_div_frac_start1_mode0;
51	u32 com_div_frac_start2_mode0;
52	u32 com_div_frac_start3_mode0;
53	u32 com_integloop_gain0_mode0;
54	u32 com_integloop_gain1_mode0;
55	u32 com_lock_cmp_en;
56	u32 com_lock_cmp1_mode0;
57	u32 com_lock_cmp2_mode0;
58	u32 com_lock_cmp3_mode0;
59	u32 com_core_clk_en;
60	u32 com_coreclk_div;
61	u32 com_vco_tune_ctrl;
62
63	u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
64	u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
65	u32 tx_lx_vmode_ctrl1[HDMI_NUM_TX_CHANNEL];
66	u32 tx_lx_vmode_ctrl2[HDMI_NUM_TX_CHANNEL];
67	u32 tx_lx_res_code_lane_tx[HDMI_NUM_TX_CHANNEL];
68	u32 tx_lx_hp_pd_enables[HDMI_NUM_TX_CHANNEL];
69
70	u32 phy_mode;
71};
72
73struct hdmi_8996_post_divider {
74	u64 vco_freq;
75	int hsclk_divsel;
76	int vco_ratio;
77	int tx_band_sel;
78	int half_rate_mode;
79};
80
81static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll)
82{
83	return platform_get_drvdata(pll->pdev);
84}
85
86static inline void hdmi_pll_write(struct hdmi_pll_8996 *pll, int offset,
87				  u32 data)
88{
89	msm_writel(data, pll->mmio_qserdes_com + offset);
90}
91
92static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset)
93{
94	return msm_readl(pll->mmio_qserdes_com + offset);
95}
96
97static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int channel,
98				      int offset, int data)
99{
100	 msm_writel(data, pll->mmio_qserdes_tx[channel] + offset);
101}
102
103static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
104				 bool gen_ssc)
105{
106	if ((frac_start != 0) || gen_ssc)
107		return (11000000 / (ref_clk / 20));
108
109	return 0x23;
110}
111
112static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
113{
114	if ((frac_start != 0) || gen_ssc)
115		return 0x16;
116
117	return 0x10;
118}
119
120static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
121{
122	if ((frac_start != 0) || gen_ssc)
123		return 0x28;
124
125	return 0x1;
126}
127
128static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
129					 bool gen_ssc)
130{
131	int digclk_divsel = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
132	u64 base;
133
134	if ((frac_start != 0) || gen_ssc)
135		base = (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK;
136	else
137		base = (1022 * ref_clk) / 100;
138
139	base <<= digclk_divsel;
140
141	return (base <= 2046 ? base : 2046);
142}
143
144static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
145{
146	u64 dividend = HDMI_PLL_CMP_CNT * fdata;
147	u32 divisor = ref_clk * 10;
148	u32 rem;
149
150	rem = do_div(dividend, divisor);
151	if (rem > (divisor >> 1))
152		dividend++;
153
154	return dividend - 1;
155}
156
157static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk)
158{
159	u64 fdata = ((u64)pll_cmp) * ref_clk * 10;
160
161	do_div(fdata, HDMI_PLL_CMP_CNT);
162
163	return fdata;
164}
165
166static int pll_get_post_div(struct hdmi_8996_post_divider *pd, u64 bclk)
167{
168	int ratio[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 };
169	int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 };
170	int tx_band_sel[] = { 0, 1, 2, 3 };
171	u64 vco_freq[60];
172	u64 vco, vco_optimal;
173	int half_rate_mode = 0;
174	int vco_optimal_index, vco_freq_index;
175	int i, j;
176
177retry:
178	vco_optimal = HDMI_VCO_MAX_FREQ;
179	vco_optimal_index = -1;
180	vco_freq_index = 0;
181	for (i = 0; i < 15; i++) {
182		for (j = 0; j < 4; j++) {
183			u32 ratio_mult = ratio[i] << tx_band_sel[j];
184
185			vco = bclk >> half_rate_mode;
186			vco *= ratio_mult;
187			vco_freq[vco_freq_index++] = vco;
188		}
189	}
190
191	for (i = 0; i < 60; i++) {
192		u64 vco_tmp = vco_freq[i];
193
194		if ((vco_tmp >= HDMI_VCO_MIN_FREQ) &&
195		    (vco_tmp <= vco_optimal)) {
196			vco_optimal = vco_tmp;
197			vco_optimal_index = i;
198		}
199	}
200
201	if (vco_optimal_index == -1) {
202		if (!half_rate_mode) {
203			half_rate_mode = 1;
204			goto retry;
205		}
206	} else {
207		pd->vco_freq = vco_optimal;
208		pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4];
209		pd->vco_ratio = ratio[vco_optimal_index / 4];
210		pd->hsclk_divsel = hs_divsel[vco_optimal_index / 4];
211
212		return 0;
213	}
214
215	return -EINVAL;
216}
217
218static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
219			 struct hdmi_8996_phy_pll_reg_cfg *cfg)
220{
221	struct hdmi_8996_post_divider pd;
222	u64 bclk;
223	u64 tmds_clk;
224	u64 dec_start;
225	u64 frac_start;
226	u64 fdata;
227	u32 pll_divisor;
228	u32 rem;
229	u32 cpctrl;
230	u32 rctrl;
231	u32 cctrl;
232	u32 integloop_gain;
233	u32 pll_cmp;
234	int i, ret;
235
236	/* bit clk = 10 * pix_clk */
237	bclk = ((u64)pix_clk) * 10;
238
239	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD)
240		tmds_clk = pix_clk >> 2;
241	else
242		tmds_clk = pix_clk;
243
244	ret = pll_get_post_div(&pd, bclk);
245	if (ret)
246		return ret;
247
248	dec_start = pd.vco_freq;
249	pll_divisor = 4 * ref_clk;
250	do_div(dec_start, pll_divisor);
251
252	frac_start = pd.vco_freq * (1 << 20);
253
254	rem = do_div(frac_start, pll_divisor);
255	frac_start -= dec_start * (1 << 20);
256	if (rem > (pll_divisor >> 1))
257		frac_start++;
258
259	cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
260	rctrl = pll_get_rctrl(frac_start, false);
261	cctrl = pll_get_cctrl(frac_start, false);
262	integloop_gain = pll_get_integloop_gain(frac_start, bclk,
263						ref_clk, false);
264
265	fdata = pd.vco_freq;
266	do_div(fdata, pd.vco_ratio);
267
268	pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
269
270	DBG("VCO freq: %llu", pd.vco_freq);
271	DBG("fdata: %llu", fdata);
272	DBG("pix_clk: %lu", pix_clk);
273	DBG("tmds clk: %llu", tmds_clk);
274	DBG("HSCLK_SEL: %d", pd.hsclk_divsel);
275	DBG("DEC_START: %llu", dec_start);
276	DBG("DIV_FRAC_START: %llu", frac_start);
277	DBG("PLL_CPCTRL: %u", cpctrl);
278	DBG("PLL_RCTRL: %u", rctrl);
279	DBG("PLL_CCTRL: %u", cctrl);
280	DBG("INTEGLOOP_GAIN: %u", integloop_gain);
281	DBG("TX_BAND: %d", pd.tx_band_sel);
282	DBG("PLL_CMP: %u", pll_cmp);
283
284	/* Convert these values to register specific values */
285	if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
286		cfg->com_svs_mode_clk_sel = 1;
287	else
288		cfg->com_svs_mode_clk_sel = 2;
289
290	cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
291	cfg->com_pll_cctrl_mode0 = cctrl;
292	cfg->com_pll_rctrl_mode0 = rctrl;
293	cfg->com_cp_ctrl_mode0 = cpctrl;
294	cfg->com_dec_start_mode0 = dec_start;
295	cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
296	cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
297	cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
298	cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
299	cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
300	cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
301	cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
302	cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
303	cfg->com_lock_cmp_en = 0x0;
304	cfg->com_core_clk_en = 0x2c;
305	cfg->com_coreclk_div = HDMI_CORECLK_DIV;
306	cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0;
307	cfg->com_vco_tune_ctrl = 0x0;
308
309	cfg->tx_lx_lane_mode[0] =
310		cfg->tx_lx_lane_mode[2] = 0x43;
311
312	cfg->tx_lx_hp_pd_enables[0] =
313		cfg->tx_lx_hp_pd_enables[1] =
314		cfg->tx_lx_hp_pd_enables[2] = 0x0c;
315	cfg->tx_lx_hp_pd_enables[3] = 0x3;
316
317	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
318		cfg->tx_lx_tx_band[i] = pd.tx_band_sel + 4;
319
320	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
321		cfg->tx_lx_tx_drv_lvl[0] =
322			cfg->tx_lx_tx_drv_lvl[1] =
323			cfg->tx_lx_tx_drv_lvl[2] = 0x25;
324		cfg->tx_lx_tx_drv_lvl[3] = 0x22;
325
326		cfg->tx_lx_tx_emp_post1_lvl[0] =
327			cfg->tx_lx_tx_emp_post1_lvl[1] =
328			cfg->tx_lx_tx_emp_post1_lvl[2] = 0x23;
329		cfg->tx_lx_tx_emp_post1_lvl[3] = 0x27;
330
331		cfg->tx_lx_vmode_ctrl1[0] =
332			cfg->tx_lx_vmode_ctrl1[1] =
333			cfg->tx_lx_vmode_ctrl1[2] =
334			cfg->tx_lx_vmode_ctrl1[3] = 0x00;
335
336		cfg->tx_lx_vmode_ctrl2[0] =
337			cfg->tx_lx_vmode_ctrl2[1] =
338			cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
339
340		cfg->tx_lx_vmode_ctrl2[3] = 0x00;
341	} else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
342		for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
343			cfg->tx_lx_tx_drv_lvl[i] = 0x25;
344			cfg->tx_lx_tx_emp_post1_lvl[i] = 0x23;
345			cfg->tx_lx_vmode_ctrl1[i] = 0x00;
346		}
347
348		cfg->tx_lx_vmode_ctrl2[0] =
349			cfg->tx_lx_vmode_ctrl2[1] =
350			cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
351		cfg->tx_lx_vmode_ctrl2[3] = 0x00;
352	} else {
353		for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
354			cfg->tx_lx_tx_drv_lvl[i] = 0x20;
355			cfg->tx_lx_tx_emp_post1_lvl[i] = 0x20;
356			cfg->tx_lx_vmode_ctrl1[i] = 0x00;
357			cfg->tx_lx_vmode_ctrl2[i] = 0x0E;
358		}
359	}
360
361	DBG("com_svs_mode_clk_sel = 0x%x", cfg->com_svs_mode_clk_sel);
362	DBG("com_hsclk_sel = 0x%x", cfg->com_hsclk_sel);
363	DBG("com_lock_cmp_en = 0x%x", cfg->com_lock_cmp_en);
364	DBG("com_pll_cctrl_mode0 = 0x%x", cfg->com_pll_cctrl_mode0);
365	DBG("com_pll_rctrl_mode0 = 0x%x", cfg->com_pll_rctrl_mode0);
366	DBG("com_cp_ctrl_mode0 = 0x%x", cfg->com_cp_ctrl_mode0);
367	DBG("com_dec_start_mode0 = 0x%x", cfg->com_dec_start_mode0);
368	DBG("com_div_frac_start1_mode0 = 0x%x", cfg->com_div_frac_start1_mode0);
369	DBG("com_div_frac_start2_mode0 = 0x%x", cfg->com_div_frac_start2_mode0);
370	DBG("com_div_frac_start3_mode0 = 0x%x", cfg->com_div_frac_start3_mode0);
371	DBG("com_integloop_gain0_mode0 = 0x%x", cfg->com_integloop_gain0_mode0);
372	DBG("com_integloop_gain1_mode0 = 0x%x", cfg->com_integloop_gain1_mode0);
373	DBG("com_lock_cmp1_mode0 = 0x%x", cfg->com_lock_cmp1_mode0);
374	DBG("com_lock_cmp2_mode0 = 0x%x", cfg->com_lock_cmp2_mode0);
375	DBG("com_lock_cmp3_mode0 = 0x%x", cfg->com_lock_cmp3_mode0);
376	DBG("com_core_clk_en = 0x%x", cfg->com_core_clk_en);
377	DBG("com_coreclk_div = 0x%x", cfg->com_coreclk_div);
378	DBG("phy_mode = 0x%x", cfg->phy_mode);
379
380	DBG("tx_l0_lane_mode = 0x%x", cfg->tx_lx_lane_mode[0]);
381	DBG("tx_l2_lane_mode = 0x%x", cfg->tx_lx_lane_mode[2]);
382
383	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
384		DBG("tx_l%d_tx_band = 0x%x", i, cfg->tx_lx_tx_band[i]);
385		DBG("tx_l%d_tx_drv_lvl = 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]);
386		DBG("tx_l%d_tx_emp_post1_lvl = 0x%x", i,
387		    cfg->tx_lx_tx_emp_post1_lvl[i]);
388		DBG("tx_l%d_vmode_ctrl1 = 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]);
389		DBG("tx_l%d_vmode_ctrl2 = 0x%x", i, cfg->tx_lx_vmode_ctrl2[i]);
390	}
391
392	return 0;
393}
394
395static int hdmi_8996_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
396				      unsigned long parent_rate)
397{
398	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
399	struct hdmi_phy *phy = pll_get_phy(pll);
400	struct hdmi_8996_phy_pll_reg_cfg cfg;
401	int i, ret;
402
403	memset(&cfg, 0x00, sizeof(cfg));
404
405	ret = pll_calculate(rate, parent_rate, &cfg);
406	if (ret) {
407		DRM_ERROR("PLL calculation failed\n");
408		return ret;
409	}
410
411	/* Initially shut down PHY */
412	DBG("Disabling PHY");
413	hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x0);
414	udelay(500);
415
416	/* Power up sequence */
417	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x04);
418
419	hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1);
420	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
421	hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0F);
422	hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0F);
423
424	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
425		hdmi_tx_chan_write(pll, i,
426				   REG_HDMI_PHY_QSERDES_TX_LX_CLKBUF_ENABLE,
427				   0x03);
428		hdmi_tx_chan_write(pll, i,
429				   REG_HDMI_PHY_QSERDES_TX_LX_TX_BAND,
430				   cfg.tx_lx_tx_band[i]);
431		hdmi_tx_chan_write(pll, i,
432				   REG_HDMI_PHY_QSERDES_TX_LX_RESET_TSYNC_EN,
433				   0x03);
434	}
435
436	hdmi_tx_chan_write(pll, 0, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
437			   cfg.tx_lx_lane_mode[0]);
438	hdmi_tx_chan_write(pll, 2, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
439			   cfg.tx_lx_lane_mode[2]);
440
441	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E);
442	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07);
443	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
444	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
445	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
446
447	/* Bypass VCO calibration */
448	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
449		       cfg.com_svs_mode_clk_sel);
450
451	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_TRIM, 0x0F);
452	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_IVCO, 0x0F);
453	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_CTRL,
454		       cfg.com_vco_tune_ctrl);
455
456	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x06);
457
458	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_SELECT, 0x30);
459	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_HSCLK_SEL,
460		       cfg.com_hsclk_sel);
461	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP_EN,
462		       cfg.com_lock_cmp_en);
463
464	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
465		       cfg.com_pll_cctrl_mode0);
466	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
467		       cfg.com_pll_rctrl_mode0);
468	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CP_CTRL_MODE0,
469		       cfg.com_cp_ctrl_mode0);
470	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DEC_START_MODE0,
471		       cfg.com_dec_start_mode0);
472	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
473		       cfg.com_div_frac_start1_mode0);
474	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
475		       cfg.com_div_frac_start2_mode0);
476	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
477		       cfg.com_div_frac_start3_mode0);
478
479	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
480		       cfg.com_integloop_gain0_mode0);
481	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
482		       cfg.com_integloop_gain1_mode0);
483
484	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
485		       cfg.com_lock_cmp1_mode0);
486	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
487		       cfg.com_lock_cmp2_mode0);
488	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
489		       cfg.com_lock_cmp3_mode0);
490
491	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
492	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORE_CLK_EN,
493		       cfg.com_core_clk_en);
494	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORECLK_DIV,
495		       cfg.com_coreclk_div);
496	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CMN_CONFIG, 0x02);
497
498	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESCODE_DIV_NUM, 0x15);
499
500	/* TX lanes setup (TX 0/1/2/3) */
501	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
502		hdmi_tx_chan_write(pll, i,
503				   REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL,
504				   cfg.tx_lx_tx_drv_lvl[i]);
505		hdmi_tx_chan_write(pll, i,
506				   REG_HDMI_PHY_QSERDES_TX_LX_TX_EMP_POST1_LVL,
507				   cfg.tx_lx_tx_emp_post1_lvl[i]);
508		hdmi_tx_chan_write(pll, i,
509				   REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL1,
510				   cfg.tx_lx_vmode_ctrl1[i]);
511		hdmi_tx_chan_write(pll, i,
512				   REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL2,
513				   cfg.tx_lx_vmode_ctrl2[i]);
514		hdmi_tx_chan_write(pll, i,
515				   REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL_OFFSET,
516				   0x00);
517		hdmi_tx_chan_write(pll, i,
518			REG_HDMI_PHY_QSERDES_TX_LX_RES_CODE_LANE_OFFSET,
519			0x00);
520		hdmi_tx_chan_write(pll, i,
521			REG_HDMI_PHY_QSERDES_TX_LX_TRAN_DRVR_EMP_EN,
522			0x03);
523		hdmi_tx_chan_write(pll, i,
524			REG_HDMI_PHY_QSERDES_TX_LX_PARRATE_REC_DETECT_IDLE_EN,
525			0x40);
526		hdmi_tx_chan_write(pll, i,
527				   REG_HDMI_PHY_QSERDES_TX_LX_HP_PD_ENABLES,
528				   cfg.tx_lx_hp_pd_enables[i]);
529	}
530
531	hdmi_phy_write(phy, REG_HDMI_8996_PHY_MODE, cfg.phy_mode);
532	hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1F);
533
534	/*
535	 * Ensure that vco configuration gets flushed to hardware before
536	 * enabling the PLL
537	 */
538	wmb();
539
540	return 0;
541}
542
543static int hdmi_8996_phy_ready_status(struct hdmi_phy *phy)
544{
545	u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
546	unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
547	u32 status;
548	int phy_ready = 0;
549
550	DBG("Waiting for PHY ready");
551
552	while (nb_tries--) {
553		status = hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS);
554		phy_ready = status & BIT(0);
555
556		if (phy_ready)
557			break;
558
559		udelay(timeout);
560	}
561
562	DBG("PHY is %sready", phy_ready ? "" : "*not* ");
563
564	return phy_ready;
565}
566
567static int hdmi_8996_pll_lock_status(struct hdmi_pll_8996 *pll)
568{
569	u32 status;
570	int nb_tries = HDMI_PLL_POLL_MAX_READS;
571	unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
572	int pll_locked = 0;
573
574	DBG("Waiting for PLL lock");
575
576	while (nb_tries--) {
577		status = hdmi_pll_read(pll,
578				       REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
579		pll_locked = status & BIT(0);
580
581		if (pll_locked)
582			break;
583
584		udelay(timeout);
585	}
586
587	DBG("HDMI PLL is %slocked", pll_locked ? "" : "*not* ");
588
589	return pll_locked;
590}
591
592static int hdmi_8996_pll_prepare(struct clk_hw *hw)
593{
594	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
595	struct hdmi_phy *phy = pll_get_phy(pll);
596	int i, ret = 0;
597
598	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x1);
599	udelay(100);
600
601	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
602	udelay(100);
603
604	ret = hdmi_8996_pll_lock_status(pll);
605	if (!ret)
606		return ret;
607
608	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
609		hdmi_tx_chan_write(pll, i,
610			REG_HDMI_PHY_QSERDES_TX_LX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
611			0x6F);
612
613	/* Disable SSC */
614	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER1, 0x0);
615	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER2, 0x0);
616	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE1, 0x0);
617	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE2, 0x0);
618	hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_EN_CENTER, 0x2);
619
620	ret = hdmi_8996_phy_ready_status(phy);
621	if (!ret)
622		return ret;
623
624	/* Restart the retiming buffer */
625	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x18);
626	udelay(1);
627	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
628
629	return 0;
630}
631
632static long hdmi_8996_pll_round_rate(struct clk_hw *hw,
633				     unsigned long rate,
634				     unsigned long *parent_rate)
635{
636	if (rate < HDMI_PCLK_MIN_FREQ)
637		return HDMI_PCLK_MIN_FREQ;
638	else if (rate > HDMI_PCLK_MAX_FREQ)
639		return HDMI_PCLK_MAX_FREQ;
640	else
641		return rate;
642}
643
644static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
645					       unsigned long parent_rate)
646{
647	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
648	u64 fdata;
649	u32 cmp1, cmp2, cmp3, pll_cmp;
650
651	cmp1 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0);
652	cmp2 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0);
653	cmp3 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0);
654
655	pll_cmp = cmp1 | (cmp2 << 8) | (cmp3 << 16);
656
657	fdata = pll_cmp_to_fdata(pll_cmp + 1, parent_rate);
658
659	do_div(fdata, 10);
660
661	return fdata;
662}
663
664static void hdmi_8996_pll_unprepare(struct clk_hw *hw)
665{
666	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
667	struct hdmi_phy *phy = pll_get_phy(pll);
668
669	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x6);
670	usleep_range(100, 150);
671}
672
673static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
674{
675	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
676	u32 status;
677	int pll_locked;
678
679	status = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
680	pll_locked = status & BIT(0);
681
682	return pll_locked;
683}
684
685static const struct clk_ops hdmi_8996_pll_ops = {
686	.set_rate = hdmi_8996_pll_set_clk_rate,
687	.round_rate = hdmi_8996_pll_round_rate,
688	.recalc_rate = hdmi_8996_pll_recalc_rate,
689	.prepare = hdmi_8996_pll_prepare,
690	.unprepare = hdmi_8996_pll_unprepare,
691	.is_enabled = hdmi_8996_pll_is_enabled,
692};
693
694static const struct clk_init_data pll_init = {
695	.name = "hdmipll",
696	.ops = &hdmi_8996_pll_ops,
697	.parent_data = (const struct clk_parent_data[]){
698		{ .fw_name = "xo", .name = "xo_board" },
699	},
700	.num_parents = 1,
701	.flags = CLK_IGNORE_UNUSED,
702};
703
704int msm_hdmi_pll_8996_init(struct platform_device *pdev)
705{
706	struct device *dev = &pdev->dev;
707	struct hdmi_pll_8996 *pll;
708	int i, ret;
709
710	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
711	if (!pll)
712		return -ENOMEM;
713
714	pll->pdev = pdev;
715
716	pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
717	if (IS_ERR(pll->mmio_qserdes_com)) {
718		DRM_DEV_ERROR(dev, "failed to map pll base\n");
719		return -ENOMEM;
720	}
721
722	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
723		char name[32];
724
725		snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
726
727		pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
728		if (IS_ERR(pll->mmio_qserdes_tx[i])) {
729			DRM_DEV_ERROR(dev, "failed to map pll base\n");
730			return -ENOMEM;
731		}
732	}
733	pll->clk_hw.init = &pll_init;
734
735	ret = devm_clk_hw_register(dev, &pll->clk_hw);
736	if (ret) {
737		DRM_DEV_ERROR(dev, "failed to register pll clock\n");
738		return ret;
739	}
740
741	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);
742	if (ret) {
743		DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret);
744		return ret;
745	}
746
747	return 0;
748}
749
750static const char * const hdmi_phy_8996_reg_names[] = {
751	"vddio",
752	"vcca",
753};
754
755static const char * const hdmi_phy_8996_clk_names[] = {
756	"iface", "ref",
757};
758
759const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
760	.type = MSM_HDMI_PHY_8996,
761	.reg_names = hdmi_phy_8996_reg_names,
762	.num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
763	.clk_names = hdmi_phy_8996_clk_names,
764	.num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
765};
766