clk: qcom: mdss: add dsi phy 12nm clock

Add clock tree and their corresponding clock
operations. Add corresponding devicetree bindings.

Change-Id: I042067a1ac5317edbdc73c8a64ae127ce6f5ff08
Signed-off-by: Venkata Prahlad Valluru <vvalluru@codeaurora.org>
tirimbino
Venkata Prahlad Valluru 5 years ago
parent e078309580
commit 1bc0f5d76d
  1. 5
      Documentation/devicetree/bindings/fb/mdss-pll.txt
  2. 2
      drivers/clk/qcom/mdss/Makefile
  3. 988
      drivers/clk/qcom/mdss/mdss-dsi-pll-12nm-util.c
  4. 723
      drivers/clk/qcom/mdss/mdss-dsi-pll-12nm.c
  5. 122
      drivers/clk/qcom/mdss/mdss-dsi-pll-12nm.h
  6. 5
      drivers/clk/qcom/mdss/mdss-dsi-pll.h
  7. 4
      drivers/clk/qcom/mdss/mdss-pll.c
  8. 1
      drivers/clk/qcom/mdss/mdss-pll.h
  9. 54
      include/dt-bindings/clock/mdss-12nm-pll-clk.h

@ -20,9 +20,8 @@ Required properties:
"qcom,mdss_dsi_pll_7nm", "qcom,mdss_dp_pll_7nm",
"qcom,mdss_dsi_pll_28lpm", "qcom,mdss_dsi_pll_14nm",
"qcom,mdss_dp_pll_14nm", "qcom,mdss_hdmi_pll_28lpm",
"qcom,mdss_dsi_pll_7nm_v2"
"qcom,mdss_dp_pll_sdm660",
"qcom,mdss_dsi_pll_sdm660"
"qcom,mdss_dsi_pll_7nm_v2", "qcom,mdss_dp_pll_sdm660",
"qcom,mdss_dsi_pll_sdm660", "qcom,mdss_dsi_pll_12nm"
- cell-index: Specifies the controller used
- reg: offset and length of the register set for the device.
- reg-names : names to refer to register sets related to this device

@ -12,3 +12,5 @@ obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm-util.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dp-pll-14nm.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-hdmi-pll-28lpm.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-12nm.o
obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-12nm-util.o

