Skip to content

Commit 7da258a

Browse files
Nellklarasm
Nell
authored andcommitted
k1x:cpufreq: support adjust the ace/tcm's frequency accroding to cpu
by the way, set the frequency of cci to 614M by default Change-Id: Ie375efff2c4432426a44d8a5a7406aa7904abd74
1 parent 083d165 commit 7da258a

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

arch/riscv/boot/dts/spacemit/k1-x.dtsi

+23
Original file line numberDiff line numberDiff line change
@@ -298,32 +298,46 @@
298298
compatible = "operating-points-v2";
299299
opp-shared;
300300

301+
clocks = <&ccu CLK_CPU_C0_ACE>, <&ccu CLK_CPU_C0_TCM>, <&ccu CLK_CCI550>;
302+
clock-names = "ace","tcm", "cci";
303+
cci-hz = /bits/ 64 <614000000>;
304+
301305
opp614400000 {
302306
opp-hz = /bits/ 64 <614400000>;
307+
tcm-hz = /bits/ 64 <307200000>;
308+
ace-hz = /bits/ 64 <307200000>;
303309
opp-microvolt = <950000>;
304310
clock-latency-ns = <200000>;
305311
};
306312

307313
opp819000000 {
308314
opp-hz = /bits/ 64 <819000000>;
309315
opp-microvolt = <950000>;
316+
tcm-hz = /bits/ 64 <409500000>;
317+
ace-hz = /bits/ 64 <409500000>;
310318
clock-latency-ns = <200000>;
311319
};
312320

313321
opp1000000000 {
314322
opp-hz = /bits/ 64 <1000000000>;
323+
tcm-hz = /bits/ 64 <500000000>;
324+
ace-hz = /bits/ 64 <500000000>;
315325
opp-microvolt = <950000>;
316326
clock-latency-ns = <200000>;
317327
};
318328

319329
opp1228800000 {
320330
opp-hz = /bits/ 64 <1228800000>;
331+
tcm-hz = /bits/ 64 <614400000>;
332+
ace-hz = /bits/ 64 <614400000>;
321333
opp-microvolt = <950000>;
322334
clock-latency-ns = <200000>;
323335
};
324336

325337
opp1600000000 {
326338
opp-hz = /bits/ 64 <1600000000>;
339+
tcm-hz = /bits/ 64 <800000000>;
340+
ace-hz = /bits/ 64 <800000000>;
327341
opp-microvolt = <950000>;
328342
clock-latency-ns = <200000>;
329343
};
@@ -333,32 +347,41 @@
333347
compatible = "operating-points-v2";
334348
opp-shared;
335349

350+
clocks = <&ccu CLK_CPU_C1_ACE>, <&ccu CLK_CCI550>;
351+
clock-names = "ace", "cci";
352+
cci-hz = /bits/ 64 <614000000>;
353+
336354
opp614400000 {
337355
opp-hz = /bits/ 64 <614400000>;
356+
ace-hz = /bits/ 64 <307200000>;
338357
opp-microvolt = <950000>;
339358
clock-latency-ns = <200000>;
340359
};
341360

342361
opp819000000 {
343362
opp-hz = /bits/ 64 <819000000>;
363+
ace-hz = /bits/ 64 <409500000>;
344364
opp-microvolt = <950000>;
345365
clock-latency-ns = <200000>;
346366
};
347367

348368
opp1000000000 {
349369
opp-hz = /bits/ 64 <1000000000>;
370+
ace-hz = /bits/ 64 <500000000>;
350371
opp-microvolt = <950000>;
351372
clock-latency-ns = <200000>;
352373
};
353374

354375
opp1228800000 {
355376
opp-hz = /bits/ 64 <1228800000>;
377+
ace-hz = /bits/ 64 <614400000>;
356378
opp-microvolt = <950000>;
357379
clock-latency-ns = <200000>;
358380
};
359381

360382
opp1600000000 {
361383
opp-hz = /bits/ 64 <1600000000>;
384+
ace-hz = /bits/ 64 <800000000>;
362385
opp-microvolt = <950000>;
363386
clock-latency-ns = <200000>;
364387
};

