Skip to content

Commit e27f84e

Browse files
committed
Merge branch 'pm-cpufreq'
* pm-cpufreq: (25 commits) dt-bindings: cpufreq: Document operating-points-v2-kryo-cpu cpufreq: Add Kryo CPU scaling driver cpufreq: Use static SRCU initializer kernel/SRCU: provide a static initializer cpufreq: Fix new policy initialization during limits updates via sysfs cpufreq: tegra20: Wrap cpufreq into platform driver cpufreq: tegra20: Allow cpufreq driver to be built as loadable module cpufreq: tegra20: Check if this is Tegra20 machine cpufreq: tegra20: Remove unneeded variable initialization cpufreq: tegra20: Remove unnecessary parentheses cpufreq: tegra20: Remove unneeded check in tegra_cpu_init cpufreq: tegra20: Release clocks properly cpufreq: tegra20: Remove EMC clock usage cpufreq: tegra20: Clean up included headers cpufreq: tegra20: Clean up whitespaces in the code cpufreq: tegra20: Change module description Revert "cpufreq: rcar: Add support for R8A7795 SoC" Revert "cpufreq: dt: Add r8a7796 support to to use generic cpufreq driver" cpufreq: intel_pstate: allow trace in passive mode cpufreq: optimize cpufreq_notify_transition() ...
2 parents d9fecca + 7938353 commit e27f84e

File tree

17 files changed

+1241
-166
lines changed

17 files changed

+1241
-166
lines changed

Documentation/devicetree/bindings/opp/kryo-cpufreq.txt

Lines changed: 680 additions & 0 deletions
Large diffs are not rendered by default.

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11654,6 +11654,13 @@ F: Documentation/devicetree/bindings/media/qcom,camss.txt
1165411654
F: Documentation/media/v4l-drivers/qcom_camss.rst
1165511655
F: drivers/media/platform/qcom/camss-8x16/
1165611656

11657+
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
11658+
M: Ilia Lin <ilia.lin@gmail.com>
11659+
L: linux-pm@vger.kernel.org
11660+
S: Maintained
11661+
F: Documentation/devicetree/bindings/opp/kryo-cpufreq.txt
11662+
F: drivers/cpufreq/qcom-cpufreq-kryo.c
11663+
1165711664
QUALCOMM EMAC GIGABIT ETHERNET DRIVER
1165811665
M: Timur Tabi <timur@codeaurora.org>
1165911666
L: netdev@vger.kernel.org

drivers/cpufreq/Kconfig.arm

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,17 @@ config ARM_OMAP2PLUS_CPUFREQ
124124
depends on ARCH_OMAP2PLUS
125125
default ARCH_OMAP2PLUS
126126

127+
config ARM_QCOM_CPUFREQ_KRYO
128+
bool "Qualcomm Kryo based CPUFreq"
129+
depends on ARM64
130+
depends on QCOM_QFPROM
131+
depends on QCOM_SMEM
132+
select PM_OPP
133+
help
134+
This adds the CPUFreq driver for Qualcomm Kryo SoC based boards.
135+
136+
If in doubt, say N.
137+
127138
config ARM_S3C_CPUFREQ
128139
bool
129140
help
@@ -264,7 +275,7 @@ config ARM_TANGO_CPUFREQ
264275
default y
265276

266277
config ARM_TEGRA20_CPUFREQ
267-
bool "Tegra20 CPUFreq support"
278+
tristate "Tegra20 CPUFreq support"
268279
depends on ARCH_TEGRA
269280
default y
270281
help

drivers/cpufreq/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
6565
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
6666
obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
6767
obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
68+
obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o
6869
obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
6970
obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
7071
obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o

drivers/cpufreq/armada-37xx-cpufreq.c

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <linux/regmap.h>
2424
#include <linux/slab.h>
2525

26+
#include "cpufreq-dt.h"
27+
2628
/* Power management in North Bridge register set */
2729
#define ARMADA_37XX_NB_L0L1 0x18
2830
#define ARMADA_37XX_NB_L2L3 0x1C
@@ -56,6 +58,16 @@
5658
*/
5759
#define LOAD_LEVEL_NR 4
5860