@ -0,0 +1,988 @@
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/iopoll.h>
#include <linux/delay.h>
#include "mdss-pll.h"
#include "mdss-dsi-pll.h"
#include "mdss-dsi-pll-12nm.h"
#define DSI_PLL_POLL_MAX_READS 15
#define DSI_PLL_POLL_TIMEOUT_US 1000
int pixel_div_set_div(void *context, unsigned int reg,
unsigned int div)
{
struct mdss_pll_resources *pll = context;
struct dsi_pll_db *pdb;
pdb = (struct dsi_pll_db *)pll->priv;
/* Programming during vco_prepare. Keep this value */
pdb->param.pixel_divhf = (div - 1);
pr_debug("ndx=%d div=%d divhf=%d\n",
pll->index, div, pdb->param.pixel_divhf);
return 0;
}
int pixel_div_get_div(void *context, unsigned int reg,
unsigned int *div)
{
int rc;
struct mdss_pll_resources *pll = context;
if (is_gdsc_disabled(pll))
return 0;
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("Failed to enable mdss dsi pll resources\n");
return rc;
}
*div = (MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SSC9) & 0x7F);
pr_debug("pixel_div = %d\n", (*div+1));
mdss_pll_resource_enable(pll, false);
return 0;
}
int set_post_div_mux_sel(void *context, unsigned int reg,
unsigned int sel)
{
struct mdss_pll_resources *pll = context;
struct dsi_pll_db *pdb;
pdb = (struct dsi_pll_db *)pll->priv;
/* Programming during vco_prepare. Keep this value */
pdb->param.post_div_mux = sel;
pr_debug("ndx=%d post_div_mux_sel=%d p_div=%d\n",
pll->index, sel, (u32) BIT(sel));
return 0;
}
int get_post_div_mux_sel(void *context, unsigned int reg,
unsigned int *sel)
{
u32 vco_cntrl = 0, cpbias_cntrl = 0;
int rc;
struct mdss_pll_resources *pll = context;
if (is_gdsc_disabled(pll))
return 0;
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("Failed to enable mdss dsi pll resources\n");
return rc;
}
vco_cntrl = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_PLL_VCO_CTRL);
vco_cntrl &= 0x30;
cpbias_cntrl = MDSS_PLL_REG_R(pll->pll_base,
DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL);
cpbias_cntrl = ((cpbias_cntrl >> 6) & 0x1);
if (cpbias_cntrl == 0) {
if (vco_cntrl == 0x00)
*sel = 0;
else if (vco_cntrl == 0x10)
*sel = 2;
else if (vco_cntrl == 0x20)
*sel = 3;
else if (vco_cntrl == 0x30)
*sel = 4;
} else if (cpbias_cntrl == 1) {
if (vco_cntrl == 0x30)
*sel = 2;
else if (vco_cntrl == 0x00)
*sel = 5;
}
mdss_pll_resource_enable(pll, false);
return 0;
}
int set_gp_mux_sel(void *context, unsigned int reg,
unsigned int sel)
{
struct mdss_pll_resources *pll = context;
struct dsi_pll_db *pdb;
pdb = (struct dsi_pll_db *)pll->priv;
/* Programming during vco_prepare. Keep this value */
pdb->param.gp_div_mux = sel;
pr_debug("ndx=%d gp_div_mux_sel=%d gp_cntrl=%d\n",
pll->index, sel, (u32) BIT(sel));
return 0;
}
int get_gp_mux_sel(void *context, unsigned int reg,
unsigned int *sel)
{
int rc;
struct mdss_pll_resources *pll = context;
u32 reg_val;
if (is_gdsc_disabled(pll))
return 0;
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("Failed to enable mdss dsi pll resources\n");
return rc;
}
reg_val = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_PLL_CTRL);
*sel = (reg_val >> 5) & 0x7;
pr_debug("gp_cntrl = %d\n", *sel);
mdss_pll_resource_enable(pll, false);
return 0;
}
static bool pll_is_pll_locked_12nm(struct mdss_pll_resources *pll,
bool is_handoff)
{
u32 status;
bool pll_locked;
/* poll for PLL ready status */
if (readl_poll_timeout_atomic((pll->pll_base +
DSIPHY_STAT0),
status,
((status & BIT(1)) > 0),
DSI_PLL_POLL_MAX_READS,
DSI_PLL_POLL_TIMEOUT_US)) {
if (!is_handoff)
pr_err("DSI PLL ndx=%d status=%x failed to Lock\n",
pll->index, status);
pll_locked = false;
} else {
pll_locked = true;
}
return pll_locked;
}
int dsi_pll_enable_seq_12nm(struct mdss_pll_resources *pll)
{
int rc = 0;
struct dsi_pll_db *pdb;
void __iomem *pll_base;
if (!pll) {
pr_err("Invalid PLL resources\n");
return -EINVAL;
}
pdb = (struct dsi_pll_db *)pll->priv;
if (!pdb) {
pr_err("No priv found\n");
return -EINVAL;
}
pll_base = pll->pll_base;
MDSS_PLL_REG_W(pll_base, DSIPHY_SYS_CTRL, 0x49);
wmb(); /* make sure register committed before enabling branch clocks */
udelay(5); /* h/w recommended delay */
MDSS_PLL_REG_W(pll_base, DSIPHY_SYS_CTRL, 0xc9);
wmb(); /* make sure register committed before enabling branch clocks */
udelay(50); /* h/w recommended delay */
if (!pll_is_pll_locked_12nm(pll, false)) {
pr_err("DSI PLL ndx=%d lock failed!\n",
pll->index);
rc = -EINVAL;
goto init_lock_err;
}
pr_debug("DSI PLL ndx:%d Locked!\n", pll->index);
init_lock_err:
return rc;
}
static int dsi_pll_enable(struct clk_hw *hw)
{
int i, rc = 0;
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
/* Try all enable sequences until one succeeds */
for (i = 0; i < vco->pll_en_seq_cnt; i++) {
rc = vco->pll_enable_seqs[i](pll);
pr_debug("DSI PLL %s after sequence #%d\n",
rc ? "unlocked" : "locked", i + 1);
if (!rc)
break;
}
if (rc)
pr_err("ndx=%d DSI PLL failed to lock\n", pll->index);
else
pll->pll_on = true;
return rc;
}
static int dsi_pll_relock(struct mdss_pll_resources *pll)
{
void __iomem *pll_base = pll->pll_base;
u32 data = 0;
int rc = 0;
data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_POWERUP_CTRL);
data &= ~BIT(1); /* remove ONPLL_OVR_EN bit */
data |= 0x1; /* set ONPLL_OVN to 0x1 */
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_POWERUP_CTRL, data);
ndelay(500); /* h/w recommended delay */
MDSS_PLL_REG_W(pll_base, DSIPHY_SYS_CTRL, 0x49);
wmb(); /* make sure register committed before enabling branch clocks */
udelay(5); /* h/w recommended delay */
MDSS_PLL_REG_W(pll_base, DSIPHY_SYS_CTRL, 0xc9);
wmb(); /* make sure register committed before enabling branch clocks */
udelay(50); /* h/w recommended delay */
if (!pll_is_pll_locked_12nm(pll, false)) {
pr_err("DSI PLL ndx=%d lock failed!\n",
pll->index);
rc = -EINVAL;
goto relock_err;
}
ndelay(50); /* h/w recommended delay */
data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_CTRL);
data |= 0x01; /* set CLK_SEL bits to 0x1 */
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data);
ndelay(500); /* h/w recommended delay */
wmb(); /* make sure register committed before enabling branch clocks */
pll->pll_on = true;
relock_err:
return rc;
}
static void dsi_pll_disable(struct clk_hw *hw)
{
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
void __iomem *pll_base = pll->pll_base;
u32 data = 0;
if (!pll->pll_on &&
mdss_pll_resource_enable(pll, true)) {
pr_err("Failed to enable mdss dsi pll=%d\n", pll->index);
return;
}
data = MDSS_PLL_REG_R(pll_base, DSIPHY_SSC0);
data &= ~BIT(6); /* disable GP_CLK_EN */
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC0, data);
ndelay(500); /* h/w recommended delay */
data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_CTRL);
data &= ~0x03; /* remove CLK_SEL bits */
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data);
ndelay(500); /* h/w recommended delay */
data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_POWERUP_CTRL);
data &= ~0x1; /* remove ONPLL_OVR bit */
data |= BIT(1); /* set ONPLL_OVR_EN to 0x1 */
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_POWERUP_CTRL, data);
ndelay(500); /* h/w recommended delay */
wmb(); /* make sure register committed before disabling branch clocks */
pll->handoff_resources = false;
mdss_pll_resource_enable(pll, false);
pll->pll_on = false;
pr_debug("DSI PLL ndx=%d Disabled\n", pll->index);
}
static u32 __mdss_dsi_get_hsfreqrange(u64 target_freq)
{
u64 bitclk_rate_mhz = div_u64((target_freq * 2), 1000000);
if (bitclk_rate_mhz >= 80 && bitclk_rate_mhz < 90)
return 0x00;
else if (bitclk_rate_mhz >= 90 && bitclk_rate_mhz < 100)
return 0x10;
else if (bitclk_rate_mhz >= 100 && bitclk_rate_mhz < 110)
return 0x20;
else if (bitclk_rate_mhz >= 110 && bitclk_rate_mhz < 120)
return 0x30;
else if (bitclk_rate_mhz >= 120 && bitclk_rate_mhz < 130)
return 0x01;
else if (bitclk_rate_mhz >= 130 && bitclk_rate_mhz < 140)
return 0x11;
else if (bitclk_rate_mhz >= 140 && bitclk_rate_mhz < 150)
return 0x21;
else if (bitclk_rate_mhz >= 150 && bitclk_rate_mhz < 160)
return 0x31;
else if (bitclk_rate_mhz >= 160 && bitclk_rate_mhz < 170)
return 0x02;
else if (bitclk_rate_mhz >= 170 && bitclk_rate_mhz < 180)
return 0x12;
else if (bitclk_rate_mhz >= 180 && bitclk_rate_mhz < 190)
return 0x22;
else if (bitclk_rate_mhz >= 190 && bitclk_rate_mhz < 205)
return 0x32;
else if (bitclk_rate_mhz >= 205 && bitclk_rate_mhz < 220)
return 0x03;
else if (bitclk_rate_mhz >= 220 && bitclk_rate_mhz < 235)
return 0x13;
else if (bitclk_rate_mhz >= 235 && bitclk_rate_mhz < 250)
return 0x23;
else if (bitclk_rate_mhz >= 250 && bitclk_rate_mhz < 275)
return 0x33;
else if (bitclk_rate_mhz >= 275 && bitclk_rate_mhz < 300)
return 0x04;
else if (bitclk_rate_mhz >= 300 && bitclk_rate_mhz < 325)
return 0x14;
else if (bitclk_rate_mhz >= 325 && bitclk_rate_mhz < 350)
return 0x25;
else if (bitclk_rate_mhz >= 350 && bitclk_rate_mhz < 400)
return 0x35;
else if (bitclk_rate_mhz >= 400 && bitclk_rate_mhz < 450)
return 0x05;
else if (bitclk_rate_mhz >= 450 && bitclk_rate_mhz < 500)
return 0x16;
else if (bitclk_rate_mhz >= 500 && bitclk_rate_mhz < 550)
return 0x26;
else if (bitclk_rate_mhz >= 550 && bitclk_rate_mhz < 600)
return 0x37;
else if (bitclk_rate_mhz >= 600 && bitclk_rate_mhz < 650)
return 0x07;
else if (bitclk_rate_mhz >= 650 && bitclk_rate_mhz < 700)
return 0x18;
else if (bitclk_rate_mhz >= 700 && bitclk_rate_mhz < 750)
return 0x28;
else if (bitclk_rate_mhz >= 750 && bitclk_rate_mhz < 800)
return 0x39;
else if (bitclk_rate_mhz >= 800 && bitclk_rate_mhz < 850)
return 0x09;
else if (bitclk_rate_mhz >= 850 && bitclk_rate_mhz < 900)
return 0x19;
else if (bitclk_rate_mhz >= 900 && bitclk_rate_mhz < 950)
return 0x29;
else if (bitclk_rate_mhz >= 950 && bitclk_rate_mhz < 1000)
return 0x3a;
else if (bitclk_rate_mhz >= 1000 && bitclk_rate_mhz < 1050)
return 0x0a;
else if (bitclk_rate_mhz >= 1050 && bitclk_rate_mhz < 1100)
return 0x1a;
else if (bitclk_rate_mhz >= 1100 && bitclk_rate_mhz < 1150)
return 0x2a;
else if (bitclk_rate_mhz >= 1150 && bitclk_rate_mhz < 1200)
return 0x3b;
else if (bitclk_rate_mhz >= 1200 && bitclk_rate_mhz < 1250)
return 0x0b;
else if (bitclk_rate_mhz >= 1250 && bitclk_rate_mhz < 1300)
return 0x1b;
else if (bitclk_rate_mhz >= 1300 && bitclk_rate_mhz < 1350)
return 0x2b;
else if (bitclk_rate_mhz >= 1350 && bitclk_rate_mhz < 1400)
return 0x3c;
else if (bitclk_rate_mhz >= 1400 && bitclk_rate_mhz < 1450)
return 0x0c;
else if (bitclk_rate_mhz >= 1450 && bitclk_rate_mhz < 1500)
return 0x1c;
else if (bitclk_rate_mhz >= 1500 && bitclk_rate_mhz < 1550)
return 0x2c;
else if (bitclk_rate_mhz >= 1550 && bitclk_rate_mhz < 1600)
return 0x3d;
else if (bitclk_rate_mhz >= 1600 && bitclk_rate_mhz < 1650)
return 0x0d;
else if (bitclk_rate_mhz >= 1650 && bitclk_rate_mhz < 1700)
return 0x1d;
else if (bitclk_rate_mhz >= 1700 && bitclk_rate_mhz < 1750)
return 0x2e;
else if (bitclk_rate_mhz >= 1750 && bitclk_rate_mhz < 1800)
return 0x3e;
else if (bitclk_rate_mhz >= 1800 && bitclk_rate_mhz < 1850)
return 0x0e;
else if (bitclk_rate_mhz >= 1850 && bitclk_rate_mhz < 1900)
return 0x1e;
else if (bitclk_rate_mhz >= 1900 && bitclk_rate_mhz < 1950)
return 0x2f;
else if (bitclk_rate_mhz >= 1950 && bitclk_rate_mhz < 2000)
return 0x3f;
else if (bitclk_rate_mhz >= 2000 && bitclk_rate_mhz < 2050)
return 0x0f;
else if (bitclk_rate_mhz >= 2050 && bitclk_rate_mhz < 2100)
return 0x40;
else if (bitclk_rate_mhz >= 2100 && bitclk_rate_mhz < 2150)
return 0x41;
else if (bitclk_rate_mhz >= 2150 && bitclk_rate_mhz < 2200)
return 0x42;
else if (bitclk_rate_mhz >= 2200 && bitclk_rate_mhz < 2250)
return 0x43;
else if (bitclk_rate_mhz >= 2250 && bitclk_rate_mhz < 2300)
return 0x44;
else if (bitclk_rate_mhz >= 2300 && bitclk_rate_mhz < 2350)
return 0x45;
else if (bitclk_rate_mhz >= 2350 && bitclk_rate_mhz < 2400)
return 0x46;
else if (bitclk_rate_mhz >= 2400 && bitclk_rate_mhz < 2450)
return 0x47;
else if (bitclk_rate_mhz >= 2450 && bitclk_rate_mhz < 2500)
return 0x48;
else
return 0x49;
}
static void __mdss_dsi_get_pll_vco_cntrl(u64 target_freq, u32 post_div_mux,
u32 *vco_cntrl, u32 *cpbias_cntrl)
{
u64 target_freq_mhz = div_u64(target_freq, 1000000);
u32 p_div = BIT(post_div_mux);
if (p_div == 1) {
*vco_cntrl = 0x00;
*cpbias_cntrl = 0;
} else if (p_div == 2) {
*vco_cntrl = 0x30;
*cpbias_cntrl = 1;
} else if (p_div == 4) {
*vco_cntrl = 0x10;
*cpbias_cntrl = 0;
} else if (p_div == 8) {
*vco_cntrl = 0x20;
*cpbias_cntrl = 0;
} else if (p_div == 16) {
*vco_cntrl = 0x30;
*cpbias_cntrl = 0;
} else {
*vco_cntrl = 0x00;
*cpbias_cntrl = 1;
}
if (target_freq_mhz <= 1250 && target_freq_mhz >= 1092)
*vco_cntrl = *vco_cntrl | 2;
else if (target_freq_mhz < 1092 && target_freq_mhz >= 950)
*vco_cntrl = *vco_cntrl | 3;
else if (target_freq_mhz < 950 && target_freq_mhz >= 712)
*vco_cntrl = *vco_cntrl | 1;
else if (target_freq_mhz < 712 && target_freq_mhz >= 546)
*vco_cntrl = *vco_cntrl | 2;
else if (target_freq_mhz < 546 && target_freq_mhz >= 475)
*vco_cntrl = *vco_cntrl | 3;
else if (target_freq_mhz < 475 && target_freq_mhz >= 356)
*vco_cntrl = *vco_cntrl | 1;
else if (target_freq_mhz < 356 && target_freq_mhz >= 273)
*vco_cntrl = *vco_cntrl | 2;
else if (target_freq_mhz < 273 && target_freq_mhz >= 237)
*vco_cntrl = *vco_cntrl | 3;
else if (target_freq_mhz < 237 && target_freq_mhz >= 178)
*vco_cntrl = *vco_cntrl | 1;
else if (target_freq_mhz < 178 && target_freq_mhz >= 136)
*vco_cntrl = *vco_cntrl | 2;
else if (target_freq_mhz < 136 && target_freq_mhz >= 118)
*vco_cntrl = *vco_cntrl | 3;
else if (target_freq_mhz < 118 && target_freq_mhz >= 89)
*vco_cntrl = *vco_cntrl | 1;
else if (target_freq_mhz < 89 && target_freq_mhz >= 68)
*vco_cntrl = *vco_cntrl | 2;
else if (target_freq_mhz < 68 && target_freq_mhz >= 57)
*vco_cntrl = *vco_cntrl | 3;
else if (target_freq_mhz < 57 && target_freq_mhz >= 44)
*vco_cntrl = *vco_cntrl | 1;
else
*vco_cntrl = *vco_cntrl | 2;
}
static u32 __mdss_dsi_get_osc_freq_target(u64 target_freq)
{
u64 target_freq_mhz = div_u64(target_freq, 1000000);
if (target_freq_mhz <= 1000)
return 1315;
else if (target_freq_mhz > 1000 && target_freq_mhz <= 1500)
return 1839;
else
return 0;
}
static u64 __mdss_dsi_pll_get_m_div(u64 vco_rate)
{
return div_u64((vco_rate * 4), 19200000);
}
static u32 __mdss_dsi_get_fsm_ovr_ctrl(u64 target_freq)
{
u64 bitclk_rate_mhz = div_u64((target_freq * 2), 1000000);
if (bitclk_rate_mhz > 1500 && bitclk_rate_mhz <= 2500)
return 0;
else
return BIT(6);
}
static void mdss_dsi_pll_12nm_calc_reg(struct mdss_pll_resources *pll,
struct dsi_pll_db *pdb)
{
struct dsi_pll_param *param = &pdb->param;
u64 target_freq = 0;
target_freq = div_u64(pll->vco_current_rate,
BIT(pdb->param.post_div_mux));
param->hsfreqrange = __mdss_dsi_get_hsfreqrange(target_freq);
__mdss_dsi_get_pll_vco_cntrl(target_freq, param->post_div_mux,
&param->vco_cntrl, &param->cpbias_cntrl);
param->osc_freq_target = __mdss_dsi_get_osc_freq_target(target_freq);
param->m_div = (u32) __mdss_dsi_pll_get_m_div(pll->vco_current_rate);
param->fsm_ovr_ctrl = __mdss_dsi_get_fsm_ovr_ctrl(target_freq);
param->prop_cntrl = 0x05;
param->int_cntrl = 0x00;
param->gmp_cntrl = 0x1;
}
static u32 __mdss_dsi_get_multi_intX100(u64 vco_rate, u32 *rem)
{
u32 reminder = 0;
u64 temp = 0;
const u32 ref_clk_rate = 19200000, quarterX100 = 25;
temp = div_u64_rem(vco_rate, ref_clk_rate, &reminder);
temp *= 100;
/*
* Multiplication integer needs to be floored in steps of 0.25
* Hence multi_intX100 needs to be rounded off in steps of 25
*/
if (reminder < (ref_clk_rate / 4)) {
*rem = reminder;
return temp;
} else if ((reminder >= (ref_clk_rate / 4)) &&
reminder < (ref_clk_rate / 2)) {
*rem = (reminder - (ref_clk_rate / 4));
return (temp + quarterX100);
} else if ((reminder >= (ref_clk_rate / 2)) &&
(reminder < ((3 * ref_clk_rate) / 4))) {
*rem = (reminder - (ref_clk_rate / 2));
return (temp + (quarterX100 * 2));
}
*rem = (reminder - ((3 * ref_clk_rate) / 4));
return (temp + (quarterX100 * 3));
}
static u32 __calc_gcd(u32 num1, u32 num2)
{
if (num2 != 0)
return __calc_gcd(num2, (num1 % num2));
else
return num1;
}
static void mdss_dsi_pll_12nm_calc_ssc(struct mdss_pll_resources *pll,
struct dsi_pll_db *pdb)
{
struct dsi_pll_param *param = &pdb->param;
u64 multi_intX100 = 0, temp = 0;
u32 temp_rem1 = 0, temp_rem2 = 0;
const u64 power_2_17 = 131072, power_2_10 = 1024;
const u32 ref_clk_rate = 19200000;
multi_intX100 = __mdss_dsi_get_multi_intX100(pll->vco_current_rate,
&temp_rem1);
/* Calculation for mpll_ssc_peak_i */
temp = (multi_intX100 * pll->ssc_ppm * power_2_17);
temp = div_u64(temp, 100); /* 100 div for multi_intX100 */
param->mpll_ssc_peak_i =
(u32) div_u64(temp, 1000000); /*10^6 for SSC PPM */
/* Calculation for mpll_stepsize_i */
param->mpll_stepsize_i = (u32) div_u64((param->mpll_ssc_peak_i *
pll->ssc_freq * power_2_10), ref_clk_rate);
/* Calculation for mpll_mint_i */
param->mpll_mint_i = (u32) (div_u64((multi_intX100 * 4), 100) - 32);
/* Calculation for mpll_frac_den */
param->mpll_frac_den = (u32) div_u64(ref_clk_rate,
__calc_gcd((u32)pll->vco_current_rate, ref_clk_rate));
/* Calculation for mpll_frac_quot_i */
temp = (temp_rem1 * power_2_17);
param->mpll_frac_quot_i =
(u32) div_u64_rem(temp, ref_clk_rate, &temp_rem2);
/* Calculation for mpll_frac_rem */
param->mpll_frac_rem = (u32) div_u64(((u64)temp_rem2 *
param->mpll_frac_den), ref_clk_rate);
pr_debug("mpll_ssc_peak_i=%d mpll_stepsize_i=%d mpll_mint_i=%d\n",
param->mpll_ssc_peak_i, param->mpll_stepsize_i,
param->mpll_mint_i);
pr_debug("mpll_frac_den=%d mpll_frac_quot_i=%d mpll_frac_rem=%d",
param->mpll_frac_den, param->mpll_frac_quot_i,
param->mpll_frac_rem);
}
static void pll_db_commit_12nm_ssc(struct mdss_pll_resources *pll,
struct dsi_pll_db *pdb)
{
void __iomem *pll_base = pll->pll_base;
struct dsi_pll_param *param = &pdb->param;
char data = 0;
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC0, 0x27);
data = (param->mpll_mint_i & 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC7, data);
data = ((param->mpll_mint_i & 0xff00) >> 8);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC8, data);
data = (param->mpll_ssc_peak_i & 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC1, data);
data = ((param->mpll_ssc_peak_i & 0xff00) >> 8);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC2, data);
data = ((param->mpll_ssc_peak_i & 0xf0000) >> 16);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC3, data);
data = (param->mpll_stepsize_i & 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC4, data);
data = ((param->mpll_stepsize_i & 0xff00) >> 8);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC5, data);
data = ((param->mpll_stepsize_i & 0x1f0000) >> 16);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC6, data);
data = (param->mpll_frac_quot_i & 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC10, data);
data = ((param->mpll_frac_quot_i & 0xff00) >> 8);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC11, data);
data = (param->mpll_frac_rem & 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC12, data);
data = ((param->mpll_frac_rem & 0xff00) >> 8);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC13, data);
data = (param->mpll_frac_den & 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC14, data);
data = ((param->mpll_frac_den & 0xff00) >> 8);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC15, data);
}
static void pll_db_commit_12nm(struct mdss_pll_resources *pll,
struct dsi_pll_db *pdb)
{
void __iomem *pll_base = pll->pll_base;
struct dsi_pll_param *param = &pdb->param;
char data = 0;
MDSS_PLL_REG_W(pll_base, DSIPHY_CTRL0, 0x01);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, 0x05);
MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_LOOP_CTRL, 0x01);
data = ((param->hsfreqrange & 0x7f) | BIT(7));
MDSS_PLL_REG_W(pll_base, DSIPHY_HS_FREQ_RAN_SEL, data);
data = ((param->vco_cntrl & 0x3f) | BIT(6));
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_CTRL, data);
data = (param->osc_freq_target & 0x7f);
MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_0, data);
data = ((param->osc_freq_target & 0xf80) >> 7);
MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_1, data);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_INPUT_LOOP_DIV_RAT_CTRL, 0x30);
data = (param->m_div & 0x3f);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOOP_DIV_RATIO_0, data);
data = ((param->m_div & 0xfc0) >> 6);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOOP_DIV_RATIO_1, data);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_INPUT_DIV_PLL_OVR, 0x60);
data = (param->prop_cntrl & 0x3f);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PROP_CHRG_PUMP_CTRL, data);
data = (param->int_cntrl & 0x3f);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_INTEG_CHRG_PUMP_CTRL, data);
data = ((param->gmp_cntrl & 0x3) << 4);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_GMP_CTRL_DIG_TST, data);
data = ((param->cpbias_cntrl & 0x1) << 6) | BIT(4);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL, data);
data = ((param->gp_div_mux & 0x7) << 5) | 0x5;
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data);
data = (param->pixel_divhf & 0x7f);
MDSS_PLL_REG_W(pll_base, DSIPHY_SSC9, data);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_ANA_PROG_CTRL, 0x03);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_ANA_TST_LOCK_ST_OVR_CTRL, 0x50);
MDSS_PLL_REG_W(pll_base,
DSIPHY_SLEWRATE_FSM_OVR_CTRL, param->fsm_ovr_ctrl);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PHA_ERR_CTRL_0, 0x01);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PHA_ERR_CTRL_1, 0x00);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOCK_FILTER, 0xff);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_UNLOCK_FILTER, 0x03);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PRO_DLY_RELOCK, 0x0c);
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOCK_DET_MODE_SEL, 0x02);
if (pll->ssc_en)
pll_db_commit_12nm_ssc(pll, pdb);
pr_debug("pll:%d\n", pll->index);
wmb(); /* make sure register committed before preparing the clocks */
}
int pll_vco_set_rate_12nm(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int rc = 0;
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
struct dsi_pll_db *pdb;
pdb = (struct dsi_pll_db *)pll->priv;
if (!pdb) {
pr_err("pll pdb not found\n");
rc = -EINVAL;
goto error;
}
pr_debug("%s: ndx=%d rate=%lu\n", __func__, pll->index, rate);
pll->vco_current_rate = rate;
pll->vco_ref_clk_rate = vco->ref_clk_rate;
error:
return rc;
}
static unsigned long pll_vco_get_rate_12nm(struct clk_hw *hw)
{
u64 vco_rate = 0;
u32 m_div_5_0 = 0, m_div_11_6 = 0, m_div = 0;
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
u64 ref_clk = vco->ref_clk_rate;
int rc;
struct mdss_pll_resources *pll = vco->priv;
if (is_gdsc_disabled(pll))
return 0;
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("Failed to enable mdss dsi pll=%d\n", pll->index);
return rc;
}
m_div_5_0 = MDSS_PLL_REG_R(pll->pll_base,
DSIPHY_PLL_LOOP_DIV_RATIO_0);
m_div_5_0 &= 0x3f;
pr_debug("m_div_5_0 = 0x%x\n", m_div_5_0);
m_div_11_6 = MDSS_PLL_REG_R(pll->pll_base,
DSIPHY_PLL_LOOP_DIV_RATIO_1);
m_div_11_6 &= 0x3f;
pr_debug("m_div_11_6 = 0x%x\n", m_div_11_6);
m_div = ((m_div_11_6 << 6) | (m_div_5_0));
vco_rate = div_u64((ref_clk * m_div), 4);
pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
mdss_pll_resource_enable(pll, false);
return (unsigned long)vco_rate;
}
long pll_vco_round_rate_12nm(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned long rrate = rate;
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
if (rate < vco->min_rate)
rrate = vco->min_rate;
if (rate > vco->max_rate)
rrate = vco->max_rate;
*parent_rate = rrate;
return rrate;
}
unsigned long vco_12nm_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
unsigned long rate = 0;
int rc;
if (!pll && is_gdsc_disabled(pll)) {
pr_err("gdsc disabled\n");
return 0;
}
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("Failed to enable mdss dsi pll=%d\n", pll->index);
return 0;
}
if (pll_is_pll_locked_12nm(pll, true)) {
pll->handoff_resources = true;
pll->pll_on = true;
rate = pll_vco_get_rate_12nm(hw);
} else {
mdss_pll_resource_enable(pll, false);
}
return rate;
}
int pll_vco_prepare_12nm(struct clk_hw *hw)
{
int rc = 0;
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
struct dsi_pll_db *pdb;
u32 data = 0;
if (!pll) {
pr_err("Dsi pll resources are not available\n");
return -EINVAL;
}
pdb = (struct dsi_pll_db *)pll->priv;
if (!pdb) {
pr_err("No prov found\n");
return -EINVAL;
}
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("ndx=%d Failed to enable mdss dsi pll resources\n",
pll->index);
return rc;
}
if ((pll->vco_cached_rate != 0)
&& (pll->vco_cached_rate == clk_hw_get_rate(hw))) {
rc = hw->init->ops->set_rate(hw, pll->vco_cached_rate,
pll->vco_cached_rate);
if (rc) {
pr_err("index=%d vco_set_rate failed. rc=%d\n",
pll->index, rc);
goto error;
}
}
/*
* For cases where DSI PHY is already enabled like:
* 1.) LP-11 during static screen
* 2.) ULPS during static screen
* 3.) Boot up with cont splash enabled where PHY is programmed in LK
* Execute the Re-lock sequence to enable the DSI PLL.
*/
data = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SYS_CTRL);
if (data & BIT(7)) {
rc = dsi_pll_relock(pll);
if (rc)
goto error;
else
goto end;
}
mdss_dsi_pll_12nm_calc_reg(pll, pdb);
if (pll->ssc_en)
mdss_dsi_pll_12nm_calc_ssc(pll, pdb);
/* commit DSI vco */
pll_db_commit_12nm(pll, pdb);
rc = dsi_pll_enable(hw);
error:
if (rc) {
mdss_pll_resource_enable(pll, false);
pr_err("ndx=%d failed to enable dsi pll\n", pll->index);
}
end:
return rc;
}
void pll_vco_unprepare_12nm(struct clk_hw *hw)
{
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
if (!pll) {
pr_err("Dsi pll resources are not available\n");
return;
}
pll->vco_cached_rate = clk_hw_get_rate(hw);
dsi_pll_disable(hw);
}
int pll_vco_enable_12nm(struct clk_hw *hw)
{
struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
struct mdss_pll_resources *pll = vco->priv;
u32 data = 0;
if (!pll) {
pr_err("Dsi pll resources are not available\n");
return -EINVAL;
}
if (!pll->pll_on) {
pr_err("DSI PLL not enabled, return\n");
return -EINVAL;
}
data = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SSC0);
data |= BIT(6); /* enable GP_CLK_EN */
MDSS_PLL_REG_W(pll->pll_base, DSIPHY_SSC0, data);
wmb(); /* make sure register committed before enabling branch clocks */
return 0;
}

