static int vco_set_rate_lpm(struct clk *c, unsigned long rate)
{
	int rc;
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	struct mdss_pll_resources *dsi_pll_res = vco->priv;

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return rc;
	}

	/*
	 * DSI PLL software reset. Add HW recommended delays after toggling
	 * the software reset bit off and back on.
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
	udelay(1000);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
	udelay(1000);

	rc = vco_set_rate(vco, rate);

	mdss_pll_resource_enable(dsi_pll_res, false);
	return rc;
}
static int gf_1_dsi_pll_enable_seq_8916(struct mdss_pll_resources *dsi_pll_res)
{
	int pll_locked = 0;

	dsi_pll_sw_reset_8916(dsi_pll_res);
	/*
	 * GF PART 1 PLL power up sequence.
	 * Add necessary delays recommended by hardware.
	 */

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x14);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
	udelay(3);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
	udelay(500);

	dsi_pll_toggle_lock_detect_8916(dsi_pll_res);

	pll_locked = dsi_pll_check_lock_status_8916(dsi_pll_res);
	return pll_locked ? 0 : -EINVAL;
}
static int dsi_pll_enable_seq_e(struct mdss_pll_resources *dsi_pll_res)
{
	int pll_locked = 0;

	dsi_pll_software_reset(dsi_pll_res);

	/*
	 * Add hardware recommended delays between register writes for
	 * the updates to take effect. These delays are necessary for the
	 * PLL to successfully lock
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
	udelay(50);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
	udelay(200);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
	udelay(200);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
	udelay(1);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
	udelay(600);

	dsi_pll_toggle_lock_detect(dsi_pll_res);
	pll_locked = dsi_pll_lock_status(dsi_pll_res);
	pr_debug("PLL status = %s\n", pll_locked ? "Locked" : "Unlocked");

	return pll_locked ? 0 : -EINVAL;
}
static void dsi_pll_toggle_lock_detect(struct mdss_pll_resources *dsi_pll_res)
{
	MDSS_PLL_REG_W(dsi_pll_res->pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
		0x0d);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
		0x0c);
	udelay(1);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
		0x0d);
}
static void dsi_pll_toggle_lock_detect_8916(
				struct mdss_pll_resources *dsi_pll_res)
{
	/* DSI PLL toggle lock detect setting */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05);
	udelay(512);
}
static void dsi_pll_sw_reset_8916(struct mdss_pll_resources *dsi_pll_res)
{
	/*
	 * DSI PLL software reset. Add HW recommended delays after toggling
	 * the software reset bit off and back on.
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
}
static int hdmi_20nm_vco_enable(struct clk *c)
{
    u32 ready_poll;
    u32 time_out_loop;
    /* Hardware recommended timeout iterator */
    u32 time_out_max = 50000;

    struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c);
    struct mdss_pll_resources *io = vco->priv;

    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x00000000);
    udelay(1);
    mb();
    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x00000003);
    udelay(1);
    mb();
    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x00000009);
    udelay(1);
    mb();

    /* Poll for C_READY and PHY READY */
    pr_debug("%s: Waiting for PHY Ready\n", __func__);
    time_out_loop = 0;
    do {
        ready_poll = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_RESET_SM);
        time_out_loop++;
        udelay(1);
    } while (((ready_poll  & (1 << 6)) == 0) &&
             (time_out_loop < time_out_max));
    if (time_out_loop >= time_out_max)
        pr_err("%s: ERROR: TIMED OUT BEFORE C READY\n", __func__);
    else
        pr_debug("%s: C READY\n", __func__);

    /* Poll for PHY READY */
    pr_debug("%s: Waiting for PHY Ready\n", __func__);
    time_out_loop = 0;
    do {
        ready_poll = MDSS_PLL_REG_R(io->phy_base, HDMI_PHY_STATUS);
        time_out_loop++;
        udelay(1);
    } while (((ready_poll & 0x1) == 0) && (time_out_loop < time_out_max));

    if (time_out_loop >= time_out_max)
        pr_err("%s: TIMED OUT BEFORE PHY READY\n", __func__);
    else
        pr_debug("%s: HDMI PHY READY\n", __func__);

    io->pll_on = true;

    return 0;
}
static void dsi_pll_software_reset(struct mdss_pll_resources *dsi_pll_res)
{
	/*
	 * Add HW recommended delays after toggling the software
	 * reset bit off and back on.
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
	udelay(1);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
	udelay(1);
}
static void hdmi_20nm_phy_pll_calc_settings(struct mdss_pll_resources *io,
        struct hdmi_pll_vco_clk *vco, u32 vco_clk, u32 tmds_clk)
{
    u32 val = 0;
    u64 dec_start_val, frac_start_val, pll_lock_cmp;

    /* Calculate decimal and fractional values */
    dec_start_val = 1000000UL * vco_clk;
    do_div(dec_start_val, HDMI_PLL_REF_CLK_RATE);
    do_div(dec_start_val, 2U);
    frac_start_val = dec_start_val;
    do_div(frac_start_val, HDMI_PLL_DIVISOR_32);
    do_div(frac_start_val, HDMI_PLL_DIVISOR_32);
    frac_start_val *= HDMI_PLL_DIVISOR;
    frac_start_val = dec_start_val - frac_start_val;
    frac_start_val *= (u64)(2 << 19);
    do_div(frac_start_val, HDMI_PLL_DIVISOR_32);
    do_div(frac_start_val, HDMI_PLL_DIVISOR_32);
    pll_lock_cmp = dec_start_val;
    do_div(pll_lock_cmp, 10U);
    pll_lock_cmp *= 0x800;
    do_div(pll_lock_cmp, HDMI_PLL_DIVISOR_32);
    do_div(pll_lock_cmp, HDMI_PLL_DIVISOR_32);
    pll_lock_cmp -= 1U;
    do_div(dec_start_val, HDMI_PLL_DIVISOR_32);
    do_div(dec_start_val, HDMI_PLL_DIVISOR_32);

    /* PLL loop bandwidth */
    val = hdmi_20nm_phy_pll_vco_reg_val(vco->ip_seti, tmds_clk);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_IP_SETI, val);
    val = hdmi_20nm_phy_pll_vco_reg_val(vco->cp_seti, tmds_clk);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CP_SETI, val);
    val = hdmi_20nm_phy_pll_vco_reg_val(vco->cp_setp, tmds_clk);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CP_SETP, val);
    val = hdmi_20nm_phy_pll_vco_reg_val(vco->ip_setp, tmds_clk);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_IP_SETP, val);
    val = hdmi_20nm_phy_pll_vco_reg_val(vco->crctrl, tmds_clk);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CRCTRL, val);

    /* PLL calibration */
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START1,
                   0x80 | (frac_start_val & 0x7F));
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START2,
                   0x80 | ((frac_start_val >> 7) & 0x7F));
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START3,
                   0x40 | ((frac_start_val >> 14) & 0x3F));
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEC_START1,
                   0x80 | (dec_start_val & 0x7F));
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEC_START2,
                   0x02 | (0x01 & dec_start_val >> 7));
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP1,
                   pll_lock_cmp & 0xFF);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP2,
                   (pll_lock_cmp >> 8) & 0xFF);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP3,
                   (pll_lock_cmp >> 16) & 0xFF);
}
int set_byte_mux_sel(struct mux_clk *clk, int sel)
{
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	pr_debug("byte mux set to %s mode\n", sel ? "indirect" : "direct");
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, (sel << 1));

	return 0;
}
static int dsi_pll_enable_seq_8916(struct mdss_pll_resources *dsi_pll_res)
{
	int pll_locked = 0;

	/*
	 * DSI PLL software reset. Add HW recommended delays after toggling
	 * the software reset bit off and back on.
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);

	/*
	 * PLL power up sequence.
	 * Add necessary delays recommended by hardware.
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
	ndelay(500);

	/* DSI PLL toggle lock detect setting */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04);
	ndelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05);
	udelay(512);

	pll_locked = dsi_pll_lock_status(dsi_pll_res);

	if (pll_locked)
		pr_debug("PLL Locked\n");
	else
		pr_err("PLL failed to lock\n");

	return pll_locked ? 0 : -EINVAL;
}
static int dsi_pll_enable_seq(struct mdss_pll_resources *dsi_pll_res)
{
	int rc = 0;

	/*
	 * PLL power up sequence
	 * Add necessary delays recommended by hardware
	 */

	/* DSI Uniphy lock detect setting */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
	/* DSI Uniphy PLL Calibration setting */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
	/* DSI Uniphy PLL lock detect mcnt */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG0, 0x10);
	/* DSI Uniphy PLL lock detect wait time */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG1, 0x1a);
	/* make sure the above register writes happen */
	wmb();
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
	/* make sure the above register writes happen */
	wmb();
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
	udelay(3);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
	udelay(3);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
	udelay(500);

	if (!dsi_pll_lock_status(dsi_pll_res)) {
		pr_err("DSI PLL lock failed\n");
		rc = -EINVAL;
	} else {
		pr_debug("DSI PLL Lock success\n");
	}

	return rc;
}
예제 #13
0
static int analog_set_div(struct div_clk *clk, int div)
{
	int rc;
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return rc;
	}

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, div - 1);

	mdss_pll_resource_enable(dsi_pll_res, false);
	return rc;
}
static int dsi_pll_enable_seq_m(struct mdss_pll_resources *dsi_pll_res)
{
	int i = 0;
	int pll_locked = 0;

	dsi_pll_software_reset(dsi_pll_res);

	/*
	 * Add hardware recommended delays between register writes for
	 * the updates to take effect. These delays are necessary for the
	 * PLL to successfully lock
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
	udelay(200);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
	udelay(200);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
	udelay(600);

	dsi_pll_toggle_lock_detect(dsi_pll_res);
	pll_locked = dsi_pll_lock_status(dsi_pll_res);
	for (i = 0; (i < DSI_PLL_SEQ_M_MAX_COUNTER) && !pll_locked; i++) {
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
		udelay(50);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
		udelay(100);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
		udelay(600);
		dsi_pll_toggle_lock_detect(dsi_pll_res);
		pll_locked = dsi_pll_lock_status(dsi_pll_res);
	}

	if (pll_locked)
		pr_debug("PLL Locked at attempt #%d\n", i);
	else
		pr_debug("PLL failed to lock after %d attempt(s)\n", i);

	return pll_locked ? 0 : -EINVAL;
}
예제 #15
0
int set_byte_mux_sel(struct mux_clk *clk, int sel)
{
	int rc;
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return rc;
	}

	pr_debug("byte mux set to %s mode\n", sel ? "indirect" : "direct");
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, (sel << 1));

	mdss_pll_resource_enable(dsi_pll_res, false);
	return 0;
}
예제 #16
0
static void dsi_pll_disable(struct clk *c)
{
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	struct mdss_pll_resources *dsi_pll_res = vco->priv;

	if (!dsi_pll_res->pll_on &&
		mdss_pll_resource_enable(dsi_pll_res, true)) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return;
	}

	dsi_pll_res->handoff_resources = false;

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00);

	mdss_pll_resource_enable(dsi_pll_res, false);
	dsi_pll_res->pll_on = false;

	pr_debug("DSI PLL Disabled\n");
	return;
}
static u32 hdmi_20nm_phy_pll_set_clk_rate(struct clk *c, u32 tmds_clk)
{
    u32 tx_band = 0;

    struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c);
    struct mdss_pll_resources *io = vco->priv;
    u64 vco_clk = tmds_clk;

    while (vco_clk > 0 && vco_clk < HDMI_PLL_MIN_VCO_CLK) {
        tx_band++;
        vco_clk *= 2;
    }

    /* Initially shut down PHY */
    pr_debug("%s: Disabling PHY\n", __func__);
    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x0);
    udelay(1000);
    mb();

    /* power-up and recommended common block settings */
    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x1F);
    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x01);
    udelay(1000);
    mb();

    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x07);
    udelay(1000);
    mb();

    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x05);
    udelay(1000);
    mb();

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x42);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_VCOTAIL_EN, 0x03);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_MODE, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_IE_TRIM, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_IP_TRIM, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CNTRL, 0x07);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_PHSEL_CONTROL, 0x04);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_IPTAT_TRIM_VCCA_TX_SEL, 0xA0);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_PHSEL_DC, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CORE_CLK_IN_SYNC_SEL, 0x00);

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_BKG_KVCO_CAL_EN, 0x00);

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x0F);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL1, 0x01);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL2, 0x01);

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYSCLK_EN_SEL_TXBAND,
                   0x4A + (0x10 * tx_band));

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG1, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG2, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BGTC, 0xFF);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_TEST_UPDN, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_VCO_TUNE, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_AMP_OS, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_EN_CENTER, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_UP, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_DN, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_KVCO_CODE,
                   tmds_clk > 300000000 ? 0x3F : 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_KVCO_COUNT1,
                   tmds_clk > 300000000 ? 0x00 : 0x8A);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_REF1, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_REF2,
                   tmds_clk > 300000000 ? 0x00 : 0x01);


    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_KVCO_CAL_CNTRL,
                   tmds_clk > 300000000 ? 0x00 : 0x1F);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG3,
                   tmds_clk > 300000000 ? 0x00 : 0x40);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG4, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG5, 0x10);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESETSM_CNTRL,
                   tmds_clk > 300000000 ? 0x80 : 0x00);

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_CAL_CSR, 0x77);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_TRIM_EN_VCOCALDONE, 0x00);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_RXTXEPCLK_EN, 0x0C);

    hdmi_20nm_phy_pll_calc_settings(io, vco, vco_clk, tmds_clk);

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP_EN, 0x11);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CNTRL, 0x07);

    /* Resistor calibration linear search */
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_START_SEG1, 0x60);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_START_SEG2, 0x60);
    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_TRIM_CONTROL, 0x01);

    MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESETSM_CNTRL2, 0x07);

    udelay(1000);
    mb();

    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_MODE, tx_band);

    /* TX lanes (transceivers) power-up sequence */
    MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_CLKBUF_ENABLE, 0x03);
    MDSS_PLL_REG_W(io->pll_base + 0x600, QSERDES_TX_L1_CLKBUF_ENABLE, 0x03);
    MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_CLKBUF_ENABLE, 0x03);
    MDSS_PLL_REG_W(io->pll_base + 0xA00, QSERDES_TX_L3_CLKBUF_ENABLE, 0x03);

    MDSS_PLL_REG_W(io->pll_base + 0x400,
                   QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03);
    MDSS_PLL_REG_W(io->pll_base + 0x600,
                   QSERDES_TX_L1_TRAN_DRVR_EMP_EN, 0x03);
    MDSS_PLL_REG_W(io->pll_base + 0x800,
                   QSERDES_TX_L2_TRAN_DRVR_EMP_EN, 0x03);
    MDSS_PLL_REG_W(io->pll_base + 0xA00,
                   QSERDES_TX_L3_TRAN_DRVR_EMP_EN, 0x03);

    MDSS_PLL_REG_W(io->pll_base + 0x400,
                   QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    , 0x6F);
    MDSS_PLL_REG_W(io->pll_base + 0x600,
                   QSERDES_TX_L1_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    , 0x6F);
    MDSS_PLL_REG_W(io->pll_base + 0x800,
                   QSERDES_TX_L2_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    , 0x6F);
    MDSS_PLL_REG_W(io->pll_base + 0xA00,
                   QSERDES_TX_L3_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    , 0x6F);

    MDSS_PLL_REG_W(io->pll_base + 0x400,
                   QSERDES_TX_L0_TX_EMP_POST1_LVL, 0x0000002F);
    MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TXCAL_CFG0, 0x000000AF);

    MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_VMODE_CTRL1, 0x08);
    MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_VMODE_CTRL1, 0x09);
    MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_VMODE_CTRL5, 0xA0);
    MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_VMODE_CTRL6, 0x01);
    MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_VMODE_CTRL5, 0xA0);
    MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_VMODE_CTRL6, 0x01);

    MDSS_PLL_REG_W(io->pll_base + 0x400,
                   QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40);
    MDSS_PLL_REG_W(io->pll_base + 0x400,
                   QSERDES_TX_L0_TX_INTERFACE_MODE, 0x00);
    MDSS_PLL_REG_W(io->pll_base + 0x600,
                   QSERDES_TX_L1_PARRATE_REC_DETECT_IDLE_EN, 0x40);
    MDSS_PLL_REG_W(io->pll_base + 0x600,
                   QSERDES_TX_L1_TX_INTERFACE_MODE, 0x00);
    MDSS_PLL_REG_W(io->pll_base + 0x800,
                   QSERDES_TX_L2_PARRATE_REC_DETECT_IDLE_EN, 0x40);
    MDSS_PLL_REG_W(io->pll_base + 0x800,
                   QSERDES_TX_L2_TX_INTERFACE_MODE, 0x00);
    MDSS_PLL_REG_W(io->pll_base + 0xA00,
                   QSERDES_TX_L3_PARRATE_REC_DETECT_IDLE_EN, 0x40);
    MDSS_PLL_REG_W(io->pll_base + 0xA00,
                   QSERDES_TX_L3_TX_INTERFACE_MODE, 0x00);

    return 0;
}
예제 #18
0
static int vco_set_rate(struct clk *c, unsigned long rate)
{
	s64 vco_clk_rate = rate;
	s32 rem;
	s64 refclk_cfg, frac_n_mode, ref_doubler_en_b;
	s64 ref_clk_to_pll, div_fbx1000, frac_n_value;
	s64 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
	s64 gen_vco_clk, cal_cfg10, cal_cfg11;
	u32 res;
	int i, rc;
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	struct mdss_pll_resources *dsi_pll_res = vco->priv;

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return rc;
	}

	/* Configure the Loop filter resistance */
	for (i = 0; i < vco->lpfr_lut_size; i++)
		if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate)
			break;
	if (i == vco->lpfr_lut_size) {
		pr_err("unable to get loop filter resistance. vco=%ld\n", rate);
		rc = -EINVAL;
		goto error;
	}
	res = vco->lpfr_lut[i].r;
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, res);

	/* Loop filter capacitance values : c1 and c2 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15);

	div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem);
	if (rem) {
		refclk_cfg = 0x1;
		frac_n_mode = 1;
		ref_doubler_en_b = 0;
	} else {
		refclk_cfg = 0x0;
		frac_n_mode = 0;
		ref_doubler_en_b = 1;
	}

	pr_debug("refclk_cfg = %lld\n", refclk_cfg);

	ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (refclk_cfg))
			  + (ref_doubler_en_b * vco->ref_clk_rate));
	div_fbx1000 = div_s64((vco_clk_rate * 1000), ref_clk_to_pll);

	div_s64_rem(div_fbx1000, 1000, &rem);
	frac_n_value = div_s64((rem * (1 << 16)), 1000);
	gen_vco_clk = div_s64(div_fbx1000 * ref_clk_to_pll, 1000);

	pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll);
	pr_debug("div_fb = %lld\n", div_fbx1000);
	pr_debug("frac_n_value = %lld\n", frac_n_value);

	pr_debug("Generated VCO Clock: %lld\n", gen_vco_clk);
	rem = 0;
	if (frac_n_mode) {
		sdm_cfg0 = (0x0 << 5);
		sdm_cfg0 |= (0x0 & 0x3f);
		sdm_cfg1 = (div_s64(div_fbx1000, 1000) & 0x3f) - 1;
		sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem);
		sdm_cfg2 = rem;
	} else {
		sdm_cfg0 = (0x1 << 5);
		sdm_cfg0 |= (div_s64(div_fbx1000, 1000) & 0x3f) - 1;
		sdm_cfg1 = (0x0 & 0x3f);
		sdm_cfg2 = 0;
		sdm_cfg3 = 0;
	}

	pr_debug("sdm_cfg0=%lld\n", sdm_cfg0);
	pr_debug("sdm_cfg1=%lld\n", sdm_cfg1);
	pr_debug("sdm_cfg2=%lld\n", sdm_cfg2);
	pr_debug("sdm_cfg3=%lld\n", sdm_cfg3);

	cal_cfg11 = div_s64_rem(gen_vco_clk, 256 * 1000000, &rem);
	cal_cfg10 = rem / 1000000;
	pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", cal_cfg10, cal_cfg11);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, (u32)(sdm_cfg1 & 0xff));
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, (u32)(sdm_cfg2 & 0xff));
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, (u32)(sdm_cfg3 & 0xff));
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00);

	/* Add hardware recommended delay for correct PLL configuration */
	udelay(1);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, (u32)refclk_cfg);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, (u32)sdm_cfg0);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, (u32)(cal_cfg10 & 0xff));
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, (u32)(cal_cfg11 & 0xff));
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20);

