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 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 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 * 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 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 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 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 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 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 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 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 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 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 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