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