61+
struct armada37xx_cpufreq_state {
62+
struct regmap *regmap;
63+
u32 nb_l0l1;
64+
u32 nb_l2l3;
65+
u32 nb_dyn_mod;
66+
u32 nb_cpu_load;
67+
};
68+
69+
static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state;
70+
5971
struct armada_37xx_dvfs {
6072
u32 cpu_freq_max;
6173
u8 divider[LOAD_LEVEL_NR];
@@ -136,7 +148,7 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
136148
clk_set_parent(clk, parent);
137149
}
138150

139-
static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
151+
static void armada37xx_cpufreq_disable_dvfs(struct regmap *base)
140152
{
141153
unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
142154
mask = ARMADA_37XX_NB_DFS_EN;
@@ -162,10 +174,47 @@ static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
162174
regmap_update_bits(base, reg, mask, mask);
163175
}
164176

177+
static int armada37xx_cpufreq_suspend(struct cpufreq_policy *policy)
178+
{
179+
struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state;
180+
181+
regmap_read(state->regmap, ARMADA_37XX_NB_L0L1, &state->nb_l0l1);
182+
regmap_read(state->regmap, ARMADA_37XX_NB_L2L3, &state->nb_l2l3);
183+
regmap_read(state->regmap, ARMADA_37XX_NB_CPU_LOAD,
184+
&state->nb_cpu_load);
185+
regmap_read(state->regmap, ARMADA_37XX_NB_DYN_MOD, &state->nb_dyn_mod);
186+
187+
return 0;
188+
}
189+
190+
static int armada37xx_cpufreq_resume(struct cpufreq_policy *policy)
191+
{
192+
struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state;
193+
194+
/* Ensure DVFS is disabled otherwise the following registers are RO */
195+
armada37xx_cpufreq_disable_dvfs(state->regmap);
196+
197+
regmap_write(state->regmap, ARMADA_37XX_NB_L0L1, state->nb_l0l1);
198+
regmap_write(state->regmap, ARMADA_37XX_NB_L2L3, state->nb_l2l3);
199+
regmap_write(state->regmap, ARMADA_37XX_NB_CPU_LOAD,
200+
state->nb_cpu_load);
201+
202+
/*
203+
* NB_DYN_MOD register is the one that actually enable back DVFS if it
204+
* was enabled before the suspend operation. This must be done last
205+
* otherwise other registers are not writable.
206+
*/
207+
regmap_write(state->regmap, ARMADA_37XX_NB_DYN_MOD, state->nb_dyn_mod);
208+
209+
return 0;
210+
}
211+
165212
static int __init armada37xx_cpufreq_driver_init(void)
166213
{
214+
struct cpufreq_dt_platform_data pdata;
167215
struct armada_37xx_dvfs *dvfs;
168216
struct platform_device *pdev;
217+
unsigned long freq;
169218
unsigned int cur_frequency;
170219
struct regmap *nb_pm_base;
171220
struct device *cpu_dev;
@@ -207,33 +256,58 @@ static int __init armada37xx_cpufreq_driver_init(void)
207256
}
208257

209258
dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
210-
if (!dvfs)
259+
if (!dvfs) {
260+
clk_put(clk);
211261
return -EINVAL;
262+
}
263+
264+
armada37xx_cpufreq_state = kmalloc(sizeof(*armada37xx_cpufreq_state),
265+
GFP_KERNEL);
266+
if (!armada37xx_cpufreq_state) {
267+
clk_put(clk);
268+
return -ENOMEM;
269+
}
270+
271+
armada37xx_cpufreq_state->regmap = nb_pm_base;
212272

213273
armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
214274
clk_put(clk);
215275

216276
for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
217277
load_lvl++) {
218-
unsigned long freq = cur_frequency / dvfs->divider[load_lvl];
278+
freq = cur_frequency / dvfs->divider[load_lvl];
219279

220280
ret = dev_pm_opp_add(cpu_dev, freq, 0);
221-
if (ret) {
222-
/* clean-up the already added opp before leaving */
223-
while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
224-
freq = cur_frequency / dvfs->divider[load_lvl];
225-
dev_pm_opp_remove(cpu_dev, freq);
226-
}
227-
return ret;
228-
}
281+
if (ret)
282+
goto remove_opp;
229283
}
230284

