From 4cdd0979ca6241bd664d3feb18ee96b0621f9978 Mon Sep 17 00:00:00 2001 From: Vinod Polimera Date: Tue, 3 Mar 2020 11:22:56 +0530 Subject: sc7180: Add display 10nm phy & pll programming support Adds basic headers as well as source required for display dsi 10nm phy & pll programming. Changes in V1: - add struct overlays to model hardware registers. - remove typedef structures. - remove dead code such as dual dsi,split config etc. Changes in V2: - remove panel related header files. - update the bitclock calculation using edid parameters. - add phy timing calculation function. - update copyright license. Changes in V3: - update the mdss clock structure. - remove dsi_phy_configinfo_type struct. - remove unused struct fields. Changes in V4: - update clock apis. - remove unused structures. Change-Id: I8ff400922ae594f558cf73a5aaa433a3a93347c2 Signed-off-by: Vinod Polimera Reviewed-on: https://review.coreboot.org/c/coreboot/+/39613 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/soc/qualcomm/sc7180/display/dsi_phy_pll.c | 148 ++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/soc/qualcomm/sc7180/display/dsi_phy_pll.c (limited to 'src/soc/qualcomm/sc7180/display/dsi_phy_pll.c') diff --git a/src/soc/qualcomm/sc7180/display/dsi_phy_pll.c b/src/soc/qualcomm/sc7180/display/dsi_phy_pll.c new file mode 100644 index 0000000000..b01fc2e436 --- /dev/null +++ b/src/soc/qualcomm/sc7180/display/dsi_phy_pll.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VCO_DELAY_USEC 1 + +/* Bit definition of SSC control registers */ +#define SSC_CENTER BIT(0) +#define SSC_EN BIT(1) + +struct dsi_pll_regs { + u32 pll_prop_gain_rate; + u32 decimal_div_start; + u32 frac_div_start_low; + u32 frac_div_start_mid; + u32 frac_div_start_high; + u32 pll_clock_inverters; +}; + +static void dsi_pll_init_val(void) +{ + write32(&phy_pll_qlink->pll_core_input_override, 0x10); + write32(&phy_pll_qlink->pll_int_loop_settings, 0x3f); + write32(&phy_pll_qlink->pll_int_loop_settings_two, 0x0); + write32(&phy_pll_qlink->pll_analog_ctrls_four, 0x0); + write32(&phy_pll_qlink->pll_int_loop_ctrls, 0x80); + write32(&phy_pll_qlink->pll_freq_update_ctrl_overrides, 0x0); + write32(&phy_pll_qlink->pll_band_sel_cal_timer_low, 0x0); + write32(&phy_pll_qlink->pll_band_sel_cal_timer_high, 0x02); + write32(&phy_pll_qlink->pll_band_sel_cal_settings, 0x82); + write32(&phy_pll_qlink->pll_band_sel_min, 0x00); + write32(&phy_pll_qlink->pll_band_sel_max, 0xff); + write32(&phy_pll_qlink->pll_band_sel_pfilt, 0x00); + write32(&phy_pll_qlink->pll_band_sel_ifilt, 0x00); + write32(&phy_pll_qlink->pll_band_sel_cal_settings_two, 0x25); + write32(&phy_pll_qlink->pll_band_sel_cal_settings_four, 0x4f); + write32(&phy_pll_qlink->pll_band_sel_icode_high, 0x0a); + write32(&phy_pll_qlink->pll_band_sel_icode_low, 0x0); + write32(&phy_pll_qlink->pll_pll_gain, 0x42); + write32(&phy_pll_qlink->pll_icode_low, 0x00); + write32(&phy_pll_qlink->pll_icode_high, 0x00); + write32(&phy_pll_qlink->pll_lockdet, 0x30); + write32(&phy_pll_qlink->pll_fastlock_ctrl, 0x04); + write32(&phy_pll_qlink->pll_pass_out_override_one, 0x00); + write32(&phy_pll_qlink->pll_pass_out_override_two, 0x00); + write32(&phy_pll_qlink->pll_rate_change, 0x01); + write32(&phy_pll_qlink->pll_digital_timers, 0x08); + write32(&phy_pll_qlink->pll_dec_frac_muxes, 0x00); + write32(&phy_pll_qlink->pll_mash_ctrl, 0x03); + write32(&phy_pll_qlink->pll_ssc_mux_ctrl, 0x0); + write32(&phy_pll_qlink->pll_ssc_ctrl, 0x0); + write32(&phy_pll_qlink->pll_pll_fastlock_en_band, 0x03); + write32(&phy_pll_qlink->pll_freq_tune_accum_init_mux, 0x0); + write32(&phy_pll_qlink->pll_lock_min_delay, 0x19); + write32(&phy_pll_qlink->pll_spare_and_jpc_overrides, 0x0); + write32(&phy_pll_qlink->pll_bias_ctrl_1, 0x40); + write32(&phy_pll_qlink->pll_bias_ctrl_2, 0x20); + write32(&phy_pll_qlink->pll_alog_obsv_bus_ctrl_1, 0x0); +} + +static void dsi_pll_calc_dec_frac(struct dsi_pll_regs *regs, + unsigned long rate) +{ + u32 frac_bits = 18; + u64 pll_freq; + u64 divider; + u64 dec, dec_multiple; + u32 frac; + u64 multiplier; + + pll_freq = rate; + divider = SRC_XO_HZ * 2; + + multiplier = 1 << frac_bits; + dec_multiple = (pll_freq * multiplier) / divider; + frac = dec_multiple % multiplier; + + dec = dec_multiple / multiplier; + if (pll_freq <= 1900UL * MHz) + regs->pll_prop_gain_rate = 8; + else if (pll_freq <= 3000UL * MHz) + regs->pll_prop_gain_rate = 10; + else + regs->pll_prop_gain_rate = 12; + + if (pll_freq < 1100UL * MHz) + regs->pll_clock_inverters = 8; + else + regs->pll_clock_inverters = 0; + + regs->decimal_div_start = dec; + regs->frac_div_start_low = (frac & 0xff); + regs->frac_div_start_mid = (frac & 0xff00) >> 8; + regs->frac_div_start_high = (frac & 0x30000) >> 16; +} + +static void dsi_pll_commit(struct dsi_pll_regs *reg) +{ + write32(&phy_pll_qlink->pll_core_input_override, 0x12); + write32(&phy_pll_qlink->pll_decimal_div_start_1, reg->decimal_div_start); + write32(&phy_pll_qlink->pll_frac_div_start_low1, reg->frac_div_start_low); + write32(&phy_pll_qlink->pll_frac_div_start_mid1, reg->frac_div_start_mid); + write32(&phy_pll_qlink->pll_frac_div_start_high1, reg->frac_div_start_high); + write32(&phy_pll_qlink->pll_lockdet_rate[0], 0x40); + write32(&phy_pll_qlink->pll_lock_delay, 0x06); + write32(&phy_pll_qlink->pll_cmode, 0x10); + write32(&phy_pll_qlink->pll_clock_inverters, reg->pll_clock_inverters); +} + +static void dsi_pll_config_hzindep_reg(struct dsi_pll_regs *reg) +{ + write32(&phy_pll_qlink->pll_analog_ctrls_one, 0x80); + write32(&phy_pll_qlink->pll_analog_ctrls_two, 0x03); + write32(&phy_pll_qlink->pll_analog_ctrls_three, 0x00); + write32(&phy_pll_qlink->pll_dsm_divider, 0x00); + write32(&phy_pll_qlink->pll_feedback_divider, 0x4e); + write32(&phy_pll_qlink->pll_cal_settings, 0x40); + write32(&phy_pll_qlink->pll_band_sel_cal_settings_three, 0xba); + write32(&phy_pll_qlink->pll_freq_detect_settings_one, 0x0c); + write32(&phy_pll_qlink->pll_outdiv, 0x00); + write32(&phy_pll_qlink->pll_core_override, 0x00); + write32(&phy_pll_qlink->pll_digital_timers_two, 0x08); + write32(&phy_pll_qlink->pll_prop_gain_rate[0], reg->pll_prop_gain_rate); + write32(&phy_pll_qlink->pll_band_set_rate[0], 0xc0); + write32(&phy_pll_qlink->pll_gain_ifilt_band[0], 0xfa); + write32(&phy_pll_qlink->pll_fl_int_gain_pfilt_band[0], 0x4c); + write32(&phy_pll_qlink->pll_lock_override, 0x80); + write32(&phy_pll_qlink->pll_pfilt, 0x29); + write32(&phy_pll_qlink->pll_ifilt, 0x3f); +} + +void dsi_phy_pll_vco_10nm_set_rate(unsigned long rate) +{ + struct dsi_pll_regs regs; + + dsi_pll_init_val(); + dsi_pll_calc_dec_frac(®s, rate); + dsi_pll_commit(®s); + dsi_pll_config_hzindep_reg(®s); +} -- cgit v1.2.3