drivers/cpufreq/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,4 @@ obj-$(CONFIG_LOONGSON3_CPUFREQ) += loongson3_cpufreq.o
105105
obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o
106106
obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o
107107
obj-$(CONFIG_SPARC_US3_CPUFREQ) += sparc-us3-cpufreq.o
108+
obj-$(CONFIG_SPACEMIT_K1X_CPUFREQ) += spacemit-cpufreq.o

drivers/cpufreq/spacemit-cpufreq.c

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#include <linux/cpufreq.h>
2+
#include <linux/kernel.h>
3+
#include <linux/module.h>
4+
#include <linux/init.h>
5+
#include <linux/cpumask.h>
6+
#include <linux/clk/clk-conf.h>
7+
#include <linux/pm_qos.h>
8+
#include <linux/notifier.h>
9+
#include "../opp/opp.h"
10+
11+
#if 0
12+
#define CCI_CLK_DEFAULT_RATE 245760
13+
14+
struct per_dev_qos {
15+
struct clk *clk;
16+
struct notifier_block notifier;
17+
struct dev_pm_qos_request req;
18+
};
19+
20+
static struct per_dev_qos *clk_dev_qos;
21+
22+
static int spacemit_handle_clk_max_notifier_call(struct notifier_block *nb, unsigned long action, void *data)
23+
{
24+
struct per_dev_qos *per_qos = container_of(nb, struct per_dev_qos, notifier);
25+
26+
clk_set_rate(per_qos->clk, action * 1000);
27+
28+
return 0;
29+
}
30+
#endif
31+
32+
static int spacemit_policy_notifier(struct notifier_block *nb,
33+
unsigned long event, void *data)
34+
{
35+
int cpu;
36+
u64 rates;
37+
static int cci_init;
38+
struct clk *cci_clk;
39+
struct device *cpu_dev;
40+
struct cpufreq_policy *policy = data;
41+
struct opp_table *opp_table;
42+
43+
cpu = cpumask_first(policy->related_cpus);
44+
cpu_dev = get_cpu_device(cpu);
45+
opp_table = _find_opp_table(cpu_dev);
46+
47+
if (cci_init == 0) {
48+
cci_clk = of_clk_get_by_name(opp_table->np, "cci");
49+
of_property_read_u64_array(opp_table->np, "cci-hz", &rates, 1);
50+
clk_set_rate(cci_clk, rates);
51+
clk_put(cci_clk);
52+
cci_init = 1;
53+
}
54+
55+
return 0;
56+
}
57+
58+
static int spacemit_processor_notifier(struct notifier_block *nb,
59+
unsigned long event, void *data)
60+
{
61+
int cpu;
62+
struct device *cpu_dev;
63+
struct cpufreq_freqs *freqs = (struct cpufreq_freqs *)data;
64+
struct cpufreq_policy *policy = ( struct cpufreq_policy *)freqs->policy;
65+
struct opp_table *opp_table;
66+
struct device_node *np;
67+
struct clk *tcm_clk, *ace_clk;
68+
u64 rates;
69+
70+
cpu = cpumask_first(policy->related_cpus);
71+
cpu_dev = get_cpu_device(cpu);
72+
opp_table = _find_opp_table(cpu_dev);
73+
74+
#if 0
75+
if (clk_dev_qos == NULL) {
76+
clk_dev_qos = (struct per_dev_qos *)devm_kzalloc(cpu_dev, sizeof(struct per_dev_qos), GFP_KERNEL);
77+
if (!clk_dev_qos) {
78+
pr_err(" allocate per device qos error\n");
79+
return -ENOMEM;
80+
}
81+
82+
clk_dev_qos->clk = of_clk_get_by_name(opp_table->np, "cci");
83+
clk_dev_qos->notifier.notifier_call = spacemit_handle_clk_max_notifier_call;
84+
dev_pm_qos_add_notifier(get_cpu_device(0), &clk_dev_qos->notifier, DEV_PM_QOS_MAX_FREQUENCY);
85+
dev_pm_qos_add_request(get_cpu_device(0), &clk_dev_qos->req, DEV_PM_QOS_MAX_FREQUENCY, CCI_CLK_DEFAULT_RATE);
86+
}
87+
#endif
88+
for_each_available_child_of_node(opp_table->np, np) {
89+
of_property_read_u64_array(np, "opp-hz", &rates, 1);
90+
if (rates == freqs->new * 1000)
91+
break;
92+
}
93+
#if 0
94+
if (event == CPUFREQ_PRECHANGE) {
95+
/* decrease the freqs */
96+
if (freqs->old > freqs->new) {
97+
/* decrease the cci first */
98+
of_property_read_u64_array(np, "cci-hz", &rates, 1);
99+
dev_pm_qos_update_request(&clk_dev_qos->req, rates / 1000);
100+
}
101+
}
102+
#endif
103+
104+
/* get the tcm/ace clk handler */
105+
tcm_clk = of_clk_get_by_name(opp_table->np, "tcm");
106+
ace_clk = of_clk_get_by_name(opp_table->np, "ace");
107+
108+
if (event == CPUFREQ_PRECHANGE) {
109+
/**
110+
* change the tcm/ace's frequency first.
111+
* binary division is safe
112+
*/
113+
if (!IS_ERR(ace_clk)) {
114+
clk_set_rate(ace_clk, clk_get_rate(clk_get_parent(ace_clk)) / 2);
115+
clk_put(ace_clk);
116+
}
117+
118+
if (!IS_ERR(tcm_clk)) {
119+
clk_set_rate(tcm_clk, clk_get_rate(clk_get_parent(tcm_clk)) / 2);
120+
clk_put(tcm_clk);
121+
}
122+
}
123+
124+
if (event == CPUFREQ_POSTCHANGE) {
125+
126+
if (!IS_ERR(tcm_clk)) {
127+
clk_get_rate(clk_get_parent(tcm_clk));
128+
/* get the tcm-hz */
129+
of_property_read_u64_array(np, "tcm-hz", &rates, 1);
130+
/* then set rate */
131+
clk_set_rate(tcm_clk, rates);
132+
clk_put(tcm_clk);
133+
}
134+
135+
if (!IS_ERR(ace_clk)) {
136+
clk_get_rate(clk_get_parent(ace_clk));
137+
/* get the ace-hz */
138+
of_property_read_u64_array(np, "ace-hz", &rates, 1);
139+
/* then set rate */
140+
clk_set_rate(ace_clk, rates);
141+
clk_put(ace_clk);
142+
}
143+
#if 0
144+
/* increase the freqs */
145+
if (freqs->old < freqs->new) {
146+
/* increase the cci after */
147+
of_property_read_u64_array(np, "cci-hz", &rates, 1);
148+
dev_pm_qos_update_request(&clk_dev_qos->req, rates / 1000);
149+
}
150+
#endif
151+
}
152+
153+
dev_pm_opp_put_opp_table(opp_table);
154+
155+
return 0;
156+
}
157+
158+
static struct notifier_block spacemit_processor_notifier_block = {
159+
.notifier_call = spacemit_processor_notifier,
160+
};
161+
162+
static struct notifier_block spacemit_policy_notifier_block = {
163+
.notifier_call = spacemit_policy_notifier,
164+
};
165+
166+
static int __init spacemit_processor_driver_init(void)
167+
{
168+
int ret;
169+
170+
ret = cpufreq_register_notifier(&spacemit_processor_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
171+
if (ret) {
172+
pr_err("register cpufreq notifier failed\n");
173+
return -EINVAL;
174+
}
175+
176+
ret = cpufreq_register_notifier(&spacemit_policy_notifier_block, CPUFREQ_POLICY_NOTIFIER);
177+
if (ret) {
178+
pr_err("register cpufreq notifier failed\n");
179+
return -EINVAL;
180+
}
181+
182+
return 0;
183+
}
184+
185+
arch_initcall(spacemit_processor_driver_init);

0 commit comments

Comments
 (0)