231285
/* Now that everything is setup, enable the DVFS at hardware level */
232286
armada37xx_cpufreq_enable_dvfs(nb_pm_base);
233287

234-
pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
288+
pdata.suspend = armada37xx_cpufreq_suspend;
289+
pdata.resume = armada37xx_cpufreq_resume;
290+
291+
pdev = platform_device_register_data(NULL, "cpufreq-dt", -1, &pdata,
292+
sizeof(pdata));
293+
ret = PTR_ERR_OR_ZERO(pdev);
294+
if (ret)
295+
goto disable_dvfs;
296+
297+
return 0;
298+
299+
disable_dvfs:
300+
armada37xx_cpufreq_disable_dvfs(nb_pm_base);
301+
remove_opp:
302+
/* clean-up the already added opp before leaving */
303+
while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
304+
freq = cur_frequency / dvfs->divider[load_lvl];
305+
dev_pm_opp_remove(cpu_dev, freq);
306+
}
307+
308+
kfree(armada37xx_cpufreq_state);
235309

236-
return PTR_ERR_OR_ZERO(pdev);
310+
return ret;
237311
}
238312
/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
239313
late_initcall(armada37xx_cpufreq_driver_init);

drivers/cpufreq/cpufreq-dt-platdev.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ static const struct of_device_id whitelist[] __initconst = {
6666
{ .compatible = "renesas,r8a7792", },
6767
{ .compatible = "renesas,r8a7793", },
6868
{ .compatible = "renesas,r8a7794", },
69-
{ .compatible = "renesas,r8a7795", },
70-
{ .compatible = "renesas,r8a7796", },
7169
{ .compatible = "renesas,sh73a0", },
7270

7371
{ .compatible = "rockchip,rk2928", },
@@ -118,6 +116,9 @@ static const struct of_device_id blacklist[] __initconst = {
118116

119117
{ .compatible = "nvidia,tegra124", },
120118

119+
{ .compatible = "qcom,apq8096", },
120+
{ .compatible = "qcom,msm8996", },
121+
121122
{ .compatible = "st,stih407", },
122123
{ .compatible = "st,stih410", },
123124

drivers/cpufreq/cpufreq-dt.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,14 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
346346
if (ret)
347347
return ret;
348348

349-
if (data && data->have_governor_per_policy)
350-
dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY;
349+
if (data) {
350+
if (data->have_governor_per_policy)
351+
dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY;
352+
353+
dt_cpufreq_driver.resume = data->resume;
354+
if (data->suspend)
355+
dt_cpufreq_driver.suspend = data->suspend;
356+
}
351357

352358
ret = cpufreq_register_driver(&dt_cpufreq_driver);
353359
if (ret)

drivers/cpufreq/cpufreq-dt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@
1212

1313
#include <linux/types.h>
1414

15+
struct cpufreq_policy;
16+
1517
struct cpufreq_dt_platform_data {
1618
bool have_governor_per_policy;
19+
20+
int (*suspend)(struct cpufreq_policy *policy);
21+
int (*resume)(struct cpufreq_policy *policy);
1722
};
1823

1924
#endif /* __CPUFREQ_DT_H__ */

drivers/cpufreq/cpufreq.c

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,7 @@ static void cpufreq_governor_limits(struct cpufreq_policy *policy);
8989
* The mutex locks both lists.
9090
*/
9191
static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
92-
static struct srcu_notifier_head cpufreq_transition_notifier_list;
93-
94-
static bool init_cpufreq_transition_notifier_list_called;
95-
static int __init init_cpufreq_transition_notifier_list(void)
96-
{
97-
srcu_init_notifier_head(&cpufreq_transition_notifier_list);
98-
init_cpufreq_transition_notifier_list_called = true;
99-
return 0;
100-
}
101-
pure_initcall(init_cpufreq_transition_notifier_list);
92+
SRCU_NOTIFIER_HEAD_STATIC(cpufreq_transition_notifier_list);
10293

10394
static int off __read_mostly;
10495
static int cpufreq_disabled(void)
@@ -300,8 +291,19 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
300291
#endif
301292
}
302293

303-
static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
304-
struct cpufreq_freqs *freqs, unsigned int state)
294+
/**
295+
* cpufreq_notify_transition - Notify frequency transition and adjust_jiffies.
296+
* @policy: cpufreq policy to enable fast frequency switching for.
297+
* @freqs: contain details of the frequency update.
298+
* @state: set to CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE.
299+
*
300+
* This function calls the transition notifiers and the "adjust_jiffies"
301+
* function. It is called twice on all CPU frequency changes that have
302+
* external effects.
303+
*/
304+
static void cpufreq_notify_transition(struct cpufreq_policy *policy,
305+
struct cpufreq_freqs *freqs,
306+
unsigned int state)
305307
{
306308
BUG_ON(irqs_disabled());
307309

@@ -313,54 +315,44 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
313315
state, freqs->new);
314316

