From 86ae67086cbce323c2696c0951280d997dcbd8fd Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 1 Oct 2020 11:25:36 +0530 Subject: [PATCH 1/2] clk: qcom: cpu-sdxnightjar: Add support for cpu clock driver Add support for sdxnightjar CPU clock driver for controlling cpu clocks. Change-Id: I1fabb167a5c2d5e42d0a8baed13bc94d31ce97bf Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-cpu-sdxlemur.c | 146 ++++++++++++++++++++++++---- 1 file changed, 129 insertions(+), 17 deletions(-) diff --git a/drivers/clk/qcom/clk-cpu-sdxlemur.c b/drivers/clk/qcom/clk-cpu-sdxlemur.c index 128b1be9be12..fefd86fdbbf5 100644 --- a/drivers/clk/qcom/clk-cpu-sdxlemur.c +++ b/drivers/clk/qcom/clk-cpu-sdxlemur.c @@ -88,26 +88,50 @@ cpucc_calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div) return tmp; } -static int cpucc_clk_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) +static int cpucc_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct clk_hw *apcs_cpu_pll_hw; + struct clk_hw *xo_hw, *gpll0_hw; struct clk_rate_request parent_req = { }; struct clk_regmap_mux_div *cpuclk = to_clk_regmap_mux_div(hw); + unsigned long rate = req->rate, rrate; + u32 div; int ret; - apcs_cpu_pll_hw = clk_hw_get_parent_by_index(hw, - P_APCS_CPU_PLL); - parent_req.rate = req->rate; - parent_req.best_parent_hw = apcs_cpu_pll_hw; - req->best_parent_hw = apcs_cpu_pll_hw; - ret = __clk_determine_rate(req->best_parent_hw, &parent_req); - if (ret) - return ret; + xo_hw = clk_hw_get_parent_by_index(hw, P_BI_TCXO); + if (rate == clk_hw_get_rate(xo_hw)) { + req->best_parent_hw = xo_hw; + req->best_parent_rate = rate; + cpuclk->div = 1; + cpuclk->src = cpuclk->parent_map[P_BI_TCXO].cfg; + return 0; + } - req->best_parent_rate = parent_req.rate; - cpuclk->src = cpuclk->parent_map[P_APCS_CPU_PLL].cfg; - cpuclk->div = 1; + gpll0_hw = clk_hw_get_parent_by_index(hw, P_GPLL0); + div = DIV_ROUND_UP((2 * (clk_hw_get_rate(gpll0_hw))), rate) - 1; + + rrate = cpucc_calc_rate(clk_hw_get_rate(gpll0_hw), 0, 0, 0, div); + /* Use the GPLL0 source */ + if (rate <= rrate) { + parent_req.best_parent_hw = gpll0_hw; + req->best_parent_hw = gpll0_hw; + req->best_parent_rate = clk_hw_get_rate(gpll0_hw); + req->rate = rrate; + cpuclk->src = cpuclk->parent_map[P_GPLL0].cfg; + } else { /* Use the APCS PLL source */ + parent_req.rate = req->rate; + parent_req.best_parent_hw = clk_hw_get_parent_by_index(hw, + P_APCS_CPU_PLL); + req->best_parent_hw = parent_req.best_parent_hw; + ret = __clk_determine_rate(req->best_parent_hw, &parent_req); + if (ret) + return ret; + + req->best_parent_rate = parent_req.rate; + cpuclk->src = cpuclk->parent_map[P_APCS_CPU_PLL].cfg; + div = 1; + } + + cpuclk->div = div; return 0; } @@ -187,6 +211,28 @@ static u8 cpucc_clk_get_parent(struct clk_hw *hw) return clk_regmap_mux_div_ops.get_parent(hw); } +/* + * We use the notifier function for switching to a temporary safe configuration + * (mux and divider), while the APSS pll is reconfigured. + */ + +static int cpucc_notifier_cb(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct clk_regmap_mux_div *cpuclk = container_of(nb, + struct clk_regmap_mux_div, clk_nb); + int ret = 0; + + if (event == PRE_RATE_CHANGE) + /* set the mux to safe source(gpll0) & div */ + ret = mux_div_set_src_div(cpuclk, cpuclk->safe_src, 1); + + if (event == ABORT_RATE_CHANGE) + pr_err("Error in configuring PLL - stay at safe src only\n"); + + return notifier_from_errno(ret); +} + static const struct clk_ops cpucc_clk_ops = { .enable = cpucc_clk_enable, .disable = cpucc_clk_disable, @@ -204,6 +250,11 @@ static struct pll_vco lucid_5lpe_vco[] = { { 249600000, 2000000000, 0 }, }; +static struct pll_vco alpha_pll_vco[] = { + { 250000000, 500000000, 3 }, + { 750000000, 1500000000, 1 }, +}; + /* Initial configuration for 1094.4 */ static const struct alpha_pll_config apcs_cpu_pll_config = { .l = 0x4E, @@ -220,6 +271,25 @@ static const struct alpha_pll_config apcs_cpu_pll_config = { .user_ctl_hi1_val = 0x00000000, }; +/* Initial configuration for 1190.4 MHz */ +static struct alpha_pll_config apcs_cpu_alpha_pll_config = { + .l = 0x3E, + .config_ctl_val = 0x4001055b, + .test_ctl_hi_val = 0x0, + .vco_val = BIT(20), + .vco_mask = 0x3 << 20, + .main_output_mask = BIT(0), +}; + +static struct clk_init_data apcs_cpu_pll_sdxnightjar = { + .name = "apcs_cpu_pll", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo_ao", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, +}; + static struct clk_alpha_pll apcs_cpu_pll = { .offset = 0x0, .vco_table = lucid_5lpe_vco, @@ -279,6 +349,7 @@ static struct clk_regmap_mux_div apcs_mux_clk = { static const struct of_device_id match_table[] = { { .compatible = "qcom,sdxlemur-apsscc" }, + { .compatible = "qcom,sdxnightjar-apsscc" }, {} }; @@ -487,6 +558,28 @@ static void cpucc_clk_populate_opp_table(struct platform_device *pdev) cpucc_clk_print_opp_table(final_cpu); } +static void cpucc_sdxnightjar_fixup(void) +{ + apcs_cpu_pll.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT]; + apcs_cpu_pll.vco_table = alpha_pll_vco; + apcs_cpu_pll.num_vco = sizeof(alpha_pll_vco); + + apcs_cpu_pll.clkr.hw.init = &apcs_cpu_pll_sdxnightjar; + apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_MIN] = 0; + apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_LOW] = 1000000000; + apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_LOW_L1] = 0; + apcs_cpu_pll.clkr.vdd_data.rate_max[VDD_NOMINAL] = 2000000000; + + /* GPLL0 as safe source Index */ + apcs_mux_clk.safe_src = 1; + apcs_mux_clk.safe_div = 1; + + apcs_mux_clk.clk_nb.notifier_call = cpucc_notifier_cb; + + clk_alpha_pll_configure(&apcs_cpu_pll, apcs_cpu_pll.clkr.regmap, + &apcs_cpu_alpha_pll_config); +} + static int cpucc_get_and_parse_dt_resource(struct platform_device *pdev, unsigned long *xo_rate) { @@ -597,6 +690,7 @@ static int cpucc_driver_probe(struct platform_device *pdev) struct clk_hw_onecell_data *data; struct device *dev = &pdev->dev; int i, ret, cpu; + bool is_sdxnightjar; unsigned long xo_rate; u32 l_val; @@ -604,9 +698,17 @@ static int cpucc_driver_probe(struct platform_device *pdev) if (ret < 0) return ret; - l_val = apcs_cpu_pll_config.l; - clk_lucid_5lpe_pll_configure(&apcs_cpu_pll, apcs_cpu_pll.clkr.regmap, - &apcs_cpu_pll_config); + is_sdxnightjar = of_device_is_compatible(pdev->dev.of_node, + "qcom,sdxnightjar-apsscc"); + + if (is_sdxnightjar) { + l_val = apcs_cpu_alpha_pll_config.l; + cpucc_sdxnightjar_fixup(); + } else { + l_val = apcs_cpu_pll_config.l; + clk_lucid_5lpe_pll_configure(&apcs_cpu_pll, apcs_cpu_pll.clkr.regmap, + &apcs_cpu_pll_config); + } data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -631,6 +733,16 @@ static int cpucc_driver_probe(struct platform_device *pdev) return ret; } + if (is_sdxnightjar) { + ret = clk_notifier_register(apcs_mux_clk.clkr.hw.clk, + &apcs_mux_clk.clk_nb); + if (ret) { + dev_err(&pdev->dev, + "failed to register clock notifier: %d\n", ret); + return ret; + } + } + /* Set to boot frequency */ ret = clk_set_rate(apcs_mux_clk.clkr.hw.clk, l_val * xo_rate); if (ret) { From b0012338704bfbac9284faf43b455fca2afbc6ac Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Wed, 23 Dec 2020 23:05:49 +0530 Subject: [PATCH 2/2] defconfig: Enable CPU clock drivers for sdxnightjar Enable CPU clock drivers to support cpu frequency scaling. Change-Id: I489ae54357a7058304ef7f9309589f772462df24 Signed-off-by: Rakesh Kota --- arch/arm/configs/vendor/sdxnightjar-debug.config | 1 + arch/arm/configs/vendor/sdxnightjar.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/sdxnightjar-debug.config b/arch/arm/configs/vendor/sdxnightjar-debug.config index 4287144f0054..a28fea6ac69a 100644 --- a/arch/arm/configs/vendor/sdxnightjar-debug.config +++ b/arch/arm/configs/vendor/sdxnightjar-debug.config @@ -41,6 +41,7 @@ CONFIG_IIO=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_SDX_DEBUGCC_NIGHTJAR=y CONFIG_COMMON_CLK_QCOM_DEBUG=y +CONFIG_CLOCK_CPU_SDXLEMUR=y CONFIG_MSM_RPM_SMD=y # CONFIG_GENERIC_ADC_BATTERY is not set # CONFIG_BATTERY_LEGO_EV3 is not set diff --git a/arch/arm/configs/vendor/sdxnightjar.config b/arch/arm/configs/vendor/sdxnightjar.config index 13d5957091df..b43d436c733f 100644 --- a/arch/arm/configs/vendor/sdxnightjar.config +++ b/arch/arm/configs/vendor/sdxnightjar.config @@ -72,6 +72,7 @@ CONFIG_IIO=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_SDX_DEBUGCC_NIGHTJAR=y CONFIG_COMMON_CLK_QCOM_DEBUG=y +CONFIG_CLOCK_CPU_SDXLEMUR=y CONFIG_MSM_RPM_SMD=y # CONFIG_GENERIC_ADC_BATTERY is not set # CONFIG_BATTERY_LEGO_EV3 is not set