1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright 2020 Michal Meloun <mmel@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 #include <sys/cpu.h> 35 #include <sys/kernel.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/module.h> 39 40 #include <machine/bus.h> 41 #include <machine/cpu.h> 42 43 #include <dev/extres/clk/clk.h> 44 #include <dev/extres/regulator/regulator.h> 45 #include <dev/ofw/ofw_bus_subr.h> 46 47 #include <arm/nvidia/tegra_efuse.h> 48 49 #include "cpufreq_if.h" 50 51 /* CPU voltage table entry */ 52 struct speedo_entry { 53 uint64_t freq; /* Frequency point */ 54 int c0; /* Coeeficient values for */ 55 int c1; /* quadratic equation: */ 56 int c2; /* c2 * speedo^2 + c1 * speedo + c0 */ 57 }; 58 59 struct cpu_volt_def { 60 int min_uvolt; /* Min allowed CPU voltage */ 61 int max_uvolt; /* Max allowed CPU voltage */ 62 int step_uvolt; /* Step of CPU voltage */ 63 int speedo_scale; /* Scaling factor for cvt */ 64 int speedo_nitems; /* Size of speedo table */ 65 struct speedo_entry *speedo_tbl; /* CPU voltage table */ 66 }; 67 68 struct cpu_speed_point { 69 uint64_t freq; /* Frequecy */ 70 int uvolt; /* Requested voltage */ 71 }; 72 73 static struct speedo_entry tegra210_speedo_tbl[] = 74 { 75 {204000000UL, 1007452, -23865, 370}, 76 {306000000UL, 1052709, -24875, 370}, 77 {408000000UL, 1099069, -25895, 370}, 78 {510000000UL, 1146534, -26905, 370}, 79 {612000000UL, 1195102, -27915, 370}, 80 {714000000UL, 1244773, -28925, 370}, 81 {816000000UL, 1295549, -29935, 370}, 82 {918000000UL, 1347428, -30955, 370}, 83 {1020000000UL, 1400411, -31965, 370}, 84 {1122000000UL, 1454497, -32975, 370}, 85 {1224000000UL, 1509687, -33985, 370}, 86 {1326000000UL, 1565981, -35005, 370}, 87 {1428000000UL, 1623379, -36015, 370}, 88 {1530000000UL, 1681880, -37025, 370}, 89 {1632000000UL, 1741485, -38035, 370}, 90 {1734000000UL, 1802194, -39055, 370}, 91 {1836000000UL, 1864006, -40065, 370}, 92 {1912500000UL, 1910780, -40815, 370}, 93 {2014500000UL, 1227000, 0, 0}, 94 {2218500000UL, 1227000, 0, 0}, 95 }; 96 97 static struct cpu_volt_def tegra210_cpu_volt_def = 98 { 99 .min_uvolt = 900000, /* 0.9 V */ 100 .max_uvolt = 1227000, /* 1.227 */ 101 .step_uvolt = 10000, /* 10 mV */ 102 .speedo_scale = 100, 103 .speedo_nitems = nitems(tegra210_speedo_tbl), 104 .speedo_tbl = tegra210_speedo_tbl, 105 }; 106 107 static uint64_t cpu_max_freq[] = { 108 1912500000UL, 109 1912500000UL, 110 2218500000UL, 111 1785000000UL, 112 1632000000UL, 113 1912500000UL, 114 2014500000UL, 115 1734000000UL, 116 1683000000UL, 117 1555500000UL, 118 1504500000UL, 119 }; 120 121 static uint64_t cpu_freq_tbl[] = { 122 204000000UL, 123 306000000UL, 124 408000000UL, 125 510000000UL, 126 612000000UL, 127 714000000UL, 128 816000000UL, 129 918000000UL, 130 1020000000UL, 131 1122000000UL, 132 1224000000UL, 133 1326000000UL, 134 1428000000UL, 135 1530000000UL, 136 1632000000UL, 137 1734000000UL, 138 1836000000UL, 139 1912500000UL, 140 2014500000UL, 141 2218500000UL, 142 }; 143 144 struct tegra210_cpufreq_softc { 145 device_t dev; 146 phandle_t node; 147 148 clk_t clk_cpu_g; 149 clk_t clk_pll_x; 150 clk_t clk_pll_p; 151 clk_t clk_dfll; 152 153 int process_id; 154 int speedo_id; 155 int speedo_value; 156 157 uint64_t cpu_max_freq; 158 struct cpu_volt_def *cpu_def; 159 struct cpu_speed_point *speed_points; 160 int nspeed_points; 161 162 struct cpu_speed_point *act_speed_point; 163 164 int latency; 165 }; 166 167 static int cpufreq_lowest_freq = 1; 168 TUNABLE_INT("hw.tegra210.cpufreq.lowest_freq", &cpufreq_lowest_freq); 169 170 #define DIV_ROUND_CLOSEST(val, div) (((val) + ((div) / 2)) / (div)) 171 172 #define ROUND_UP(val, div) roundup(val, div) 173 #define ROUND_DOWN(val, div) rounddown(val, div) 174 175 /* 176 * Compute requesetd voltage for given frequency and SoC process variations, 177 * - compute base voltage from speedo value using speedo table 178 * - round up voltage to next regulator step 179 * - clamp it to regulator limits 180 */ 181 static int 182 freq_to_voltage(struct tegra210_cpufreq_softc *sc, uint64_t freq) 183 { 184 int uv, scale, min_uvolt, max_uvolt, step_uvolt; 185 struct speedo_entry *ent; 186 int i; 187 188 /* Get speedo entry with higher frequency */ 189 ent = NULL; 190 for (i = 0; i < sc->cpu_def->speedo_nitems; i++) { 191 if (sc->cpu_def->speedo_tbl[i].freq >= freq) { 192 ent = &sc->cpu_def->speedo_tbl[i]; 193 break; 194 } 195 } 196 if (ent == NULL) 197 ent = &sc->cpu_def->speedo_tbl[sc->cpu_def->speedo_nitems - 1]; 198 scale = sc->cpu_def->speedo_scale; 199 200 201 /* uV = (c2 * speedo / scale + c1) * speedo / scale + c0) */ 202 uv = DIV_ROUND_CLOSEST(ent->c2 * sc->speedo_value, scale); 203 uv = DIV_ROUND_CLOSEST((uv + ent->c1) * sc->speedo_value, scale) + 204 ent->c0; 205 step_uvolt = sc->cpu_def->step_uvolt; 206 /* Round up it to next regulator step */ 207 uv = ROUND_UP(uv, step_uvolt); 208 209 /* Clamp result */ 210 min_uvolt = ROUND_UP(sc->cpu_def->min_uvolt, step_uvolt); 211 max_uvolt = ROUND_DOWN(sc->cpu_def->max_uvolt, step_uvolt); 212 if (uv < min_uvolt) 213 uv = min_uvolt; 214 if (uv > max_uvolt) 215 uv = max_uvolt; 216 return (uv); 217 218 } 219 220 static void 221 build_speed_points(struct tegra210_cpufreq_softc *sc) { 222 int i; 223 224 sc->nspeed_points = nitems(cpu_freq_tbl); 225 sc->speed_points = malloc(sizeof(struct cpu_speed_point) * 226 sc->nspeed_points, M_DEVBUF, M_NOWAIT); 227 for (i = 0; i < sc->nspeed_points; i++) { 228 sc->speed_points[i].freq = cpu_freq_tbl[i]; 229 sc->speed_points[i].uvolt = freq_to_voltage(sc, 230 cpu_freq_tbl[i]); 231 } 232 } 233 234 static struct cpu_speed_point * 235 get_speed_point(struct tegra210_cpufreq_softc *sc, uint64_t freq) 236 { 237 int i; 238 239 if (sc->speed_points[0].freq >= freq) 240 return (sc->speed_points + 0); 241 242 for (i = 0; i < sc->nspeed_points - 1; i++) { 243 if (sc->speed_points[i + 1].freq > freq) 244 return (sc->speed_points + i); 245 } 246 247 return (sc->speed_points + sc->nspeed_points - 1); 248 } 249 250 static int 251 tegra210_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count) 252 { 253 struct tegra210_cpufreq_softc *sc; 254 int i, j, max_cnt; 255 256 if (sets == NULL || count == NULL) 257 return (EINVAL); 258 259 sc = device_get_softc(dev); 260 memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count)); 261 262 max_cnt = min(sc->nspeed_points, *count); 263 for (i = 0, j = sc->nspeed_points - 1; j >= 0; j--) { 264 if (sc->cpu_max_freq < sc->speed_points[j].freq) 265 continue; 266 sets[i].freq = sc->speed_points[j].freq / 1000000; 267 sets[i].volts = sc->speed_points[j].uvolt / 1000; 268 sets[i].lat = sc->latency; 269 sets[i].dev = dev; 270 i++; 271 } 272 *count = i; 273 274 return (0); 275 } 276 277 static int 278 set_cpu_freq(struct tegra210_cpufreq_softc *sc, uint64_t freq) 279 { 280 struct cpu_speed_point *point; 281 int rv; 282 283 point = get_speed_point(sc, freq); 284 285 /* Set PLLX frequency */ 286 rv = clk_set_freq(sc->clk_pll_x, point->freq, CLK_SET_ROUND_DOWN); 287 if (rv != 0) { 288 device_printf(sc->dev, "Can't set CPU clock frequency\n"); 289 return (rv); 290 } 291 292 sc->act_speed_point = point; 293 294 return (0); 295 } 296 297 static int 298 tegra210_cpufreq_set(device_t dev, const struct cf_setting *cf) 299 { 300 struct tegra210_cpufreq_softc *sc; 301 uint64_t freq; 302 int rv; 303 304 if (cf == NULL || cf->freq < 0) 305 return (EINVAL); 306 307 sc = device_get_softc(dev); 308 309 freq = cf->freq; 310 if (freq < cpufreq_lowest_freq) 311 freq = cpufreq_lowest_freq; 312 freq *= 1000000; 313 if (freq >= sc->cpu_max_freq) 314 freq = sc->cpu_max_freq; 315 rv = set_cpu_freq(sc, freq); 316 317 return (rv); 318 } 319 320 static int 321 tegra210_cpufreq_get(device_t dev, struct cf_setting *cf) 322 { 323 struct tegra210_cpufreq_softc *sc; 324 325 if (cf == NULL) 326 return (EINVAL); 327 328 sc = device_get_softc(dev); 329 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf)); 330 cf->dev = NULL; 331 cf->freq = sc->act_speed_point->freq / 1000000; 332 cf->volts = sc->act_speed_point->uvolt / 1000; 333 /* Transition latency in us. */ 334 cf->lat = sc->latency; 335 /* Driver providing this setting. */ 336 cf->dev = dev; 337 338 return (0); 339 } 340 341 342 static int 343 tegra210_cpufreq_type(device_t dev, int *type) 344 { 345 346 if (type == NULL) 347 return (EINVAL); 348 *type = CPUFREQ_TYPE_ABSOLUTE; 349 350 return (0); 351 } 352 353 static int 354 get_fdt_resources(struct tegra210_cpufreq_softc *sc, phandle_t node) 355 { 356 int rv; 357 device_t parent_dev; 358 359 parent_dev = device_get_parent(sc->dev); 360 361 rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_g", &sc->clk_cpu_g); 362 if (rv != 0) { 363 device_printf(sc->dev, "Cannot get 'cpu_g' clock: %d\n", rv); 364 return (ENXIO); 365 } 366 367 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_x", &sc->clk_pll_x); 368 if (rv != 0) { 369 device_printf(sc->dev, "Cannot get 'pll_x' clock\n"); 370 return (ENXIO); 371 } 372 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_p", &sc->clk_pll_p); 373 if (rv != 0) { 374 device_printf(parent_dev, "Cannot get 'pll_p' clock\n"); 375 return (ENXIO); 376 } 377 rv = clk_get_by_ofw_name(parent_dev, 0, "dfll", &sc->clk_dfll); 378 379 /* XXX DPLL is not implemented yet */ 380 #if 0 381 if (rv != 0) { 382 device_printf(sc->dev, "Cannot get 'dfll' clock\n"); 383 return (ENXIO); 384 } 385 #endif 386 return (0); 387 } 388 389 static void 390 tegra210_cpufreq_identify(driver_t *driver, device_t parent) 391 { 392 phandle_t root; 393 394 root = OF_finddevice("/"); 395 if (!ofw_bus_node_is_compatible(root, "nvidia,tegra210")) 396 return; 397 398 if (device_get_unit(parent) != 0) 399 return; 400 if (device_find_child(parent, "tegra210_cpufreq", -1) != NULL) 401 return; 402 if (BUS_ADD_CHILD(parent, 0, "tegra210_cpufreq", -1) == NULL) 403 device_printf(parent, "add child failed\n"); 404 } 405 406 static int 407 tegra210_cpufreq_probe(device_t dev) 408 { 409 410 device_set_desc(dev, "CPU Frequency Control"); 411 412 return (0); 413 } 414 415 static int 416 tegra210_cpufreq_attach(device_t dev) 417 { 418 struct tegra210_cpufreq_softc *sc; 419 uint64_t freq; 420 int rv; 421 422 sc = device_get_softc(dev); 423 sc->dev = dev; 424 sc->node = ofw_bus_get_node(device_get_parent(dev)); 425 426 sc->process_id = tegra_sku_info.cpu_process_id; 427 sc->speedo_id = tegra_sku_info.cpu_speedo_id; 428 sc->speedo_value = tegra_sku_info.cpu_speedo_value; 429 430 sc->cpu_def = &tegra210_cpu_volt_def; 431 432 rv = get_fdt_resources(sc, sc->node); 433 if (rv != 0) { 434 return (rv); 435 } 436 437 build_speed_points(sc); 438 439 rv = clk_get_freq(sc->clk_cpu_g, &freq); 440 if (rv != 0) { 441 device_printf(dev, "Can't get CPU clock frequency\n"); 442 return (rv); 443 } 444 if (sc->speedo_id < nitems(cpu_max_freq)) 445 sc->cpu_max_freq = cpu_max_freq[sc->speedo_id]; 446 else 447 sc->cpu_max_freq = cpu_max_freq[0]; 448 sc->act_speed_point = get_speed_point(sc, freq); 449 450 /* Set safe startup CPU frequency. */ 451 rv = set_cpu_freq(sc, 1632000000); 452 if (rv != 0) { 453 device_printf(dev, "Can't set initial CPU clock frequency\n"); 454 return (rv); 455 } 456 457 /* This device is controlled by cpufreq(4). */ 458 cpufreq_register(dev); 459 460 return (0); 461 } 462 463 static int 464 tegra210_cpufreq_detach(device_t dev) 465 { 466 struct tegra210_cpufreq_softc *sc; 467 468 sc = device_get_softc(dev); 469 cpufreq_unregister(dev); 470 471 if (sc->clk_cpu_g != NULL) 472 clk_release(sc->clk_cpu_g); 473 if (sc->clk_pll_x != NULL) 474 clk_release(sc->clk_pll_x); 475 if (sc->clk_pll_p != NULL) 476 clk_release(sc->clk_pll_p); 477 if (sc->clk_dfll != NULL) 478 clk_release(sc->clk_dfll); 479 return (0); 480 } 481 482 static device_method_t tegra210_cpufreq_methods[] = { 483 /* Device interface */ 484 DEVMETHOD(device_identify, tegra210_cpufreq_identify), 485 DEVMETHOD(device_probe, tegra210_cpufreq_probe), 486 DEVMETHOD(device_attach, tegra210_cpufreq_attach), 487 DEVMETHOD(device_detach, tegra210_cpufreq_detach), 488 489 /* cpufreq interface */ 490 DEVMETHOD(cpufreq_drv_set, tegra210_cpufreq_set), 491 DEVMETHOD(cpufreq_drv_get, tegra210_cpufreq_get), 492 DEVMETHOD(cpufreq_drv_settings, tegra210_cpufreq_settings), 493 DEVMETHOD(cpufreq_drv_type, tegra210_cpufreq_type), 494 495 DEVMETHOD_END 496 }; 497 498 static devclass_t tegra210_cpufreq_devclass; 499 static DEFINE_CLASS_0(tegra210_cpufreq, tegra210_cpufreq_driver, 500 tegra210_cpufreq_methods, sizeof(struct tegra210_cpufreq_softc)); 501 DRIVER_MODULE(tegra210_cpufreq, cpu, tegra210_cpufreq_driver, 502 tegra210_cpufreq_devclass, NULL, NULL); 503