@ -0,0 +1,723 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/iopoll.h>
#include <linux/delay.h>
#include "mdss-dsi-pll.h"
#include "mdss-pll.h"
#include <dt-bindings/clock/mdss-12nm-pll-clk.h>
#include "mdss-dsi-pll-12nm.h"
#define VCO_DELAY_USEC 1
static struct regmap_config dsi_pll_12nm_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x800,
};
static const struct clk_ops clk_ops_vco_12nm = {
.recalc_rate = vco_12nm_recalc_rate,
.set_rate = pll_vco_set_rate_12nm,
.round_rate = pll_vco_round_rate_12nm,
.prepare = pll_vco_prepare_12nm,
.unprepare = pll_vco_unprepare_12nm,
};
static struct regmap_bus pclk_div_regmap_bus = {
.reg_write = pixel_div_set_div,
.reg_read = pixel_div_get_div,
};
static struct regmap_bus post_div_mux_regmap_bus = {
.reg_write = set_post_div_mux_sel,
.reg_read = get_post_div_mux_sel,
};
static struct regmap_bus gp_div_mux_regmap_bus = {
.reg_write = set_gp_mux_sel,
.reg_read = get_gp_mux_sel,
};
/*
* Clock tree model for generating DSI byte clock and pclk for 12nm DSI PLL
*
*
* +---------------+
* +----------| vco_clk |----------+
* | +---------------+ |
* | |
* | |
* | |
* +---------+---------+----+----+---------+---------+ |
* | | | | | | |
* | | | | | | |
* | | | | | | |
* +---v---+ +---v---+ +---v---+ +---v---+ +---v---+ +---v---+ |
* | DIV(1)| | DIV(2)| | DIV(4)| | DIV(8)| |DIV(16)| |DIV(32)| |
* +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |
* | | | | | | |
* | | +---+ +---+ | | |
* | +-----------+ | | +-----------+ | |
* +-------------------+ | | | | +-------------------+ |
* | | | | | | |
* +--v-v-v-v-v-v---+ |
* \ post_div_mux / |
* \ / |
* +-----+----+ +---------------------+
* | |
* +------------------------+ |
* | |
* +----v----+ +---------+---------+----+----+---------+---------+
* | DIV-4 | | | | | | |
* +----+----+ | | | | | |
* | +---v---+ +---v---+ +---v---+ +---v---+ +---v---+ +---v---+
* | | DIV(1)| | DIV(2)| | DIV(4)| | DIV(8)| |DIV(16)| |DIV(32)|
* | +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+
* | | | | | | |
* v | | +---+ +---+ | |
* byte_clk_src | +-----------+ | | +-----------+ |
* +-------------------+ | | | | +-------------------+
* | | | | | |
* +--v-v-v-v-v-v---+
* \ gp_cntrl_mux /
* \ /
* +-----+----+
* |
* |
* +-------v-------+
* | (DIV + 1) |
* | DIV = 0...127 |
* +-------+-------+
* |
* |
* v
* dsi_pclk input to Clock Controller MND
*/
static struct dsi_pll_db pll_db[DSI_PLL_MAX];
static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
.ref_clk_rate = 19200000UL,
.min_rate = 1000000000UL,
.max_rate = 2000000000UL,
.pll_en_seq_cnt = 1,
.pll_enable_seqs[0] = dsi_pll_enable_seq_12nm,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_vco_clk",
.parent_names = (const char *[]){"bi_tcxo"},
.num_parents = 1,
.ops = &clk_ops_vco_12nm,
.flags = CLK_GET_RATE_NOCACHE,
},
};
static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
.ref_clk_rate = 19200000UL,
.min_rate = 1000000000UL,
.max_rate = 2000000000UL,
.pll_en_seq_cnt = 1,
.pll_enable_seqs[0] = dsi_pll_enable_seq_12nm,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_vco_clk",
.parent_names = (const char *[]){"bi_tcxo"},
.num_parents = 1,
.ops = &clk_ops_vco_12nm,
.flags = CLK_GET_RATE_NOCACHE,
},
};
static struct clk_fixed_factor dsi0pll_post_div1 = {
.div = 1,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div1",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_post_div2 = {
.div = 2,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div2",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_post_div4 = {
.div = 4,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div4",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_post_div8 = {
.div = 8,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div8",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_post_div16 = {
.div = 16,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div16",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_post_div32 = {
.div = 32,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div32",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_regmap_mux dsi0pll_post_div_mux = {
.reg = DSIPHY_PLL_VCO_CTRL,
.shift = 4,
.width = 2,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_div_mux",
.parent_names = (const char *[]){"dsi0pll_post_div1",
"dsi0pll_post_div2",
"dsi0pll_post_div4",
"dsi0pll_post_div8",
"dsi0pll_post_div16",
"dsi0pll_post_div32"},
.num_parents = 6,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_mux_closest_ops,
},
},
};
static struct clk_fixed_factor dsi1pll_post_div1 = {
.div = 1,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div1",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_post_div2 = {
.div = 2,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div2",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_post_div4 = {
.div = 4,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div4",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_post_div8 = {
.div = 8,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div8",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_post_div16 = {
.div = 16,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div16",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_post_div32 = {
.div = 32,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div32",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_regmap_mux dsi1pll_post_div_mux = {
.reg = DSIPHY_PLL_VCO_CTRL,
.shift = 4,
.width = 2,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_div_mux",
.parent_names = (const char *[]){"dsi1pll_post_div1",
"dsi1pll_post_div2",
"dsi1pll_post_div4",
"dsi1pll_post_div8",
"dsi1pll_post_div16",
"dsi1pll_post_div32"},
.num_parents = 6,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_mux_closest_ops,
},
},
};
static struct clk_fixed_factor dsi0pll_gp_div1 = {
.div = 1,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div1",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_gp_div2 = {
.div = 2,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div2",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_gp_div4 = {
.div = 4,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div4",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_gp_div8 = {
.div = 8,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div8",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_gp_div16 = {
.div = 16,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div16",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi0pll_gp_div32 = {
.div = 32,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div32",
.parent_names = (const char *[]){"dsi0pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_regmap_mux dsi0pll_gp_div_mux = {
.reg = DSIPHY_PLL_CTRL,
.shift = 5,
.width = 3,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_gp_div_mux",
.parent_names = (const char *[]){"dsi0pll_gp_div1",
"dsi0pll_gp_div2",
"dsi0pll_gp_div4",
"dsi0pll_gp_div8",
"dsi0pll_gp_div16",
"dsi0pll_gp_div32"},
.num_parents = 6,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_mux_closest_ops,
},
},
};
static struct clk_fixed_factor dsi1pll_gp_div1 = {
.div = 1,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div1",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_gp_div2 = {
.div = 2,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div2",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_gp_div4 = {
.div = 4,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div4",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_gp_div8 = {
.div = 8,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div8",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_gp_div16 = {
.div = 16,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div16",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_gp_div32 = {
.div = 32,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div32",
.parent_names = (const char *[]){"dsi1pll_vco_clk"},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_regmap_mux dsi1pll_gp_div_mux = {
.reg = DSIPHY_PLL_CTRL,
.shift = 5,
.width = 3,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_gp_div_mux",
.parent_names = (const char *[]){"dsi1pll_gp_div1",
"dsi1pll_gp_div2",
"dsi1pll_gp_div4",
"dsi1pll_gp_div8",
"dsi1pll_gp_div16",
"dsi1pll_gp_div32"},
.num_parents = 6,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_mux_closest_ops,
},
},
};
static struct clk_regmap_div dsi0pll_pclk_src = {
.reg = DSIPHY_SSC9,
.shift = 0,
.width = 6,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_pclk_src",
.parent_names = (const char *[]){
"dsi0pll_gp_div_mux"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_div_ops,
},
},
};
static struct clk_regmap_div dsi1pll_pclk_src = {
.reg = DSIPHY_SSC9,
.shift = 0,
.width = 6,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_pclk_src",
.parent_names = (const char *[]){
"dsi1pll_gp_div_mux"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_div_ops,
},
},
};
static struct clk_fixed_factor dsi0pll_byte_clk_src = {
.div = 4,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_byte_clk_src",
.parent_names = (const char *[]){"dsi0pll_post_div_mux"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_fixed_factor dsi1pll_byte_clk_src = {
.div = 4,
.mult = 1,
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_byte_clk_src",
.parent_names = (const char *[]){"dsi1pll_post_div_mux"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_fixed_factor_ops,
},
};
static struct clk_hw *mdss_dsi_pllcc_12nm[] = {
[VCO_CLK_0] = &dsi0pll_vco_clk.hw,
[POST_DIV1_0_CLK] = &dsi0pll_post_div1.hw,
[POST_DIV2_0_CLK] = &dsi0pll_post_div2.hw,
[POST_DIV4_0_CLK] = &dsi0pll_post_div4.hw,
[POST_DIV8_0_CLK] = &dsi0pll_post_div8.hw,
[POST_DIV16_0_CLK] = &dsi0pll_post_div16.hw,
[POST_DIV32_0_CLK] = &dsi0pll_post_div32.hw,
[POST_DIV_MUX_0_CLK] = &dsi0pll_post_div_mux.clkr.hw,
[GP_DIV1_0_CLK] = &dsi0pll_gp_div1.hw,
[GP_DIV2_0_CLK] = &dsi0pll_gp_div2.hw,
[GP_DIV4_0_CLK] = &dsi0pll_gp_div4.hw,
[GP_DIV8_0_CLK] = &dsi0pll_gp_div8.hw,
[GP_DIV16_0_CLK] = &dsi0pll_gp_div16.hw,
[GP_DIV32_0_CLK] = &dsi0pll_gp_div32.hw,
[GP_DIV_MUX_0_CLK] = &dsi0pll_gp_div_mux.clkr.hw,
[PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src.clkr.hw,
[BYTE_CLK_SRC_0_CLK] = &dsi0pll_byte_clk_src.hw,
[VCO_CLK_1] = &dsi1pll_vco_clk.hw,
[POST_DIV1_1_CLK] = &dsi1pll_post_div1.hw,
[POST_DIV2_1_CLK] = &dsi1pll_post_div2.hw,
[POST_DIV4_1_CLK] = &dsi1pll_post_div4.hw,
[POST_DIV8_1_CLK] = &dsi1pll_post_div8.hw,
[POST_DIV16_1_CLK] = &dsi1pll_post_div16.hw,
[POST_DIV32_1_CLK] = &dsi1pll_post_div32.hw,
[POST_DIV_MUX_1_CLK] = &dsi1pll_post_div_mux.clkr.hw,
[GP_DIV1_1_CLK] = &dsi1pll_gp_div1.hw,
[GP_DIV2_1_CLK] = &dsi1pll_gp_div2.hw,
[GP_DIV4_1_CLK] = &dsi1pll_gp_div4.hw,
[GP_DIV8_1_CLK] = &dsi1pll_gp_div8.hw,
[GP_DIV16_1_CLK] = &dsi1pll_gp_div16.hw,
[GP_DIV32_1_CLK] = &dsi1pll_gp_div32.hw,
[GP_DIV_MUX_1_CLK] = &dsi1pll_gp_div_mux.clkr.hw,
[PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src.clkr.hw,
[BYTE_CLK_SRC_1_CLK] = &dsi1pll_byte_clk_src.hw,
};
int dsi_pll_clock_register_12nm(struct platform_device *pdev,
struct mdss_pll_resources *pll_res)
{
int rc = 0, ndx, i;
struct clk *clk;
struct clk_onecell_data *clk_data;
int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_12nm);
struct regmap *rmap;
struct dsi_pll_db *pdb;
if (!pdev || !pdev->dev.of_node ||
!pll_res || !pll_res->pll_base || !pll_res->phy_base) {
pr_err("Invalid params\n");
return -EINVAL;
}
ndx = pll_res->index;
if (ndx >= DSI_PLL_MAX) {
pr_err("pll index(%d) NOT supported\n", ndx);
return -EINVAL;
}
pdb = &pll_db[ndx];
pll_res->priv = pdb;
pll_res->vco_delay = VCO_DELAY_USEC;
pdb->pll = pll_res;
ndx++;
ndx %= DSI_PLL_MAX;
pdb->next = &pll_db[ndx];
clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks *
sizeof(struct clk *)), GFP_KERNEL);
if (!clk_data->clks) {
devm_kfree(&pdev->dev, clk_data);
return -ENOMEM;
}
clk_data->clk_num = num_clks;
/* Establish client data */
if (ndx == 0) {
rmap = devm_regmap_init(&pdev->dev, &post_div_mux_regmap_bus,
pll_res, &dsi_pll_12nm_config);
dsi0pll_post_div_mux.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &gp_div_mux_regmap_bus,
pll_res, &dsi_pll_12nm_config);
dsi0pll_gp_div_mux.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &pclk_div_regmap_bus,
pll_res, &dsi_pll_12nm_config);
dsi0pll_pclk_src.clkr.regmap = rmap;
dsi0pll_vco_clk.priv = pll_res;
for (i = VCO_CLK_0; i <= BYTE_CLK_SRC_0_CLK; i++) {
clk = devm_clk_register(&pdev->dev,
mdss_dsi_pllcc_12nm[i]);
if (IS_ERR(clk)) {
pr_err("clk registration failed for DSI clock:%d\n",
pll_res->index);
rc = -EINVAL;
goto clk_register_fail;
}
clk_data->clks[i] = clk;
}
rc = of_clk_add_provider(pdev->dev.of_node,
of_clk_src_onecell_get, clk_data);
} else {
rmap = devm_regmap_init(&pdev->dev, &post_div_mux_regmap_bus,
pll_res, &dsi_pll_12nm_config);
dsi1pll_post_div_mux.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &gp_div_mux_regmap_bus,
pll_res, &dsi_pll_12nm_config);
dsi1pll_gp_div_mux.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &pclk_div_regmap_bus,
pll_res, &dsi_pll_12nm_config);
dsi1pll_pclk_src.clkr.regmap = rmap;
dsi1pll_vco_clk.priv = pll_res;
for (i = VCO_CLK_1; i <= BYTE_CLK_SRC_1_CLK; i++) {
clk = devm_clk_register(&pdev->dev,
mdss_dsi_pllcc_12nm[i]);
if (IS_ERR(clk)) {
pr_err("clk registration failed for DSI clock:%d\n",
pll_res->index);
rc = -EINVAL;
goto clk_register_fail;
}
clk_data->clks[i] = clk;
}
rc = of_clk_add_provider(pdev->dev.of_node,
of_clk_src_onecell_get, clk_data);
}
if (!rc) {
pr_info("Registered DSI PLL ndx=%d, clocks successfully", ndx);
return rc;
}
clk_register_fail:
devm_kfree(&pdev->dev, clk_data->clks);
devm_kfree(&pdev->dev, clk_data);
return rc;
}

