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