diff options
| author | Sandeep Panda <spanda@codeaurora.org> | 2016-11-18 14:20:06 +0530 |
|---|---|---|
| committer | Sandeep Panda <spanda@codeaurora.org> | 2016-12-16 15:51:27 +0530 |
| commit | 6a21dcc9bf61ffbb511b7d58b2744ee1b8cfddef (patch) | |
| tree | 85cf99f72adb9f0f9586d84b514e28864a4da188 | |
| parent | 3162449f7d245d45f007d4ea3224576ddf1bcc63 (diff) | |
clk: qcom: add common clock framework support for MDSS PLL
Model and configure MDSS DSI PLL using upstream clock framework
APIs. Add changes to define and register vco, divider, mux clcoks
as per common clock infrastructure.
Change-Id: Idc51070e2bb36d1a757d2714d2875a99901321a7
Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
| -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 |
