Skip to content

Commit 441ee69

Browse files
kdrag0nExactExampl
authored andcommitted
clk: qcom: clk-cpu-osm: Allow overriding CPU frequency tables in DT
Sometimes, it may be desirable to use CPU frequency tables different from the ones in the hardware's OSM LUTs. This commit adds support for overriding each CPU's frequency table with a list of allowed frequencies defined in the OSM driver's DT node. Signed-off-by: Danny Lin <danny@kdrag0n.dev>
1 parent 97d02d0 commit 441ee69

2 files changed

Lines changed: 110 additions & 6 deletions

File tree

Documentation/devicetree/bindings/arm/msm/qcom,osm.txt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ Properties:
5858
Value type: <phandle>
5959
Definition: Phandle to the aux clock device.
6060

61+
- qcom,cpufreq-table-XX
62+
Usage: optional
63+
Value type: <u32>
64+
Definition: List of frequencies (in kHz) to expose in CPU XX's cpufreq table.
65+
All frequencies present in hardware will be exposed if this list
66+
is not present.
67+
6168
Example:
6269
clock_cpucc: qcom,cpucc@0x17d41000 {
6370
compatible = "qcom,clk-cpu-osm";
@@ -74,4 +81,49 @@ Example:
7481
clock-names = "xo_ao";
7582
clocks = <&clock_rpmh RPMH_CXO_CLK_A>;
7683
#clock-cells = <1>;
84+
qcom,cpufreq-table-0 =
85+
< 300000>,
86+
< 403200>,
87+
< 480000>,
88+
< 576000>,
89+
< 652800>,
90+
< 748800>,
91+
< 825600>,
92+
< 902400>,
93+
< 979200>,
94+
<1056000>,
95+
<1132800>,
96+
<1228800>,
97+
<1324800>,
98+
<1420800>,
99+
<1516800>,
100+
<1612800>,
101+
<1689600>,
102+
<1766400>;
103+
104+
qcom,cpufreq-table-4 =
105+
< 825600>,
106+
< 902400>,
107+
< 979200>,
108+
<1056000>,
109+
<1209600>,
110+
<1286400>,
111+
<1363200>,
112+
<1459200>,
113+
<1536000>,
114+
<1612800>,
115+
<1689600>,
116+
<1766400>,
117+
<1843200>,
118+
<1920000>,
119+
<1996800>,
120+
<2092800>,
121+
<2169600>,
122+
<2246400>,
123+
<2323200>,
124+
<2400000>,
125+
<2476800>,
126+
<2553600>,
127+
<2649600>,
128+
<2803200>;
77129
};

drivers/clk/qcom/clk-cpu-osm.c

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct osm_entry {
8080
};
8181

