* [PATCH v2 0/5] clk: qcom: Add support for SM8150 GCC @ 2019-06-12 9:17 Vinod Koul 2019-06-12 9:17 ` [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast Vinod Koul ` (3 more replies) 0 siblings, 4 replies; 14+ messages in thread From: Vinod Koul @ 2019-06-12 9:17 UTC (permalink / raw) To: Stephen Boyd Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Deepak Katragadda, Andy Gross, David Brown, Michael Turquette, linux-clk, Taniya Das This series adds suport for SM8150 GCC which requires Trion PLLs and adds that as well. Also fixed some minor nits seen in clk-alpha-pll code and module alias for qcs404 gcc driver. Changes since v2: - add more descripton on changes done on patches for upstreaming - fix comments by Stephen and convert clk driver to use modern way of specifying clk parent names. - Add 3 patches for issues seen in code Deepak Katragadda (2): clk: qcom: clk-alpha-pll: Add support for Trion PLLs clk: qcom: gcc: Add global clock controller driver for SM8150 Vinod Koul (3): clk: qcom: clk-alpha-pll: Remove unnecessary cast clk: qcom: clk-alpha-pll: Remove post_div_table checks clk: qcom: gcc-qcs404: Add MODULE_ALIAS .../devicetree/bindings/clock/qcom,gcc.txt | 1 + drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clk-alpha-pll.c | 247 +- drivers/clk/qcom/clk-alpha-pll.h | 7 + drivers/clk/qcom/gcc-qcs404.c | 1 + drivers/clk/qcom/gcc-sm8150.c | 3720 +++++++++++++++++ include/dt-bindings/clock/qcom,gcc-sm8150.h | 243 ++ 8 files changed, 4210 insertions(+), 17 deletions(-) create mode 100644 drivers/clk/qcom/gcc-sm8150.c create mode 100644 include/dt-bindings/clock/qcom,gcc-sm8150.h Thanks -- 2.20.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast 2019-06-12 9:17 [PATCH v2 0/5] clk: qcom: Add support for SM8150 GCC Vinod Koul @ 2019-06-12 9:17 ` Vinod Koul 2019-06-17 4:37 ` Bjorn Andersson 2019-06-12 9:17 ` [PATCH v2 2/5] clk: qcom: clk-alpha-pll: Remove post_div_table checks Vinod Koul ` (2 subsequent siblings) 3 siblings, 1 reply; 14+ messages in thread From: Vinod Koul @ 2019-06-12 9:17 UTC (permalink / raw) To: Stephen Boyd Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Andy Gross, David Brown, Michael Turquette, linux-clk We have couple of instances in the driver with unnecessary u64 casts, drop them. Signed-off-by: Vinod Koul <vkoul@kernel.org> --- drivers/clk/qcom/clk-alpha-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 0ced4a5a9a17..b48707693ffd 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -832,7 +832,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, int div; /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */ - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; + div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1; return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, @@ -1094,7 +1094,7 @@ static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw, return -EINVAL; } - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); + div = DIV_ROUND_UP_ULL(parent_rate, rate); for (i = 0; i < pll->num_post_div; i++) { if (pll->post_div_table[i].div == div) { val = pll->post_div_table[i].val; -- 2.20.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast 2019-06-12 9:17 ` [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast Vinod Koul @ 2019-06-17 4:37 ` Bjorn Andersson 2019-06-24 7:46 ` Vinod Koul 0 siblings, 1 reply; 14+ messages in thread From: Bjorn Andersson @ 2019-06-17 4:37 UTC (permalink / raw) To: Vinod Koul Cc: Stephen Boyd, linux-arm-msm, Andy Gross, David Brown, Michael Turquette, linux-clk On Wed 12 Jun 02:17 PDT 2019, Vinod Koul wrote: > We have couple of instances in the driver with unnecessary > u64 casts, drop them. > > Signed-off-by: Vinod Koul <vkoul@kernel.org> > --- > drivers/clk/qcom/clk-alpha-pll.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c > index 0ced4a5a9a17..b48707693ffd 100644 > --- a/drivers/clk/qcom/clk-alpha-pll.c > +++ b/drivers/clk/qcom/clk-alpha-pll.c > @@ -832,7 +832,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, > int div; > > /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */ > - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; > + div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1; Afaict DIV_ROUND_UP_ULL() will first add "parent_rate" and "rate" and then stash this in a unsigned long long and do the division. So what happens if parent_rate + rate > 32 bits on a 32-bit target? (Shouldn't there be a cast of (ll) in the macro to ULL?) Regards, Bjorn > > return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), > PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, > @@ -1094,7 +1094,7 @@ static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw, > return -EINVAL; > } > > - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); > + div = DIV_ROUND_UP_ULL(parent_rate, rate); > for (i = 0; i < pll->num_post_div; i++) { > if (pll->post_div_table[i].div == div) { > val = pll->post_div_table[i].val; > -- > 2.20.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast 2019-06-17 4:37 ` Bjorn Andersson @ 2019-06-24 7:46 ` Vinod Koul 0 siblings, 0 replies; 14+ messages in thread From: Vinod Koul @ 2019-06-24 7:46 UTC (permalink / raw) To: Bjorn Andersson Cc: Stephen Boyd, linux-arm-msm, Andy Gross, David Brown, Michael Turquette, linux-clk On 16-06-19, 21:37, Bjorn Andersson wrote: > On Wed 12 Jun 02:17 PDT 2019, Vinod Koul wrote: > > > We have couple of instances in the driver with unnecessary > > u64 casts, drop them. > > > > Signed-off-by: Vinod Koul <vkoul@kernel.org> > > --- > > drivers/clk/qcom/clk-alpha-pll.c | 4 ++-- > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c > > index 0ced4a5a9a17..b48707693ffd 100644 > > --- a/drivers/clk/qcom/clk-alpha-pll.c > > +++ b/drivers/clk/qcom/clk-alpha-pll.c > > @@ -832,7 +832,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, > > int div; > > > > /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */ > > - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; > > + div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1; > > Afaict DIV_ROUND_UP_ULL() will first add "parent_rate" and "rate" and > then stash this in a unsigned long long and do the division. So what > happens if parent_rate + rate > 32 bits on a 32-bit target? > > (Shouldn't there be a cast of (ll) in the macro to ULL?) Agreed, though DIV_ROUND_DOWN_ULL does it correctly, right fix would be to make it: #define DIV_ROUND_UP_ULL(ll, d) DIV_ROUND_DOWN_ULL(unsigned long long(ll) + (d) - 1, (d)) I will post that as well.. Thanks -- ~Vinod ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 2/5] clk: qcom: clk-alpha-pll: Remove post_div_table checks 2019-06-12 9:17 [PATCH v2 0/5] clk: qcom: Add support for SM8150 GCC Vinod Koul 2019-06-12 9:17 ` [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast Vinod Koul @ 2019-06-12 9:17 ` Vinod Koul 2019-06-17 4:28 ` Bjorn Andersson 2019-06-12 9:17 ` [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS Vinod Koul 2019-06-12 9:17 ` [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs Vinod Koul 3 siblings, 1 reply; 14+ messages in thread From: Vinod Koul @ 2019-06-12 9:17 UTC (permalink / raw) To: Stephen Boyd Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Andy Gross, David Brown, Michael Turquette, linux-clk We want users to code properly and fix the post_div_table missing and not reply on core to check. So remove the post_div_table check. Signed-off-by: Vinod Koul <vkoul@kernel.org> --- drivers/clk/qcom/clk-alpha-pll.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index b48707693ffd..2c6773188761 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1036,11 +1036,6 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, u32 i, div = 1, val; int ret; - if (!pll->post_div_table) { - pr_err("Missing the post_div_table for the PLL\n"); - return -EINVAL; - } - ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); if (ret) return ret; @@ -1063,11 +1058,6 @@ static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, { struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); - if (!pll->post_div_table) { - pr_err("Missing the post_div_table for the PLL\n"); - return -EINVAL; - } - return divider_round_rate(hw, rate, prate, pll->post_div_table, pll->width, CLK_DIVIDER_ROUND_CLOSEST); } @@ -1089,11 +1079,6 @@ static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw, if (val & PLL_VOTE_FSM_ENA) return 0; - if (!pll->post_div_table) { - pr_err("Missing the post_div_table for the PLL\n"); - return -EINVAL; - } - div = DIV_ROUND_UP_ULL(parent_rate, rate); for (i = 0; i < pll->num_post_div; i++) { if (pll->post_div_table[i].div == div) { -- 2.20.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/5] clk: qcom: clk-alpha-pll: Remove post_div_table checks 2019-06-12 9:17 ` [PATCH v2 2/5] clk: qcom: clk-alpha-pll: Remove post_div_table checks Vinod Koul @ 2019-06-17 4:28 ` Bjorn Andersson 0 siblings, 0 replies; 14+ messages in thread From: Bjorn Andersson @ 2019-06-17 4:28 UTC (permalink / raw) To: Vinod Koul Cc: Stephen Boyd, linux-arm-msm, Andy Gross, David Brown, Michael Turquette, linux-clk On Wed 12 Jun 02:17 PDT 2019, Vinod Koul wrote: > We want users to code properly and fix the post_div_table missing and > not reply on core to check. So remove the post_div_table check. > Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> > Signed-off-by: Vinod Koul <vkoul@kernel.org> > --- > drivers/clk/qcom/clk-alpha-pll.c | 15 --------------- > 1 file changed, 15 deletions(-) > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c > index b48707693ffd..2c6773188761 100644 > --- a/drivers/clk/qcom/clk-alpha-pll.c > +++ b/drivers/clk/qcom/clk-alpha-pll.c > @@ -1036,11 +1036,6 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, > u32 i, div = 1, val; > int ret; > > - if (!pll->post_div_table) { > - pr_err("Missing the post_div_table for the PLL\n"); > - return -EINVAL; > - } > - > ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); > if (ret) > return ret; > @@ -1063,11 +1058,6 @@ static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, > { > struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > > - if (!pll->post_div_table) { > - pr_err("Missing the post_div_table for the PLL\n"); > - return -EINVAL; > - } > - > return divider_round_rate(hw, rate, prate, pll->post_div_table, > pll->width, CLK_DIVIDER_ROUND_CLOSEST); > } > @@ -1089,11 +1079,6 @@ static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw, > if (val & PLL_VOTE_FSM_ENA) > return 0; > > - if (!pll->post_div_table) { > - pr_err("Missing the post_div_table for the PLL\n"); > - return -EINVAL; > - } > - > div = DIV_ROUND_UP_ULL(parent_rate, rate); > for (i = 0; i < pll->num_post_div; i++) { > if (pll->post_div_table[i].div == div) { > -- > 2.20.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS 2019-06-12 9:17 [PATCH v2 0/5] clk: qcom: Add support for SM8150 GCC Vinod Koul 2019-06-12 9:17 ` [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast Vinod Koul 2019-06-12 9:17 ` [PATCH v2 2/5] clk: qcom: clk-alpha-pll: Remove post_div_table checks Vinod Koul @ 2019-06-12 9:17 ` Vinod Koul 2019-06-17 4:26 ` Bjorn Andersson 2019-06-12 9:17 ` [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs Vinod Koul 3 siblings, 1 reply; 14+ messages in thread From: Vinod Koul @ 2019-06-12 9:17 UTC (permalink / raw) To: Stephen Boyd Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Andy Gross, David Brown, Michael Turquette, linux-clk MODULE_ALIAS was missing for this driver which can be built as a module, so add the MODULE_ALIAS. Signed-off-by: Vinod Koul <vkoul@kernel.org> --- drivers/clk/qcom/gcc-qcs404.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c index a54807eb3b28..eb3ac7a26fb8 100644 --- a/drivers/clk/qcom/gcc-qcs404.c +++ b/drivers/clk/qcom/gcc-qcs404.c @@ -2828,3 +2828,4 @@ module_exit(gcc_qcs404_exit); MODULE_DESCRIPTION("Qualcomm GCC QCS404 Driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gcc-qcs404"); -- 2.20.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS 2019-06-12 9:17 ` [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS Vinod Koul @ 2019-06-17 4:26 ` Bjorn Andersson 2019-06-24 7:55 ` Vinod Koul 0 siblings, 1 reply; 14+ messages in thread From: Bjorn Andersson @ 2019-06-17 4:26 UTC (permalink / raw) To: Vinod Koul Cc: Stephen Boyd, linux-arm-msm, Andy Gross, David Brown, Michael Turquette, linux-clk On Wed 12 Jun 02:17 PDT 2019, Vinod Koul wrote: > MODULE_ALIAS was missing for this driver which can be built as a > module, so add the MODULE_ALIAS. > MODULE_ALIAS() serves the purpose of providing an module alias for the driver, which allows the automatic kernel module loader to insmod the driver as a device needing it is being registered. When the device is instantiated through the OF code path the compatible will be matched against the MODULE_DEVICE_TABLE(of, ) and if the device is programmatically registered (through platform_device_register_*()) then the alias "platform:XYZ" will be used. So, unless we're going to support module autoloading of this driver from a board file no alias should be needed. Regards, Bjorn > Signed-off-by: Vinod Koul <vkoul@kernel.org> > --- > drivers/clk/qcom/gcc-qcs404.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c > index a54807eb3b28..eb3ac7a26fb8 100644 > --- a/drivers/clk/qcom/gcc-qcs404.c > +++ b/drivers/clk/qcom/gcc-qcs404.c > @@ -2828,3 +2828,4 @@ module_exit(gcc_qcs404_exit); > > MODULE_DESCRIPTION("Qualcomm GCC QCS404 Driver"); > MODULE_LICENSE("GPL v2"); > +MODULE_ALIAS("platform:gcc-qcs404"); > -- > 2.20.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS 2019-06-17 4:26 ` Bjorn Andersson @ 2019-06-24 7:55 ` Vinod Koul 0 siblings, 0 replies; 14+ messages in thread From: Vinod Koul @ 2019-06-24 7:55 UTC (permalink / raw) To: Bjorn Andersson Cc: Stephen Boyd, linux-arm-msm, Andy Gross, David Brown, Michael Turquette, linux-clk On 16-06-19, 21:26, Bjorn Andersson wrote: > On Wed 12 Jun 02:17 PDT 2019, Vinod Koul wrote: > > > MODULE_ALIAS was missing for this driver which can be built as a > > module, so add the MODULE_ALIAS. > > > > MODULE_ALIAS() serves the purpose of providing an module alias for the > driver, which allows the automatic kernel module loader to insmod the > driver as a device needing it is being registered. > > When the device is instantiated through the OF code path the compatible > will be matched against the MODULE_DEVICE_TABLE(of, ) and if the device > is programmatically registered (through platform_device_register_*()) > then the alias "platform:XYZ" will be used. Thanks for the explanation Bjorn :) > > So, unless we're going to support module autoloading of this driver from > a board file no alias should be needed. Nope we dont, so will drop this one and as well as from SM8150 driver -- ~Vinod ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs 2019-06-12 9:17 [PATCH v2 0/5] clk: qcom: Add support for SM8150 GCC Vinod Koul ` (2 preceding siblings ...) 2019-06-12 9:17 ` [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS Vinod Koul @ 2019-06-12 9:17 ` Vinod Koul 2019-06-13 3:04 ` Taniya Das 3 siblings, 1 reply; 14+ messages in thread From: Vinod Koul @ 2019-06-12 9:17 UTC (permalink / raw) To: Stephen Boyd Cc: linux-arm-msm, Bjorn Andersson, Deepak Katragadda, Andy Gross, David Brown, Michael Turquette, linux-clk, Taniya Das, Vinod Koul From: Deepak Katragadda <dkatraga@codeaurora.org> Add programming sequence support for managing the Trion PLLs. Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org> Signed-off-by: Taniya Das <tdas@codeaurora.org> [vkoul: Fix style and format issues convert to use pll type infrastructure remove unnecessary checks in code remove unused code] Signed-off-by: Vinod Koul <vkoul@kernel.org> --- drivers/clk/qcom/clk-alpha-pll.c | 228 +++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 7 + 2 files changed, 235 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 2c6773188761..30210f5c6726 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -32,6 +32,7 @@ # define PLL_LOCK_DET BIT(31) #define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL]) +#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL]) #define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL]) #define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U]) @@ -44,14 +45,17 @@ # define PLL_VCO_MASK 0x3 #define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U]) +#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1]) #define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) #define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) +#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U11]) #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) +#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL]) const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [CLK_ALPHA_PLL_TYPE_DEFAULT] = { @@ -96,6 +100,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_OPMODE] = 0x2c, [PLL_OFF_FRAC] = 0x38, }, + [CLK_ALPHA_PLL_TYPE_TRION] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_CAL_L_VAL] = 0x08, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_USER_CTL_U] = 0x10, + [PLL_OFF_USER_CTL_U1] = 0x14, + [PLL_OFF_CONFIG_CTL] = 0x18, + [PLL_OFF_CONFIG_CTL_U] = 0x1c, + [PLL_OFF_CONFIG_CTL_U1] = 0x20, + [PLL_OFF_TEST_CTL] = 0x24, + [PLL_OFF_TEST_CTL_U] = 0x28, + [PLL_OFF_STATUS] = 0x30, + [PLL_OFF_OPMODE] = 0x38, + [PLL_OFF_ALPHA_VAL] = 0x40, + [PLL_OFF_CAL_VAL] = 0x44, + }, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); @@ -120,6 +140,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define FABIA_PLL_OUT_MASK 0x7 #define FABIA_PLL_RATE_MARGIN 500 +#define TRION_PLL_STANDBY 0x0 +#define TRION_PLL_RUN 0x1 +#define TRION_PLL_OUT_MASK 0x7 + #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) @@ -730,6 +754,130 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate, return alpha_huayra_pll_round_rate(rate, *prate, &l, &a); } +static int trion_pll_is_enabled(struct clk_alpha_pll *pll, + struct regmap *regmap) +{ + u32 mode_regval, opmode_regval; + int ret; + + ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval); + ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval); + if (ret) + return 0; + + return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL)); +} + +static int clk_trion_pll_is_enabled(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + + return trion_pll_is_enabled(pll, pll->clkr.regmap); +} + +static int clk_trion_pll_enable(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 val; + int ret; + + ret = regmap_read(regmap, PLL_MODE(pll), &val); + if (ret) + return ret; + + /* If in FSM mode, just vote for it */ + if (val & PLL_VOTE_FSM_ENA) { + ret = clk_enable_regmap(hw); + if (ret) + return ret; + return wait_for_pll_enable_active(pll); + } + + /* Set operation mode to RUN */ + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN); + + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + + /* Enable the PLL outputs */ + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), + TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK); + if (ret) + return ret; + + /* Enable the global PLL outputs */ + return regmap_update_bits(regmap, PLL_MODE(pll), + PLL_OUTCTRL, PLL_OUTCTRL); +} + +static void clk_trion_pll_disable(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 val; + int ret; + + ret = regmap_read(regmap, PLL_MODE(pll), &val); + if (ret) + return; + + /* If in FSM mode, just unvote it */ + if (val & PLL_VOTE_FSM_ENA) { + clk_disable_regmap(hw); + return; + } + + /* Disable the global PLL output */ + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + if (ret) + return; + + /* Disable the PLL outputs */ + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), + TRION_PLL_OUT_MASK, 0); + if (ret) + return; + + /* Place the PLL mode in STANDBY */ + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY); + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); +} + +static unsigned long +clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 l, frac; + u64 prate = parent_rate; + + regmap_read(regmap, PLL_L_VAL(pll), &l); + regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); + + return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH); +} + +static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + unsigned long min_freq, max_freq; + u32 l; + u64 a; + + rate = alpha_pll_round_rate(rate, *prate, + &l, &a, ALPHA_REG_16BIT_WIDTH); + if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) + return rate; + + min_freq = pll->vco_table[0].min_freq; + max_freq = pll->vco_table[pll->num_vco - 1].max_freq; + + return clamp(rate, min_freq, max_freq); +} + const struct clk_ops clk_alpha_pll_ops = { .enable = clk_alpha_pll_enable, .disable = clk_alpha_pll_disable, @@ -760,6 +908,15 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { }; EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); +const struct clk_ops clk_trion_fixed_pll_ops = { + .enable = clk_trion_pll_enable, + .disable = clk_trion_pll_disable, + .is_enabled = clk_trion_pll_is_enabled, + .recalc_rate = clk_trion_pll_recalc_rate, + .round_rate = clk_trion_pll_round_rate, +}; +EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops); + static unsigned long clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -1053,6 +1210,77 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, return (parent_rate / div); } +static unsigned long +clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 i, div = 1, val; + + regmap_read(regmap, PLL_USER_CTL(pll), &val); + + val >>= pll->post_div_shift; + val &= PLL_POST_DIV_MASK(pll); + + for (i = 0; i < pll->num_post_div; i++) { + if (pll->post_div_table[i].val == val) { + div = pll->post_div_table[i].div; + break; + } + } + + return (parent_rate / div); +} + +static long +clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + + return divider_round_rate(hw, rate, prate, pll->post_div_table, + pll->width, CLK_DIVIDER_ROUND_CLOSEST); +}; + +static int +clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + struct regmap *regmap = pll->clkr.regmap; + int i, val = 0, div, ret; + + /* + * If the PLL is in FSM mode, then treat the set_rate callback + * as a no-operation. + */ + ret = regmap_read(regmap, PLL_MODE(pll), &val); + if (ret) + return ret; + + if (val & PLL_VOTE_FSM_ENA) + return 0; + + div = DIV_ROUND_UP_ULL(parent_rate, rate); + for (i = 0; i < pll->num_post_div; i++) { + if (pll->post_div_table[i].div == div) { + val = pll->post_div_table[i].val; + break; + } + } + + return regmap_update_bits(regmap, PLL_USER_CTL(pll), + PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, + val << PLL_POST_DIV_SHIFT); +} + +const struct clk_ops clk_trion_pll_postdiv_ops = { + .recalc_rate = clk_trion_pll_postdiv_recalc_rate, + .round_rate = clk_trion_pll_postdiv_round_rate, + .set_rate = clk_trion_pll_postdiv_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops); + static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 66755f0f84fc..15f27f4b06df 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -13,22 +13,27 @@ enum { CLK_ALPHA_PLL_TYPE_HUAYRA, CLK_ALPHA_PLL_TYPE_BRAMMO, CLK_ALPHA_PLL_TYPE_FABIA, + CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_MAX, }; enum { PLL_OFF_L_VAL, + PLL_OFF_CAL_L_VAL, PLL_OFF_ALPHA_VAL, PLL_OFF_ALPHA_VAL_U, PLL_OFF_USER_CTL, PLL_OFF_USER_CTL_U, + PLL_OFF_USER_CTL_U1, PLL_OFF_CONFIG_CTL, PLL_OFF_CONFIG_CTL_U, + PLL_OFF_CONFIG_CTL_U1, PLL_OFF_TEST_CTL, PLL_OFF_TEST_CTL_U, PLL_OFF_STATUS, PLL_OFF_OPMODE, PLL_OFF_FRAC, + PLL_OFF_CAL_VAL, PLL_OFF_MAX_REGS }; @@ -117,5 +122,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); +extern const struct clk_ops clk_trion_fixed_pll_ops; +extern const struct clk_ops clk_trion_pll_postdiv_ops; #endif -- 2.20.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs 2019-06-12 9:17 ` [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs Vinod Koul @ 2019-06-13 3:04 ` Taniya Das 2019-06-14 5:42 ` Vinod Koul 0 siblings, 1 reply; 14+ messages in thread From: Taniya Das @ 2019-06-13 3:04 UTC (permalink / raw) To: Vinod Koul, Stephen Boyd Cc: linux-arm-msm, Bjorn Andersson, Deepak Katragadda, Andy Gross, David Brown, Michael Turquette, linux-clk Hi Vinod, The trion PLL needs to be configured before it is enabled. The PLL cannot LOCK without the calibration. Could you please add "clk_trion_pll_configure()" function? On 6/12/2019 2:47 PM, Vinod Koul wrote: > From: Deepak Katragadda <dkatraga@codeaurora.org> > > Add programming sequence support for managing the Trion > PLLs. > > Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org> > Signed-off-by: Taniya Das <tdas@codeaurora.org> > [vkoul: Fix style and format issues > convert to use pll type infrastructure > remove unnecessary checks in code > remove unused code] > Signed-off-by: Vinod Koul <vkoul@kernel.org> > --- > drivers/clk/qcom/clk-alpha-pll.c | 228 +++++++++++++++++++++++++++++++ > drivers/clk/qcom/clk-alpha-pll.h | 7 + > 2 files changed, 235 insertions(+) > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c > index 2c6773188761..30210f5c6726 100644 > --- a/drivers/clk/qcom/clk-alpha-pll.c > +++ b/drivers/clk/qcom/clk-alpha-pll.c > @@ -32,6 +32,7 @@ > # define PLL_LOCK_DET BIT(31) > > #define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL]) > +#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL]) > #define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL]) > #define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U]) > > @@ -44,14 +45,17 @@ > # define PLL_VCO_MASK 0x3 > > #define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U]) > +#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1]) > > #define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) > #define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) > +#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U11]) > #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) > #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) > #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) > #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) > #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) > +#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL]) > > const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { > [CLK_ALPHA_PLL_TYPE_DEFAULT] = { > @@ -96,6 +100,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { > [PLL_OFF_OPMODE] = 0x2c, > [PLL_OFF_FRAC] = 0x38, > }, > + [CLK_ALPHA_PLL_TYPE_TRION] = { > + [PLL_OFF_L_VAL] = 0x04, > + [PLL_OFF_CAL_L_VAL] = 0x08, > + [PLL_OFF_USER_CTL] = 0x0c, > + [PLL_OFF_USER_CTL_U] = 0x10, > + [PLL_OFF_USER_CTL_U1] = 0x14, > + [PLL_OFF_CONFIG_CTL] = 0x18, > + [PLL_OFF_CONFIG_CTL_U] = 0x1c, > + [PLL_OFF_CONFIG_CTL_U1] = 0x20, > + [PLL_OFF_TEST_CTL] = 0x24, > + [PLL_OFF_TEST_CTL_U] = 0x28, > + [PLL_OFF_STATUS] = 0x30, > + [PLL_OFF_OPMODE] = 0x38, > + [PLL_OFF_ALPHA_VAL] = 0x40, > + [PLL_OFF_CAL_VAL] = 0x44, > + }, > }; > EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); > > @@ -120,6 +140,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); > #define FABIA_PLL_OUT_MASK 0x7 > #define FABIA_PLL_RATE_MARGIN 500 > > +#define TRION_PLL_STANDBY 0x0 > +#define TRION_PLL_RUN 0x1 > +#define TRION_PLL_OUT_MASK 0x7 > + > #define pll_alpha_width(p) \ > ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ > ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) > @@ -730,6 +754,130 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate, > return alpha_huayra_pll_round_rate(rate, *prate, &l, &a); > } > > +static int trion_pll_is_enabled(struct clk_alpha_pll *pll, > + struct regmap *regmap) > +{ > + u32 mode_regval, opmode_regval; > + int ret; > + > + ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval); > + ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval); > + if (ret) > + return 0; > + > + return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL)); > +} > + > +static int clk_trion_pll_is_enabled(struct clk_hw *hw) > +{ > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > + > + return trion_pll_is_enabled(pll, pll->clkr.regmap); > +} > + > +static int clk_trion_pll_enable(struct clk_hw *hw) > +{ > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > + struct regmap *regmap = pll->clkr.regmap; > + u32 val; > + int ret; > + > + ret = regmap_read(regmap, PLL_MODE(pll), &val); > + if (ret) > + return ret; > + > + /* If in FSM mode, just vote for it */ > + if (val & PLL_VOTE_FSM_ENA) { > + ret = clk_enable_regmap(hw); > + if (ret) > + return ret; > + return wait_for_pll_enable_active(pll); > + } > + > + /* Set operation mode to RUN */ > + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN); > + > + ret = wait_for_pll_enable_lock(pll); > + if (ret) > + return ret; > + > + /* Enable the PLL outputs */ > + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), > + TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK); > + if (ret) > + return ret; > + > + /* Enable the global PLL outputs */ > + return regmap_update_bits(regmap, PLL_MODE(pll), > + PLL_OUTCTRL, PLL_OUTCTRL); > +} > + > +static void clk_trion_pll_disable(struct clk_hw *hw) > +{ > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > + struct regmap *regmap = pll->clkr.regmap; > + u32 val; > + int ret; > + > + ret = regmap_read(regmap, PLL_MODE(pll), &val); > + if (ret) > + return; > + > + /* If in FSM mode, just unvote it */ > + if (val & PLL_VOTE_FSM_ENA) { > + clk_disable_regmap(hw); > + return; > + } > + > + /* Disable the global PLL output */ > + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); > + if (ret) > + return; > + > + /* Disable the PLL outputs */ > + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), > + TRION_PLL_OUT_MASK, 0); > + if (ret) > + return; > + > + /* Place the PLL mode in STANDBY */ > + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY); > + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); > +} > + > +static unsigned long > +clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) > +{ > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > + struct regmap *regmap = pll->clkr.regmap; > + u32 l, frac; > + u64 prate = parent_rate; > + > + regmap_read(regmap, PLL_L_VAL(pll), &l); > + regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); > + > + return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH); > +} > + > +static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate, > + unsigned long *prate) > +{ > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > + unsigned long min_freq, max_freq; > + u32 l; > + u64 a; > + > + rate = alpha_pll_round_rate(rate, *prate, > + &l, &a, ALPHA_REG_16BIT_WIDTH); > + if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) > + return rate; > + > + min_freq = pll->vco_table[0].min_freq; > + max_freq = pll->vco_table[pll->num_vco - 1].max_freq; > + > + return clamp(rate, min_freq, max_freq); > +} > + > const struct clk_ops clk_alpha_pll_ops = { > .enable = clk_alpha_pll_enable, > .disable = clk_alpha_pll_disable, > @@ -760,6 +908,15 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { > }; > EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); > > +const struct clk_ops clk_trion_fixed_pll_ops = { > + .enable = clk_trion_pll_enable, > + .disable = clk_trion_pll_disable, > + .is_enabled = clk_trion_pll_is_enabled, > + .recalc_rate = clk_trion_pll_recalc_rate, > + .round_rate = clk_trion_pll_round_rate, > +}; > +EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops); > + > static unsigned long > clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) > { > @@ -1053,6 +1210,77 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, > return (parent_rate / div); > } > > +static unsigned long > +clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) > +{ > + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > + struct regmap *regmap = pll->clkr.regmap; > + u32 i, div = 1, val; > + > + regmap_read(regmap, PLL_USER_CTL(pll), &val); > + > + val >>= pll->post_div_shift; > + val &= PLL_POST_DIV_MASK(pll); > + > + for (i = 0; i < pll->num_post_div; i++) { > + if (pll->post_div_table[i].val == val) { > + div = pll->post_div_table[i].div; > + break; > + } > + } > + > + return (parent_rate / div); > +} > + > +static long > +clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, > + unsigned long *prate) > +{ > + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > + > + return divider_round_rate(hw, rate, prate, pll->post_div_table, > + pll->width, CLK_DIVIDER_ROUND_CLOSEST); > +}; > + > +static int > +clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, > + unsigned long parent_rate) > +{ > + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > + struct regmap *regmap = pll->clkr.regmap; > + int i, val = 0, div, ret; > + > + /* > + * If the PLL is in FSM mode, then treat the set_rate callback > + * as a no-operation. > + */ > + ret = regmap_read(regmap, PLL_MODE(pll), &val); > + if (ret) > + return ret; > + > + if (val & PLL_VOTE_FSM_ENA) > + return 0; > + > + div = DIV_ROUND_UP_ULL(parent_rate, rate); > + for (i = 0; i < pll->num_post_div; i++) { > + if (pll->post_div_table[i].div == div) { > + val = pll->post_div_table[i].val; > + break; > + } > + } > + > + return regmap_update_bits(regmap, PLL_USER_CTL(pll), > + PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, > + val << PLL_POST_DIV_SHIFT); > +} > + > +const struct clk_ops clk_trion_pll_postdiv_ops = { > + .recalc_rate = clk_trion_pll_postdiv_recalc_rate, > + .round_rate = clk_trion_pll_postdiv_round_rate, > + .set_rate = clk_trion_pll_postdiv_set_rate, > +}; > +EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops); > + > static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, > unsigned long rate, unsigned long *prate) > { > diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h > index 66755f0f84fc..15f27f4b06df 100644 > --- a/drivers/clk/qcom/clk-alpha-pll.h > +++ b/drivers/clk/qcom/clk-alpha-pll.h > @@ -13,22 +13,27 @@ enum { > CLK_ALPHA_PLL_TYPE_HUAYRA, > CLK_ALPHA_PLL_TYPE_BRAMMO, > CLK_ALPHA_PLL_TYPE_FABIA, > + CLK_ALPHA_PLL_TYPE_TRION, > CLK_ALPHA_PLL_TYPE_MAX, > }; > > enum { > PLL_OFF_L_VAL, > + PLL_OFF_CAL_L_VAL, > PLL_OFF_ALPHA_VAL, > PLL_OFF_ALPHA_VAL_U, > PLL_OFF_USER_CTL, > PLL_OFF_USER_CTL_U, > + PLL_OFF_USER_CTL_U1, > PLL_OFF_CONFIG_CTL, > PLL_OFF_CONFIG_CTL_U, > + PLL_OFF_CONFIG_CTL_U1, > PLL_OFF_TEST_CTL, > PLL_OFF_TEST_CTL_U, > PLL_OFF_STATUS, > PLL_OFF_OPMODE, > PLL_OFF_FRAC, > + PLL_OFF_CAL_VAL, > PLL_OFF_MAX_REGS > }; > > @@ -117,5 +122,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, > const struct alpha_pll_config *config); > void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, > const struct alpha_pll_config *config); > +extern const struct clk_ops clk_trion_fixed_pll_ops; > +extern const struct clk_ops clk_trion_pll_postdiv_ops; > > #endif > -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation. -- ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs 2019-06-13 3:04 ` Taniya Das @ 2019-06-14 5:42 ` Vinod Koul 2019-06-17 6:10 ` Taniya Das 0 siblings, 1 reply; 14+ messages in thread From: Vinod Koul @ 2019-06-14 5:42 UTC (permalink / raw) To: Taniya Das Cc: Stephen Boyd, linux-arm-msm, Bjorn Andersson, Deepak Katragadda, Andy Gross, David Brown, Michael Turquette, linux-clk Hi Taniya, On 13-06-19, 08:34, Taniya Das wrote: > Hi Vinod, > > The trion PLL needs to be configured before it is enabled. The PLL cannot > LOCK without the calibration. > > Could you please add "clk_trion_pll_configure()" function? First it is not recommended to top post! Please reply inline. Yes I did see that, I will check that. Is there any way to find PLL is configured or not? I want to avoid using inited variable as done in downstream. Thanks > On 6/12/2019 2:47 PM, Vinod Koul wrote: > > From: Deepak Katragadda <dkatraga@codeaurora.org> > > > > Add programming sequence support for managing the Trion > > PLLs. > > > > Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org> > > Signed-off-by: Taniya Das <tdas@codeaurora.org> > > [vkoul: Fix style and format issues > > convert to use pll type infrastructure > > remove unnecessary checks in code > > remove unused code] > > Signed-off-by: Vinod Koul <vkoul@kernel.org> > > --- > > drivers/clk/qcom/clk-alpha-pll.c | 228 +++++++++++++++++++++++++++++++ > > drivers/clk/qcom/clk-alpha-pll.h | 7 + > > 2 files changed, 235 insertions(+) > > > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c > > index 2c6773188761..30210f5c6726 100644 > > --- a/drivers/clk/qcom/clk-alpha-pll.c > > +++ b/drivers/clk/qcom/clk-alpha-pll.c > > @@ -32,6 +32,7 @@ > > # define PLL_LOCK_DET BIT(31) > > #define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL]) > > +#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL]) > > #define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL]) > > #define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U]) > > @@ -44,14 +45,17 @@ > > # define PLL_VCO_MASK 0x3 > > #define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U]) > > +#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1]) > > #define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) > > #define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) > > +#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U11]) > > #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) > > #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) > > #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) > > #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) > > #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) > > +#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL]) > > const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { > > [CLK_ALPHA_PLL_TYPE_DEFAULT] = { > > @@ -96,6 +100,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { > > [PLL_OFF_OPMODE] = 0x2c, > > [PLL_OFF_FRAC] = 0x38, > > }, > > + [CLK_ALPHA_PLL_TYPE_TRION] = { > > + [PLL_OFF_L_VAL] = 0x04, > > + [PLL_OFF_CAL_L_VAL] = 0x08, > > + [PLL_OFF_USER_CTL] = 0x0c, > > + [PLL_OFF_USER_CTL_U] = 0x10, > > + [PLL_OFF_USER_CTL_U1] = 0x14, > > + [PLL_OFF_CONFIG_CTL] = 0x18, > > + [PLL_OFF_CONFIG_CTL_U] = 0x1c, > > + [PLL_OFF_CONFIG_CTL_U1] = 0x20, > > + [PLL_OFF_TEST_CTL] = 0x24, > > + [PLL_OFF_TEST_CTL_U] = 0x28, > > + [PLL_OFF_STATUS] = 0x30, > > + [PLL_OFF_OPMODE] = 0x38, > > + [PLL_OFF_ALPHA_VAL] = 0x40, > > + [PLL_OFF_CAL_VAL] = 0x44, > > + }, > > }; > > EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); > > @@ -120,6 +140,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); > > #define FABIA_PLL_OUT_MASK 0x7 > > #define FABIA_PLL_RATE_MARGIN 500 > > +#define TRION_PLL_STANDBY 0x0 > > +#define TRION_PLL_RUN 0x1 > > +#define TRION_PLL_OUT_MASK 0x7 > > + > > #define pll_alpha_width(p) \ > > ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ > > ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) > > @@ -730,6 +754,130 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate, > > return alpha_huayra_pll_round_rate(rate, *prate, &l, &a); > > } > > +static int trion_pll_is_enabled(struct clk_alpha_pll *pll, > > + struct regmap *regmap) > > +{ > > + u32 mode_regval, opmode_regval; > > + int ret; > > + > > + ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval); > > + ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval); > > + if (ret) > > + return 0; > > + > > + return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL)); > > +} > > + > > +static int clk_trion_pll_is_enabled(struct clk_hw *hw) > > +{ > > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > > + > > + return trion_pll_is_enabled(pll, pll->clkr.regmap); > > +} > > + > > +static int clk_trion_pll_enable(struct clk_hw *hw) > > +{ > > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > > + struct regmap *regmap = pll->clkr.regmap; > > + u32 val; > > + int ret; > > + > > + ret = regmap_read(regmap, PLL_MODE(pll), &val); > > + if (ret) > > + return ret; > > + > > + /* If in FSM mode, just vote for it */ > > + if (val & PLL_VOTE_FSM_ENA) { > > + ret = clk_enable_regmap(hw); > > + if (ret) > > + return ret; > > + return wait_for_pll_enable_active(pll); > > + } > > + > > + /* Set operation mode to RUN */ > > + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN); > > + > > + ret = wait_for_pll_enable_lock(pll); > > + if (ret) > > + return ret; > > + > > + /* Enable the PLL outputs */ > > + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), > > + TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK); > > + if (ret) > > + return ret; > > + > > + /* Enable the global PLL outputs */ > > + return regmap_update_bits(regmap, PLL_MODE(pll), > > + PLL_OUTCTRL, PLL_OUTCTRL); > > +} > > + > > +static void clk_trion_pll_disable(struct clk_hw *hw) > > +{ > > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > > + struct regmap *regmap = pll->clkr.regmap; > > + u32 val; > > + int ret; > > + > > + ret = regmap_read(regmap, PLL_MODE(pll), &val); > > + if (ret) > > + return; > > + > > + /* If in FSM mode, just unvote it */ > > + if (val & PLL_VOTE_FSM_ENA) { > > + clk_disable_regmap(hw); > > + return; > > + } > > + > > + /* Disable the global PLL output */ > > + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); > > + if (ret) > > + return; > > + > > + /* Disable the PLL outputs */ > > + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), > > + TRION_PLL_OUT_MASK, 0); > > + if (ret) > > + return; > > + > > + /* Place the PLL mode in STANDBY */ > > + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY); > > + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); > > +} > > + > > +static unsigned long > > +clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) > > +{ > > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > > + struct regmap *regmap = pll->clkr.regmap; > > + u32 l, frac; > > + u64 prate = parent_rate; > > + > > + regmap_read(regmap, PLL_L_VAL(pll), &l); > > + regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); > > + > > + return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH); > > +} > > + > > +static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate, > > + unsigned long *prate) > > +{ > > + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); > > + unsigned long min_freq, max_freq; > > + u32 l; > > + u64 a; > > + > > + rate = alpha_pll_round_rate(rate, *prate, > > + &l, &a, ALPHA_REG_16BIT_WIDTH); > > + if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) > > + return rate; > > + > > + min_freq = pll->vco_table[0].min_freq; > > + max_freq = pll->vco_table[pll->num_vco - 1].max_freq; > > + > > + return clamp(rate, min_freq, max_freq); > > +} > > + > > const struct clk_ops clk_alpha_pll_ops = { > > .enable = clk_alpha_pll_enable, > > .disable = clk_alpha_pll_disable, > > @@ -760,6 +908,15 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { > > }; > > EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); > > +const struct clk_ops clk_trion_fixed_pll_ops = { > > + .enable = clk_trion_pll_enable, > > + .disable = clk_trion_pll_disable, > > + .is_enabled = clk_trion_pll_is_enabled, > > + .recalc_rate = clk_trion_pll_recalc_rate, > > + .round_rate = clk_trion_pll_round_rate, > > +}; > > +EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops); > > + > > static unsigned long > > clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) > > { > > @@ -1053,6 +1210,77 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, > > return (parent_rate / div); > > } > > +static unsigned long > > +clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) > > +{ > > + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > > + struct regmap *regmap = pll->clkr.regmap; > > + u32 i, div = 1, val; > > + > > + regmap_read(regmap, PLL_USER_CTL(pll), &val); > > + > > + val >>= pll->post_div_shift; > > + val &= PLL_POST_DIV_MASK(pll); > > + > > + for (i = 0; i < pll->num_post_div; i++) { > > + if (pll->post_div_table[i].val == val) { > > + div = pll->post_div_table[i].div; > > + break; > > + } > > + } > > + > > + return (parent_rate / div); > > +} > > + > > +static long > > +clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, > > + unsigned long *prate) > > +{ > > + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > > + > > + return divider_round_rate(hw, rate, prate, pll->post_div_table, > > + pll->width, CLK_DIVIDER_ROUND_CLOSEST); > > +}; > > + > > +static int > > +clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, > > + unsigned long parent_rate) > > +{ > > + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); > > + struct regmap *regmap = pll->clkr.regmap; > > + int i, val = 0, div, ret; > > + > > + /* > > + * If the PLL is in FSM mode, then treat the set_rate callback > > + * as a no-operation. > > + */ > > + ret = regmap_read(regmap, PLL_MODE(pll), &val); > > + if (ret) > > + return ret; > > + > > + if (val & PLL_VOTE_FSM_ENA) > > + return 0; > > + > > + div = DIV_ROUND_UP_ULL(parent_rate, rate); > > + for (i = 0; i < pll->num_post_div; i++) { > > + if (pll->post_div_table[i].div == div) { > > + val = pll->post_div_table[i].val; > > + break; > > + } > > + } > > + > > + return regmap_update_bits(regmap, PLL_USER_CTL(pll), > > + PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, > > + val << PLL_POST_DIV_SHIFT); > > +} > > + > > +const struct clk_ops clk_trion_pll_postdiv_ops = { > > + .recalc_rate = clk_trion_pll_postdiv_recalc_rate, > > + .round_rate = clk_trion_pll_postdiv_round_rate, > > + .set_rate = clk_trion_pll_postdiv_set_rate, > > +}; > > +EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops); > > + > > static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, > > unsigned long rate, unsigned long *prate) > > { > > diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h > > index 66755f0f84fc..15f27f4b06df 100644 > > --- a/drivers/clk/qcom/clk-alpha-pll.h > > +++ b/drivers/clk/qcom/clk-alpha-pll.h > > @@ -13,22 +13,27 @@ enum { > > CLK_ALPHA_PLL_TYPE_HUAYRA, > > CLK_ALPHA_PLL_TYPE_BRAMMO, > > CLK_ALPHA_PLL_TYPE_FABIA, > > + CLK_ALPHA_PLL_TYPE_TRION, > > CLK_ALPHA_PLL_TYPE_MAX, > > }; > > enum { > > PLL_OFF_L_VAL, > > + PLL_OFF_CAL_L_VAL, > > PLL_OFF_ALPHA_VAL, > > PLL_OFF_ALPHA_VAL_U, > > PLL_OFF_USER_CTL, > > PLL_OFF_USER_CTL_U, > > + PLL_OFF_USER_CTL_U1, > > PLL_OFF_CONFIG_CTL, > > PLL_OFF_CONFIG_CTL_U, > > + PLL_OFF_CONFIG_CTL_U1, > > PLL_OFF_TEST_CTL, > > PLL_OFF_TEST_CTL_U, > > PLL_OFF_STATUS, > > PLL_OFF_OPMODE, > > PLL_OFF_FRAC, > > + PLL_OFF_CAL_VAL, > > PLL_OFF_MAX_REGS > > }; > > @@ -117,5 +122,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, > > const struct alpha_pll_config *config); > > void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, > > const struct alpha_pll_config *config); > > +extern const struct clk_ops clk_trion_fixed_pll_ops; > > +extern const struct clk_ops clk_trion_pll_postdiv_ops; > > #endif > > > > -- > QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member > of Code Aurora Forum, hosted by The Linux Foundation. > > -- -- ~Vinod ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs 2019-06-14 5:42 ` Vinod Koul @ 2019-06-17 6:10 ` Taniya Das 2019-06-17 6:16 ` Vinod Koul 0 siblings, 1 reply; 14+ messages in thread From: Taniya Das @ 2019-06-17 6:10 UTC (permalink / raw) To: Vinod Koul Cc: Stephen Boyd, linux-arm-msm, Bjorn Andersson, Deepak Katragadda, Andy Gross, David Brown, Michael Turquette, linux-clk Hi Vinod, On 6/14/2019 11:12 AM, Vinod Koul wrote: > Hi Taniya, > > On 13-06-19, 08:34, Taniya Das wrote: >> Hi Vinod, >> >> The trion PLL needs to be configured before it is enabled. The PLL cannot >> LOCK without the calibration. >> >> Could you please add "clk_trion_pll_configure()" function? > > First it is not recommended to top post! Please reply inline. > > Yes I did see that, I will check that. Is there any way to find PLL is > configured or not? I want to avoid using inited variable as done in > downstream. > These PLLs which are controlled by High Level OS would not be configured and we should not rely on the configurations which are done previously for these PLLs. > Thanks > >> On 6/12/2019 2:47 PM, Vinod Koul wrote: >>> From: Deepak Katragadda <dkatraga@codeaurora.org> >>> >>> Add programming sequence support for managing the Trion >>> PLLs. >>> >>> Signed-off-by: Deepak Katragadda <dkatraga@codeaurora.org> >>> Signed-off-by: Taniya Das <tdas@codeaurora.org> >>> [vkoul: Fix style and format issues >>> convert to use pll type infrastructure >>> remove unnecessary checks in code >>> remove unused code] >>> Signed-off-by: Vinod Koul <vkoul@kernel.org> >>> --- >>> drivers/clk/qcom/clk-alpha-pll.c | 228 +++++++++++++++++++++++++++++++ >>> drivers/clk/qcom/clk-alpha-pll.h | 7 + >>> 2 files changed, 235 insertions(+) >>> >>> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c >>> index 2c6773188761..30210f5c6726 100644 >>> --- a/drivers/clk/qcom/clk-alpha-pll.c >>> +++ b/drivers/clk/qcom/clk-alpha-pll.c >>> @@ -32,6 +32,7 @@ >>> # define PLL_LOCK_DET BIT(31) >>> #define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL]) >>> +#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL]) >>> #define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL]) >>> #define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U]) >>> @@ -44,14 +45,17 @@ >>> # define PLL_VCO_MASK 0x3 >>> #define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U]) >>> +#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1]) >>> #define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) >>> #define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) >>> +#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U11]) >>> #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) >>> #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) >>> #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) >>> #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) >>> #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) >>> +#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL]) >>> const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { >>> [CLK_ALPHA_PLL_TYPE_DEFAULT] = { >>> @@ -96,6 +100,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { >>> [PLL_OFF_OPMODE] = 0x2c, >>> [PLL_OFF_FRAC] = 0x38, >>> }, >>> + [CLK_ALPHA_PLL_TYPE_TRION] = { >>> + [PLL_OFF_L_VAL] = 0x04, >>> + [PLL_OFF_CAL_L_VAL] = 0x08, >>> + [PLL_OFF_USER_CTL] = 0x0c, >>> + [PLL_OFF_USER_CTL_U] = 0x10, >>> + [PLL_OFF_USER_CTL_U1] = 0x14, >>> + [PLL_OFF_CONFIG_CTL] = 0x18, >>> + [PLL_OFF_CONFIG_CTL_U] = 0x1c, >>> + [PLL_OFF_CONFIG_CTL_U1] = 0x20, >>> + [PLL_OFF_TEST_CTL] = 0x24, >>> + [PLL_OFF_TEST_CTL_U] = 0x28, >>> + [PLL_OFF_STATUS] = 0x30, >>> + [PLL_OFF_OPMODE] = 0x38, >>> + [PLL_OFF_ALPHA_VAL] = 0x40, >>> + [PLL_OFF_CAL_VAL] = 0x44, >>> + }, >>> }; >>> EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); >>> @@ -120,6 +140,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); >>> #define FABIA_PLL_OUT_MASK 0x7 >>> #define FABIA_PLL_RATE_MARGIN 500 >>> +#define TRION_PLL_STANDBY 0x0 >>> +#define TRION_PLL_RUN 0x1 >>> +#define TRION_PLL_OUT_MASK 0x7 >>> + >>> #define pll_alpha_width(p) \ >>> ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ >>> ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) >>> @@ -730,6 +754,130 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate, >>> return alpha_huayra_pll_round_rate(rate, *prate, &l, &a); >>> } >>> +static int trion_pll_is_enabled(struct clk_alpha_pll *pll, >>> + struct regmap *regmap) >>> +{ >>> + u32 mode_regval, opmode_regval; >>> + int ret; >>> + >>> + ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval); >>> + ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval); >>> + if (ret) >>> + return 0; >>> + >>> + return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL)); >>> +} >>> + >>> +static int clk_trion_pll_is_enabled(struct clk_hw *hw) >>> +{ >>> + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); >>> + >>> + return trion_pll_is_enabled(pll, pll->clkr.regmap); >>> +} >>> + >>> +static int clk_trion_pll_enable(struct clk_hw *hw) >>> +{ >>> + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); >>> + struct regmap *regmap = pll->clkr.regmap; >>> + u32 val; >>> + int ret; >>> + >>> + ret = regmap_read(regmap, PLL_MODE(pll), &val); >>> + if (ret) >>> + return ret; >>> + >>> + /* If in FSM mode, just vote for it */ >>> + if (val & PLL_VOTE_FSM_ENA) { >>> + ret = clk_enable_regmap(hw); >>> + if (ret) >>> + return ret; >>> + return wait_for_pll_enable_active(pll); >>> + } >>> + >>> + /* Set operation mode to RUN */ >>> + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN); >>> + >>> + ret = wait_for_pll_enable_lock(pll); >>> + if (ret) >>> + return ret; >>> + >>> + /* Enable the PLL outputs */ >>> + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), >>> + TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK); >>> + if (ret) >>> + return ret; >>> + >>> + /* Enable the global PLL outputs */ >>> + return regmap_update_bits(regmap, PLL_MODE(pll), >>> + PLL_OUTCTRL, PLL_OUTCTRL); >>> +} >>> + >>> +static void clk_trion_pll_disable(struct clk_hw *hw) >>> +{ >>> + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); >>> + struct regmap *regmap = pll->clkr.regmap; >>> + u32 val; >>> + int ret; >>> + >>> + ret = regmap_read(regmap, PLL_MODE(pll), &val); >>> + if (ret) >>> + return; >>> + >>> + /* If in FSM mode, just unvote it */ >>> + if (val & PLL_VOTE_FSM_ENA) { >>> + clk_disable_regmap(hw); >>> + return; >>> + } >>> + >>> + /* Disable the global PLL output */ >>> + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); >>> + if (ret) >>> + return; >>> + >>> + /* Disable the PLL outputs */ >>> + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), >>> + TRION_PLL_OUT_MASK, 0); >>> + if (ret) >>> + return; >>> + >>> + /* Place the PLL mode in STANDBY */ >>> + regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY); >>> + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); >>> +} >>> + >>> +static unsigned long >>> +clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) >>> +{ >>> + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); >>> + struct regmap *regmap = pll->clkr.regmap; >>> + u32 l, frac; >>> + u64 prate = parent_rate; >>> + >>> + regmap_read(regmap, PLL_L_VAL(pll), &l); >>> + regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); >>> + >>> + return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH); >>> +} >>> + >>> +static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate, >>> + unsigned long *prate) >>> +{ >>> + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); >>> + unsigned long min_freq, max_freq; >>> + u32 l; >>> + u64 a; >>> + >>> + rate = alpha_pll_round_rate(rate, *prate, >>> + &l, &a, ALPHA_REG_16BIT_WIDTH); >>> + if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) >>> + return rate; >>> + >>> + min_freq = pll->vco_table[0].min_freq; >>> + max_freq = pll->vco_table[pll->num_vco - 1].max_freq; >>> + >>> + return clamp(rate, min_freq, max_freq); >>> +} >>> + >>> const struct clk_ops clk_alpha_pll_ops = { >>> .enable = clk_alpha_pll_enable, >>> .disable = clk_alpha_pll_disable, >>> @@ -760,6 +908,15 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { >>> }; >>> EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); >>> +const struct clk_ops clk_trion_fixed_pll_ops = { >>> + .enable = clk_trion_pll_enable, >>> + .disable = clk_trion_pll_disable, >>> + .is_enabled = clk_trion_pll_is_enabled, >>> + .recalc_rate = clk_trion_pll_recalc_rate, >>> + .round_rate = clk_trion_pll_round_rate, >>> +}; >>> +EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops); >>> + >>> static unsigned long >>> clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) >>> { >>> @@ -1053,6 +1210,77 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, >>> return (parent_rate / div); >>> } >>> +static unsigned long >>> +clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) >>> +{ >>> + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); >>> + struct regmap *regmap = pll->clkr.regmap; >>> + u32 i, div = 1, val; >>> + >>> + regmap_read(regmap, PLL_USER_CTL(pll), &val); >>> + >>> + val >>= pll->post_div_shift; >>> + val &= PLL_POST_DIV_MASK(pll); >>> + >>> + for (i = 0; i < pll->num_post_div; i++) { >>> + if (pll->post_div_table[i].val == val) { >>> + div = pll->post_div_table[i].div; >>> + break; >>> + } >>> + } >>> + >>> + return (parent_rate / div); >>> +} >>> + >>> +static long >>> +clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, >>> + unsigned long *prate) >>> +{ >>> + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); >>> + >>> + return divider_round_rate(hw, rate, prate, pll->post_div_table, >>> + pll->width, CLK_DIVIDER_ROUND_CLOSEST); >>> +}; >>> + >>> +static int >>> +clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, >>> + unsigned long parent_rate) >>> +{ >>> + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); >>> + struct regmap *regmap = pll->clkr.regmap; >>> + int i, val = 0, div, ret; >>> + >>> + /* >>> + * If the PLL is in FSM mode, then treat the set_rate callback >>> + * as a no-operation. >>> + */ >>> + ret = regmap_read(regmap, PLL_MODE(pll), &val); >>> + if (ret) >>> + return ret; >>> + >>> + if (val & PLL_VOTE_FSM_ENA) >>> + return 0; >>> + >>> + div = DIV_ROUND_UP_ULL(parent_rate, rate); >>> + for (i = 0; i < pll->num_post_div; i++) { >>> + if (pll->post_div_table[i].div == div) { >>> + val = pll->post_div_table[i].val; >>> + break; >>> + } >>> + } >>> + >>> + return regmap_update_bits(regmap, PLL_USER_CTL(pll), >>> + PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, >>> + val << PLL_POST_DIV_SHIFT); >>> +} >>> + >>> +const struct clk_ops clk_trion_pll_postdiv_ops = { >>> + .recalc_rate = clk_trion_pll_postdiv_recalc_rate, >>> + .round_rate = clk_trion_pll_postdiv_round_rate, >>> + .set_rate = clk_trion_pll_postdiv_set_rate, >>> +}; >>> +EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops); >>> + >>> static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, >>> unsigned long rate, unsigned long *prate) >>> { >>> diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h >>> index 66755f0f84fc..15f27f4b06df 100644 >>> --- a/drivers/clk/qcom/clk-alpha-pll.h >>> +++ b/drivers/clk/qcom/clk-alpha-pll.h >>> @@ -13,22 +13,27 @@ enum { >>> CLK_ALPHA_PLL_TYPE_HUAYRA, >>> CLK_ALPHA_PLL_TYPE_BRAMMO, >>> CLK_ALPHA_PLL_TYPE_FABIA, >>> + CLK_ALPHA_PLL_TYPE_TRION, >>> CLK_ALPHA_PLL_TYPE_MAX, >>> }; >>> enum { >>> PLL_OFF_L_VAL, >>> + PLL_OFF_CAL_L_VAL, >>> PLL_OFF_ALPHA_VAL, >>> PLL_OFF_ALPHA_VAL_U, >>> PLL_OFF_USER_CTL, >>> PLL_OFF_USER_CTL_U, >>> + PLL_OFF_USER_CTL_U1, >>> PLL_OFF_CONFIG_CTL, >>> PLL_OFF_CONFIG_CTL_U, >>> + PLL_OFF_CONFIG_CTL_U1, >>> PLL_OFF_TEST_CTL, >>> PLL_OFF_TEST_CTL_U, >>> PLL_OFF_STATUS, >>> PLL_OFF_OPMODE, >>> PLL_OFF_FRAC, >>> + PLL_OFF_CAL_VAL, >>> PLL_OFF_MAX_REGS >>> }; >>> @@ -117,5 +122,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, >>> const struct alpha_pll_config *config); >>> void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, >>> const struct alpha_pll_config *config); >>> +extern const struct clk_ops clk_trion_fixed_pll_ops; >>> +extern const struct clk_ops clk_trion_pll_postdiv_ops; >>> #endif >>> >> >> -- >> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member >> of Code Aurora Forum, hosted by The Linux Foundation. >> >> -- > -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation. -- ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs 2019-06-17 6:10 ` Taniya Das @ 2019-06-17 6:16 ` Vinod Koul 0 siblings, 0 replies; 14+ messages in thread From: Vinod Koul @ 2019-06-17 6:16 UTC (permalink / raw) To: Taniya Das Cc: Stephen Boyd, linux-arm-msm, Bjorn Andersson, Deepak Katragadda, Andy Gross, David Brown, Michael Turquette, linux-clk On 17-06-19, 11:40, Taniya Das wrote: > Hi Vinod, > > On 6/14/2019 11:12 AM, Vinod Koul wrote: > > Hi Taniya, > > > > On 13-06-19, 08:34, Taniya Das wrote: > > > Hi Vinod, > > > > > > The trion PLL needs to be configured before it is enabled. The PLL cannot > > > LOCK without the calibration. > > > > > > Could you please add "clk_trion_pll_configure()" function? > > > > First it is not recommended to top post! Please reply inline. > > > > Yes I did see that, I will check that. Is there any way to find PLL is > > configured or not? I want to avoid using inited variable as done in > > downstream. > > > > These PLLs which are controlled by High Level OS would not be configured and > we should not rely on the configurations which are done previously for these > PLLs. Thanks, would it make sense then to do the initialization of the PLL in driver probe. That would ensure HLOS is configuring them properly. -- ~Vinod ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2019-06-24 7:58 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-06-12 9:17 [PATCH v2 0/5] clk: qcom: Add support for SM8150 GCC Vinod Koul 2019-06-12 9:17 ` [PATCH v2 1/5] clk: qcom: clk-alpha-pll: Remove unnecessary cast Vinod Koul 2019-06-17 4:37 ` Bjorn Andersson 2019-06-24 7:46 ` Vinod Koul 2019-06-12 9:17 ` [PATCH v2 2/5] clk: qcom: clk-alpha-pll: Remove post_div_table checks Vinod Koul 2019-06-17 4:28 ` Bjorn Andersson 2019-06-12 9:17 ` [PATCH v2 3/5] clk: qcom: gcc-qcs404: Add MODULE_ALIAS Vinod Koul 2019-06-17 4:26 ` Bjorn Andersson 2019-06-24 7:55 ` Vinod Koul 2019-06-12 9:17 ` [PATCH v2 4/5] clk: qcom: clk-alpha-pll: Add support for Trion PLLs Vinod Koul 2019-06-13 3:04 ` Taniya Das 2019-06-14 5:42 ` Vinod Koul 2019-06-17 6:10 ` Taniya Das 2019-06-17 6:16 ` Vinod Koul
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).