Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/cpufreq/imx6q-cpufreq.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2013 Freescale Semiconductor, Inc.
4
*/
5
6
#include <linux/clk.h>
7
#include <linux/cpu.h>
8
#include <linux/cpufreq.h>
9
#include <linux/err.h>
10
#include <linux/module.h>
11
#include <linux/nvmem-consumer.h>
12
#include <linux/of.h>
13
#include <linux/of_address.h>
14
#include <linux/pm_opp.h>
15
#include <linux/platform_device.h>
16
#include <linux/regulator/consumer.h>
17
#include <linux/mfd/syscon.h>
18
#include <linux/regmap.h>
19
20
#define PU_SOC_VOLTAGE_NORMAL 1250000
21
#define PU_SOC_VOLTAGE_HIGH 1275000
22
#define FREQ_1P2_GHZ 1200000000
23
24
static struct regulator *arm_reg;
25
static struct regulator *pu_reg;
26
static struct regulator *soc_reg;
27
28
enum IMX6_CPUFREQ_CLKS {
29
ARM,
30
PLL1_SYS,
31
STEP,
32
PLL1_SW,
33
PLL2_PFD2_396M,
34
/* MX6UL requires two more clks */
35
PLL2_BUS,
36
SECONDARY_SEL,
37
};
38
#define IMX6Q_CPUFREQ_CLK_NUM 5
39
#define IMX6UL_CPUFREQ_CLK_NUM 7
40
41
static int num_clks;
42
static struct clk_bulk_data clks[] = {
43
{ .id = "arm" },
44
{ .id = "pll1_sys" },
45
{ .id = "step" },
46
{ .id = "pll1_sw" },
47
{ .id = "pll2_pfd2_396m" },
48
{ .id = "pll2_bus" },
49
{ .id = "secondary_sel" },
50
};
51
52
static struct device *cpu_dev;
53
static struct cpufreq_frequency_table *freq_table;
54
static unsigned int max_freq;
55
static unsigned int transition_latency;
56
57
static u32 *imx6_soc_volt;
58
static u32 soc_opp_count;
59
60
static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
61
{
62
struct dev_pm_opp *opp;
63
unsigned long freq_hz, volt, volt_old;
64
unsigned int old_freq, new_freq;
65
bool pll1_sys_temp_enabled = false;
66
int ret;
67
68
new_freq = freq_table[index].frequency;
69
freq_hz = new_freq * 1000;
70
old_freq = clk_get_rate(clks[ARM].clk) / 1000;
71
72
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
73
if (IS_ERR(opp)) {
74
dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
75
return PTR_ERR(opp);
76
}
77
78
volt = dev_pm_opp_get_voltage(opp);
79
dev_pm_opp_put(opp);
80
81
volt_old = regulator_get_voltage(arm_reg);
82
83
dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
84
old_freq / 1000, volt_old / 1000,
85
new_freq / 1000, volt / 1000);
86
87
/* scaling up? scale voltage before frequency */
88
if (new_freq > old_freq) {
89
if (!IS_ERR(pu_reg)) {
90
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
91
if (ret) {
92
dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
93
return ret;
94
}
95
}
96
ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
97
if (ret) {
98
dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret);
99
return ret;
100
}
101
ret = regulator_set_voltage_tol(arm_reg, volt, 0);
102
if (ret) {
103
dev_err(cpu_dev,
104
"failed to scale vddarm up: %d\n", ret);
105
return ret;
106
}
107
}
108
109
/*
110
* The setpoints are selected per PLL/PDF frequencies, so we need to
111
* reprogram PLL for frequency scaling. The procedure of reprogramming
112
* PLL1 is as below.
113
* For i.MX6UL, it has a secondary clk mux, the cpu frequency change
114
* flow is slightly different from other i.MX6 OSC.
115
* The cpu frequeny change flow for i.MX6(except i.MX6UL) is as below:
116
* - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it
117
* - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
118
* - Disable pll2_pfd2_396m_clk
119
*/
120
if (of_machine_is_compatible("fsl,imx6ul") ||
121
of_machine_is_compatible("fsl,imx6ull")) {
122
/*
123
* When changing pll1_sw_clk's parent to pll1_sys_clk,
124
* CPU may run at higher than 528MHz, this will lead to
125
* the system unstable if the voltage is lower than the
126
* voltage of 528MHz, so lower the CPU frequency to one
127
* half before changing CPU frequency.
128
*/
129
clk_set_rate(clks[ARM].clk, (old_freq >> 1) * 1000);
130
clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
131
if (freq_hz > clk_get_rate(clks[PLL2_PFD2_396M].clk))
132
clk_set_parent(clks[SECONDARY_SEL].clk,
133
clks[PLL2_BUS].clk);
134
else
135
clk_set_parent(clks[SECONDARY_SEL].clk,
136
clks[PLL2_PFD2_396M].clk);
137
clk_set_parent(clks[STEP].clk, clks[SECONDARY_SEL].clk);
138
clk_set_parent(clks[PLL1_SW].clk, clks[STEP].clk);
139
if (freq_hz > clk_get_rate(clks[PLL2_BUS].clk)) {
140
clk_set_rate(clks[PLL1_SYS].clk, new_freq * 1000);
141
clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
142
}
143
} else {
144
clk_set_parent(clks[STEP].clk, clks[PLL2_PFD2_396M].clk);
145
clk_set_parent(clks[PLL1_SW].clk, clks[STEP].clk);
146
if (freq_hz > clk_get_rate(clks[PLL2_PFD2_396M].clk)) {
147
clk_set_rate(clks[PLL1_SYS].clk, new_freq * 1000);
148
clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
149
} else {
150
/* pll1_sys needs to be enabled for divider rate change to work. */
151
pll1_sys_temp_enabled = true;
152
clk_prepare_enable(clks[PLL1_SYS].clk);
153
}
154
}
155
156
/* Ensure the arm clock divider is what we expect */
157
ret = clk_set_rate(clks[ARM].clk, new_freq * 1000);
158
if (ret) {
159
int ret1;
160
161
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
162
ret1 = regulator_set_voltage_tol(arm_reg, volt_old, 0);
163
if (ret1)
164
dev_warn(cpu_dev,
165
"failed to restore vddarm voltage: %d\n", ret1);
166
return ret;
167
}
168
169
/* PLL1 is only needed until after ARM-PODF is set. */
170
if (pll1_sys_temp_enabled)
171
clk_disable_unprepare(clks[PLL1_SYS].clk);
172
173
/* scaling down? scale voltage after frequency */
174
if (new_freq < old_freq) {
175
ret = regulator_set_voltage_tol(arm_reg, volt, 0);
176
if (ret)
177
dev_warn(cpu_dev,
178
"failed to scale vddarm down: %d\n", ret);
179
ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
180
if (ret)
181
dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
182
if (!IS_ERR(pu_reg)) {
183
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
184
if (ret)
185
dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
186
}
187
}
188
189
return 0;
190
}
191
192
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
193
{
194
policy->clk = clks[ARM].clk;
195
cpufreq_generic_init(policy, freq_table, transition_latency);
196
policy->suspend_freq = max_freq;
197
198
return 0;
199
}
200
201
static struct cpufreq_driver imx6q_cpufreq_driver = {
202
.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
203
CPUFREQ_IS_COOLING_DEV,
204
.verify = cpufreq_generic_frequency_table_verify,
205
.target_index = imx6q_set_target,
206
.get = cpufreq_generic_get,
207
.init = imx6q_cpufreq_init,
208
.register_em = cpufreq_register_em_with_opp,
209
.name = "imx6q-cpufreq",
210
.suspend = cpufreq_generic_suspend,
211
};
212
213
static void imx6x_disable_freq_in_opp(struct device *dev, unsigned long freq)
214
{
215
int ret = dev_pm_opp_disable(dev, freq);
216
217
if (ret < 0 && ret != -ENODEV)
218
dev_warn(dev, "failed to disable %ldMHz OPP\n", freq / 1000000);
219
}
220
221
#define OCOTP_CFG3 0x440
222
#define OCOTP_CFG3_SPEED_SHIFT 16
223
#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
224
#define OCOTP_CFG3_SPEED_996MHZ 0x2
225
#define OCOTP_CFG3_SPEED_852MHZ 0x1
226
227
static int imx6q_opp_check_speed_grading(struct device *dev)
228
{
229
u32 val;
230
int ret;
231
232
if (of_property_present(dev->of_node, "nvmem-cells")) {
233
ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
234
if (ret)
235
return ret;
236
} else {
237
struct regmap *ocotp;
238
239
ocotp = syscon_regmap_lookup_by_compatible("fsl,imx6q-ocotp");
240
if (IS_ERR(ocotp))
241
return -ENOENT;
242
243
/*
244
* SPEED_GRADING[1:0] defines the max speed of ARM:
245
* 2b'11: 1200000000Hz;
246
* 2b'10: 996000000Hz;
247
* 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
248
* 2b'00: 792000000Hz;
249
* We need to set the max speed of ARM according to fuse map.
250
*/
251
regmap_read(ocotp, OCOTP_CFG3, &val);
252
}
253
254
val >>= OCOTP_CFG3_SPEED_SHIFT;
255
val &= 0x3;
256
257
if (val < OCOTP_CFG3_SPEED_996MHZ)
258
imx6x_disable_freq_in_opp(dev, 996000000);
259
260
if (of_machine_is_compatible("fsl,imx6q") ||
261
of_machine_is_compatible("fsl,imx6qp")) {
262
if (val != OCOTP_CFG3_SPEED_852MHZ)
263
imx6x_disable_freq_in_opp(dev, 852000000);
264
265
if (val != OCOTP_CFG3_SPEED_1P2GHZ)
266
imx6x_disable_freq_in_opp(dev, 1200000000);
267
}
268
269
return 0;
270
}
271
272
#define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2
273
#define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
274
#define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
275
276
static int imx6ul_opp_check_speed_grading(struct device *dev)
277
{
278
u32 val;
279
int ret = 0;
280
281
if (of_property_present(dev->of_node, "nvmem-cells")) {
282
ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
283
if (ret)
284
return ret;
285
} else {
286
struct regmap *ocotp;
287
288
ocotp = syscon_regmap_lookup_by_compatible("fsl,imx6ul-ocotp");
289
if (IS_ERR(ocotp))
290
ocotp = syscon_regmap_lookup_by_compatible("fsl,imx6ull-ocotp");
291
292
if (IS_ERR(ocotp))
293
return -ENOENT;
294
295
regmap_read(ocotp, OCOTP_CFG3, &val);
296
}
297
298
/*
299
* Speed GRADING[1:0] defines the max speed of ARM:
300
* 2b'00: Reserved;
301
* 2b'01: 528000000Hz;
302
* 2b'10: 696000000Hz on i.MX6UL, 792000000Hz on i.MX6ULL;
303
* 2b'11: 900000000Hz on i.MX6ULL only;
304
* We need to set the max speed of ARM according to fuse map.
305
*/
306
val >>= OCOTP_CFG3_SPEED_SHIFT;
307
val &= 0x3;
308
309
if (of_machine_is_compatible("fsl,imx6ul"))
310
if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
311
imx6x_disable_freq_in_opp(dev, 696000000);
312
313
if (of_machine_is_compatible("fsl,imx6ull")) {
314
if (val < OCOTP_CFG3_6ULL_SPEED_792MHZ)
315
imx6x_disable_freq_in_opp(dev, 792000000);
316
317
if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
318
imx6x_disable_freq_in_opp(dev, 900000000);
319
}
320
321
return ret;
322
}
323
324
static int imx6q_cpufreq_probe(struct platform_device *pdev)
325
{
326
struct device_node *np;
327
struct dev_pm_opp *opp;
328
unsigned long min_volt, max_volt;
329
int num, ret;
330
const struct property *prop;
331
const __be32 *val;
332
u32 nr, i, j;
333
334
cpu_dev = get_cpu_device(0);
335
if (!cpu_dev) {
336
pr_err("failed to get cpu0 device\n");
337
return -ENODEV;
338
}
339
340
np = of_node_get(cpu_dev->of_node);
341
if (!np) {
342
dev_err(cpu_dev, "failed to find cpu0 node\n");
343
return -ENOENT;
344
}
345
346
if (of_machine_is_compatible("fsl,imx6ul") ||
347
of_machine_is_compatible("fsl,imx6ull"))
348
num_clks = IMX6UL_CPUFREQ_CLK_NUM;
349
else
350
num_clks = IMX6Q_CPUFREQ_CLK_NUM;
351
352
ret = clk_bulk_get(cpu_dev, num_clks, clks);
353
if (ret)
354
goto put_node;
355
356
arm_reg = regulator_get(cpu_dev, "arm");
357
pu_reg = regulator_get_optional(cpu_dev, "pu");
358
soc_reg = regulator_get(cpu_dev, "soc");
359
if (PTR_ERR(arm_reg) == -EPROBE_DEFER ||
360
PTR_ERR(soc_reg) == -EPROBE_DEFER ||
361
PTR_ERR(pu_reg) == -EPROBE_DEFER) {
362
ret = -EPROBE_DEFER;
363
dev_dbg(cpu_dev, "regulators not ready, defer\n");
364
goto put_reg;
365
}
366
if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
367
dev_err(cpu_dev, "failed to get regulators\n");
368
ret = -ENOENT;
369
goto put_reg;
370
}
371
372
ret = dev_pm_opp_of_add_table(cpu_dev);
373
if (ret < 0) {
374
dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
375
goto put_reg;
376
}
377
378
if (of_machine_is_compatible("fsl,imx6ul") ||
379
of_machine_is_compatible("fsl,imx6ull")) {
380
ret = imx6ul_opp_check_speed_grading(cpu_dev);
381
} else {
382
ret = imx6q_opp_check_speed_grading(cpu_dev);
383
}
384
if (ret) {
385
dev_err_probe(cpu_dev, ret, "failed to read ocotp\n");
386
goto out_free_opp;
387
}
388
389
num = dev_pm_opp_get_opp_count(cpu_dev);
390
if (num < 0) {
391
ret = num;
392
dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
393
goto out_free_opp;
394
}
395
396
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
397
if (ret) {
398
dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
399
goto out_free_opp;
400
}
401
402
/* Make imx6_soc_volt array's size same as arm opp number */
403
imx6_soc_volt = devm_kcalloc(cpu_dev, num, sizeof(*imx6_soc_volt),
404
GFP_KERNEL);
405
if (imx6_soc_volt == NULL) {
406
ret = -ENOMEM;
407
goto free_freq_table;
408
}
409
410
prop = of_find_property(np, "fsl,soc-operating-points", NULL);
411
if (!prop || !prop->value)
412
goto soc_opp_out;
413
414
/*
415
* Each OPP is a set of tuples consisting of frequency and
416
* voltage like <freq-kHz vol-uV>.
417
*/
418
nr = prop->length / sizeof(u32);
419
if (nr % 2 || (nr / 2) < num)
420
goto soc_opp_out;
421
422
for (j = 0; j < num; j++) {
423
val = prop->value;
424
for (i = 0; i < nr / 2; i++) {
425
unsigned long freq = be32_to_cpup(val++);
426
unsigned long volt = be32_to_cpup(val++);
427
if (freq_table[j].frequency == freq) {
428
imx6_soc_volt[soc_opp_count++] = volt;
429
break;
430
}
431
}
432
}
433
434
soc_opp_out:
435
/* use fixed soc opp volt if no valid soc opp info found in dtb */
436
if (soc_opp_count != num) {
437
dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n");
438
for (j = 0; j < num; j++)
439
imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL;
440
if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ)
441
imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH;
442
}
443
444
if (of_property_read_u32(np, "clock-latency", &transition_latency))
445
transition_latency = CPUFREQ_ETERNAL;
446
447
/*
448
* Calculate the ramp time for max voltage change in the
449
* VDDSOC and VDDPU regulators.
450
*/
451
ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
452
if (ret > 0)
453
transition_latency += ret * 1000;
454
if (!IS_ERR(pu_reg)) {
455
ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
456
if (ret > 0)
457
transition_latency += ret * 1000;
458
}
459
460
/*
461
* OPP is maintained in order of increasing frequency, and
462
* freq_table initialised from OPP is therefore sorted in the
463
* same order.
464
*/
465
max_freq = freq_table[--num].frequency;
466
opp = dev_pm_opp_find_freq_exact(cpu_dev,
467
freq_table[0].frequency * 1000, true);
468
min_volt = dev_pm_opp_get_voltage(opp);
469
dev_pm_opp_put(opp);
470
opp = dev_pm_opp_find_freq_exact(cpu_dev, max_freq * 1000, true);
471
max_volt = dev_pm_opp_get_voltage(opp);
472
dev_pm_opp_put(opp);
473
474
ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
475
if (ret > 0)
476
transition_latency += ret * 1000;
477
478
ret = cpufreq_register_driver(&imx6q_cpufreq_driver);
479
if (ret) {
480
dev_err(cpu_dev, "failed register driver: %d\n", ret);
481
goto free_freq_table;
482
}
483
484
of_node_put(np);
485
return 0;
486
487
free_freq_table:
488
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
489
out_free_opp:
490
dev_pm_opp_of_remove_table(cpu_dev);
491
put_reg:
492
if (!IS_ERR(arm_reg))
493
regulator_put(arm_reg);
494
if (!IS_ERR(pu_reg))
495
regulator_put(pu_reg);
496
if (!IS_ERR(soc_reg))
497
regulator_put(soc_reg);
498
499
clk_bulk_put(num_clks, clks);
500
put_node:
501
of_node_put(np);
502
503
return ret;
504
}
505
506
static void imx6q_cpufreq_remove(struct platform_device *pdev)
507
{
508
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
509
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
510
dev_pm_opp_of_remove_table(cpu_dev);
511
regulator_put(arm_reg);
512
if (!IS_ERR(pu_reg))
513
regulator_put(pu_reg);
514
regulator_put(soc_reg);
515
516
clk_bulk_put(num_clks, clks);
517
}
518
519
static struct platform_driver imx6q_cpufreq_platdrv = {
520
.driver = {
521
.name = "imx6q-cpufreq",
522
},
523
.probe = imx6q_cpufreq_probe,
524
.remove = imx6q_cpufreq_remove,
525
};
526
module_platform_driver(imx6q_cpufreq_platdrv);
527
528
MODULE_ALIAS("platform:imx6q-cpufreq");
529
MODULE_AUTHOR("Shawn Guo <[email protected]>");
530
MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver");
531
MODULE_LICENSE("GPL");
532
533