diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-12-18 14:48:01 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-12-18 14:48:01 -0800 |
| commit | 2d28ff09533427b3fc0b9651eff8c1d936f2cfb4 (patch) | |
| tree | 33afe4d672e31712e4d087dc5c5fd5d27581f976 | |
| parent | 4d86efbfe8d21ec46c88477249108fb67b673ce2 (diff) | |
| parent | 6a21dcc9bf61ffbb511b7d58b2744ee1b8cfddef (diff) | |
Merge "clk: qcom: add common clock framework support for MDSS PLL"
| -rw-r--r-- | drivers/clk/qcom/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/clk/qcom/Makefile | 2 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/Makefile | 9 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c (renamed from drivers/clk/qcom/mdss/mdss-dsi-pll-8996-util.c) | 344 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c | 614 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.h (renamed from drivers/clk/qcom/mdss/mdss-dsi-pll-8996.h) | 54 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c | 566 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-dsi-pll.h | 65 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-pll-util.c | 1 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-pll.c | 25 | ||||
| -rw-r--r-- | drivers/clk/qcom/mdss/mdss-pll.h | 27 | ||||
| -rw-r--r-- | include/dt-bindings/clock/mdss-pll-clk.h | 42 |
13 files changed, 896 insertions, 858 deletions
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 36ab5cf68740..2148dad33e87 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -218,3 +218,5 @@ config QCOM_A53 Support for the A53 clock controller on MSM devices. Say Y if you want to support CPU frequency scaling on devices such as MSM8916. + +source "drivers/clk/qcom/mdss/Kconfig" diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 595254f69db1..176dc3103cdb 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -37,3 +37,5 @@ obj-$(CONFIG_KRAITCC) += krait-cc.o obj-$(CONFIG_QCOM_A53) += clk-a53.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o + +obj-y += mdss/ diff --git a/drivers/clk/qcom/mdss/Kconfig b/drivers/clk/qcom/mdss/Kconfig index 229780e45bb8..7213e375f1ef 100644 --- a/drivers/clk/qcom/mdss/Kconfig +++ b/drivers/clk/qcom/mdss/Kconfig @@ -1,5 +1,6 @@ -config MSM_MDSS_PLL +config QCOM_MDSS_PLL bool "MDSS pll programming" + depends on COMMON_CLK_QCOM ---help--- It provides support for DSI, eDP and HDMI interface pll programming on MDSS hardware. It also handles the pll specific resources and turn them on/off when diff --git a/drivers/clk/qcom/mdss/Makefile b/drivers/clk/qcom/mdss/Makefile index 75891dc10dda..6a0a1de1e942 100644 --- a/drivers/clk/qcom/mdss/Makefile +++ b/drivers/clk/qcom/mdss/Makefile @@ -1,5 +1,4 @@ -obj-$(CONFIG_MSM_MDSS_PLL) += mdss-pll-util.o -obj-$(CONFIG_MSM_MDSS_PLL) += mdss-pll.o -obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-8996.o -obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-8996-util.o -obj-$(CONFIG_MSM_MDSS_PLL) += mdss-hdmi-pll-8996.o +obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-pll-util.o +obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-pll.o +obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm.o +obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm-util.o diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c index 6d2694d5a2e9..a4044955c68f 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996-util.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c @@ -16,37 +16,18 @@ #include <linux/err.h> #include <linux/iopoll.h> #include <linux/delay.h> -#include <linux/clk/msm-clock-generic.h> #include "mdss-pll.h" #include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-8996.h" +#include "mdss-dsi-pll-14nm.h" #define DSI_PLL_POLL_MAX_READS 15 #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; -} - -int get_mdss_byte_mux_sel_8996(struct mux_clk *clk) -{ - return 0; -} - -int set_mdss_pixel_mux_sel_8996(struct mux_clk *clk, int sel) -{ - return 0; -} +#define VCO_REF_CLK_RATE 19200000 -int get_mdss_pixel_mux_sel_8996(struct mux_clk *clk) -{ - return 0; -} +#define CEIL(x, y) (((x) + ((y)-1)) / (y)) static int mdss_pll_read_stored_trim_codes( struct mdss_pll_resources *dsi_pll_res, s64 vco_clk_rate) @@ -94,9 +75,9 @@ end_read: return rc; } -int post_n1_div_set_div(struct div_clk *clk, int div) +int post_n1_div_set_div(void *context, unsigned int reg, unsigned int div) { - struct mdss_pll_resources *pll = clk->priv; + struct mdss_pll_resources *pll = context; struct dsi_pll_db *pdb; struct dsi_pll_output *pout; int rc; @@ -108,6 +89,9 @@ int post_n1_div_set_div(struct div_clk *clk, int div) return rc; } + /* in common clock framework the divider value provided is one less */ + div++; + pdb = (struct dsi_pll_db *)pll->priv; pout = &pdb->out; @@ -120,8 +104,6 @@ int post_n1_div_set_div(struct div_clk *clk, int div) * support bit_clk above 86.67Mhz */ - /* this is for vco/bit clock */ - pout->pll_postdiv = 1; /* fixed, divided by 1 */ pout->pll_n1div = div; n1div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); @@ -138,11 +120,15 @@ int post_n1_div_set_div(struct div_clk *clk, int div) return 0; } -int post_n1_div_get_div(struct div_clk *clk) +int post_n1_div_get_div(void *context, unsigned int reg, unsigned int *div) { - u32 div; int rc; - struct mdss_pll_resources *pll = clk->priv; + struct mdss_pll_resources *pll = context; + struct dsi_pll_db *pdb; + struct dsi_pll_output *pout; + + pdb = (struct dsi_pll_db *)pll->priv; + pout = &pdb->out; if (is_gdsc_disabled(pll)) return 0; @@ -159,20 +145,33 @@ int post_n1_div_get_div(struct div_clk *clk) * fot the time being, assume postdiv = 1 */ - div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - div &= 0xF; - pr_debug("n1 div = %d\n", div); + *div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); + *div &= 0xF; + + /* + * initialize n1div here, it will get updated when + * corresponding set_div is called. + */ + pout->pll_n1div = *div; + + /* common clock framework will add one to the divider value sent */ + if (*div == 0) + *div = 1; /* value of zero means div is 2 as per SWI */ + else + *div -= 1; + + pr_debug("post n1 get div = %d\n", *div); mdss_pll_resource_enable(pll, false); - return div; + return rc; } -int n2_div_set_div(struct div_clk *clk, int div) +int n2_div_set_div(void *context, unsigned int reg, unsigned int div) { int rc; u32 n2div; - struct mdss_pll_resources *pll = clk->priv; + struct mdss_pll_resources *pll = context; struct dsi_pll_db *pdb; struct dsi_pll_output *pout; struct mdss_pll_resources *slave; @@ -183,6 +182,12 @@ int n2_div_set_div(struct div_clk *clk, int div) return rc; } + /* + * in common clock framework the actual divider value + * provided is one less. + */ + div++; + pdb = (struct dsi_pll_db *)pll->priv; pout = &pdb->out; @@ -208,9 +213,9 @@ int n2_div_set_div(struct div_clk *clk, int div) return rc; } -int shadow_n2_div_set_div(struct div_clk *clk, int div) +int shadow_n2_div_set_div(void *context, unsigned int reg, unsigned int div) { - struct mdss_pll_resources *pll = clk->priv; + struct mdss_pll_resources *pll = context; struct dsi_pll_db *pdb; struct dsi_pll_output *pout; u32 data; @@ -218,6 +223,12 @@ int shadow_n2_div_set_div(struct div_clk *clk, int div) pdb = pll->priv; pout = &pdb->out; + /* + * in common clock framework the actual divider value + * provided is one less. + */ + div++; + pout->pll_n2div = div; data = (pout->pll_n1div | (pout->pll_n2div << 4)); @@ -228,15 +239,20 @@ int shadow_n2_div_set_div(struct div_clk *clk, int div) return 0; } -int n2_div_get_div(struct div_clk *clk) +int n2_div_get_div(void *context, unsigned int reg, unsigned int *div) { int rc; u32 n2div; - struct mdss_pll_resources *pll = clk->priv; + struct mdss_pll_resources *pll = context; + struct dsi_pll_db *pdb; + struct dsi_pll_output *pout; if (is_gdsc_disabled(pll)) return 0; + pdb = (struct dsi_pll_db *)pll->priv; + pout = &pdb->out; + rc = mdss_pll_resource_enable(pll, true); if (rc) { pr_err("Failed to enable mdss dsi pll=%d resources\n", @@ -247,15 +263,27 @@ int n2_div_get_div(struct div_clk *clk) n2div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); n2div >>= 4; n2div &= 0x0f; - + /* + * initialize n2div here, it will get updated when + * corresponding set_div is called. + */ + pout->pll_n2div = n2div; mdss_pll_resource_enable(pll, false); - pr_debug("ndx=%d div=%d\n", pll->index, n2div); + *div = n2div; + + /* common clock framework will add one to the divider value sent */ + if (*div == 0) + *div = 1; /* value of zero means div is 2 as per SWI */ + else + *div -= 1; + + pr_debug("ndx=%d div=%d\n", pll->index, *div); - return n2div; + return rc; } -static bool pll_is_pll_locked_8996(struct mdss_pll_resources *pll) +static bool pll_is_pll_locked_14nm(struct mdss_pll_resources *pll) { u32 status; bool pll_locked; @@ -286,7 +314,7 @@ static bool pll_is_pll_locked_8996(struct mdss_pll_resources *pll) return pll_locked; } -static void dsi_pll_start_8996(void __iomem *pll_base) +static void dsi_pll_start_14nm(void __iomem *pll_base) { pr_debug("start PLL at base=%p\n", pll_base); @@ -294,14 +322,14 @@ static void dsi_pll_start_8996(void __iomem *pll_base) MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 1); } -static void dsi_pll_stop_8996(void __iomem *pll_base) +static void dsi_pll_stop_14nm(void __iomem *pll_base) { pr_debug("stop PLL at base=%p\n", pll_base); MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 0); } -int dsi_pll_enable_seq_8996(struct mdss_pll_resources *pll) +int dsi_pll_enable_seq_14nm(struct mdss_pll_resources *pll) { int rc = 0; @@ -310,14 +338,14 @@ int dsi_pll_enable_seq_8996(struct mdss_pll_resources *pll) return -EINVAL; } - dsi_pll_start_8996(pll->pll_base); + dsi_pll_start_14nm(pll->pll_base); /* * both DSIPHY_PLL_CLKBUFLR_EN and DSIPHY_CMN_GLBL_TEST_CTRL - * enabled at mdss_dsi_8996_phy_config() + * enabled at mdss_dsi_14nm_phy_config() */ - if (!pll_is_pll_locked_8996(pll)) { + if (!pll_is_pll_locked_14nm(pll)) { pr_err("DSI PLL ndx=%d lock failed\n", pll->index); rc = -EINVAL; goto init_lock_err; @@ -329,10 +357,10 @@ init_lock_err: return rc; } -static int dsi_pll_enable(struct clk *c) +static int dsi_pll_enable(struct clk_hw *hw) { int i, rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); struct mdss_pll_resources *pll = vco->priv; /* Try all enable sequences until one succeeds */ @@ -352,9 +380,9 @@ static int dsi_pll_enable(struct clk *c) return rc; } -static void dsi_pll_disable(struct clk *c) +static void dsi_pll_disable(struct clk_hw *hw) { - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); struct mdss_pll_resources *pll = vco->priv; struct mdss_pll_resources *slave; @@ -367,7 +395,7 @@ static void dsi_pll_disable(struct clk *c) pll->handoff_resources = false; slave = pll->slave; - dsi_pll_stop_8996(pll->pll_base); + dsi_pll_stop_14nm(pll->pll_base); mdss_pll_resource_enable(pll, false); @@ -376,7 +404,7 @@ static void dsi_pll_disable(struct clk *c) pr_debug("DSI PLL ndx=%d Disabled\n", pll->index); } -static void mdss_dsi_pll_8996_input_init(struct mdss_pll_resources *pll, +static void mdss_dsi_pll_14nm_input_init(struct mdss_pll_resources *pll, struct dsi_pll_db *pdb) { pdb->in.fref = 19200000; /* 19.2 Mhz*/ @@ -414,9 +442,10 @@ static void mdss_dsi_pll_8996_input_init(struct mdss_pll_resources *pll, pdb->in.pll_iptat_trim = 7; pdb->in.pll_c3ctrl = 2; /* 2 */ pdb->in.pll_r3ctrl = 1; /* 1 */ + pdb->out.pll_postdiv = 1; } -static void pll_8996_ssc_calc(struct mdss_pll_resources *pll, +static void pll_14nm_ssc_calc(struct mdss_pll_resources *pll, struct dsi_pll_db *pdb) { u32 period, ssc_period; @@ -457,7 +486,7 @@ static void pll_8996_ssc_calc(struct mdss_pll_resources *pll, pdb->out.ssc_step_size = step_size; } -static void pll_8996_dec_frac_calc(struct mdss_pll_resources *pll, +static void pll_14nm_dec_frac_calc(struct mdss_pll_resources *pll, struct dsi_pll_db *pdb) { struct dsi_pll_input *pin = &pdb->in; @@ -501,7 +530,7 @@ static void pll_8996_dec_frac_calc(struct mdss_pll_resources *pll, pout->cmn_ldo_cntrl = 0x1c; } -static u32 pll_8996_kvco_slop(u32 vrate) +static u32 pll_14nm_kvco_slop(u32 vrate) { u32 slop = 0; @@ -515,7 +544,7 @@ static u32 pll_8996_kvco_slop(u32 vrate) return slop; } -static void pll_8996_calc_vco_count(struct dsi_pll_db *pdb, +static void pll_14nm_calc_vco_count(struct dsi_pll_db *pdb, s64 vco_clk_rate, s64 fref) { struct dsi_pll_input *pin = &pdb->in; @@ -540,7 +569,7 @@ static void pll_8996_calc_vco_count(struct dsi_pll_db *pdb, data -= 1; pout->pll_kvco_div_ref = data; - cnt = pll_8996_kvco_slop(vco_clk_rate); + cnt = pll_14nm_kvco_slop(vco_clk_rate); cnt *= 2; do_div(cnt, 100); cnt *= pin->kvco_measure_time; @@ -659,7 +688,7 @@ static void pll_db_commit_common(struct mdss_pll_resources *pll, MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_CRCTRL, data); } -static void pll_db_commit_8996(struct mdss_pll_resources *pll, +static void pll_db_commit_14nm(struct mdss_pll_resources *pll, struct dsi_pll_db *pdb) { void __iomem *pll_base = pll->pll_base; @@ -753,7 +782,7 @@ static void pll_db_commit_8996(struct mdss_pll_resources *pll, /* * pll_source_finding: * Both GLBL_TEST_CTRL and CLKBUFLR_EN are configured - * at mdss_dsi_8996_phy_config() + * at mdss_dsi_14nm_phy_config() */ static int pll_source_finding(struct mdss_pll_resources *pll) { @@ -820,10 +849,59 @@ static void pll_source_setup(struct mdss_pll_resources *pll) other->slave = pll; } -int pll_vco_set_rate_8996(struct clk *c, unsigned long rate) +unsigned long pll_vco_recalc_rate_14nm(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); + struct mdss_pll_resources *pll = vco->priv; + u64 vco_rate, multiplier = BIT(20); + s32 div_frac_start; + u32 dec_start; + u64 ref_clk = vco->ref_clk_rate; + int rc; + + if (pll->vco_current_rate) + return (unsigned long)pll->vco_current_rate; + + 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; + } + + dec_start = MDSS_PLL_REG_R(pll->pll_base, + DSIPHY_PLL_DEC_START); + dec_start &= 0x0ff; + pr_debug("dec_start = 0x%x\n", dec_start); + + div_frac_start = (MDSS_PLL_REG_R(pll->pll_base, + DSIPHY_PLL_DIV_FRAC_START3) & 0x0f) << 16; + div_frac_start |= (MDSS_PLL_REG_R(pll->pll_base, + DSIPHY_PLL_DIV_FRAC_START2) & 0x0ff) << 8; + div_frac_start |= MDSS_PLL_REG_R(pll->pll_base, + DSIPHY_PLL_DIV_FRAC_START1) & 0x0ff; + pr_debug("div_frac_start = 0x%x\n", div_frac_start); + + vco_rate = ref_clk * dec_start; + vco_rate += ((ref_clk * div_frac_start) / multiplier); + + pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); + + mdss_pll_resource_enable(pll, false); + + pr_debug("%s: returning vco rate as %lu\n", + __func__, (unsigned long)vco_rate); + return (unsigned long)vco_rate; +} + +int pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); struct mdss_pll_resources *pll = vco->priv; struct mdss_pll_resources *slave; struct dsi_pll_db *pdb; @@ -848,30 +926,30 @@ 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(pll, pdb); + mdss_dsi_pll_14nm_input_init(pll, pdb); - pll_8996_dec_frac_calc(pll, pdb); + pll_14nm_dec_frac_calc(pll, pdb); if (pll->ssc_en) - pll_8996_ssc_calc(pll, pdb); + pll_14nm_ssc_calc(pll, pdb); - pll_8996_calc_vco_count(pdb, pll->vco_current_rate, + pll_14nm_calc_vco_count(pdb, pll->vco_current_rate, pll->vco_ref_clk_rate); /* commit slave if split display is enabled */ slave = pll->slave; if (slave) - pll_db_commit_8996(slave, pdb); + pll_db_commit_14nm(slave, pdb); /* commit master itself */ - pll_db_commit_8996(pll, pdb); + pll_db_commit_14nm(pll, pdb); mdss_pll_resource_enable(pll, false); return rc; } -static void shadow_pll_dynamic_refresh_8996(struct mdss_pll_resources *pll, +static void shadow_pll_dynamic_refresh_14nm(struct mdss_pll_resources *pll, struct dsi_pll_db *pdb) { struct dsi_pll_output *pout = &pdb->out; @@ -931,10 +1009,11 @@ static void shadow_pll_dynamic_refresh_8996(struct mdss_pll_resources *pll, wmb(); } -int shadow_pll_vco_set_rate_8996(struct clk *c, unsigned long rate) +int shadow_pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); struct mdss_pll_resources *pll = vco->priv; struct dsi_pll_db *pdb; s64 vco_clk_rate = (s64)rate; @@ -968,14 +1047,14 @@ int shadow_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(pll, pdb); + mdss_dsi_pll_14nm_input_init(pll, pdb); - pll_8996_dec_frac_calc(pll, pdb); + pll_14nm_dec_frac_calc(pll, pdb); - pll_8996_calc_vco_count(pdb, pll->vco_current_rate, + pll_14nm_calc_vco_count(pdb, pll->vco_current_rate, pll->vco_ref_clk_rate); - shadow_pll_dynamic_refresh_8996(pll, pdb); + shadow_pll_dynamic_refresh_14nm(pll, pdb); rc = mdss_pll_resource_enable(pll, false); if (rc) { @@ -986,53 +1065,12 @@ int shadow_pll_vco_set_rate_8996(struct clk *c, unsigned long rate) return rc; } -unsigned long pll_vco_get_rate_8996(struct clk *c) -{ - u64 vco_rate, multiplier = BIT(20); - s32 div_frac_start; - u32 dec_start; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - 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; - } - - dec_start = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DEC_START); - dec_start &= 0x0ff; - pr_debug("dec_start = 0x%x\n", dec_start); - - div_frac_start = (MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START3) & 0x0f) << 16; - div_frac_start |= (MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START2) & 0x0ff) << 8; - div_frac_start |= MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START1) & 0x0ff; - pr_debug("div_frac_start = 0x%x\n", div_frac_start); - - vco_rate = ref_clk * dec_start; - vco_rate += ((ref_clk * div_frac_start) / multiplier); - - 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_8996(struct clk *c, unsigned long rate) +long pll_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) { unsigned long rrate = rate; u32 div; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); div = vco->min_rate / rate; if (div > 15) { @@ -1046,46 +1084,14 @@ long pll_vco_round_rate_8996(struct clk *c, unsigned long rate) if (rate > vco->max_rate) rrate = vco->max_rate; + *parent_rate = rrate; return rrate; } -enum handoff pll_vco_handoff_8996(struct clk *c) -{ - int rc; - enum handoff ret = HANDOFF_DISABLED_CLK; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - - if (is_gdsc_disabled(pll)) - return HANDOFF_DISABLED_CLK; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); - return ret; - } - - if (pll_is_pll_locked_8996(pll)) { - pll->handoff_resources = true; - pll->pll_on = true; - c->rate = pll_vco_get_rate_8996(c); - ret = HANDOFF_ENABLED_CLK; - } else { - mdss_pll_resource_enable(pll, false); - } - - return ret; -} - -enum handoff shadow_pll_vco_handoff_8996(struct clk *c) -{ - return HANDOFF_DISABLED_CLK; -} - -int pll_vco_prepare_8996(struct clk *c) +int pll_vco_prepare_14nm(struct clk_hw *hw) { int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); struct mdss_pll_resources *pll = vco->priv; if (!pll) { @@ -1101,8 +1107,9 @@ int pll_vco_prepare_8996(struct clk *c) } if ((pll->vco_cached_rate != 0) - && (pll->vco_cached_rate == c->rate)) { - rc = c->ops->set_rate(c, pll->vco_cached_rate); + && (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", rc, pll->index); @@ -1111,7 +1118,7 @@ int pll_vco_prepare_8996(struct clk *c) } } - rc = dsi_pll_enable(c); + rc = dsi_pll_enable(hw); if (rc) { mdss_pll_resource_enable(pll, false); @@ -1122,9 +1129,9 @@ error: return rc; } -void pll_vco_unprepare_8996(struct clk *c) +void pll_vco_unprepare_14nm(struct clk_hw *hw) { - struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct dsi_pll_vco_clk *vco = to_vco_hw(hw); struct mdss_pll_resources *pll = vco->priv; if (!pll) { @@ -1132,6 +1139,17 @@ void pll_vco_unprepare_8996(struct clk *c) return; } - pll->vco_cached_rate = c->rate; - dsi_pll_disable(c); + pll->vco_cached_rate = clk_hw_get_rate(hw); + dsi_pll_disable(hw); +} + +int dsi_mux_set_parent_14nm(void *context, unsigned int reg, unsigned int val) +{ + return 0; +} + +int dsi_mux_get_parent_14nm(void *context, unsigned int reg, unsigned int *val) +{ + *val = 0; + return 0; } diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c new file mode 100644 index 000000000000..667a1512d54f --- /dev/null +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c @@ -0,0 +1,614 @@ +/* Copyright (c) 2015-2016, 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/delay.h> +#include <linux/workqueue.h> + +#include "mdss-pll.h" +#include "mdss-dsi-pll.h" +#include "mdss-dsi-pll-14nm.h" + +#define VCO_DELAY_USEC 1 + +static struct dsi_pll_db pll_db[DSI_PLL_NUM]; + +static struct regmap_config dsi_pll_14nm_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x588, +}; + +static struct regmap_bus post_n1_div_regmap_bus = { + .reg_write = post_n1_div_set_div, + .reg_read = post_n1_div_get_div, +}; + +static struct regmap_bus n2_div_regmap_bus = { + .reg_write = n2_div_set_div, + .reg_read = n2_div_get_div, +}; + +static struct regmap_bus shadow_n2_div_regmap_bus = { + .reg_write = shadow_n2_div_set_div, + .reg_read = n2_div_get_div, +}; + +static struct regmap_bus dsi_mux_regmap_bus = { + .reg_write = dsi_mux_set_parent_14nm, + .reg_read = dsi_mux_get_parent_14nm, +}; + +/* Op structures */ +static struct clk_ops clk_ops_dsi_vco = { + .recalc_rate = pll_vco_recalc_rate_14nm, + .set_rate = pll_vco_set_rate_14nm, + .round_rate = pll_vco_round_rate_14nm, + .prepare = pll_vco_prepare_14nm, + .unprepare = pll_vco_unprepare_14nm, +}; + +/* Shadow ops for dynamic refresh */ +static struct clk_ops clk_ops_shadow_dsi_vco = { + .recalc_rate = pll_vco_recalc_rate_14nm, + .set_rate = shadow_pll_vco_set_rate_14nm, + .round_rate = pll_vco_round_rate_14nm, +}; + +static struct dsi_pll_vco_clk dsi0pll_vco_clk = { + .ref_clk_rate = 19200000UL, + .min_rate = 1300000000UL, + .max_rate = 2600000000UL, + .pll_en_seq_cnt = 1, + .pll_enable_seqs[0] = dsi_pll_enable_seq_14nm, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_vco_clk_14nm", + .parent_names = (const char *[]){ "xo_board" }, + .num_parents = 1, + .ops = &clk_ops_dsi_vco, + }, +}; + +static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = { + .ref_clk_rate = 19200000u, + .min_rate = 1300000000u, + .max_rate = 2600000000u, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_shadow_vco_clk_14nm", + .parent_names = (const char *[]){ "xo_board" }, + .num_parents = 1, + .ops = &clk_ops_shadow_dsi_vco, + }, +}; + +static struct dsi_pll_vco_clk dsi1pll_vco_clk = { + .ref_clk_rate = 19200000UL, + .min_rate = 1300000000UL, + .max_rate = 2600000000UL, + .pll_en_seq_cnt = 1, + .pll_enable_seqs[0] = dsi_pll_enable_seq_14nm, + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_vco_clk_14nm", + .parent_names = (const char *[]){ "xo_board" }, + .num_parents = 1, + .ops = &clk_ops_dsi_vco, + }, +}; + +static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = { + .ref_clk_rate = 19200000u, + .min_rate = 1300000000u, + .max_rate = 2600000000u, + .pll_en_seq_cnt = 1, + .pll_enable_seqs[0] = dsi_pll_enable_seq_14nm, + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_shadow_vco_clk_14nm", + .parent_names = (const char *[]){ "xo_board" }, + .num_parents = 1, + .ops = &clk_ops_shadow_dsi_vco, + }, +}; + +static struct clk_regmap_div dsi0pll_post_n1_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_post_n1_div_clk", + .parent_names = + (const char *[]){ "dsi0pll_vco_clk_14nm" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi0pll_shadow_post_n1_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_shadow_post_n1_div_clk", + .parent_names = + (const char *[]){"dsi0pll_shadow_vco_clk_14nm"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi1pll_post_n1_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_post_n1_div_clk", + .parent_names = + (const char *[]){ "dsi1pll_vco_clk_14nm" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi1pll_shadow_post_n1_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_shadow_post_n1_div_clk", + .parent_names = + (const char *[]){"dsi1pll_shadow_vco_clk_14nm"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi0pll_n2_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_n2_div_clk", + .parent_names = + (const char *[]){ "dsi0pll_post_n1_div_clk" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi0pll_shadow_n2_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_shadow_n2_div_clk", + .parent_names = + (const char *[]){ "dsi0pll_shadow_post_n1_div_clk" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi1pll_n2_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_n2_div_clk", + .parent_names = + (const char *[]){ "dsi1pll_post_n1_div_clk" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_regmap_div dsi1pll_shadow_n2_div_clk = { + .reg = 0x48, + .shift = 0, + .width = 4, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_shadow_n2_div_clk", + .parent_names = + (const char *[]){ "dsi1pll_shadow_post_n1_div_clk" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_regmap_div_ops, + }, + }, +}; + +static struct clk_fixed_factor dsi0pll_pixel_clk_src = { + .div = 2, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_pixel_clk_src", + .parent_names = (const char *[]){ "dsi0pll_n2_div_clk" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi0pll_shadow_pixel_clk_src = { + .div = 2, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_shadow_pixel_clk_src", + .parent_names = (const char *[]){ "dsi0pll_shadow_n2_div_clk" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi1pll_pixel_clk_src = { + .div = 2, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_pixel_clk_src", + .parent_names = (const char *[]){ "dsi1pll_n2_div_clk" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi1pll_shadow_pixel_clk_src = { + .div = 2, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_shadow_pixel_clk_src", + .parent_names = (const char *[]){ "dsi1pll_shadow_n2_div_clk" }, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_regmap_mux dsi0pll_pixel_clk_mux = { + .reg = 0x48, + .shift = 0, + .width = 1, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_pixel_clk_mux", + .parent_names = + (const char *[]){ "dsi0pll_pixel_clk_src", + "dsi0pll_shadow_pixel_clk_src"}, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux dsi1pll_pixel_clk_mux = { + .reg = 0x48, + .shift = 0, + .width = 1, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_pixel_clk_mux", + .parent_names = + (const char *[]){ "dsi1pll_pixel_clk_src", + "dsi1pll_shadow_pixel_clk_src"}, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_fixed_factor dsi0pll_byte_clk_src = { + .div = 8, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_byte_clk_src", + .parent_names = (const char *[]){ "dsi0pll_post_n1_div_clk" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi0pll_shadow_byte_clk_src = { + .div = 8, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_shadow_byte_clk_src", + .parent_names = + (const char *[]){ "dsi0pll_shadow_post_n1_div_clk" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi1pll_byte_clk_src = { + .div = 8, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_byte_clk_src", + .parent_names = (const char *[]){ "dsi1pll_post_n1_div_clk" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor dsi1pll_shadow_byte_clk_src = { + .div = 8, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_shadow_byte_clk_src", + .parent_names = + (const char *[]){ "dsi1pll_shadow_post_n1_div_clk" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_regmap_mux dsi0pll_byte_clk_mux = { + .reg = 0x48, + .shift = 0, + .width = 1, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_byte_clk_mux", + .parent_names = + (const char *[]){"dsi0pll_byte_clk_src", + "dsi0pll_shadow_byte_clk_src"}, + .num_parents = 2, + .ops = &clk_regmap_mux_closest_ops, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + }, + }, +}; + +static struct clk_regmap_mux dsi1pll_byte_clk_mux = { + .reg = 0x48, + .shift = 0, + .width = 1, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_byte_clk_mux", + .parent_names = + (const char *[]){"dsi1pll_byte_clk_src", + "dsi1pll_shadow_byte_clk_src"}, + .num_parents = 2, + .ops = &clk_regmap_mux_closest_ops, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + }, + }, +}; + +static struct clk_hw *mdss_dsi_pllcc_14nm[] = { + [BYTE0_MUX_CLK] = &dsi0pll_byte_clk_mux.clkr.hw, + [BYTE0_SRC_CLK] = &dsi0pll_byte_clk_src.hw, + [PIX0_MUX_CLK] = &dsi0pll_pixel_clk_mux.clkr.hw, + [PIX0_SRC_CLK] = &dsi0pll_pixel_clk_src.hw, + [N2_DIV_0_CLK] = &dsi0pll_n2_div_clk.clkr.hw, + [POST_N1_DIV_0_CLK] = &dsi0pll_post_n1_div_clk.clkr.hw, + [VCO_CLK_0_CLK] = &dsi0pll_vco_clk.hw, + [SHADOW_BYTE0_SRC_CLK] = &dsi0pll_shadow_byte_clk_src.hw, + [SHADOW_PIX0_SRC_CLK] = &dsi0pll_shadow_pixel_clk_src.hw, + [SHADOW_N2_DIV_0_CLK] = &dsi0pll_shadow_n2_div_clk.clkr.hw, + [SHADOW_POST_N1_DIV_0_CLK] = &dsi0pll_shadow_post_n1_div_clk.clkr.hw, + [SHADOW_VCO_CLK_0_CLK] = &dsi0pll_shadow_vco_clk.hw, + [BYTE1_MUX_CLK] = &dsi1pll_byte_clk_mux.clkr.hw, + [BYTE1_SRC_CLK] = &dsi1pll_byte_clk_src.hw, + [PIX1_MUX_CLK] = &dsi1pll_pixel_clk_mux.clkr.hw, + [PIX1_SRC_CLK] = &dsi1pll_pixel_clk_src.hw, + [N2_DIV_1_CLK] = &dsi1pll_n2_div_clk.clkr.hw, + [POST_N1_DIV_1_CLK] = &dsi1pll_post_n1_div_clk.clkr.hw, + [VCO_CLK_1_CLK] = &dsi1pll_vco_clk.hw, + [SHADOW_BYTE1_SRC_CLK] = &dsi1pll_shadow_byte_clk_src.hw, + [SHADOW_PIX1_SRC_CLK] = &dsi1pll_shadow_pixel_clk_src.hw, + [SHADOW_N2_DIV_1_CLK] = &dsi1pll_shadow_n2_div_clk.clkr.hw, + [SHADOW_POST_N1_DIV_1_CLK] = &dsi1pll_shadow_post_n1_div_clk.clkr.hw, + [SHADOW_VCO_CLK_1_CLK] = &dsi1pll_shadow_vco_clk.hw, +}; + +int dsi_pll_clock_register_14nm(struct platform_device *pdev, + struct mdss_pll_resources *pll_res) +{ + int rc = 0, ndx, i; + int const ssc_freq_default = 31500; /* default h/w recommended value */ + int const ssc_ppm_default = 5000; /* default h/w recommended value */ + struct dsi_pll_db *pdb; + struct clk_onecell_data *clk_data; + struct clk *clk; + struct regmap *regmap; + int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_14nm); + + if (!pdev || !pdev->dev.of_node) { + pr_err("Invalid input parameters\n"); + return -EINVAL; + } + + if (!pll_res || !pll_res->pll_base) { + pr_err("Invalid PLL resources\n"); + return -EPROBE_DEFER; + } + + if (pll_res->index >= DSI_PLL_NUM) { + pr_err("pll ndx=%d is NOT supported\n", pll_res->index); + return -EINVAL; + } + + ndx = pll_res->index; + pdb = &pll_db[ndx]; + pll_res->priv = pdb; + pdb->pll = pll_res; + ndx++; + ndx %= DSI_PLL_NUM; + pdb->next = &pll_db[ndx]; + + if (pll_res->ssc_en) { + if (!pll_res->ssc_freq) + pll_res->ssc_freq = ssc_freq_default; + if (!pll_res->ssc_ppm) + pll_res->ssc_ppm = ssc_ppm_default; + } + + 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; + + /* Set client data to mux, div and vco clocks. */ + if (pll_res->index == DSI_PLL_1) { + regmap = devm_regmap_init(&pdev->dev, &post_n1_div_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi1pll_post_n1_div_clk.clkr.regmap = regmap; + dsi1pll_shadow_post_n1_div_clk.clkr.regmap = regmap; + + regmap = devm_regmap_init(&pdev->dev, &n2_div_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi1pll_n2_div_clk.clkr.regmap = regmap; + + regmap = devm_regmap_init(&pdev->dev, &shadow_n2_div_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi1pll_shadow_n2_div_clk.clkr.regmap = regmap; + + regmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi1pll_byte_clk_mux.clkr.regmap = regmap; + dsi1pll_pixel_clk_mux.clkr.regmap = regmap; + + dsi1pll_vco_clk.priv = pll_res; + dsi1pll_shadow_vco_clk.priv = pll_res; + + pll_res->vco_delay = VCO_DELAY_USEC; + + for (i = BYTE1_MUX_CLK; i <= SHADOW_VCO_CLK_1_CLK; i++) { + pr_debug("register clk: %d index: %d\n", + i, pll_res->index); + clk = devm_clk_register(&pdev->dev, + mdss_dsi_pllcc_14nm[i]); + if (IS_ERR(clk)) { + pr_err("clk registration failed for DSI: %d\n", + pll_res->index); + rc = -EINVAL; + goto clk_reg_fail; + } + clk_data->clks[i] = clk; + } + + rc = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, clk_data); + } else { + regmap = devm_regmap_init(&pdev->dev, &post_n1_div_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi0pll_post_n1_div_clk.clkr.regmap = regmap; + dsi0pll_shadow_post_n1_div_clk.clkr.regmap = regmap; + + regmap = devm_regmap_init(&pdev->dev, &n2_div_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi0pll_n2_div_clk.clkr.regmap = regmap; + + regmap = devm_regmap_init(&pdev->dev, &shadow_n2_div_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi0pll_shadow_n2_div_clk.clkr.regmap = regmap; + + regmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, + pll_res, &dsi_pll_14nm_config); + dsi0pll_byte_clk_mux.clkr.regmap = regmap; + dsi0pll_pixel_clk_mux.clkr.regmap = regmap; + + dsi0pll_vco_clk.priv = pll_res; + dsi0pll_shadow_vco_clk.priv = pll_res; + pll_res->vco_delay = VCO_DELAY_USEC; + + for (i = BYTE0_MUX_CLK; i <= SHADOW_VCO_CLK_0_CLK; i++) { + pr_debug("reg clk: %d index: %d\n", i, pll_res->index); + clk = devm_clk_register(&pdev->dev, + mdss_dsi_pllcc_14nm[i]); + if (IS_ERR(clk)) { + pr_err("clk registration failed for DSI: %d\n", + pll_res->index); + rc = -EINVAL; + goto clk_reg_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\n", + pll_res->index); + return rc; + } + +clk_reg_fail: + devm_kfree(&pdev->dev, clk_data->clks); + devm_kfree(&pdev->dev, clk_data); + return rc; +} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.h b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.h index 611e79101d4f..c2a3b12d8174 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.h +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.h @@ -10,8 +10,8 @@ * GNU General Public License for more details. */ -#ifndef MDSS_DSI_PLL_8996_H -#define MDSS_DSI_PLL_8996_H +#ifndef MDSS_DSI_PLL_14NM_H +#define MDSS_DSI_PLL_14NM_H #define DSIPHY_CMN_CLK_CFG0 0x0010 #define DSIPHY_CMN_CLK_CFG1 0x0014 @@ -197,25 +197,31 @@ enum { PLL_MASTER }; -int pll_vco_set_rate_8996(struct clk *c, unsigned long rate); -long pll_vco_round_rate_8996(struct clk *c, unsigned long rate); -enum handoff pll_vco_handoff_8996(struct clk *c); -enum handoff shadow_pll_vco_handoff_8996(struct clk *c); -int shadow_post_n1_div_set_div(struct div_clk *clk, int div); -int shadow_post_n1_div_get_div(struct div_clk *clk); -int shadow_n2_div_set_div(struct div_clk *clk, int div); -int shadow_n2_div_get_div(struct div_clk *clk); -int shadow_pll_vco_set_rate_8996(struct clk *c, unsigned long rate); -int pll_vco_prepare_8996(struct clk *c); -void pll_vco_unprepare_8996(struct clk *c); -int set_mdss_byte_mux_sel_8996(struct mux_clk *clk, int sel); -int get_mdss_byte_mux_sel_8996(struct mux_clk *clk); -int set_mdss_pixel_mux_sel_8996(struct mux_clk *clk, int sel); -int get_mdss_pixel_mux_sel_8996(struct mux_clk *clk); -int post_n1_div_set_div(struct div_clk *clk, int div); -int post_n1_div_get_div(struct div_clk *clk); -int n2_div_set_div(struct div_clk *clk, int div); -int n2_div_get_div(struct div_clk *clk); -int dsi_pll_enable_seq_8996(struct mdss_pll_resources *pll); - -#endif /* MDSS_DSI_PLL_8996_H */ +int pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); +int shadow_pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); +long pll_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate); +unsigned long pll_vco_recalc_rate_14nm(struct clk_hw *hw, + unsigned long parent_rate); + +int pll_vco_prepare_14nm(struct clk_hw *hw); +void pll_vco_unprepare_14nm(struct clk_hw *hw); + +int shadow_post_n1_div_set_div(void *context, + unsigned int reg, unsigned int div); +int shadow_post_n1_div_get_div(void *context, + unsigned int reg, unsigned int *div); +int shadow_n2_div_set_div(void *context, unsigned int reg, unsigned int div); +int shadow_n2_div_get_div(void *context, unsigned int reg, unsigned int *div); + +int post_n1_div_set_div(void *context, unsigned int reg, unsigned int div); +int post_n1_div_get_div(void *context, unsigned int reg, unsigned int *div); +int n2_div_set_div(void *context, unsigned int reg, unsigned int div); +int n2_div_get_div(void *context, unsigned int reg, unsigned int *div); +int dsi_pll_enable_seq_14nm(struct mdss_pll_resources *pll); +int dsi_mux_set_parent_14nm(void *context, unsigned int reg, unsigned int val); +int dsi_mux_get_parent_14nm(void *context, unsigned int reg, unsigned int *val); + +#endif /* MDSS_DSI_PLL_14NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c deleted file mode 100644 index 1de1b997a041..000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c +++ /dev/null @@ -1,566 +0,0 @@ -/* Copyright (c) 2015-2016, 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/delay.h> -#include <linux/clk/msm-clk-provider.h> -#include <linux/clk/msm-clk.h> -#include <linux/workqueue.h> -#include <linux/clk/msm-clock-generic.h> -#include <dt-bindings/clock/msm-clocks-8996.h> - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-8996.h" - -#define VCO_DELAY_USEC 1 - -static struct dsi_pll_db pll_db[DSI_PLL_NUM]; - -static struct clk_ops n2_clk_src_ops; -static struct clk_ops shadow_n2_clk_src_ops; -static struct clk_ops byte_clk_src_ops; -static struct clk_ops post_n1_div_clk_src_ops; -static struct clk_ops shadow_post_n1_div_clk_src_ops; - -static struct clk_ops clk_ops_gen_mux_dsi; - -/* Op structures */ -static struct clk_ops clk_ops_dsi_vco = { - .set_rate = pll_vco_set_rate_8996, - .round_rate = pll_vco_round_rate_8996, - .handoff = pll_vco_handoff_8996, - .prepare = pll_vco_prepare_8996, - .unprepare = pll_vco_unprepare_8996, -}; - -static struct clk_div_ops post_n1_div_ops = { - .set_div = post_n1_div_set_div, - .get_div = post_n1_div_get_div, -}; - -static struct clk_div_ops n2_div_ops = { /* hr_oclk3 */ - .set_div = n2_div_set_div, - .get_div = n2_div_get_div, -}; - -static struct clk_mux_ops mdss_byte_mux_ops = { - .set_mux_sel = set_mdss_byte_mux_sel_8996, - .get_mux_sel = get_mdss_byte_mux_sel_8996, -}; - -static struct clk_mux_ops mdss_pixel_mux_ops = { - .set_mux_sel = set_mdss_pixel_mux_sel_8996, - .get_mux_sel = get_mdss_pixel_mux_sel_8996, -}; - -/* Shadow ops for dynamic refresh */ -static struct clk_ops clk_ops_shadow_dsi_vco = { - .set_rate = shadow_pll_vco_set_rate_8996, - .round_rate = pll_vco_round_rate_8996, - .handoff = shadow_pll_vco_handoff_8996, -}; - -static struct clk_div_ops shadow_post_n1_div_ops = { - .set_div = post_n1_div_set_div, -}; - -static struct clk_div_ops shadow_n2_div_ops = { - .set_div = shadow_n2_div_set_div, -}; - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1300000000UL, - .max_rate = 2600000000UL, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8996, - .c = { - .dbg_name = "dsi0pll_vco_clk_8996", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi0pll_vco_clk.c), - }, -}; - -static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = { - .ref_clk_rate = 19200000u, - .min_rate = 1300000000u, - .max_rate = 2600000000u, - .c = { - .dbg_name = "dsi0pll_shadow_vco_clk", - .ops = &clk_ops_shadow_dsi_vco, - CLK_INIT(dsi0pll_shadow_vco_clk.c), - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1300000000UL, - .max_rate = 2600000000UL, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8996, - .c = { - .dbg_name = "dsi1pll_vco_clk_8996", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi1pll_vco_clk.c), - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = { - .ref_clk_rate = 19200000u, - .min_rate = 1300000000u, - .max_rate = 2600000000u, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8996, - .c = { - .dbg_name = "dsi1pll_shadow_vco_clk", - .ops = &clk_ops_shadow_dsi_vco, - CLK_INIT(dsi1pll_shadow_vco_clk.c), - }, -}; - -static struct div_clk dsi0pll_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &post_n1_div_ops, - .c = { - .parent = &dsi0pll_vco_clk.c, - .dbg_name = "dsi0pll_post_n1_div_clk", - .ops = &post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_shadow_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_post_n1_div_ops, - .c = { - .parent = &dsi0pll_shadow_vco_clk.c, - .dbg_name = "dsi0pll_shadow_post_n1_div_clk", - .ops = &shadow_post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_shadow_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &post_n1_div_ops, - .c = { - .parent = &dsi1pll_vco_clk.c, - .dbg_name = "dsi1pll_post_n1_div_clk", - .ops = &post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_shadow_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_post_n1_div_ops, - .c = { - .parent = &dsi1pll_shadow_vco_clk.c, - .dbg_name = "dsi1pll_shadow_post_n1_div_clk", - .ops = &shadow_post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_shadow_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &n2_div_ops, - .c = { - .parent = &dsi0pll_post_n1_div_clk.c, - .dbg_name = "dsi0pll_n2_div_clk", - .ops = &n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_n2_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_shadow_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_n2_div_ops, - .c = { - .parent = &dsi0pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi0pll_shadow_n2_div_clk", - .ops = &shadow_n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_shadow_n2_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &n2_div_ops, - .c = { - .parent = &dsi1pll_post_n1_div_clk.c, - .dbg_name = "dsi1pll_n2_div_clk", - .ops = &n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_n2_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_shadow_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_n2_div_ops, - .c = { - .parent = &dsi1pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi1pll_shadow_n2_div_clk", - .ops = &shadow_n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_shadow_n2_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi0pll_n2_div_clk.c, - .dbg_name = "dsi0pll_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_pixel_clk_src.c), - }, -}; - -static struct div_clk dsi0pll_shadow_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi0pll_shadow_n2_div_clk.c, - .dbg_name = "dsi0pll_shadow_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_shadow_pixel_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi1pll_n2_div_clk.c, - .dbg_name = "dsi1pll_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_pixel_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_shadow_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi1pll_shadow_n2_div_clk.c, - .dbg_name = "dsi1pll_shadow_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_shadow_pixel_clk_src.c), - }, -}; - -static struct mux_clk dsi0pll_pixel_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi0pll_pixel_clk_src.c, 0}, - {&dsi0pll_shadow_pixel_clk_src.c, 1}, - }, - .ops = &mdss_pixel_mux_ops, - .c = { - .parent = &dsi0pll_pixel_clk_src.c, - .dbg_name = "dsi0pll_pixel_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_pixel_clk_mux.c), - } -}; - -static struct mux_clk dsi1pll_pixel_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi1pll_pixel_clk_src.c, 0}, - {&dsi1pll_shadow_pixel_clk_src.c, 1}, - }, - .ops = &mdss_pixel_mux_ops, - .c = { - .parent = &dsi1pll_pixel_clk_src.c, - .dbg_name = "dsi1pll_pixel_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_pixel_clk_mux.c), - } -}; - -static struct div_clk dsi0pll_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi0pll_post_n1_div_clk.c, - .dbg_name = "dsi0pll_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi0pll_byte_clk_src.c), - }, -}; - -static struct div_clk dsi0pll_shadow_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi0pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi0pll_shadow_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi0pll_shadow_byte_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi1pll_post_n1_div_clk.c, - .dbg_name = "dsi1pll_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi1pll_byte_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_shadow_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi1pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi1pll_shadow_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi1pll_shadow_byte_clk_src.c), - }, -}; - -static struct mux_clk dsi0pll_byte_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi0pll_byte_clk_src.c, 0}, - {&dsi0pll_shadow_byte_clk_src.c, 1}, - }, - .ops = &mdss_byte_mux_ops, - .c = { - .parent = &dsi0pll_byte_clk_src.c, - .dbg_name = "dsi0pll_byte_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_byte_clk_mux.c), - } -}; -static struct mux_clk dsi1pll_byte_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi1pll_byte_clk_src.c, 0}, - {&dsi1pll_shadow_byte_clk_src.c, 1}, - }, - .ops = &mdss_byte_mux_ops, - .c = { - .parent = &dsi1pll_byte_clk_src.c, - .dbg_name = "dsi1pll_byte_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_byte_clk_mux.c), - } -}; - -static struct clk_lookup mdss_dsi_pllcc_8996[] = { - CLK_LIST(dsi0pll_byte_clk_mux), - CLK_LIST(dsi0pll_byte_clk_src), - CLK_LIST(dsi0pll_pixel_clk_mux), - CLK_LIST(dsi0pll_pixel_clk_src), - CLK_LIST(dsi0pll_n2_div_clk), - CLK_LIST(dsi0pll_post_n1_div_clk), - CLK_LIST(dsi0pll_vco_clk), - CLK_LIST(dsi0pll_shadow_byte_clk_src), - CLK_LIST(dsi0pll_shadow_pixel_clk_src), - CLK_LIST(dsi0pll_shadow_n2_div_clk), - CLK_LIST(dsi0pll_shadow_post_n1_div_clk), - CLK_LIST(dsi0pll_shadow_vco_clk), -}; - -static struct clk_lookup mdss_dsi_pllcc_8996_1[] = { - CLK_LIST(dsi1pll_byte_clk_mux), - CLK_LIST(dsi1pll_byte_clk_src), - CLK_LIST(dsi1pll_pixel_clk_mux), - CLK_LIST(dsi1pll_pixel_clk_src), - CLK_LIST(dsi1pll_n2_div_clk), - CLK_LIST(dsi1pll_post_n1_div_clk), - CLK_LIST(dsi1pll_vco_clk), - CLK_LIST(dsi1pll_shadow_byte_clk_src), - CLK_LIST(dsi1pll_shadow_pixel_clk_src), - CLK_LIST(dsi1pll_shadow_n2_div_clk), - CLK_LIST(dsi1pll_shadow_post_n1_div_clk), - CLK_LIST(dsi1pll_shadow_vco_clk), -}; - -int dsi_pll_clock_register_8996(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0, ndx; - int const ssc_freq_default = 31500; /* default h/w recommended value */ - int const ssc_ppm_default = 5000; /* default h/w recommended value */ - struct dsi_pll_db *pdb; - - if (!pdev || !pdev->dev.of_node) { - pr_err("Invalid input parameters\n"); - return -EINVAL; - } - - if (!pll_res || !pll_res->pll_base) { - pr_err("Invalid PLL resources\n"); - return -EPROBE_DEFER; - } - - if (pll_res->index >= DSI_PLL_NUM) { - pr_err("pll ndx=%d is NOT supported\n", pll_res->index); - return -EINVAL; - } - - ndx = pll_res->index; - pdb = &pll_db[ndx]; - pll_res->priv = pdb; - pdb->pll = pll_res; - ndx++; - ndx %= DSI_PLL_NUM; - pdb->next = &pll_db[ndx]; - - /* Set clock source operations */ - - /* hr_oclk3, pixel */ - n2_clk_src_ops = clk_ops_slave_div; - n2_clk_src_ops.prepare = mdss_pll_div_prepare; - - shadow_n2_clk_src_ops = clk_ops_slave_div; - - /* hr_ockl2, byte, vco pll */ - post_n1_div_clk_src_ops = clk_ops_div; - post_n1_div_clk_src_ops.prepare = mdss_pll_div_prepare; - - shadow_post_n1_div_clk_src_ops = clk_ops_div; - - byte_clk_src_ops = clk_ops_div; - byte_clk_src_ops.prepare = mdss_pll_div_prepare; - - clk_ops_gen_mux_dsi = clk_ops_gen_mux; - clk_ops_gen_mux_dsi.round_rate = parent_round_rate; - clk_ops_gen_mux_dsi.set_rate = parent_set_rate; - - if (pll_res->ssc_en) { - if (!pll_res->ssc_freq) - pll_res->ssc_freq = ssc_freq_default; - if (!pll_res->ssc_ppm) - pll_res->ssc_ppm = ssc_ppm_default; - } - - /* Set client data to mux, div and vco clocks. */ - if (pll_res->index == DSI_PLL_1) { - dsi1pll_byte_clk_src.priv = pll_res; - dsi1pll_pixel_clk_src.priv = pll_res; - dsi1pll_post_n1_div_clk.priv = pll_res; - dsi1pll_n2_div_clk.priv = pll_res; - dsi1pll_vco_clk.priv = pll_res; - - dsi1pll_shadow_byte_clk_src.priv = pll_res; - dsi1pll_shadow_pixel_clk_src.priv = pll_res; - dsi1pll_shadow_post_n1_div_clk.priv = pll_res; - dsi1pll_shadow_n2_div_clk.priv = pll_res; - dsi1pll_shadow_vco_clk.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8996_1, - ARRAY_SIZE(mdss_dsi_pllcc_8996_1)); - } else { - dsi0pll_byte_clk_src.priv = pll_res; - dsi0pll_pixel_clk_src.priv = pll_res; - dsi0pll_post_n1_div_clk.priv = pll_res; - dsi0pll_n2_div_clk.priv = pll_res; - dsi0pll_vco_clk.priv = pll_res; - - dsi0pll_shadow_byte_clk_src.priv = pll_res; - dsi0pll_shadow_pixel_clk_src.priv = pll_res; - dsi0pll_shadow_post_n1_div_clk.priv = pll_res; - dsi0pll_shadow_n2_div_clk.priv = pll_res; - dsi0pll_shadow_vco_clk.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8996, - ARRAY_SIZE(mdss_dsi_pllcc_8996)); - } - - if (!rc) { - pr_info("Registered DSI PLL ndx=%d clocks successfully\n", - pll_res->index); - } - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll.h b/drivers/clk/qcom/mdss/mdss-dsi-pll.h index 286c99e339c6..822d5181435d 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll.h +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll.h @@ -31,6 +31,8 @@ struct lpfr_cfg { }; struct dsi_pll_vco_clk { + struct clk_hw hw; + unsigned long ref_clk_rate; unsigned long min_rate; unsigned long max_rate; @@ -39,72 +41,15 @@ struct dsi_pll_vco_clk { u32 lpfr_lut_size; void *priv; - struct clk c; - int (*pll_enable_seqs[MAX_DSI_PLL_EN_SEQS]) (struct mdss_pll_resources *dsi_pll_Res); }; -static inline struct dsi_pll_vco_clk *to_vco_clk(struct clk *clk) +static inline struct dsi_pll_vco_clk *to_vco_hw(struct clk_hw *hw) { - return container_of(clk, struct dsi_pll_vco_clk, c); + return container_of(hw, struct dsi_pll_vco_clk, hw); } -int dsi_pll_clock_register_hpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -int dsi_pll_clock_register_20nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -int dsi_pll_clock_register_lpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -int dsi_pll_clock_register_8996(struct platform_device *pdev, +int dsi_pll_clock_register_14nm(struct platform_device *pdev, struct mdss_pll_resources *pll_res); -int dsi_pll_clock_register_8998(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int set_byte_mux_sel(struct mux_clk *clk, int sel); -int get_byte_mux_sel(struct mux_clk *clk); -int dsi_pll_mux_prepare(struct clk *c); -int fixed_4div_set_div(struct div_clk *clk, int div); -int fixed_4div_get_div(struct div_clk *clk); -int digital_set_div(struct div_clk *clk, int div); -int digital_get_div(struct div_clk *clk); -int analog_set_div(struct div_clk *clk, int div); -int analog_get_div(struct div_clk *clk); -int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res); -int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate); -unsigned long vco_get_rate(struct clk *c); -long vco_round_rate(struct clk *c, unsigned long rate); -enum handoff vco_handoff(struct clk *c); -int vco_prepare(struct clk *c); -void vco_unprepare(struct clk *c); - -/* APIs for 20nm PHY PLL */ -int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate); -int shadow_pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, - unsigned long rate); -long pll_20nm_vco_round_rate(struct clk *c, unsigned long rate); -enum handoff pll_20nm_vco_handoff(struct clk *c); -int pll_20nm_vco_prepare(struct clk *c); -void pll_20nm_vco_unprepare(struct clk *c); -int pll_20nm_vco_enable_seq(struct mdss_pll_resources *dsi_pll_res); - -int set_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel); -int set_shadow_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel); -int get_bypass_lp_div_mux_sel(struct mux_clk *clk); -int fixed_hr_oclk2_set_div(struct div_clk *clk, int div); -int shadow_fixed_hr_oclk2_set_div(struct div_clk *clk, int div); -int fixed_hr_oclk2_get_div(struct div_clk *clk); -int hr_oclk3_set_div(struct div_clk *clk, int div); -int shadow_hr_oclk3_set_div(struct div_clk *clk, int div); -int hr_oclk3_get_div(struct div_clk *clk); -int ndiv_set_div(struct div_clk *clk, int div); -int shadow_ndiv_set_div(struct div_clk *clk, int div); -int ndiv_get_div(struct div_clk *clk); -void __dsi_pll_disable(void __iomem *pll_base); - -int set_mdss_pixel_mux_sel(struct mux_clk *clk, int sel); -int get_mdss_pixel_mux_sel(struct mux_clk *clk); -int set_mdss_byte_mux_sel(struct mux_clk *clk, int sel); -int get_mdss_byte_mux_sel(struct mux_clk *clk); - #endif diff --git a/drivers/clk/qcom/mdss/mdss-pll-util.c b/drivers/clk/qcom/mdss/mdss-pll-util.c index 690c53f30eb7..881c973ec1b6 100644 --- a/drivers/clk/qcom/mdss/mdss-pll-util.c +++ b/drivers/clk/qcom/mdss/mdss-pll-util.c @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/err.h> #include <linux/string.h> -#include <linux/clk/msm-clock-generic.h> #include <linux/of_address.h> #include <linux/dma-mapping.h> #include <linux/vmalloc.h> diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c index 8264d2e5a3cd..b4b73ea4211a 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.c +++ b/drivers/clk/qcom/mdss/mdss-pll.c @@ -19,12 +19,9 @@ #include <linux/err.h> #include <linux/delay.h> #include <linux/iopoll.h> -#include <linux/clk/msm-clock-generic.h> #include "mdss-pll.h" #include "mdss-dsi-pll.h" -#include "mdss-hdmi-pll.h" -#include "mdss-dp-pll.h" int mdss_pll_resource_enable(struct mdss_pll_resources *pll_res, bool enable) { @@ -175,27 +172,7 @@ static int mdss_pll_clock_register(struct platform_device *pdev, switch (pll_res->pll_interface_type) { case MDSS_DSI_PLL_8996: - rc = dsi_pll_clock_register_8996(pdev, pll_res); - break; - case MDSS_DSI_PLL_8998: - rc = dsi_pll_clock_register_8998(pdev, pll_res); - case MDSS_DP_PLL_8998: - rc = dp_pll_clock_register_8998(pdev, pll_res); - break; - case MDSS_HDMI_PLL_8996: - rc = hdmi_8996_v1_pll_clock_register(pdev, pll_res); - break; - case MDSS_HDMI_PLL_8996_V2: - rc = hdmi_8996_v2_pll_clock_register(pdev, pll_res); - break; - case MDSS_HDMI_PLL_8996_V3: - rc = hdmi_8996_v3_pll_clock_register(pdev, pll_res); - break; - case MDSS_HDMI_PLL_8996_V3_1_8: - rc = hdmi_8996_v3_1p8_pll_clock_register(pdev, pll_res); - break; - case MDSS_HDMI_PLL_8998: - rc = hdmi_8998_pll_clock_register(pdev, pll_res); + rc = dsi_pll_clock_register_14nm(pdev, pll_res); break; case MDSS_UNKNOWN_PLL: default: diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h index 8fffaf30d4ec..3528dcfd0cb5 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ b/drivers/clk/qcom/mdss/mdss-pll.h @@ -14,8 +14,16 @@ #define __MDSS_PLL_H #include <linux/mdss_io_util.h> -#include <linux/clk/msm-clock-generic.h> +#include <linux/clk-provider.h> #include <linux/io.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/regmap.h> + +#include "../clk-regmap.h" +#include "../clk-regmap-divider.h" +#include "../clk-regmap-mux.h" +#include <dt-bindings/clock/mdss-pll-clk.h> #define MDSS_PLL_REG_W(base, offset, data) \ writel_relaxed((data), (base) + (offset)) @@ -200,21 +208,12 @@ static inline bool is_gdsc_disabled(struct mdss_pll_resources *pll_res) (!(readl_relaxed(pll_res->gdsc_base) & BIT(0)))) ? false : true; } -static inline int mdss_pll_div_prepare(struct clk *c) +static inline int mdss_pll_div_prepare(struct clk_hw *hw) { - struct div_clk *div = to_div_clk(c); + struct clk_hw *parent_hw = clk_hw_get_parent(hw); /* Restore the divider's value */ - return div->ops->set_div(div, div->data.div); -} - -static inline int mdss_set_mux_sel(struct mux_clk *clk, int sel) -{ - return 0; -} - -static inline int mdss_get_mux_sel(struct mux_clk *clk) -{ - return 0; + return hw->init->ops->set_rate(hw, clk_hw_get_rate(hw), + clk_hw_get_rate(parent_hw)); } int mdss_pll_resource_enable(struct mdss_pll_resources *pll_res, bool enable); diff --git a/include/dt-bindings/clock/mdss-pll-clk.h b/include/dt-bindings/clock/mdss-pll-clk.h new file mode 100644 index 000000000000..8cd0b2a9bc98 --- /dev/null +++ b/include/dt-bindings/clock/mdss-pll-clk.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2016, 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_PLL_CLK_H +#define __MDSS_PLL_CLK_H + +/* DSI PLL clocks */ +#define BYTE0_MUX_CLK 0 +#define BYTE0_SRC_CLK 1 +#define PIX0_MUX_CLK 2 +#define PIX0_SRC_CLK 3 +#define N2_DIV_0_CLK 4 +#define POST_N1_DIV_0_CLK 5 +#define VCO_CLK_0_CLK 6 +#define SHADOW_BYTE0_SRC_CLK 7 +#define SHADOW_PIX0_SRC_CLK 8 +#define SHADOW_N2_DIV_0_CLK 9 +#define SHADOW_POST_N1_DIV_0_CLK 10 +#define SHADOW_VCO_CLK_0_CLK 11 +#define BYTE1_MUX_CLK 12 +#define BYTE1_SRC_CLK 13 +#define PIX1_MUX_CLK 14 +#define PIX1_SRC_CLK 15 +#define N2_DIV_1_CLK 16 +#define POST_N1_DIV_1_CLK 17 +#define VCO_CLK_1_CLK 18 +#define SHADOW_BYTE1_SRC_CLK 19 +#define SHADOW_PIX1_SRC_CLK 20 +#define SHADOW_N2_DIV_1_CLK 21 +#define SHADOW_POST_N1_DIV_1_CLK 22 +#define SHADOW_VCO_CLK_1_CLK 23 + +#endif |
