1 /*-
2 * Copyright (c) 2016 Michal Meloun <[email protected]>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/cpu.h>
34 #include <sys/kernel.h>
35 #include <sys/lock.h>
36 #include <sys/malloc.h>
37 #include <sys/module.h>
38
39 #include <machine/bus.h>
40 #include <machine/cpu.h>
41
42 #include <dev/extres/clk/clk.h>
43 #include <dev/extres/regulator/regulator.h>
44 #include <dev/ofw/ofw_bus_subr.h>
45
46 #include <arm/nvidia/tegra_efuse.h>
47
48 #include "cpufreq_if.h"
49
50 #define XXX
51
52 /* CPU voltage table entry */
53 struct speedo_entry {
54 uint64_t freq; /* Frequency point */
55 int c0; /* Coeeficient values for */
56 int c1; /* quadratic equation: */
57 int c2; /* c2 * speedo^2 + c1 * speedo + c0 */
58 };
59
60 struct cpu_volt_def {
61 int min_uvolt; /* Min allowed CPU voltage */
62 int max_uvolt; /* Max allowed CPU voltage */
63 int step_uvolt; /* Step of CPU voltage */
64 int speedo_scale; /* Scaling factor for cvt */
65 int speedo_nitems; /* Size of speedo table */
66 struct speedo_entry *speedo_tbl; /* CPU voltage table */
67 };
68
69 struct cpu_speed_point {
70 uint64_t freq; /* Frequecy */
71 int uvolt; /* Requested voltage */
72 };
73
74 static struct speedo_entry tegra124_speedo_dpll_tbl[] =
75 {
76 { 204000000ULL, 1112619, -29295, 402},
77 { 306000000ULL, 1150460, -30585, 402},
78 { 408000000ULL, 1190122, -31865, 402},
79 { 510000000ULL, 1231606, -33155, 402},
80 { 612000000ULL, 1274912, -34435, 402},
81 { 714000000ULL, 1320040, -35725, 402},
82 { 816000000ULL, 1366990, -37005, 402},
83 { 918000000ULL, 1415762, -38295, 402},
84 {1020000000ULL, 1466355, -39575, 402},
85 {1122000000ULL, 1518771, -40865, 402},
86 {1224000000ULL, 1573009, -42145, 402},
87 {1326000000ULL, 1629068, -43435, 402},
88 {1428000000ULL, 1686950, -44715, 402},
89 {1530000000ULL, 1746653, -46005, 402},
90 {1632000000ULL, 1808179, -47285, 402},
91 {1734000000ULL, 1871526, -48575, 402},
92 {1836000000ULL, 1936696, -49855, 402},
93 {1938000000ULL, 2003687, -51145, 402},
94 {2014500000ULL, 2054787, -52095, 402},
95 {2116500000ULL, 2124957, -53385, 402},
96 {2218500000ULL, 2196950, -54665, 402},
97 {2320500000ULL, 2270765, -55955, 402},
98 {2320500000ULL, 2270765, -55955, 402},
99 {2422500000ULL, 2346401, -57235, 402},
100 {2524500000ULL, 2437299, -58535, 402},
101 };
102
103 static struct cpu_volt_def tegra124_cpu_volt_dpll_def =
104 {
105 .min_uvolt = 900000, /* 0.9 V */
106 .max_uvolt = 1260000, /* 1.26 */
107 .step_uvolt = 10000, /* 10 mV */
108 .speedo_scale = 100,
109 .speedo_nitems = nitems(tegra124_speedo_dpll_tbl),
110 .speedo_tbl = tegra124_speedo_dpll_tbl,
111 };
112
113 static struct speedo_entry tegra124_speedo_pllx_tbl[] =
114 {
115 { 204000000ULL, 800000, 0, 0},
116 { 306000000ULL, 800000, 0, 0},
117 { 408000000ULL, 800000, 0, 0},
118 { 510000000ULL, 800000, 0, 0},
119 { 612000000ULL, 800000, 0, 0},
120 { 714000000ULL, 800000, 0, 0},
121 { 816000000ULL, 820000, 0, 0},
122 { 918000000ULL, 840000, 0, 0},
123 {1020000000ULL, 880000, 0, 0},
124 {1122000000ULL, 900000, 0, 0},
125 {1224000000ULL, 930000, 0, 0},
126 {1326000000ULL, 960000, 0, 0},
127 {1428000000ULL, 990000, 0, 0},
128 {1530000000ULL, 1020000, 0, 0},
129 {1632000000ULL, 1070000, 0, 0},
130 {1734000000ULL, 1100000, 0, 0},
131 {1836000000ULL, 1140000, 0, 0},
132 {1938000000ULL, 1180000, 0, 0},
133 {2014500000ULL, 1220000, 0, 0},
134 {2116500000ULL, 1260000, 0, 0},
135 {2218500000ULL, 1310000, 0, 0},
136 {2320500000ULL, 1360000, 0, 0},
137 {2397000000ULL, 1400000, 0, 0},
138 {2499000000ULL, 1400000, 0, 0},
139 };
140
141 static struct cpu_volt_def tegra124_cpu_volt_pllx_def =
142 {
143 .min_uvolt = 1000000, /* XXX 0.9 V doesn't work on all boards */
144 .max_uvolt = 1260000, /* 1.26 */
145 .step_uvolt = 10000, /* 10 mV */
146 .speedo_scale = 100,
147 .speedo_nitems = nitems(tegra124_speedo_pllx_tbl),
148 .speedo_tbl = tegra124_speedo_pllx_tbl,
149 };
150
151 static uint64_t cpu_freq_tbl[] = {
152 204000000ULL,
153 306000000ULL,
154 408000000ULL,
155 510000000ULL,
156 612000000ULL,
157 714000000ULL,
158 816000000ULL,
159 918000000ULL,
160 1020000000ULL,
161 1122000000ULL,
162 1224000000ULL,
163 1326000000ULL,
164 1428000000ULL,
165 1530000000ULL,
166 1632000000ULL,
167 1734000000ULL,
168 1836000000ULL,
169 1938000000ULL,
170 2014000000ULL,
171 2116000000ULL,
172 2218000000ULL,
173 2320000000ULL,
174 2422000000ULL,
175 2524000000ULL,
176 };
177
178 static uint64_t cpu_max_freq[] = {
179 2014500000ULL,
180 2320500000ULL,
181 2116500000ULL,
182 2524500000ULL,
183 };
184
185 struct tegra124_cpufreq_softc {
186 device_t dev;
187 phandle_t node;
188
189 regulator_t supply_vdd_cpu;
190 clk_t clk_cpu_g;
191 clk_t clk_cpu_lp;
192 clk_t clk_pll_x;
193 clk_t clk_pll_p;
194 clk_t clk_dfll;
195
196 int process_id;
197 int speedo_id;
198 int speedo_value;
199
200 uint64_t cpu_max_freq;
201 struct cpu_volt_def *cpu_def;
202 struct cpu_speed_point *speed_points;
203 int nspeed_points;
204
205 struct cpu_speed_point *act_speed_point;
206
207 int latency;
208 };
209
210 static int cpufreq_lowest_freq = 1;
211 TUNABLE_INT("hw.tegra124.cpufreq.lowest_freq", &cpufreq_lowest_freq);
212
213 #define DIV_ROUND_CLOSEST(val, div) (((val) + ((div) / 2)) / (div))
214
215 #define ROUND_UP(val, div) roundup(val, div)
216 #define ROUND_DOWN(val, div) rounddown(val, div)
217
218 /*
219 * Compute requesetd voltage for given frequency and SoC process variations,
220 * - compute base voltage from speedo value using speedo table
221 * - round up voltage to next regulator step
222 * - clamp it to regulator limits
223 */
224 static int
freq_to_voltage(struct tegra124_cpufreq_softc * sc,uint64_t freq)225 freq_to_voltage(struct tegra124_cpufreq_softc *sc, uint64_t freq)
226 {
227 int uv, scale, min_uvolt, max_uvolt, step_uvolt;
228 struct speedo_entry *ent;
229 int i;
230
231 /* Get speedo entry with higher frequency */
232 ent = NULL;
233 for (i = 0; i < sc->cpu_def->speedo_nitems; i++) {
234 if (sc->cpu_def->speedo_tbl[i].freq >= freq) {
235 ent = &sc->cpu_def->speedo_tbl[i];
236 break;
237 }
238 }
239 if (ent == NULL)
240 ent = &sc->cpu_def->speedo_tbl[sc->cpu_def->speedo_nitems - 1];
241 scale = sc->cpu_def->speedo_scale;
242
243 /* uV = (c2 * speedo / scale + c1) * speedo / scale + c0) */
244 uv = DIV_ROUND_CLOSEST(ent->c2 * sc->speedo_value, scale);
245 uv = DIV_ROUND_CLOSEST((uv + ent->c1) * sc->speedo_value, scale) +
246 ent->c0;
247 step_uvolt = sc->cpu_def->step_uvolt;
248 /* Round up it to next regulator step */
249 uv = ROUND_UP(uv, step_uvolt);
250
251 /* Clamp result */
252 min_uvolt = ROUND_UP(sc->cpu_def->min_uvolt, step_uvolt);
253 max_uvolt = ROUND_DOWN(sc->cpu_def->max_uvolt, step_uvolt);
254 if (uv < min_uvolt)
255 uv = min_uvolt;
256 if (uv > max_uvolt)
257 uv = max_uvolt;
258 return (uv);
259
260 }
261
262 static void
build_speed_points(struct tegra124_cpufreq_softc * sc)263 build_speed_points(struct tegra124_cpufreq_softc *sc) {
264 int i;
265
266 sc->nspeed_points = nitems(cpu_freq_tbl);
267 sc->speed_points = malloc(sizeof(struct cpu_speed_point) *
268 sc->nspeed_points, M_DEVBUF, M_NOWAIT);
269 for (i = 0; i < sc->nspeed_points; i++) {
270 sc->speed_points[i].freq = cpu_freq_tbl[i];
271 sc->speed_points[i].uvolt = freq_to_voltage(sc,
272 cpu_freq_tbl[i]);
273 }
274 }
275
276 static struct cpu_speed_point *
get_speed_point(struct tegra124_cpufreq_softc * sc,uint64_t freq)277 get_speed_point(struct tegra124_cpufreq_softc *sc, uint64_t freq)
278 {
279 int i;
280
281 if (sc->speed_points[0].freq >= freq)
282 return (sc->speed_points + 0);
283
284 for (i = 0; i < sc->nspeed_points - 1; i++) {
285 if (sc->speed_points[i + 1].freq > freq)
286 return (sc->speed_points + i);
287 }
288
289 return (sc->speed_points + sc->nspeed_points - 1);
290 }
291
292 static int
tegra124_cpufreq_settings(device_t dev,struct cf_setting * sets,int * count)293 tegra124_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
294 {
295 struct tegra124_cpufreq_softc *sc;
296 int i, j, max_cnt;
297
298 if (sets == NULL || count == NULL)
299 return (EINVAL);
300
301 sc = device_get_softc(dev);
302 memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
303
304 max_cnt = min(sc->nspeed_points, *count);
305 for (i = 0, j = sc->nspeed_points - 1; j >= 0; j--) {
306 if (sc->cpu_max_freq < sc->speed_points[j].freq)
307 continue;
308 sets[i].freq = sc->speed_points[j].freq / 1000000;
309 sets[i].volts = sc->speed_points[j].uvolt / 1000;
310 sets[i].lat = sc->latency;
311 sets[i].dev = dev;
312 i++;
313 }
314 *count = i;
315
316 return (0);
317 }
318
319 static int
set_cpu_freq(struct tegra124_cpufreq_softc * sc,uint64_t freq)320 set_cpu_freq(struct tegra124_cpufreq_softc *sc, uint64_t freq)
321 {
322 struct cpu_speed_point *point;
323 int rv;
324
325 point = get_speed_point(sc, freq);
326
327 if (sc->act_speed_point->uvolt < point->uvolt) {
328 /* set cpu voltage */
329 rv = regulator_set_voltage(sc->supply_vdd_cpu,
330 point->uvolt, point->uvolt);
331 DELAY(10000);
332 if (rv != 0)
333 return (rv);
334 }
335
336 /* Switch supermux to PLLP first */
337 rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_p);
338 if (rv != 0) {
339 device_printf(sc->dev, "Can't set parent to PLLP\n");
340 return (rv);
341 }
342
343 /* Set PLLX frequency */
344 rv = clk_set_freq(sc->clk_pll_x, point->freq, CLK_SET_ROUND_DOWN);
345 if (rv != 0) {
346 device_printf(sc->dev, "Can't set CPU clock frequency\n");
347 return (rv);
348 }
349
350 rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_x);
351 if (rv != 0) {
352 device_printf(sc->dev, "Can't set parent to PLLX\n");
353 return (rv);
354 }
355
356 if (sc->act_speed_point->uvolt > point->uvolt) {
357 /* set cpu voltage */
358 rv = regulator_set_voltage(sc->supply_vdd_cpu,
359 point->uvolt, point->uvolt);
360 if (rv != 0)
361 return (rv);
362 }
363
364 sc->act_speed_point = point;
365
366 return (0);
367 }
368
369 static int
tegra124_cpufreq_set(device_t dev,const struct cf_setting * cf)370 tegra124_cpufreq_set(device_t dev, const struct cf_setting *cf)
371 {
372 struct tegra124_cpufreq_softc *sc;
373 uint64_t freq;
374 int rv;
375
376 if (cf == NULL || cf->freq < 0)
377 return (EINVAL);
378
379 sc = device_get_softc(dev);
380
381 freq = cf->freq;
382 if (freq < cpufreq_lowest_freq)
383 freq = cpufreq_lowest_freq;
384 freq *= 1000000;
385 if (freq >= sc->cpu_max_freq)
386 freq = sc->cpu_max_freq;
387 rv = set_cpu_freq(sc, freq);
388
389 return (rv);
390 }
391
392 static int
tegra124_cpufreq_get(device_t dev,struct cf_setting * cf)393 tegra124_cpufreq_get(device_t dev, struct cf_setting *cf)
394 {
395 struct tegra124_cpufreq_softc *sc;
396
397 if (cf == NULL)
398 return (EINVAL);
399
400 sc = device_get_softc(dev);
401 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
402 cf->dev = NULL;
403 cf->freq = sc->act_speed_point->freq / 1000000;
404 cf->volts = sc->act_speed_point->uvolt / 1000;
405 /* Transition latency in us. */
406 cf->lat = sc->latency;
407 /* Driver providing this setting. */
408 cf->dev = dev;
409
410 return (0);
411 }
412
413 static int
tegra124_cpufreq_type(device_t dev,int * type)414 tegra124_cpufreq_type(device_t dev, int *type)
415 {
416
417 if (type == NULL)
418 return (EINVAL);
419 *type = CPUFREQ_TYPE_ABSOLUTE;
420
421 return (0);
422 }
423
424 static int
get_fdt_resources(struct tegra124_cpufreq_softc * sc,phandle_t node)425 get_fdt_resources(struct tegra124_cpufreq_softc *sc, phandle_t node)
426 {
427 int rv;
428 device_t parent_dev;
429
430 parent_dev = device_get_parent(sc->dev);
431 rv = regulator_get_by_ofw_property(parent_dev, 0, "vdd-cpu-supply",
432 &sc->supply_vdd_cpu);
433 if (rv != 0) {
434 device_printf(sc->dev, "Cannot get 'vdd-cpu' regulator\n");
435 return (rv);
436 }
437
438 rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_g", &sc->clk_cpu_g);
439 if (rv != 0) {
440 device_printf(sc->dev, "Cannot get 'cpu_g' clock: %d\n", rv);
441 return (ENXIO);
442 }
443
444 rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_lp", &sc->clk_cpu_lp);
445 if (rv != 0) {
446 device_printf(sc->dev, "Cannot get 'cpu_lp' clock\n");
447 return (ENXIO);
448 }
449
450 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_x", &sc->clk_pll_x);
451 if (rv != 0) {
452 device_printf(sc->dev, "Cannot get 'pll_x' clock\n");
453 return (ENXIO);
454 }
455 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_p", &sc->clk_pll_p);
456 if (rv != 0) {
457 device_printf(parent_dev, "Cannot get 'pll_p' clock\n");
458 return (ENXIO);
459 }
460 rv = clk_get_by_ofw_name(parent_dev, 0, "dfll", &sc->clk_dfll);
461 if (rv != 0) {
462 /* XXX DPLL is not implemented yet */
463 /*
464 device_printf(sc->dev, "Cannot get 'dfll' clock\n");
465 return (ENXIO);
466 */
467 }
468 return (0);
469 }
470
471 static void
tegra124_cpufreq_identify(driver_t * driver,device_t parent)472 tegra124_cpufreq_identify(driver_t *driver, device_t parent)
473 {
474 phandle_t root;
475
476 root = OF_finddevice("/");
477 if (!ofw_bus_node_is_compatible(root, "nvidia,tegra124"))
478 return;
479
480 if (device_get_unit(parent) != 0)
481 return;
482 if (device_find_child(parent, "tegra124_cpufreq", -1) != NULL)
483 return;
484 if (BUS_ADD_CHILD(parent, 0, "tegra124_cpufreq", -1) == NULL)
485 device_printf(parent, "add child failed\n");
486 }
487
488 static int
tegra124_cpufreq_probe(device_t dev)489 tegra124_cpufreq_probe(device_t dev)
490 {
491
492 device_set_desc(dev, "CPU Frequency Control");
493
494 return (0);
495 }
496
497 static int
tegra124_cpufreq_attach(device_t dev)498 tegra124_cpufreq_attach(device_t dev)
499 {
500 struct tegra124_cpufreq_softc *sc;
501 uint64_t freq;
502 int rv;
503
504 sc = device_get_softc(dev);
505 sc->dev = dev;
506 sc->node = ofw_bus_get_node(device_get_parent(dev));
507
508 sc->process_id = tegra_sku_info.cpu_process_id;
509 sc->speedo_id = tegra_sku_info.cpu_speedo_id;
510 sc->speedo_value = tegra_sku_info.cpu_speedo_value;
511
512 /* Tegra 124 */
513 /* XXX DPLL is not implemented yet */
514 if (1)
515 sc->cpu_def = &tegra124_cpu_volt_pllx_def;
516 else
517 sc->cpu_def = &tegra124_cpu_volt_dpll_def;
518
519 rv = get_fdt_resources(sc, sc->node);
520 if (rv != 0) {
521 return (rv);
522 }
523
524 build_speed_points(sc);
525
526 rv = clk_get_freq(sc->clk_cpu_g, &freq);
527 if (rv != 0) {
528 device_printf(dev, "Can't get CPU clock frequency\n");
529 return (rv);
530 }
531 if (sc->speedo_id < nitems(cpu_max_freq))
532 sc->cpu_max_freq = cpu_max_freq[sc->speedo_id];
533 else
534 sc->cpu_max_freq = cpu_max_freq[0];
535 sc->act_speed_point = get_speed_point(sc, freq);
536
537 /* Set safe startup CPU frequency. */
538 rv = set_cpu_freq(sc, 1632000000);
539 if (rv != 0) {
540 device_printf(dev, "Can't set initial CPU clock frequency\n");
541 return (rv);
542 }
543
544 /* This device is controlled by cpufreq(4). */
545 cpufreq_register(dev);
546
547 return (0);
548 }
549
550 static int
tegra124_cpufreq_detach(device_t dev)551 tegra124_cpufreq_detach(device_t dev)
552 {
553 struct tegra124_cpufreq_softc *sc;
554
555 sc = device_get_softc(dev);
556 cpufreq_unregister(dev);
557
558 if (sc->supply_vdd_cpu != NULL)
559 regulator_release(sc->supply_vdd_cpu);
560
561 if (sc->clk_cpu_g != NULL)
562 clk_release(sc->clk_cpu_g);
563 if (sc->clk_cpu_lp != NULL)
564 clk_release(sc->clk_cpu_lp);
565 if (sc->clk_pll_x != NULL)
566 clk_release(sc->clk_pll_x);
567 if (sc->clk_pll_p != NULL)
568 clk_release(sc->clk_pll_p);
569 if (sc->clk_dfll != NULL)
570 clk_release(sc->clk_dfll);
571 return (0);
572 }
573
574 static device_method_t tegra124_cpufreq_methods[] = {
575 /* Device interface */
576 DEVMETHOD(device_identify, tegra124_cpufreq_identify),
577 DEVMETHOD(device_probe, tegra124_cpufreq_probe),
578 DEVMETHOD(device_attach, tegra124_cpufreq_attach),
579 DEVMETHOD(device_detach, tegra124_cpufreq_detach),
580
581 /* cpufreq interface */
582 DEVMETHOD(cpufreq_drv_set, tegra124_cpufreq_set),
583 DEVMETHOD(cpufreq_drv_get, tegra124_cpufreq_get),
584 DEVMETHOD(cpufreq_drv_settings, tegra124_cpufreq_settings),
585 DEVMETHOD(cpufreq_drv_type, tegra124_cpufreq_type),
586
587 DEVMETHOD_END
588 };
589
590 static devclass_t tegra124_cpufreq_devclass;
591 static DEFINE_CLASS_0(tegra124_cpufreq, tegra124_cpufreq_driver,
592 tegra124_cpufreq_methods, sizeof(struct tegra124_cpufreq_softc));
593 DRIVER_MODULE(tegra124_cpufreq, cpu, tegra124_cpufreq_driver,
594 tegra124_cpufreq_devclass, NULL, NULL);
595