summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c115
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll-8996.h13
-rw-r--r--drivers/clk/msm/mdss/mdss-pll.c10
-rw-r--r--drivers/clk/msm/mdss/mdss-pll.h3
4 files changed, 125 insertions, 16 deletions
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
index 10aa2bd16928..438bed4f7c03 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
@@ -26,6 +26,8 @@
#define DSI_PLL_POLL_TIMEOUT_US 1000
#define MSM8996_DSI_PLL_REVISION_2 2
+#define CEIL(x, y) (((x) + ((y)-1)) / (y))
+
int set_mdss_byte_mux_sel_8996(struct mux_clk *clk, int sel)
{
return 0;
@@ -303,12 +305,13 @@ static void dsi_pll_disable(struct clk *c)
return;
}
-static void mdss_dsi_pll_8996_input_init(struct dsi_pll_db *pdb)
+static void mdss_dsi_pll_8996_input_init(struct mdss_pll_resources *pll,
+ struct dsi_pll_db *pdb)
{
pdb->in.fref = 19200000; /* 19.2 Mhz*/
pdb->in.fdata = 0; /* bit clock rate */
pdb->in.dsiclk_sel = 1; /* 1, reg: 0x0014 */
- pdb->in.ssc_en = 0; /* 1, reg: 0x0494, bit 0 */
+ pdb->in.ssc_en = pll->ssc_en; /* 1, reg: 0x0494, bit 0 */
pdb->in.ldo_en = 0; /* 0, reg: 0x004c, bit 0 */
/* fixed input */
@@ -319,8 +322,8 @@ static void mdss_dsi_pll_8996_input_init(struct dsi_pll_db *pdb)
pdb->in.pll_wakeup_timer = 5; /* 5, reg: 0x043c, bit 0 - 2 */
pdb->in.plllock_cnt = 1; /* 1, reg: 0x0488, bit 1 - 2 */
pdb->in.plllock_rng = 0; /* 0, reg: 0x0488, bit 3 - 4 */
- pdb->in.ssc_center_spread = 0; /* 0, reg: 0x0494, bit 1 */
- pdb->in.ssc_adj_per = 37; /* 37, reg: 0x498, bit 0 - 9 */
+ pdb->in.ssc_center = pll->ssc_center;/* 0, reg: 0x0494, bit 1 */
+ pdb->in.ssc_adj_period = 37; /* 37, reg: 0x498, bit 0 - 9 */
pdb->in.ssc_spread = 5; /* 0.005, 5kppm */
pdb->in.ssc_freq = 31500; /* 31.5 khz */
@@ -342,8 +345,49 @@ static void mdss_dsi_pll_8996_input_init(struct dsi_pll_db *pdb)
pdb->in.pll_r3ctrl = 1; /* 1 */
}
-static void pll_8996_dec_frac_calc(struct dsi_pll_db *pdb,
- struct mdss_pll_resources *pll)
+static void pll_8996_ssc_calc(struct mdss_pll_resources *pll,
+ struct dsi_pll_db *pdb)
+{
+ u32 period, ssc_period;
+ u32 ref, rem;
+ s64 step_size;
+
+ pr_debug("%s: vco=%lld ref=%lld\n", __func__,
+ pll->vco_current_rate, pll->vco_ref_clk_rate);
+
+ ssc_period = pdb->in.ssc_freq / 500;
+ period = pll->vco_ref_clk_rate / 1000;
+ ssc_period = CEIL(period, ssc_period);
+ ssc_period -= 1;
+ pdb->out.ssc_period = ssc_period;
+
+ pr_debug("%s: ssc, freq=%d spread=%d period=%d\n", __func__,
+ pdb->in.ssc_freq, pdb->in.ssc_spread, pdb->out.ssc_period);
+
+ step_size = (u32)pll->vco_current_rate;
+ ref = pll->vco_ref_clk_rate;
+ ref /= 1000;
+ step_size = div_s64(step_size, ref);
+ step_size <<= 20;
+ step_size = div_s64(step_size, 1000);
+ step_size *= pdb->in.ssc_spread;
+ step_size = div_s64(step_size, 1000);
+ step_size *= (pdb->in.ssc_adj_period + 1);
+
+ rem = 0;
+ step_size = div_s64_rem(step_size, ssc_period + 1, &rem);
+ if (rem)
+ step_size++;
+
+ pr_debug("%s: step_size=%lld\n", __func__, step_size);
+
+ step_size &= 0x0ffff; /* take lower 16 bits */
+
+ pdb->out.ssc_step_size = step_size;
+}
+
+static void pll_8996_dec_frac_calc(struct mdss_pll_resources *pll,
+ struct dsi_pll_db *pdb)
{
struct dsi_pll_input *pin = &pdb->in;
struct dsi_pll_output *pout = &pdb->out;
@@ -438,9 +482,47 @@ static void pll_8996_calc_vco_count(struct dsi_pll_db *pdb,
pout->pll_kvco_code = 0;
}
-static void pll_db_commit_common(void __iomem *pll_base,
+static void pll_db_commit_ssc(struct mdss_pll_resources *pll,
+ struct dsi_pll_db *pdb)
+{
+ void __iomem *pll_base = pll->pll_base;
+ struct dsi_pll_input *pin = &pdb->in;
+ struct dsi_pll_output *pout = &pdb->out;
+ char data;
+
+ data = pin->ssc_adj_period;
+ data &= 0x0ff;
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER1, data);
+ data = (pin->ssc_adj_period >> 8);
+ data &= 0x03;
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER2, data);
+
+ data = pout->ssc_period;
+ data &= 0x0ff;
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER1, data);
+ data = (pout->ssc_period >> 8);
+ data &= 0x0ff;
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER2, data);
+
+ data = pout->ssc_step_size;
+ data &= 0x0ff;
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE1, data);
+ data = (pout->ssc_step_size >> 8);
+ data &= 0x0ff;
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE2, data);
+
+ data = (pin->ssc_center & 0x01);
+ data <<= 1;
+ data |= 0x01; /* enable */
+ MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_EN_CENTER, data);
+
+ wmb(); /* make sure register committed */
+}
+
+static void pll_db_commit_common(struct mdss_pll_resources *pll,
struct dsi_pll_db *pdb)
{
+ void __iomem *pll_base = pll->pll_base;
struct dsi_pll_input *pin = &pdb->in;
struct dsi_pll_output *pout = &pdb->out;
char data;
@@ -506,9 +588,10 @@ static void pll_db_commit_common(void __iomem *pll_base,
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_CRCTRL, data);
}
-static void pll_db_commit_8996(void __iomem *pll_base,
+static void pll_db_commit_8996(struct mdss_pll_resources *pll,
struct dsi_pll_db *pdb)
{
+ void __iomem *pll_base = pll->pll_base;
struct dsi_pll_input *pin = &pdb->in;
struct dsi_pll_output *pout = &pdb->out;
char data;
@@ -516,7 +599,7 @@ static void pll_db_commit_8996(void __iomem *pll_base,
data = pout->cmn_ldo_cntrl;
MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_LDO_CNTRL, data);
- pll_db_commit_common(pll_base, pdb);
+ pll_db_commit_common(pll, pdb);
/* de assert pll start and apply pll sw reset */
/* stop pll */
@@ -590,6 +673,9 @@ static void pll_db_commit_8996(void __iomem *pll_base,
data = (pout->pll_n1div | (pout->pll_n2div << 4));
MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CLK_CFG0, data);
+ if (pll->ssc_en)
+ pll_db_commit_ssc(pll, pdb);
+
wmb(); /* make sure register committed */
}
@@ -691,9 +777,12 @@ int pll_vco_set_rate_8996(struct clk *c, unsigned long rate)
pll->vco_current_rate = rate;
pll->vco_ref_clk_rate = vco->ref_clk_rate;
- mdss_dsi_pll_8996_input_init(pdb);
+ mdss_dsi_pll_8996_input_init(pll, pdb);
+
+ pll_8996_dec_frac_calc(pll, pdb);
- pll_8996_dec_frac_calc(pdb, pll);
+ if (pll->ssc_en)
+ pll_8996_ssc_calc(pll, pdb);
pll_8996_calc_vco_count(pdb, pll->vco_current_rate,
pll->vco_ref_clk_rate);
@@ -701,10 +790,10 @@ int pll_vco_set_rate_8996(struct clk *c, unsigned long rate)
/* commit slave if split display is enabled */
slave = pll->slave;
if (slave)
- pll_db_commit_8996(slave->pll_base, pdb);
+ pll_db_commit_8996(slave, pdb);
/* commit master itself */
- pll_db_commit_8996(pll->pll_base, pdb);
+ pll_db_commit_8996(pll, pdb);
mdss_pll_resource_enable(pll, false);
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8996.h b/drivers/clk/msm/mdss/mdss-dsi-pll-8996.h
index 94c50acfb771..e78184376cc4 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-8996.h
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8996.h
@@ -52,6 +52,13 @@
#define DSIPHY_PLL_PLLLOCK_CMP_EN 0x0488
#define DSIPHY_PLL_DEC_START 0x0490
+#define DSIPHY_PLL_SSC_EN_CENTER 0x0494
+#define DSIPHY_PLL_SSC_ADJ_PER1 0x0498
+#define DSIPHY_PLL_SSC_ADJ_PER2 0x049c
+#define DSIPHY_PLL_SSC_PER1 0x04a0
+#define DSIPHY_PLL_SSC_PER2 0x04a4
+#define DSIPHY_PLL_SSC_STEP_SIZE1 0x04a8
+#define DSIPHY_PLL_SSC_STEP_SIZE2 0x04ac
#define DSIPHY_PLL_DIV_FRAC_START1 0x04b4
#define DSIPHY_PLL_DIV_FRAC_START2 0x04b8
#define DSIPHY_PLL_DIV_FRAC_START3 0x04bc
@@ -85,8 +92,8 @@ struct dsi_pll_input {
u32 pll_wakeup_timer; /* 5, reg: 0x043c, bit 0 - 2 */
u32 plllock_cnt; /* 1, reg: 0x0488, bit 1 - 2 */
u32 plllock_rng; /* 1, reg: 0x0488, bit 3 - 4 */
- u32 ssc_center_spread; /* 0, reg: 0x0494, bit 1 */
- u32 ssc_adj_per; /* 37, reg: 0x498, bit 0 - 9 */
+ u32 ssc_center; /* 0, reg: 0x0494, bit 1 */
+ u32 ssc_adj_period; /* 37, reg: 0x498, bit 0 - 9 */
u32 ssc_spread; /* 0.005 */
u32 ssc_freq; /* unknown */
u32 pll_ie_trim; /* 4, reg: 0x0400 */
@@ -115,7 +122,7 @@ struct dsi_pll_output {
u32 pll_txclk_en; /* reg: 0x04c0 */
u32 dec_start; /* reg: 0x0490 */
u32 div_frac_start; /* reg: 0x04b4, 0x4b8, 0x04bc */
- u32 ssc_per; /* reg: 0x04a0, 0x04a4 */
+ u32 ssc_period; /* reg: 0x04a0, 0x04a4 */
u32 ssc_step_size; /* reg: 0x04a8, 0x04ac */
u32 plllock_cmp; /* reg: 0x047c, 0x0480, 0x0484 */
u32 pll_vco_div_ref; /* reg: 0x046c, 0x0470 */
diff --git a/drivers/clk/msm/mdss/mdss-pll.c b/drivers/clk/msm/mdss/mdss-pll.c
index bf118be406cb..81ae1defd29c 100644
--- a/drivers/clk/msm/mdss/mdss-pll.c
+++ b/drivers/clk/msm/mdss/mdss-pll.c
@@ -222,6 +222,16 @@ static int mdss_pll_probe(struct platform_device *pdev)
pll_res->index = 0;
}
+ pll_res->ssc_en = of_property_read_bool(pdev->dev.of_node,
+ "qcom,dsi-pll-ssc-en");
+
+ pll_res->ssc_center = false;
+
+ label = of_get_property(pdev->dev.of_node,
+ "qcom,dsi-pll-ssc-mode", NULL);
+ if (label && !strcmp(label, "center-spread"))
+ pll_res->ssc_center = true;
+
pll_base_reg = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "pll_base");
if (!pll_base_reg) {
diff --git a/drivers/clk/msm/mdss/mdss-pll.h b/drivers/clk/msm/mdss/mdss-pll.h
index 365c21d3f0ca..79eb5abeaa83 100644
--- a/drivers/clk/msm/mdss/mdss-pll.h
+++ b/drivers/clk/msm/mdss/mdss-pll.h
@@ -124,6 +124,9 @@ struct mdss_pll_resources {
*/
uint32_t index;
+ bool ssc_en; /* share pll with master */
+ bool ssc_center; /* default is down spread */
+
struct mdss_pll_resources *slave;
/*