315317
switch (state) {
316-
317318
case CPUFREQ_PRECHANGE:
318-
/* detect if the driver reported a value as "old frequency"
319+
/*
320+
* Detect if the driver reported a value as "old frequency"
319321
* which is not equal to what the cpufreq core thinks is
320322
* "old frequency".
321323
*/
322324
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
323-
if ((policy) && (policy->cpu == freqs->cpu) &&
324-
(policy->cur) && (policy->cur != freqs->old)) {
325+
if (policy->cur && (policy->cur != freqs->old)) {
325326
pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n",
326327
freqs->old, policy->cur);
327328
freqs->old = policy->cur;
328329
}
329330
}
330-
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
331-
CPUFREQ_PRECHANGE, freqs);
331+
332+
for_each_cpu(freqs->cpu, policy->cpus) {
333+
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
334+
CPUFREQ_PRECHANGE, freqs);
335+
}
336+
332337
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
333338
break;
334339

335340
case CPUFREQ_POSTCHANGE:
336341
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
337-
pr_debug("FREQ: %lu - CPU: %lu\n",
338-
(unsigned long)freqs->new, (unsigned long)freqs->cpu);
339-
trace_cpu_frequency(freqs->new, freqs->cpu);
342+
pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new,
343+
cpumask_pr_args(policy->cpus));
344+
345+
for_each_cpu(freqs->cpu, policy->cpus) {
346+
trace_cpu_frequency(freqs->new, freqs->cpu);
347+
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
348+
CPUFREQ_POSTCHANGE, freqs);
349+
}
350+
340351
cpufreq_stats_record_transition(policy, freqs->new);
341-
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
342-
CPUFREQ_POSTCHANGE, freqs);
343-
if (likely(policy) && likely(policy->cpu == freqs->cpu))
344-
policy->cur = freqs->new;
345-
break;
352+
policy->cur = freqs->new;
346353
}
347354
}
348355

349-
/**
350-
* cpufreq_notify_transition - call notifier chain and adjust_jiffies
351-
* on frequency transition.
352-
*
353-
* This function calls the transition notifiers and the "adjust_jiffies"
354-
* function. It is called twice on all CPU frequency changes that have
355-
* external effects.
356-
*/
357-
static void cpufreq_notify_transition(struct cpufreq_policy *policy,
358-
struct cpufreq_freqs *freqs, unsigned int state)
359-
{
360-
for_each_cpu(freqs->cpu, policy->cpus)
361-
__cpufreq_notify_transition(policy, freqs, state);
362-
}
363-
364356
/* Do post notifications when there are chances that transition has failed */
365357
static void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
366358
struct cpufreq_freqs *freqs, int transition_failed)
@@ -696,6 +688,8 @@ static ssize_t store_##file_name \
696688
struct cpufreq_policy new_policy; \
697689
\
698690
memcpy(&new_policy, policy, sizeof(*policy)); \
691+
new_policy.min = policy->user_policy.min; \
692+
new_policy.max = policy->user_policy.max; \
699693
\
700694
ret = sscanf(buf, "%u", &new_policy.object); \
701695
if (ret != 1) \
@@ -1764,8 +1758,6 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
17641758
if (cpufreq_disabled())
17651759
return -EINVAL;
17661760

1767-
WARN_ON(!init_cpufreq_transition_notifier_list_called);
1768-
17691761
switch (list) {
17701762
case CPUFREQ_TRANSITION_NOTIFIER:
17711763
mutex_lock(&cpufreq_fast_switch_lock);

0 commit comments

Comments
 (0)