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