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