cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdmi_phy_8996.c (21254B)


      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 char * const hdmi_pll_parents[] = {
    695	"xo",
    696};
    697
    698static const struct clk_init_data pll_init = {
    699	.name = "hdmipll",
    700	.ops = &hdmi_8996_pll_ops,
    701	.parent_names = hdmi_pll_parents,
    702	.num_parents = ARRAY_SIZE(hdmi_pll_parents),
    703	.flags = CLK_IGNORE_UNUSED,
    704};
    705
    706int msm_hdmi_pll_8996_init(struct platform_device *pdev)
    707{
    708	struct device *dev = &pdev->dev;
    709	struct hdmi_pll_8996 *pll;
    710	struct clk *clk;
    711	int i;
    712
    713	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
    714	if (!pll)
    715		return -ENOMEM;
    716
    717	pll->pdev = pdev;
    718
    719	pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
    720	if (IS_ERR(pll->mmio_qserdes_com)) {
    721		DRM_DEV_ERROR(dev, "failed to map pll base\n");
    722		return -ENOMEM;
    723	}
    724
    725	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
    726		char name[32];
    727
    728		snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
    729
    730		pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
    731		if (IS_ERR(pll->mmio_qserdes_tx[i])) {
    732			DRM_DEV_ERROR(dev, "failed to map pll base\n");
    733			return -ENOMEM;
    734		}
    735	}
    736	pll->clk_hw.init = &pll_init;
    737
    738	clk = devm_clk_register(dev, &pll->clk_hw);
    739	if (IS_ERR(clk)) {
    740		DRM_DEV_ERROR(dev, "failed to register pll clock\n");
    741		return -EINVAL;
    742	}
    743
    744	return 0;
    745}
    746
    747static const char * const hdmi_phy_8996_reg_names[] = {
    748	"vddio",
    749	"vcca",
    750};
    751
    752static const char * const hdmi_phy_8996_clk_names[] = {
    753	"iface", "ref",
    754};
    755
    756const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
    757	.type = MSM_HDMI_PHY_8996,
    758	.reg_names = hdmi_phy_8996_reg_names,
    759	.num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
    760	.clk_names = hdmi_phy_8996_clk_names,
    761	.num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
    762};