Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

clk: qcom: a53-pll: Add MSM8939 a53pll support

MSM8939 has 3 a53pll clocks with different frequency table for Cluster0,
Cluster1 and CCI. It adds function qcom_a53pll_get_freq_tbl() to create
pll_freq_tbl from OPP, so that those a53pll frequencies can be defined
in DT with operating-points-v2 bindings rather than being coded in the
driver. In this case, one compatible rather than three would be needed
for these 3 a53pll clocks.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Link: https://lore.kernel.org/r/20210704024032.11559-5-shawn.guo@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Shawn Guo and committed by
Stephen Boyd
5d9bc010 f9a6a326

+58 -1
+58 -1
drivers/clk/qcom/a53-pll.c
··· 6 6 * Author: Georgi Djakov <georgi.djakov@linaro.org> 7 7 */ 8 8 9 + #include <linux/clk.h> 9 10 #include <linux/clk-provider.h> 10 11 #include <linux/kernel.h> 11 12 #include <linux/platform_device.h> 13 + #include <linux/pm_opp.h> 12 14 #include <linux/regmap.h> 13 15 #include <linux/module.h> 14 16 ··· 35 33 .max_register = 0x40, 36 34 .fast_io = true, 37 35 }; 36 + 37 + static struct pll_freq_tbl *qcom_a53pll_get_freq_tbl(struct device *dev) 38 + { 39 + struct pll_freq_tbl *freq_tbl; 40 + unsigned long xo_freq; 41 + unsigned long freq; 42 + struct clk *xo_clk; 43 + int count; 44 + int ret; 45 + int i; 46 + 47 + xo_clk = devm_clk_get(dev, "xo"); 48 + if (IS_ERR(xo_clk)) 49 + return NULL; 50 + 51 + xo_freq = clk_get_rate(xo_clk); 52 + 53 + ret = devm_pm_opp_of_add_table(dev); 54 + if (ret) 55 + return NULL; 56 + 57 + count = dev_pm_opp_get_opp_count(dev); 58 + if (count <= 0) 59 + return NULL; 60 + 61 + freq_tbl = devm_kcalloc(dev, count + 1, sizeof(*freq_tbl), GFP_KERNEL); 62 + if (!freq_tbl) 63 + return NULL; 64 + 65 + for (i = 0, freq = 0; i < count; i++, freq++) { 66 + struct dev_pm_opp *opp; 67 + 68 + opp = dev_pm_opp_find_freq_ceil(dev, &freq); 69 + if (IS_ERR(opp)) 70 + return NULL; 71 + 72 + /* Skip the freq that is not divisible */ 73 + if (freq % xo_freq) 74 + continue; 75 + 76 + freq_tbl[i].freq = freq; 77 + freq_tbl[i].l = freq / xo_freq; 78 + freq_tbl[i].n = 1; 79 + 80 + dev_pm_opp_put(opp); 81 + } 82 + 83 + return freq_tbl; 84 + } 38 85 39 86 static int qcom_a53pll_probe(struct platform_device *pdev) 40 87 { ··· 116 65 pll->mode_reg = 0x00; 117 66 pll->status_reg = 0x1c; 118 67 pll->status_bit = 16; 119 - pll->freq_tbl = a53pll_freq; 68 + 69 + pll->freq_tbl = qcom_a53pll_get_freq_tbl(dev); 70 + if (!pll->freq_tbl) { 71 + /* Fall on a53pll_freq if no freq_tbl is found from OPP */ 72 + pll->freq_tbl = a53pll_freq; 73 + } 120 74 121 75 /* Use an unique name by appending @unit-address */ 122 76 init.name = devm_kasprintf(dev, GFP_KERNEL, "a53pll%s", ··· 152 96 153 97 static const struct of_device_id qcom_a53pll_match_table[] = { 154 98 { .compatible = "qcom,msm8916-a53pll" }, 99 + { .compatible = "qcom,msm8939-a53pll" }, 155 100 { } 156 101 }; 157 102 MODULE_DEVICE_TABLE(of, qcom_a53pll_match_table);