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; 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 for (i = 0, j = sc->nspeed_points - 1; j >= 0; j--) { 263 if (sc->cpu_max_freq < sc->speed_points[j].freq) 264 continue; 265 sets[i].freq = sc->speed_points[j].freq / 1000000; 266 sets[i].volts = sc->speed_points[j].uvolt / 1000; 267 sets[i].lat = sc->latency; 268 sets[i].dev = dev; 269 i++; 270 } 271 *count = i; 272 273 return (0); 274 } 275 276 static int 277 set_cpu_freq(struct tegra210_cpufreq_softc *sc, uint64_t freq) 278 { 279 struct cpu_speed_point *point; 280 int rv; 281 282 point = get_speed_point(sc, freq); 283 284 /* Set PLLX frequency */ 285 rv = clk_set_freq(sc->clk_pll_x, point->freq, CLK_SET_ROUND_DOWN); 286 if (rv != 0) { 287 device_printf(sc->dev, "Can't set CPU clock frequency\n"); 288 return (rv); 289 } 290 291 sc->act_speed_point = point; 292 293 return (0); 294 } 295 296 static int 297 tegra210_cpufreq_set(device_t dev, const struct cf_setting *cf) 298 { 299 struct tegra210_cpufreq_softc *sc; 300 uint64_t freq; 301 int rv; 302 303 if (cf == NULL || cf->freq < 0) 304 return (EINVAL); 305 306 sc = device_get_softc(dev); 307 308 freq = cf->freq; 309 if (freq < cpufreq_lowest_freq) 310 freq = cpufreq_lowest_freq; 311 freq *= 1000000; 312 if (freq >= sc->cpu_max_freq) 313 freq = sc->cpu_max_freq; 314 rv = set_cpu_freq(sc, freq); 315 316 return (rv); 317 } 318 319 static int 320 tegra210_cpufreq_get(device_t dev, struct cf_setting *cf) 321 { 322 struct tegra210_cpufreq_softc *sc; 323 324 if (cf == NULL) 325 return (EINVAL); 326 327 sc = device_get_softc(dev); 328 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf)); 329 cf->dev = NULL; 330 cf->freq = sc->act_speed_point->freq / 1000000; 331 cf->volts = sc->act_speed_point->uvolt / 1000; 332 /* Transition latency in us. */ 333 cf->lat = sc->latency; 334 /* Driver providing this setting. */ 335 cf->dev = dev; 336 337 return (0); 338 } 339 340 341 static int 342 tegra210_cpufreq_type(device_t dev, int *type) 343 { 344 345 if (type == NULL) 346 return (EINVAL); 347 *type = CPUFREQ_TYPE_ABSOLUTE; 348 349 return (0); 350 } 351 352 static int 353 get_fdt_resources(struct tegra210_cpufreq_softc *sc, phandle_t node) 354 { 355 int rv; 356 device_t parent_dev; 357 358 parent_dev = device_get_parent(sc->dev); 359 360 rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_g", &sc->clk_cpu_g); 361 if (rv != 0) { 362 device_printf(sc->dev, "Cannot get 'cpu_g' clock: %d\n", rv); 363 return (ENXIO); 364 } 365 366 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_x", &sc->clk_pll_x); 367 if (rv != 0) { 368 device_printf(sc->dev, "Cannot get 'pll_x' clock\n"); 369 return (ENXIO); 370 } 371 rv = clk_get_by_ofw_name(parent_dev, 0, "pll_p", &sc->clk_pll_p); 372 if (rv != 0) { 373 device_printf(parent_dev, "Cannot get 'pll_p' clock\n"); 374 return (ENXIO); 375 } 376 rv = clk_get_by_ofw_name(parent_dev, 0, "dfll", &sc->clk_dfll); 377 378 /* XXX DPLL is not implemented yet */ 379 #if 0 380 if (rv != 0) { 381 device_printf(sc->dev, "Cannot get 'dfll' clock\n"); 382 return (ENXIO); 383 } 384 #endif 385 return (0); 386 } 387 388 static void 389 tegra210_cpufreq_identify(driver_t *driver, device_t parent) 390 { 391 phandle_t root; 392 393 root = OF_finddevice("/"); 394 if (!ofw_bus_node_is_compatible(root, "nvidia,tegra210")) 395 return; 396 397 if (device_get_unit(parent) != 0) 398 return; 399 if (device_find_child(parent, "tegra210_cpufreq", -1) != NULL) 400 return; 401 if (BUS_ADD_CHILD(parent, 0, "tegra210_cpufreq", -1) == NULL) 402 device_printf(parent, "add child failed\n"); 403 } 404 405 static int 406 tegra210_cpufreq_probe(device_t dev) 407 { 408 409 device_set_desc(dev, "CPU Frequency Control"); 410 411 return (0); 412 } 413 414 static int 415 tegra210_cpufreq_attach(device_t dev) 416 { 417 struct tegra210_cpufreq_softc *sc; 418 uint64_t freq; 419 int rv; 420 421 sc = device_get_softc(dev); 422 sc->dev = dev; 423 sc->node = ofw_bus_get_node(device_get_parent(dev)); 424 425 sc->process_id = tegra_sku_info.cpu_process_id; 426 sc->speedo_id = tegra_sku_info.cpu_speedo_id; 427 sc->speedo_value = tegra_sku_info.cpu_speedo_value; 428 429 sc->cpu_def = &tegra210_cpu_volt_def; 430 431 rv = get_fdt_resources(sc, sc->node); 432 if (rv != 0) { 433 return (rv); 434 } 435 436 build_speed_points(sc); 437 438 rv = clk_get_freq(sc->clk_cpu_g, &freq); 439 if (rv != 0) { 440 device_printf(dev, "Can't get CPU clock frequency\n"); 441 return (rv); 442 } 443 if (sc->speedo_id < nitems(cpu_max_freq)) 444 sc->cpu_max_freq = cpu_max_freq[sc->speedo_id]; 445 else 446 sc->cpu_max_freq = cpu_max_freq[0]; 447 sc->act_speed_point = get_speed_point(sc, freq); 448 449 /* Set safe startup CPU frequency. */ 450 rv = set_cpu_freq(sc, 1632000000); 451 if (rv != 0) { 452 device_printf(dev, "Can't set initial CPU clock frequency\n"); 453 return (rv); 454 } 455 456 /* This device is controlled by cpufreq(4). */ 457 cpufreq_register(dev); 458 459 return (0); 460 } 461 462 static int 463 tegra210_cpufreq_detach(device_t dev) 464 { 465 struct tegra210_cpufreq_softc *sc; 466 467 sc = device_get_softc(dev); 468 cpufreq_unregister(dev); 469 470 if (sc->clk_cpu_g != NULL) 471 clk_release(sc->clk_cpu_g); 472 if (sc->clk_pll_x != NULL) 473 clk_release(sc->clk_pll_x); 474 if (sc->clk_pll_p != NULL) 475 clk_release(sc->clk_pll_p); 476 if (sc->clk_dfll != NULL) 477 clk_release(sc->clk_dfll); 478 return (0); 479 } 480 481 static device_method_t tegra210_cpufreq_methods[] = { 482 /* Device interface */ 483 DEVMETHOD(device_identify, tegra210_cpufreq_identify), 484 DEVMETHOD(device_probe, tegra210_cpufreq_probe), 485 DEVMETHOD(device_attach, tegra210_cpufreq_attach), 486 DEVMETHOD(device_detach, tegra210_cpufreq_detach), 487 488 /* cpufreq interface */ 489 DEVMETHOD(cpufreq_drv_set, tegra210_cpufreq_set), 490 DEVMETHOD(cpufreq_drv_get, tegra210_cpufreq_get), 491 DEVMETHOD(cpufreq_drv_settings, tegra210_cpufreq_settings), 492 DEVMETHOD(cpufreq_drv_type, tegra210_cpufreq_type), 493 494 DEVMETHOD_END 495 }; 496 497 static DEFINE_CLASS_0(tegra210_cpufreq, tegra210_cpufreq_driver, 498 tegra210_cpufreq_methods, sizeof(struct tegra210_cpufreq_softc)); 499 DRIVER_MODULE(tegra210_cpufreq, cpu, tegra210_cpufreq_driver, NULL, NULL); 500