@ -0,0 +1,122 @@
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef MDSS_DSI_PLL_12NM_H
#define MDSS_DSI_PLL_12NM_H
#define DSIPHY_PLL_POWERUP_CTRL 0x034
#define DSIPHY_PLL_PROP_CHRG_PUMP_CTRL 0x038
#define DSIPHY_PLL_INTEG_CHRG_PUMP_CTRL 0x03c
#define DSIPHY_PLL_ANA_TST_LOCK_ST_OVR_CTRL 0x044
#define DSIPHY_PLL_VCO_CTRL 0x048
#define DSIPHY_PLL_GMP_CTRL_DIG_TST 0x04c
#define DSIPHY_PLL_PHA_ERR_CTRL_0 0x050
#define DSIPHY_PLL_LOCK_FILTER 0x054
#define DSIPHY_PLL_UNLOCK_FILTER 0x058
#define DSIPHY_PLL_INPUT_DIV_PLL_OVR 0x05c
#define DSIPHY_PLL_LOOP_DIV_RATIO_0 0x060
#define DSIPHY_PLL_INPUT_LOOP_DIV_RAT_CTRL 0x064
#define DSIPHY_PLL_PRO_DLY_RELOCK 0x06c
#define DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL 0x070
#define DSIPHY_PLL_LOCK_DET_MODE_SEL 0x074
#define DSIPHY_PLL_ANA_PROG_CTRL 0x07c
#define DSIPHY_HS_FREQ_RAN_SEL 0x110
#define DSIPHY_SLEWRATE_FSM_OVR_CTRL 0x280
#define DSIPHY_SLEWRATE_DDL_LOOP_CTRL 0x28c
#define DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_0 0x290
#define DSIPHY_PLL_PHA_ERR_CTRL_1 0x2e4
#define DSIPHY_PLL_LOOP_DIV_RATIO_1 0x2e8
#define DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_1 0x328
#define DSIPHY_SSC0 0x394
#define DSIPHY_SSC7 0x3b0
#define DSIPHY_SSC8 0x3b4
#define DSIPHY_SSC1 0x398
#define DSIPHY_SSC2 0x39c
#define DSIPHY_SSC3 0x3a0
#define DSIPHY_SSC4 0x3a4
#define DSIPHY_SSC5 0x3a8
#define DSIPHY_SSC6 0x3ac
#define DSIPHY_SSC10 0x360
#define DSIPHY_SSC11 0x364
#define DSIPHY_SSC12 0x368
#define DSIPHY_SSC13 0x36c
#define DSIPHY_SSC14 0x370
#define DSIPHY_SSC15 0x374
#define DSIPHY_SSC7 0x3b0
#define DSIPHY_SSC8 0x3b4
#define DSIPHY_SSC9 0x3b8
#define DSIPHY_STAT0 0x3e0
#define DSIPHY_CTRL0 0x3e8
#define DSIPHY_SYS_CTRL 0x3f0
#define DSIPHY_PLL_CTRL 0x3f8
struct dsi_pll_param {
u32 hsfreqrange;
u32 vco_cntrl;
u32 osc_freq_target;
u32 m_div;
u32 prop_cntrl;
u32 int_cntrl;
u32 gmp_cntrl;
u32 cpbias_cntrl;
/* mux and dividers */
u32 gp_div_mux;
u32 post_div_mux;
u32 pixel_divhf;
u32 fsm_ovr_ctrl;
/* ssc_params */
u32 mpll_ssc_peak_i;
u32 mpll_stepsize_i;
u32 mpll_mint_i;
u32 mpll_frac_den;
u32 mpll_frac_quot_i;
u32 mpll_frac_rem;
};
enum {
DSI_PLL_0,
DSI_PLL_1,
DSI_PLL_MAX
};
struct dsi_pll_db {
struct dsi_pll_db *next;
struct mdss_pll_resources *pll;
struct dsi_pll_param param;
};
int pll_vco_set_rate_12nm(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
long pll_vco_round_rate_12nm(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate);
unsigned long vco_12nm_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate);
int pll_vco_prepare_12nm(struct clk_hw *hw);
void pll_vco_unprepare_12nm(struct clk_hw *hw);
int pll_vco_enable_12nm(struct clk_hw *hw);
int pixel_div_set_div(void *context, unsigned int reg,
unsigned int div);
int pixel_div_get_div(void *context, unsigned int reg,
unsigned int *div);
int set_post_div_mux_sel(void *context, unsigned int reg,
unsigned int sel);
int get_post_div_mux_sel(void *context, unsigned int reg,
unsigned int *sel);
int set_gp_mux_sel(void *context, unsigned int reg,
unsigned int sel);
int get_gp_mux_sel(void *context, unsigned int reg,
unsigned int *sel);
int dsi_pll_enable_seq_12nm(struct mdss_pll_resources *pll);
#endif /* MDSS_DSI_PLL_12NM_H */

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -48,6 +48,9 @@ int dsi_pll_clock_register_7nm(struct platform_device *pdev,
struct mdss_pll_resources *pll_res);
int dsi_pll_clock_register_28lpm(struct platform_device *pdev,
struct mdss_pll_resources *pll_res);
int dsi_pll_clock_register_12nm(struct platform_device *pdev,
struct mdss_pll_resources *pll_res);
static inline struct dsi_pll_vco_clk *to_vco_clk_hw(struct clk_hw *hw)
{

@ -196,6 +196,9 @@ static int mdss_pll_clock_register(struct platform_device *pdev,
case MDSS_HDMI_PLL_28LPM:
rc = hdmi_pll_clock_register_28lpm(pdev, pll_res);
break;
case MDSS_DSI_PLL_12NM:
rc = dsi_pll_clock_register_12nm(pdev, pll_res);
break;
case MDSS_UNKNOWN_PLL:
default:
rc = -EINVAL;
@ -434,6 +437,7 @@ static const struct of_device_id mdss_pll_dt_match[] = {
{.compatible = "qcom,mdss_dp_pll_14nm"},
{.compatible = "qcom,mdss_hdmi_pll_28lpm"},
{.compatible = "qcom,mdss_dsi_pll_sdm660"},
{.compatible = "qcom,mdss_dsi_pll_12nm"},
{}
};

@ -52,6 +52,7 @@ enum {
MDSS_DSI_PLL_14NM,
MDSS_DP_PLL_14NM,
MDSS_HDMI_PLL_28LPM,
MDSS_DSI_PLL_12NM,
MDSS_UNKNOWN_PLL,
};

@ -0,0 +1,54 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MDSS_10NM_PLL_CLK_H
#define __MDSS_10NM_PLL_CLK_H
/* DSI PLL clocks */
#define VCO_CLK_0 0
#define POST_DIV1_0_CLK 1
#define POST_DIV2_0_CLK 2
#define POST_DIV4_0_CLK 3
#define POST_DIV8_0_CLK 4
#define POST_DIV16_0_CLK 5
#define POST_DIV32_0_CLK 6
#define POST_DIV_MUX_0_CLK 7
#define GP_DIV1_0_CLK 8
#define GP_DIV2_0_CLK 9
#define GP_DIV4_0_CLK 10
#define GP_DIV8_0_CLK 11
#define GP_DIV16_0_CLK 12
#define GP_DIV32_0_CLK 13
#define GP_DIV_MUX_0_CLK 14
#define PCLK_SRC_MUX_0_CLK 15
#define BYTE_CLK_SRC_0_CLK 16
#define VCO_CLK_1 17
#define POST_DIV1_1_CLK 18
#define POST_DIV2_1_CLK 19
#define POST_DIV4_1_CLK 20
#define POST_DIV8_1_CLK 21
#define POST_DIV16_1_CLK 22
#define POST_DIV32_1_CLK 23
#define POST_DIV_MUX_1_CLK 24
#define GP_DIV1_1_CLK 25
#define GP_DIV2_1_CLK 26
#define GP_DIV4_1_CLK 27
#define GP_DIV8_1_CLK 28
#define GP_DIV16_1_CLK 29
#define GP_DIV32_1_CLK 30
#define GP_DIV_MUX_1_CLK 31
#define PCLK_SRC_MUX_1_CLK 32
#define BYTE_CLK_SRC_1_CLK 33
#endif
Loading…
Cancel
Save