8282
struct clk_osm {
83+
struct device *dev;
8384
struct clk_hw hw;
8485
struct osm_entry osm_table[OSM_TABLE_SIZE];
8586
struct dentry *debugfs;
@@ -90,6 +91,7 @@ struct clk_osm {
9091
u32 num_entries;
9192
u32 cluster_num;
9293
u32 core_num;
94+
u32 osm_table_size;
9395
unsigned long rate;
9496
u64 total_cycle_counter;
9597
u32 prev_cycle_counter;
@@ -386,6 +388,7 @@ static struct clk_init_data osm_clks_init[] = {
386388
static struct clk_osm l3_clk = {
387389
.cluster_num = 0,
388390
.max_core_count = 4,
391+
.osm_table_size = OSM_TABLE_SIZE,
389392
.hw.init = &osm_clks_init[0],
390393
};
391394

@@ -397,6 +400,7 @@ static DEFINE_CLK_VOTER(l3_gpu_vote_clk, l3_clk, 0);
397400
static struct clk_osm pwrcl_clk = {
398401
.cluster_num = 1,
399402
.max_core_count = 4,
403+
.osm_table_size = OSM_TABLE_SIZE,
400404
.hw.init = &osm_clks_init[1],
401405
};
402406

@@ -481,6 +485,7 @@ static struct clk_osm cpu5_pwrcl_clk = {
481485
static struct clk_osm perfcl_clk = {
482486
.cluster_num = 2,
483487
.max_core_count = 4,
488+
.osm_table_size = OSM_TABLE_SIZE,
484489
.hw.init = &osm_clks_init[2],
485490
};
486491

@@ -717,14 +722,31 @@ static unsigned int osm_cpufreq_get(unsigned int cpu)
717722
return XO_RATE * curr_lval / 1000;
718723
}
719724

725+
static bool osm_dt_find_freq(u32 *of_table, int of_len, long frequency)
726+
{
727+
int i;
728+
729+
if (!of_table)
730+
return true;
731+
732+
for (i = 0; i < of_len; i++) {
733+
if (frequency == of_table[i])
734+
return true;
735+
}
736+
737+
return false;
738+
}
739+
720740
static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy)
721741
{
722742
struct cpufreq_frequency_table *table;
723743
struct clk_osm *c, *parent;
724744
struct clk_hw *p_hw;
725-
int ret;
745+
int ret, of_len;
726746
unsigned int i, prev_cc = 0;
727747
unsigned int xo_kHz;
748+
u32 *of_table = NULL;
749+
char tbl_name[] = "qcom,cpufreq-table-##";
728750

729751
c = osm_configure_policy(policy);
730752
if (!c) {
@@ -748,11 +770,33 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy)
748770
}
749771
xo_kHz = clk_hw_get_rate(p_hw) / 1000;
750772

751-
table = kcalloc(OSM_TABLE_SIZE + 1, sizeof(*table), GFP_KERNEL);
773+
table = kcalloc(parent->osm_table_size + 1, sizeof(*table), GFP_KERNEL);
774+
775+
snprintf(tbl_name, sizeof(tbl_name), "qcom,cpufreq-table-%d", policy->cpu);
776+
if (of_find_property(parent->dev->of_node, tbl_name, &of_len) && of_len > 0) {
777+
of_len /= sizeof(*of_table);
778+
779+
of_table = kcalloc(of_len, sizeof(*of_table), GFP_KERNEL);
780+
if (!of_table) {
781+
pr_err("failed to allocate DT frequency table memory for CPU%d\n",
782+
policy->cpu);
783+
return -ENOMEM;
784+
}
785+
786+
ret = of_property_read_u32_array(parent->dev->of_node, tbl_name,
787+
of_table, of_len);
788+
if (ret) {
789+
pr_err("failed to read DT frequency table for CPU%d, err=%d\n",
790+
policy->cpu, ret);
791+
return ret;
792+
}
793+
}
794+
795+
table = kcalloc(parent->osm_table_size + 1, sizeof(*table), GFP_KERNEL);
752796
if (!table)
753797
return -ENOMEM;
754798

755-
for (i = 0; i < OSM_TABLE_SIZE; i++) {
799+
for (i = 0; i < parent->osm_table_size; i++) {
756800
u32 data, src, div, lval, core_count;
757801

758802
data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
@@ -767,6 +811,10 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy)
767811
table[i].frequency = xo_kHz * lval;
768812
table[i].driver_data = table[i].frequency;
769813

814+
/* Ignore frequency if not present in DT table */
815+
if (!osm_dt_find_freq(of_table, of_len, table[i].frequency))
816+
table[i].frequency = CPUFREQ_ENTRY_INVALID;
817+
770818
if (core_count != parent->max_core_count)
771819
table[i].frequency = CPUFREQ_ENTRY_INVALID;
772820

@@ -795,9 +843,12 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy)
795843

796844
policy->cpuinfo.transition_latency = MIN_RATE_LIMIT_US;
797845
policy->driver_data = c;
846+
847+
kfree(of_table);
798848
return 0;
799849

800850
err:
851+
kfree(of_table);
801852
kfree(table);
802853
return ret;
803854
}
@@ -1019,10 +1070,11 @@ static u64 clk_osm_get_cpu_cycle_counter(int cpu)
10191070

10201071
static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
10211072
{
1022-
u32 data, src, lval, i, j = OSM_TABLE_SIZE;
1073+
u32 data, src, lval, i, j = c->osm_table_size;
10231074
struct clk_vdd_class *vdd = osm_clks_init[c->cluster_num].vdd_class;
10241075

1025-
for (i = 0; i < OSM_TABLE_SIZE; i++) {
1076+
c->dev = &pdev->dev;
1077+
for (i = 0; i < c->osm_table_size; i++) {
10261078
data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
10271079
src = ((data & GENMASK(31, 30)) >> 30);
10281080
lval = (data & GENMASK(7, 0));
@@ -1044,7 +1096,7 @@ static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
10441096
c->osm_table[i].virtual_corner,
10451097
c->osm_table[i].open_loop_volt);
10461098

1047-
if (i > 0 && j == OSM_TABLE_SIZE &&
1099+
if (i > 0 && j == c->osm_table_size &&
10481100
c->osm_table[i].frequency ==
10491101
c->osm_table[i - 1].frequency &&
10501102
c->osm_table[i].ccount == c->osm_table[i - 1].ccount)

0 commit comments

Comments
 (0)