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
142 static struct cpu_volt_def tegra124_cpu_volt_pllx_def =
143 {
144 .min_uvolt = 1000000, /* XXX 0.9 V doesn't work on all boards */
145 .max_uvolt = 1260000, /* 1.26 */
146 .step_uvolt = 10000, /* 10 mV */
147 .speedo_scale = 100,
148 .speedo_nitems = nitems(tegra124_speedo_pllx_tbl),
149 .speedo_tbl = tegra124_speedo_pllx_tbl,
150 };
151
152 static uint64_t cpu_freq_tbl[] = {
153 204000000ULL,
154 306000000ULL,
155 408000000ULL,
156 510000000ULL,
157 612000000ULL,
158 714000000ULL,
159 816000000ULL,
160 918000000ULL,
161 1020000000ULL,
162 1122000000ULL,
163 1224000000ULL,
164 1326000000ULL,
165 1428000000ULL,
166 1530000000ULL,
167 1632000000ULL,
168 1734000000ULL,
169 1836000000ULL,
170 1938000000ULL,
171 2014000000ULL,
172 2116000000ULL,
173 2218000000ULL,
174 2320000000ULL,
175 2422000000ULL,
176 2524000000ULL,
177 };
178
179 static uint64_t cpu_max_freq[] = {
180 2014500000ULL,
181 2320500000ULL,
182 2116500000ULL,
183 2524500000ULL,
184 };
185
186 struct tegra124_cpufreq_softc {
187 device_t dev;
188 phandle_t node;
189
190 regulator_t supply_vdd_cpu;
191 clk_t clk_cpu_g;
192 clk_t clk_cpu_lp;
193 clk_t clk_pll_x;
194 clk_t clk_pll_p;
195 clk_t clk_dfll;
196
197 int process_id;
198 int speedo_id;
199 int speedo_value;
200
201 uint64_t cpu_max_freq;
202 struct cpu_volt_def *cpu_def;
203 struct cpu_speed_point *speed_points;
204 int nspeed_points;
205
206 struct cpu_speed_point *act_speed_point;
207
208 int latency;
209 };
210
211 static int cpufreq_lowest_freq = 1;
212 TUNABLE_INT("hw.tegra124.cpufreq.lowest_freq", &cpufreq_lowest_freq);
213
214 #define DIV_ROUND_CLOSEST(val, div) (((val) + ((div) / 2)) / (div))
215
216 #define ROUND_UP(val, div) roundup(val, div)
217 #define ROUND_DOWN(val, div) rounddown(val, div)
218
219 /*
220 * Compute requesetd voltage for given frequency and SoC process variations,
221 * - compute base voltage from speedo value using speedo table
222 * - round up voltage to next regulator step
223 * - clamp it to regulator limits
224 */
225 static int
freq_to_voltage(struct tegra124_cpufreq_softc * sc,uint64_t freq)226 freq_to_voltage(struct tegra124_cpufreq_softc *sc, uint64_t freq)
227 {
228 int uv, scale, min_uvolt, max_uvolt, step_uvolt;
229 struct speedo_entry *ent;
230 int i;
231
232 /* Get speedo entry with higher frequency */
233 ent = NULL;
234 for (i = 0; i < sc->cpu_def->speedo_nitems; i++) {
235 if (sc->cpu_def->speedo_tbl[i].freq >= freq) {
236 ent = &sc->cpu_def->speedo_tbl[i];
237 break;
238 }
239 }
240 if (ent == NULL)
241 ent = &sc->cpu_def->speedo_tbl[sc->cpu_def->speedo_nitems - 1];
242 scale = sc->cpu_def->speedo_scale;
243
244
245 /* uV = (c2 * speedo / scale + c1) * speedo / scale + c0) */
246 uv = DIV_ROUND_CLOSEST(ent->c2 * sc->speedo_value, scale);
247 uv = DIV_ROUND_CLOSEST((uv + ent->c1) * sc->speedo_value, scale) +
248 ent->c0;
249 step_uvolt = sc->cpu_def->step_uvolt;
250 /* Round up it to next regulator step */
251 uv = ROUND_UP(uv, step_uvolt);
252
253 /* Clamp result */
254 min_uvolt = ROUND_UP(sc->cpu_def->min_uvolt, step_uvolt);
255 max_uvolt = ROUND_DOWN(sc->cpu_def->max_uvolt, step_uvolt);
256 if (uv < min_uvolt)
257 uv = min_uvolt;
258 if (uv > max_uvolt)
259 uv = max_uvolt;
260 return (uv);
261
262 }
263
264 static void
build_speed_points(struct tegra124_cpufreq_softc * sc)265 build_speed_points(struct tegra124_cpufreq_softc *sc) {
266 int i;
267
268 sc->nspeed_points = nitems(cpu_freq_tbl);
269 sc->speed_points = malloc(sizeof(struct cpu_speed_point) *
270 sc->nspeed_points, M_DEVBUF, M_NOWAIT);
271 for (i = 0; i < sc->nspeed_points; i++) {
272 sc->speed_points[i].freq = cpu_freq_tbl[i];
273 sc->speed_points[i].uvolt = freq_to_voltage(sc,
274 cpu_freq_tbl[i]);
275 }
276 }
277
278 static struct cpu_speed_point *
get_speed_point(struct tegra124_cpufreq_softc * sc,uint64_t freq)279 get_speed_point(struct tegra124_cpufreq_softc *sc, uint64_t freq)
280 {
281 int i;
282
283 if (sc->speed_points[0].freq >= freq)
284 return (sc->speed_points + 0);
285
286 for (i = 0; i < sc->nspeed_points - 1; i++) {
287 if (sc->speed_points[i + 1].freq > freq)
288 return (sc->speed_points + i);
289 }
290
291 return (sc->speed_points + sc->nspeed_points - 1);
292 }
293
294 static int
tegra124_cpufreq_settings(device_t dev,struct cf_setting * sets,int * count)295 tegra124_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
296 {
297 struct tegra124_cpufreq_softc *sc;
298 int i, j, max_cnt;
299
300 if (sets == NULL || count == NULL)
301 return (EINVAL);
302
303 sc = device_get_softc(dev);
304 memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
305
306 max_cnt = min(sc->nspeed_points, *count);
307 for (i = 0, j = sc->nspeed_points - 1; j >= 0; j--) {
308 if (sc->cpu_max_freq < sc->speed_points[j].freq)
309 continue;
310 sets[i].freq = sc->speed_points[j].freq / 1000000;
311 sets[i].volts = sc->speed_points[j].uvolt / 1000;
312 sets[i].lat = sc->latency;
313 sets[i].dev = dev;
314 i++;
315 }
316 *count = i;
317
318 return (0);
319 }
320
321 static int
set_cpu_freq(struct tegra124_cpufreq_softc * sc,uint64_t freq)322 set_cpu_freq(struct tegra124_cpufreq_softc *sc, uint64_t freq)
323 {
324 struct cpu_speed_point *point;
325 int rv;
326
327 point = get_speed_point(sc, freq);
328
329 if (sc->act_speed_point->uvolt < point->uvolt) {
330 /* set cpu voltage */
331 rv = regulator_set_voltage(sc->supply_vdd_cpu,
332 point->uvolt, point->uvolt);
333 DELAY(10000);
334 if (rv != 0)
335 return (rv);
336 }
337
338 /* Switch supermux to PLLP first */
339 rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_p);
340 if (rv != 0) {
341 device_printf(sc->dev, "Can't set parent to PLLP\n");
342 return (rv);
343 }
344
345 /* Set PLLX frequency */
346 rv = clk_set_freq(sc->clk_pll_x, point->freq, CLK_SET_ROUND_DOWN);
347 if (rv != 0) {
348 device_printf(sc->dev, "Can't set CPU clock frequency\n");
349 return (rv);
350 }
351
352 rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_x);
353 if (rv != 0) {
354 device_printf(sc->dev, "Can't set parent to PLLX\n");
355 return (rv);
356 }
357
358 if (sc->act_speed_point->uvolt > point->uvolt) {
359 /* set cpu voltage */
360 rv = regulator_set_voltage(sc->supply_vdd_cpu,
361 point->uvolt, point->uvolt);
362 if (rv != 0)
363 return (rv);
364 }
365
366 sc->act_speed_point = point;
367
368 return (0);
369 }
370
371 static int
tegra124_cpufreq_set(device_t dev,const struct cf_setting * cf)372 tegra124_cpufreq_set(device_t dev, const struct cf_setting *cf)
373 {
374 struct tegra124_cpufreq_softc *sc;
375 uint64_t freq;
376 int rv;
377
378 if (cf == NULL || cf->freq < 0)
379 return (EINVAL);
380
381 sc = device_get_softc(dev);
382
383 freq = cf->freq;
384 if (freq < cpufreq_lowest_freq)
385 freq = cpufreq_lowest_freq;
386 freq *= 1000000;
387 if (freq >= sc->cpu_max_freq)
388 freq = sc->cpu_max_freq;
389 rv = set_cpu_freq(sc, freq);
390
391 return (rv);
392 }
393
394 static int
tegra124_cpufreq_get(device_t dev,struct cf_setting * cf)395 tegra124_cpufreq_get(device_t dev, struct cf_setting *cf)
396 {
397 struct tegra124_cpufreq_softc *sc;
398
399 if (cf == NULL)
400 return (EINVAL);
401
402 sc = device_get_softc(dev);
403 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
404 cf->dev = NULL;
405 cf->freq = sc->act_speed_point->freq / 1000000;
406 cf->volts = sc->act_speed_point->uvolt / 1000;
407 /* Transition latency in us. */
408 cf->lat = sc->latency;
409 /* Driver providing this setting. */
410 cf->dev = dev;
411
412 return (0);
413 }
414
415
416 static int
tegra124_cpufreq_type(device_t dev,int * type)417 tegra124_cpufreq_type(device_t dev, int *type)
418 {
419
420 if (type == NULL)
421 return (EINVAL);
422 *type = CPUFREQ_TYPE_ABSOLUTE;
423
424 return (0);
425 }
426
427 static int
get_fdt_resources(struct tegra124_cpufreq_softc * sc,phandle_t node)428 get_fdt_resources(struct tegra124_cpufreq_softc *sc, phandle_t node)
429 {
430 int rv;
431 device_t parent_dev;
432
433 parent_dev = device_get_parent(sc->dev);
434 rv = regulator_get_by_ofw_property(parent_dev, 0, "vdd-cpu-supply",
435 &sc->supply_vdd_cpu);
436 if (rv != 0) {
437 device_printf(sc->dev, "Cannot get 'vdd-cpu' regulator\n");
438 return (rv);
439 }
440
441 rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_g", &sc->clk_cpu_g);
442 if (rv != 0) {
443 device_printf(sc->dev, "Cannot get 'cpu_g' clock: %d\n", rv);
444 return (ENXIO);
445 }
446
447 rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_lp", &sc->clk_cpu_lp);
448 if (rv != 0) {
449 device_printf(sc->dev, "Cannot get 'cpu_lp' clock\n");
450 return (ENXIO);
451 }
452
453 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_x", &sc->clk_pll_x);
454 if (rv != 0) {
455 device_printf(sc->dev, "Cannot get 'pll_x' clock\n");
456 return (ENXIO);
457 }
458 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_p", &sc->clk_pll_p);
459 if (rv != 0) {
460 device_printf(parent_dev, "Cannot get 'pll_p' clock\n");
461 return (ENXIO);
462 }
463 rv = clk_get_by_ofw_name(parent_dev, 0, "dfll", &sc->clk_dfll);
464 if (rv != 0) {
465 /* XXX DPLL is not implemented yet */
466 /*
467 device_printf(sc->dev, "Cannot get 'dfll' clock\n");
468 return (ENXIO);
469 */
470 }
471 return (0);
472 }
473
474 static void
tegra124_cpufreq_identify(driver_t * driver,device_t parent)475 tegra124_cpufreq_identify(driver_t *driver, device_t parent)
476 {
477 phandle_t root;
478
479 root = OF_finddevice("/");
480 if (!ofw_bus_node_is_compatible(root, "nvidia,tegra124"))
481 return;
482
483 if (device_get_unit(parent) != 0)
484 return;
485 if (device_find_child(parent, "tegra124_cpufreq", -1) != NULL)
486 return;
487 if (BUS_ADD_CHILD(parent, 0, "tegra124_cpufreq", -1) == NULL)
488 device_printf(parent, "add child failed\n");
489 }
490
491 static int
tegra124_cpufreq_probe(device_t dev)492 tegra124_cpufreq_probe(device_t dev)
493 {
494
495 device_set_desc(dev, "CPU Frequency Control");
496
497 return (0);
498 }
499
500 static int
tegra124_cpufreq_attach(device_t dev)501 tegra124_cpufreq_attach(device_t dev)
502 {
503 struct tegra124_cpufreq_softc *sc;
504 uint64_t freq;
505 int rv;
506
507 sc = device_get_softc(dev);
508 sc->dev = dev;
509 sc->node = ofw_bus_get_node(device_get_parent(dev));
510
511 sc->process_id = tegra_sku_info.cpu_process_id;
512 sc->speedo_id = tegra_sku_info.cpu_speedo_id;
513 sc->speedo_value = tegra_sku_info.cpu_speedo_value;
514
515 /* Tegra 124 */
516 /* XXX DPLL is not implemented yet */
517 if (1)
518 sc->cpu_def = &tegra124_cpu_volt_pllx_def;
519 else
520 sc->cpu_def = &tegra124_cpu_volt_dpll_def;
521
522
523 rv = get_fdt_resources(sc, sc->node);
524 if (rv != 0) {
525 return (rv);
526 }
527
528 build_speed_points(sc);
529
530 rv = clk_get_freq(sc->clk_cpu_g, &freq);
531 if (rv != 0) {
532 device_printf(dev, "Can't get CPU clock frequency\n");
533 return (rv);
534 }
535 if (sc->speedo_id < nitems(cpu_max_freq))
536 sc->cpu_max_freq = cpu_max_freq[sc->speedo_id];
537 else
538 sc->cpu_max_freq = cpu_max_freq[0];
539 sc->act_speed_point = get_speed_point(sc, freq);
540
541 /* Set safe startup CPU frequency. */
542 rv = set_cpu_freq(sc, 1632000000);
543 if (rv != 0) {
544 device_printf(dev, "Can't set initial CPU clock frequency\n");
545 return (rv);
546 }
547
548 /* This device is controlled by cpufreq(4). */
549 cpufreq_register(dev);
550
551 return (0);
552 }
553
554 static int
tegra124_cpufreq_detach(device_t dev)555 tegra124_cpufreq_detach(device_t dev)
556 {
557 struct tegra124_cpufreq_softc *sc;
558
559 sc = device_get_softc(dev);
560 cpufreq_unregister(dev);
561
562 if (sc->supply_vdd_cpu != NULL)
563 regulator_release(sc->supply_vdd_cpu);
564
565 if (sc->clk_cpu_g != NULL)
566 clk_release(sc->clk_cpu_g);
567 if (sc->clk_cpu_lp != NULL)
568 clk_release(sc->clk_cpu_lp);
569 if (sc->clk_pll_x != NULL)
570 clk_release(sc->clk_pll_x);
571 if (sc->clk_pll_p != NULL)
572 clk_release(sc->clk_pll_p);
573 if (sc->clk_dfll != NULL)
574 clk_release(sc->clk_dfll);
575 return (0);
576 }
577
578 static device_method_t tegra124_cpufreq_methods[] = {
579 /* Device interface */
580 DEVMETHOD(device_identify, tegra124_cpufreq_identify),
581 DEVMETHOD(device_probe, tegra124_cpufreq_probe),
582 DEVMETHOD(device_attach, tegra124_cpufreq_attach),
583 DEVMETHOD(device_detach, tegra124_cpufreq_detach),
584
585 /* cpufreq interface */
586 DEVMETHOD(cpufreq_drv_set, tegra124_cpufreq_set),
587 DEVMETHOD(cpufreq_drv_get, tegra124_cpufreq_get),
588 DEVMETHOD(cpufreq_drv_settings, tegra124_cpufreq_settings),
589 DEVMETHOD(cpufreq_drv_type, tegra124_cpufreq_type),
590
591 DEVMETHOD_END
592 };
593
594 static devclass_t tegra124_cpufreq_devclass;
595 static DEFINE_CLASS_0(tegra124_cpufreq, tegra124_cpufreq_driver,
596 tegra124_cpufreq_methods, sizeof(struct tegra124_cpufreq_softc));
597 DRIVER_MODULE(tegra124_cpufreq, cpu, tegra124_cpufreq_driver,
598 tegra124_cpufreq_devclass, NULL, NULL);
599