error:
	mdss_pll_resource_enable(dsi_pll_res, false);
	return rc;
}
예제 #19
0
static int dsi_pll_enable_seq_8974(struct mdss_pll_resources *dsi_pll_res)
{
	int i, rc = 0;
	u32 max_reads, timeout_us;
	int pll_locked;

	dsi_pll_software_reset(dsi_pll_res);

	/*
	 * PLL power up sequence.
	 * Add necessary delays recommeded by hardware.
	 */
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
	udelay(1);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
	udelay(200);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
	udelay(500);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
	udelay(500);

	for (i = 0; i < 2; i++) {
		udelay(100);
		/* DSI Uniphy lock detect setting */
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0c);
		udelay(100);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
				DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
		/* poll for PLL ready status */
		max_reads = 5;
		timeout_us = 100;

		pll_locked = dsi_pll_lock_status(dsi_pll_res);
		if (pll_locked)
			break;

		dsi_pll_software_reset(dsi_pll_res);
		/*
		 * PLL power up sequence.
		 * Add necessary delays recommeded by hardware.
		 */
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x1);
		udelay(1);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x5);
		udelay(200);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x7);
		udelay(250);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x5);
		udelay(200);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x7);
		udelay(500);
		MDSS_PLL_REG_W(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0xf);
		udelay(500);

	}

	if (!pll_locked) {
		pr_err("DSI PLL lock failed\n");
		rc = -EINVAL;
	} else {
		pr_debug("DSI PLL Lock success\n");
	}

	return rc;
}