1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2024 Freebox SAS
7 #include <linux/clk-provider.h>
8 #include <linux/delay.h>
12 #define HDMI_VCO_MAX_FREQ 12000000000UL
13 #define HDMI_VCO_MIN_FREQ 8000000000UL
15 #define HDMI_PCLK_MAX_FREQ 600000000
16 #define HDMI_PCLK_MIN_FREQ 25000000
18 #define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL
19 #define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL
20 #define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL
21 #define HDMI_CORECLK_DIV 5
22 #define HDMI_DEFAULT_REF_CLOCK 19200000
23 #define HDMI_PLL_CMP_CNT 1024
25 #define HDMI_PLL_POLL_MAX_READS 100
26 #define HDMI_PLL_POLL_TIMEOUT_US 150
28 #define HDMI_NUM_TX_CHANNEL 4
30 struct hdmi_pll_8998 {
31 struct platform_device *pdev;
36 void __iomem *mmio_qserdes_com;
38 void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
41 #define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8998, clk_hw)
43 struct hdmi_8998_phy_pll_reg_cfg {
44 u32 com_svs_mode_clk_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;
56 u32 com_lock_cmp1_mode0;
57 u32 com_lock_cmp2_mode0;
58 u32 com_lock_cmp3_mode0;
60 u32 com_coreclk_div_mode0;
62 u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
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_pre_driver_1[HDMI_NUM_TX_CHANNEL];
66 u32 tx_lx_pre_driver_2[HDMI_NUM_TX_CHANNEL];
67 u32 tx_lx_res_code_offset[HDMI_NUM_TX_CHANNEL];
72 struct hdmi_8998_post_divider {
80 static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8998 *pll)
82 return platform_get_drvdata(pll->pdev);
85 static inline void hdmi_pll_write(struct hdmi_pll_8998 *pll, int offset,
88 writel(data, pll->mmio_qserdes_com + offset);
91 static inline u32 hdmi_pll_read(struct hdmi_pll_8998 *pll, int offset)
93 return readl(pll->mmio_qserdes_com + offset);
96 static inline void hdmi_tx_chan_write(struct hdmi_pll_8998 *pll, int channel,
99 writel(data, pll->mmio_qserdes_tx[channel] + offset);
102 static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
105 if ((frac_start != 0) || gen_ssc)
111 static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
113 if ((frac_start != 0) || gen_ssc)
119 static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
121 if ((frac_start != 0) || gen_ssc)
127 static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
130 int digclk_divsel = bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
133 if ((frac_start != 0) || gen_ssc)
138 base <<= (digclk_divsel == 2 ? 1 : 0);
143 static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
145 u64 dividend = HDMI_PLL_CMP_CNT * fdata;
146 u32 divisor = ref_clk * 10;
149 rem = do_div(dividend, divisor);
150 if (rem > (divisor >> 1))
156 #define HDMI_REF_CLOCK_HZ ((u64)19200000)
157 #define HDMI_MHZ_TO_HZ ((u64)1000000)
158 static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
160 static const u32 ratio_list[] = {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25};
161 static const u32 band_list[] = {0, 1, 2, 3};
162 u32 const sz_ratio = ARRAY_SIZE(ratio_list);
163 u32 const sz_band = ARRAY_SIZE(band_list);
164 u32 const cmp_cnt = 1024;
165 u32 const th_min = 500, th_max = 1000;
166 u32 half_rate_mode = 0;
170 u32 found_hsclk_divsel = 0, found_vco_ratio;
171 u32 found_tx_band_sel;
172 u64 const min_freq = HDMI_VCO_MIN_FREQ, max_freq = HDMI_VCO_MAX_FREQ;
173 u64 freq_list[ARRAY_SIZE(ratio_list) * ARRAY_SIZE(band_list)];
178 freq_optimal = max_freq;
182 for (i = 0; i < sz_ratio; i++) {
183 for (j = 0; j < sz_band; j++) {
184 u64 freq = div_u64(bclk, (1 << half_rate_mode));
186 freq *= (ratio_list[i] * (1 << band_list[j]));
187 freq_list[list_elements++] = freq;
191 for (k = 0; k < ARRAY_SIZE(freq_list); k++) {
192 u32 const clks_pll_div = 2, core_clk_div = 5;
193 u32 const rng1 = 16, rng2 = 8;
195 u64 core_clk, rvar1, rem;
197 core_clk = div_u64(freq_list[k],
198 ratio_list[k / sz_band] * clks_pll_div *
201 rvar1 = HDMI_REF_CLOCK_HZ * rng1 * HDMI_MHZ_TO_HZ;
202 rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem);
203 if (rem > ((cmp_cnt * core_clk) >> 1))
207 rvar1 = HDMI_REF_CLOCK_HZ * rng2 * HDMI_MHZ_TO_HZ;
208 rvar1 = div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem);
209 if (rem > ((cmp_cnt * core_clk) >> 1))
213 if (freq_list[k] >= min_freq &&
214 freq_list[k] <= max_freq) {
215 if ((th1 >= th_min && th1 <= th_max) ||
216 (th2 >= th_min && th2 <= th_max)) {
217 if (freq_list[k] <= freq_optimal) {
218 freq_optimal = freq_list[k];
225 if (optimal_index == -1) {
226 if (!half_rate_mode) {
228 goto find_optimal_index;
233 found_vco_ratio = ratio_list[optimal_index / sz_band];
234 found_tx_band_sel = band_list[optimal_index % sz_band];
235 found_vco_freq = freq_optimal;
238 switch (found_vco_ratio) {
240 found_hsclk_divsel = 15;
243 found_hsclk_divsel = 0;
246 found_hsclk_divsel = 4;
249 found_hsclk_divsel = 8;
252 found_hsclk_divsel = 12;
255 found_hsclk_divsel = 1;
258 found_hsclk_divsel = 5;
261 found_hsclk_divsel = 2;
264 found_hsclk_divsel = 9;
267 found_hsclk_divsel = 13;
270 found_hsclk_divsel = 14;
274 pd->vco_freq = found_vco_freq;
275 pd->tx_band_sel = found_tx_band_sel;
276 pd->vco_ratio = found_vco_ratio;
277 pd->hsclk_divsel = found_hsclk_divsel;
282 static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
283 struct hdmi_8998_phy_pll_reg_cfg *cfg)
285 struct hdmi_8998_post_divider pd;
299 /* bit clk = 10 * pix_clk */
300 bclk = ((u64)pix_clk) * 10;
302 ret = pll_get_post_div(&pd, bclk);
306 dec_start = pd.vco_freq;
307 pll_divisor = 4 * ref_clk;
308 do_div(dec_start, pll_divisor);
310 frac_start = pd.vco_freq * (1 << 20);
312 rem = do_div(frac_start, pll_divisor);
313 frac_start -= dec_start * (1 << 20);
314 if (rem > (pll_divisor >> 1))
317 cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
318 rctrl = pll_get_rctrl(frac_start, false);
319 cctrl = pll_get_cctrl(frac_start, false);
320 integloop_gain = pll_get_integloop_gain(frac_start, bclk,
324 do_div(fdata, pd.vco_ratio);
326 pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
328 /* Convert these values to register specific values */
329 if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
330 cfg->com_svs_mode_clk_sel = 1;
332 cfg->com_svs_mode_clk_sel = 2;
334 cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
335 cfg->com_pll_cctrl_mode0 = cctrl;
336 cfg->com_pll_rctrl_mode0 = rctrl;
337 cfg->com_cp_ctrl_mode0 = cpctrl;
338 cfg->com_dec_start_mode0 = dec_start;
339 cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
340 cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
341 cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
342 cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
343 cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
344 cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
345 cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
346 cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
347 cfg->com_lock_cmp_en = 0x0;
348 cfg->com_core_clk_en = 0x2c;
349 cfg->com_coreclk_div_mode0 = HDMI_CORECLK_DIV;
350 cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x5 : 0x4;
352 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
353 cfg->tx_lx_tx_band[i] = pd.tx_band_sel;
355 if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
356 cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
357 cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
358 cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
359 cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
360 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03;
361 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x02;
362 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03;
363 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
364 cfg->tx_lx_pre_driver_1[0] = 0x00;
365 cfg->tx_lx_pre_driver_1[1] = 0x00;
366 cfg->tx_lx_pre_driver_1[2] = 0x00;
367 cfg->tx_lx_pre_driver_1[3] = 0x00;
368 cfg->tx_lx_pre_driver_2[0] = 0x1C;
369 cfg->tx_lx_pre_driver_2[1] = 0x1C;
370 cfg->tx_lx_pre_driver_2[2] = 0x1C;
371 cfg->tx_lx_pre_driver_2[3] = 0x00;
372 cfg->tx_lx_res_code_offset[0] = 0x03;
373 cfg->tx_lx_res_code_offset[1] = 0x00;
374 cfg->tx_lx_res_code_offset[2] = 0x00;
375 cfg->tx_lx_res_code_offset[3] = 0x03;
376 } else if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) {
377 cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
378 cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
379 cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
380 cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
381 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x03;
382 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x03;
383 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x03;
384 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
385 cfg->tx_lx_pre_driver_1[0] = 0x00;
386 cfg->tx_lx_pre_driver_1[1] = 0x00;
387 cfg->tx_lx_pre_driver_1[2] = 0x00;
388 cfg->tx_lx_pre_driver_1[3] = 0x00;
389 cfg->tx_lx_pre_driver_2[0] = 0x16;
390 cfg->tx_lx_pre_driver_2[1] = 0x16;
391 cfg->tx_lx_pre_driver_2[2] = 0x16;
392 cfg->tx_lx_pre_driver_2[3] = 0x18;
393 cfg->tx_lx_res_code_offset[0] = 0x03;
394 cfg->tx_lx_res_code_offset[1] = 0x00;
395 cfg->tx_lx_res_code_offset[2] = 0x00;
396 cfg->tx_lx_res_code_offset[3] = 0x00;
397 } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
398 cfg->tx_lx_tx_drv_lvl[0] = 0x0f;
399 cfg->tx_lx_tx_drv_lvl[1] = 0x0f;
400 cfg->tx_lx_tx_drv_lvl[2] = 0x0f;
401 cfg->tx_lx_tx_drv_lvl[3] = 0x0f;
402 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x05;
403 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x05;
404 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x05;
405 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
406 cfg->tx_lx_pre_driver_1[0] = 0x00;
407 cfg->tx_lx_pre_driver_1[1] = 0x00;
408 cfg->tx_lx_pre_driver_1[2] = 0x00;
409 cfg->tx_lx_pre_driver_1[3] = 0x00;
410 cfg->tx_lx_pre_driver_2[0] = 0x0E;
411 cfg->tx_lx_pre_driver_2[1] = 0x0E;
412 cfg->tx_lx_pre_driver_2[2] = 0x0E;
413 cfg->tx_lx_pre_driver_2[3] = 0x0E;
414 cfg->tx_lx_res_code_offset[0] = 0x00;
415 cfg->tx_lx_res_code_offset[1] = 0x00;
416 cfg->tx_lx_res_code_offset[2] = 0x00;
417 cfg->tx_lx_res_code_offset[3] = 0x00;
419 cfg->tx_lx_tx_drv_lvl[0] = 0x01;
420 cfg->tx_lx_tx_drv_lvl[1] = 0x01;
421 cfg->tx_lx_tx_drv_lvl[2] = 0x01;
422 cfg->tx_lx_tx_drv_lvl[3] = 0x00;
423 cfg->tx_lx_tx_emp_post1_lvl[0] = 0x00;
424 cfg->tx_lx_tx_emp_post1_lvl[1] = 0x00;
425 cfg->tx_lx_tx_emp_post1_lvl[2] = 0x00;
426 cfg->tx_lx_tx_emp_post1_lvl[3] = 0x00;
427 cfg->tx_lx_pre_driver_1[0] = 0x00;
428 cfg->tx_lx_pre_driver_1[1] = 0x00;
429 cfg->tx_lx_pre_driver_1[2] = 0x00;
430 cfg->tx_lx_pre_driver_1[3] = 0x00;
431 cfg->tx_lx_pre_driver_2[0] = 0x16;
432 cfg->tx_lx_pre_driver_2[1] = 0x16;
433 cfg->tx_lx_pre_driver_2[2] = 0x16;
434 cfg->tx_lx_pre_driver_2[3] = 0x18;
435 cfg->tx_lx_res_code_offset[0] = 0x00;
436 cfg->tx_lx_res_code_offset[1] = 0x00;
437 cfg->tx_lx_res_code_offset[2] = 0x00;
438 cfg->tx_lx_res_code_offset[3] = 0x00;
444 static int hdmi_8998_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
445 unsigned long parent_rate)
447 struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
448 struct hdmi_phy *phy = pll_get_phy(pll);
449 struct hdmi_8998_phy_pll_reg_cfg cfg = {};
452 ret = pll_calculate(rate, parent_rate, &cfg);
454 DRM_ERROR("PLL calculation failed\n");
458 /* Initially shut down PHY */
459 hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x0);
462 /* Power up sequence */
463 hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x1);
464 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
465 hdmi_phy_write(phy, REG_HDMI_8998_PHY_CMN_CTRL, 0x6);
467 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
468 hdmi_tx_chan_write(pll, i,
469 REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND,
470 cfg.tx_lx_tx_band[i]);
471 hdmi_tx_chan_write(pll, i,
472 REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE,
474 hdmi_tx_chan_write(pll, i,
475 REG_HDMI_8998_PHY_TXn_LANE_MODE,
479 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x02);
480 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x0B);
481 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
482 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
483 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
485 /* Bypass VCO calibration */
486 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
487 cfg.com_svs_mode_clk_sel);
489 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_IVCO, 0x07);
490 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_CTRL, 0x00);
492 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_SEL, 0x30);
493 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_HSCLK_SEL,
495 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP_EN,
496 cfg.com_lock_cmp_en);
498 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
499 cfg.com_pll_cctrl_mode0);
500 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
501 cfg.com_pll_rctrl_mode0);
502 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CP_CTRL_MODE0,
503 cfg.com_cp_ctrl_mode0);
504 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DEC_START_MODE0,
505 cfg.com_dec_start_mode0);
506 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
507 cfg.com_div_frac_start1_mode0);
508 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
509 cfg.com_div_frac_start2_mode0);
510 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
511 cfg.com_div_frac_start3_mode0);
513 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
514 cfg.com_integloop_gain0_mode0);
515 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
516 cfg.com_integloop_gain1_mode0);
518 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
519 cfg.com_lock_cmp1_mode0);
520 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
521 cfg.com_lock_cmp2_mode0);
522 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
523 cfg.com_lock_cmp3_mode0);
525 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
526 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORE_CLK_EN,
527 cfg.com_core_clk_en);
528 hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORECLK_DIV_MODE0,
529 cfg.com_coreclk_div_mode0);
531 /* TX lanes setup (TX 0/1/2/3) */
532 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
533 hdmi_tx_chan_write(pll, i,
534 REG_HDMI_8998_PHY_TXn_DRV_LVL,
535 cfg.tx_lx_tx_drv_lvl[i]);
536 hdmi_tx_chan_write(pll, i,
537 REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL,
538 cfg.tx_lx_tx_emp_post1_lvl[i]);
539 hdmi_tx_chan_write(pll, i,
540 REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1,
541 cfg.tx_lx_pre_driver_1[i]);
542 hdmi_tx_chan_write(pll, i,
543 REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2,
544 cfg.tx_lx_pre_driver_2[i]);
545 hdmi_tx_chan_write(pll, i,
546 REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_OFFSET,
547 cfg.tx_lx_res_code_offset[i]);
550 hdmi_phy_write(phy, REG_HDMI_8998_PHY_MODE, cfg.phy_mode);
552 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
553 hdmi_tx_chan_write(pll, i,
554 REG_HDMI_8998_PHY_TXn_LANE_CONFIG,
559 * Ensure that vco configuration gets flushed to hardware before
569 static int hdmi_8998_phy_ready_status(struct hdmi_phy *phy)
571 u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
572 unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
577 status = hdmi_phy_read(phy, REG_HDMI_8998_PHY_STATUS);
578 phy_ready = status & BIT(0);
589 static int hdmi_8998_pll_lock_status(struct hdmi_pll_8998 *pll)
592 int nb_tries = HDMI_PLL_POLL_MAX_READS;
593 unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
597 status = hdmi_pll_read(pll,
598 REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS);
599 pll_locked = status & BIT(0);
610 static int hdmi_8998_pll_prepare(struct clk_hw *hw)
612 struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
613 struct hdmi_phy *phy = pll_get_phy(pll);
616 hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x1);
619 hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59);
622 ret = hdmi_8998_pll_lock_status(pll);
626 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
627 hdmi_tx_chan_write(pll, i,
628 REG_HDMI_8998_PHY_TXn_LANE_CONFIG, 0x1F);
631 /* Ensure all registers are flushed to hardware */
634 ret = hdmi_8998_phy_ready_status(phy);
638 /* Restart the retiming buffer */
639 hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x58);
641 hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59);
643 /* Ensure all registers are flushed to hardware */
649 static long hdmi_8998_pll_round_rate(struct clk_hw *hw,
651 unsigned long *parent_rate)
653 if (rate < HDMI_PCLK_MIN_FREQ)
654 return HDMI_PCLK_MIN_FREQ;
655 else if (rate > HDMI_PCLK_MAX_FREQ)
656 return HDMI_PCLK_MAX_FREQ;
661 static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw,
662 unsigned long parent_rate)
664 struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
668 static void hdmi_8998_pll_unprepare(struct clk_hw *hw)
670 struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
671 struct hdmi_phy *phy = pll_get_phy(pll);
673 hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0);
674 usleep_range(100, 150);
677 static int hdmi_8998_pll_is_enabled(struct clk_hw *hw)
679 struct hdmi_pll_8998 *pll = hw_clk_to_pll(hw);
683 status = hdmi_pll_read(pll, REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS);
684 pll_locked = status & BIT(0);
689 static const struct clk_ops hdmi_8998_pll_ops = {
690 .set_rate = hdmi_8998_pll_set_clk_rate,
691 .round_rate = hdmi_8998_pll_round_rate,
692 .recalc_rate = hdmi_8998_pll_recalc_rate,
693 .prepare = hdmi_8998_pll_prepare,
694 .unprepare = hdmi_8998_pll_unprepare,
695 .is_enabled = hdmi_8998_pll_is_enabled,
698 static const struct clk_init_data pll_init = {
700 .ops = &hdmi_8998_pll_ops,
701 .parent_data = (const struct clk_parent_data[]){
702 { .fw_name = "xo", .name = "xo_board" },
705 .flags = CLK_IGNORE_UNUSED,
708 int msm_hdmi_pll_8998_init(struct platform_device *pdev)
710 struct device *dev = &pdev->dev;
711 struct hdmi_pll_8998 *pll;
714 pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
720 pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
721 if (IS_ERR(pll->mmio_qserdes_com)) {
722 DRM_DEV_ERROR(dev, "failed to map pll base\n");
726 for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
729 snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
731 pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
732 if (IS_ERR(pll->mmio_qserdes_tx[i])) {
733 DRM_DEV_ERROR(dev, "failed to map pll base\n");
737 pll->clk_hw.init = &pll_init;
739 ret = devm_clk_hw_register(dev, &pll->clk_hw);
741 DRM_DEV_ERROR(dev, "failed to register pll clock\n");
745 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);
747 DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
754 static const char * const hdmi_phy_8998_reg_names[] = {
759 static const char * const hdmi_phy_8998_clk_names[] = {
760 "iface", "ref", "xo",
763 const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg = {
764 .type = MSM_HDMI_PHY_8998,
765 .reg_names = hdmi_phy_8998_reg_names,
766 .num_regs = ARRAY_SIZE(hdmi_phy_8998_reg_names),
767 .clk_names = hdmi_phy_8998_clk_names,
768 .num_clks = ARRAY_SIZE(hdmi_phy_8998_clk_names),