Skip to content

Commit 5d9bc01

Browse files
Shawn Guobebarino
authored andcommitted
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>
1 parent f9a6a32 commit 5d9bc01

1 file changed

Lines changed: 58 additions & 1 deletion

File tree

drivers/clk/qcom/a53-pll.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
* Author: Georgi Djakov <georgi.djakov@linaro.org>
77
*/
88

9+
#include <linux/clk.h>
910
#include <linux/clk-provider.h>
1011
#include <linux/kernel.h>
1112
#include <linux/platform_device.h>
13+
#include <linux/pm_opp.h>
1214
#include <linux/regmap.h>
1315
#include <linux/module.h>
1416

@@ -34,6 +36,55 @@ static const struct regmap_config a53pll_regmap_config = {
3436
.fast_io = true,
3537
};
3638

39+
static struct pll_freq_tbl *qcom_a53pll_get_freq_tbl(struct device *dev)
40+
{
41+
struct pll_freq_tbl *freq_tbl;
42+
unsigned long xo_freq;
43+
unsigned long freq;
44+
struct clk *xo_clk;
45+
int count;
46+
int ret;
47+
int i;
48+
49+
xo_clk = devm_clk_get(dev, "xo");
50+
if (IS_ERR(xo_clk))
51+
return NULL;
52+
53+
xo_freq = clk_get_rate(xo_clk);
54+
55+
ret = devm_pm_opp_of_add_table(dev);
56+
if (ret)
57+
return NULL;
58+
59+
count = dev_pm_opp_get_opp_count(dev);
60+
if (count <= 0)
61+
return NULL;
62+
63+
freq_tbl = devm_kcalloc(dev, count + 1, sizeof(*freq_tbl), GFP_KERNEL);
64+
if (!freq_tbl)
65+
return NULL;
66+
67+
for (i = 0, freq = 0; i < count; i++, freq++) {
68+
struct dev_pm_opp *opp;
69+
70+
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
71+
if (IS_ERR(opp))
72+
return NULL;
73+
74+
/* Skip the freq that is not divisible */
75+
if (freq % xo_freq)
76+
continue;
77+
78+
freq_tbl[i].freq = freq;
79+
freq_tbl[i].l = freq / xo_freq;
80+
freq_tbl[i].n = 1;
81+
82+
dev_pm_opp_put(opp);
83+
}
84+
85+
return freq_tbl;
86+
}
87+
3788
static int qcom_a53pll_probe(struct platform_device *pdev)
3889
{
3990
struct device *dev = &pdev->dev;
@@ -65,7 +116,12 @@ static int qcom_a53pll_probe(struct platform_device *pdev)
65116
pll->mode_reg = 0x00;
66117
pll->status_reg = 0x1c;
67118
pll->status_bit = 16;
68-
pll->freq_tbl = a53pll_freq;
119+
120+
pll->freq_tbl = qcom_a53pll_get_freq_tbl(dev);
121+
if (!pll->freq_tbl) {
122+
/* Fall on a53pll_freq if no freq_tbl is found from OPP */
123+
pll->freq_tbl = a53pll_freq;
124+
}
69125

70126
/* Use an unique name by appending @unit-address */
71127
init.name = devm_kasprintf(dev, GFP_KERNEL, "a53pll%s",
@@ -96,6 +152,7 @@ static int qcom_a53pll_probe(struct platform_device *pdev)
96152

97153
static const struct of_device_id qcom_a53pll_match_table[] = {
98154
{ .compatible = "qcom,msm8916-a53pll" },
155+
{ .compatible = "qcom,msm8939-a53pll" },
99156
{ }
100157
};
101158
MODULE_DEVICE_TABLE(of, qcom_a53pll_match_table);

0 commit comments

Comments
 (0)