1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Tegra124 DFLL FCPU clock source driver 4 * 5 * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved. 6 * 7 * Aleksandr Frid <afrid@nvidia.com> 8 * Paul Walmsley <pwalmsley@nvidia.com> 9 */ 10 11 #include <linux/cpu.h> 12 #include <linux/err.h> 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/regulator/consumer.h> 18 #include <soc/tegra/fuse.h> 19 20 #include "clk.h" 21 #include "clk-dfll.h" 22 #include "cvb.h" 23 24 struct dfll_fcpu_data { 25 const unsigned long *cpu_max_freq_table; 26 unsigned int cpu_max_freq_table_size; 27 const struct cvb_table *cpu_cvb_tables; 28 unsigned int cpu_cvb_tables_size; 29 }; 30 31 /* Maximum CPU frequency, indexed by CPU speedo id */ 32 static const unsigned long tegra114_cpu_max_freq_table[] = { 33 [0] = 2040000000UL, 34 [1] = 1810500000UL, 35 [2] = 1912500000UL, 36 [3] = 1810500000UL, 37 }; 38 39 #define T114_CPU_CVB_TABLE \ 40 .min_millivolts = 1000, \ 41 .max_millivolts = 1320, \ 42 .speedo_scale = 100, \ 43 .voltage_scale = 1000, \ 44 .entries = { \ 45 { 306000000UL, { 2190643, -141851, 3576 } }, \ 46 { 408000000UL, { 2250968, -144331, 3576 } }, \ 47 { 510000000UL, { 2313333, -146811, 3576 } }, \ 48 { 612000000UL, { 2377738, -149291, 3576 } }, \ 49 { 714000000UL, { 2444183, -151771, 3576 } }, \ 50 { 816000000UL, { 2512669, -154251, 3576 } }, \ 51 { 918000000UL, { 2583194, -156731, 3576 } }, \ 52 { 1020000000UL, { 2655759, -159211, 3576 } }, \ 53 { 1122000000UL, { 2730365, -161691, 3576 } }, \ 54 { 1224000000UL, { 2807010, -164171, 3576 } }, \ 55 { 1326000000UL, { 2885696, -166651, 3576 } }, \ 56 { 1428000000UL, { 2966422, -169131, 3576 } }, \ 57 { 1530000000UL, { 3049183, -171601, 3576 } }, \ 58 { 1606500000UL, { 3112179, -173451, 3576 } }, \ 59 { 1708500000UL, { 3198504, -175931, 3576 } }, \ 60 { 1810500000UL, { 3304747, -179126, 3576 } }, \ 61 { 1912500000UL, { 3395401, -181606, 3576 } }, \ 62 { 0UL, { 0, 0, 0 } }, \ 63 }, \ 64 .cpu_dfll_data = { \ 65 .tune0_low = 0x00b0039d, \ 66 .tune0_high = 0x00b0009d, \ 67 .tune1 = 0x0000001f, \ 68 .tune_high_min_millivolts = 1050, \ 69 } 70 71 static const struct cvb_table tegra114_cpu_cvb_tables[] = { 72 { 73 .speedo_id = 0, 74 .process_id = -1, 75 .min_millivolts = 1000, 76 .max_millivolts = 1250, 77 .speedo_scale = 100, 78 .voltage_scale = 100, 79 .entries = { 80 { 306000000UL, { 107330, -1569, 0 } }, 81 { 408000000UL, { 111250, -1666, 0 } }, 82 { 510000000UL, { 110000, -1460, 0 } }, 83 { 612000000UL, { 117290, -1745, 0 } }, 84 { 714000000UL, { 122700, -1910, 0 } }, 85 { 816000000UL, { 125620, -1945, 0 } }, 86 { 918000000UL, { 130560, -2076, 0 } }, 87 { 1020000000UL, { 137280, -2303, 0 } }, 88 { 1122000000UL, { 146440, -2660, 0 } }, 89 { 1224000000UL, { 152190, -2825, 0 } }, 90 { 1326000000UL, { 157520, -2953, 0 } }, 91 { 1428000000UL, { 166100, -3261, 0 } }, 92 { 1530000000UL, { 176410, -3647, 0 } }, 93 { 1632000000UL, { 189620, -4186, 0 } }, 94 { 1734000000UL, { 203190, -4725, 0 } }, 95 { 1836000000UL, { 222670, -5573, 0 } }, 96 { 1938000000UL, { 256210, -7165, 0 } }, 97 { 2040000000UL, { 250050, -6544, 0 } }, 98 { 0UL, { 0, 0, 0 } }, 99 }, 100 .cpu_dfll_data = { 101 .tune0_low = 0x00b0019d, 102 .tune0_high = 0x00b0019d, 103 .tune1 = 0x0000001f, 104 .tune_high_min_millivolts = 1000, 105 } 106 }, 107 { 108 .speedo_id = 1, 109 .process_id = -1, 110 T114_CPU_CVB_TABLE 111 }, 112 { 113 .speedo_id = 2, 114 .process_id = -1, 115 T114_CPU_CVB_TABLE 116 }, 117 { 118 .speedo_id = 3, 119 .process_id = -1, 120 T114_CPU_CVB_TABLE 121 }, 122 }; 123 124 /* Maximum CPU frequency, indexed by CPU speedo id */ 125 static const unsigned long tegra124_cpu_max_freq_table[] = { 126 [0] = 2014500000UL, 127 [1] = 2320500000UL, 128 [2] = 2116500000UL, 129 [3] = 2524500000UL, 130 }; 131 132 static const struct cvb_table tegra124_cpu_cvb_tables[] = { 133 { 134 .speedo_id = -1, 135 .process_id = -1, 136 .min_millivolts = 900, 137 .max_millivolts = 1260, 138 .speedo_scale = 100, 139 .voltage_scale = 1000, 140 .entries = { 141 { 204000000UL, { 1112619, -29295, 402 } }, 142 { 306000000UL, { 1150460, -30585, 402 } }, 143 { 408000000UL, { 1190122, -31865, 402 } }, 144 { 510000000UL, { 1231606, -33155, 402 } }, 145 { 612000000UL, { 1274912, -34435, 402 } }, 146 { 714000000UL, { 1320040, -35725, 402 } }, 147 { 816000000UL, { 1366990, -37005, 402 } }, 148 { 918000000UL, { 1415762, -38295, 402 } }, 149 { 1020000000UL, { 1466355, -39575, 402 } }, 150 { 1122000000UL, { 1518771, -40865, 402 } }, 151 { 1224000000UL, { 1573009, -42145, 402 } }, 152 { 1326000000UL, { 1629068, -43435, 402 } }, 153 { 1428000000UL, { 1686950, -44715, 402 } }, 154 { 1530000000UL, { 1746653, -46005, 402 } }, 155 { 1632000000UL, { 1808179, -47285, 402 } }, 156 { 1734000000UL, { 1871526, -48575, 402 } }, 157 { 1836000000UL, { 1936696, -49855, 402 } }, 158 { 1938000000UL, { 2003687, -51145, 402 } }, 159 { 2014500000UL, { 2054787, -52095, 402 } }, 160 { 2116500000UL, { 2124957, -53385, 402 } }, 161 { 2218500000UL, { 2196950, -54665, 402 } }, 162 { 2320500000UL, { 2270765, -55955, 402 } }, 163 { 2422500000UL, { 2346401, -57235, 402 } }, 164 { 2524500000UL, { 2437299, -58535, 402 } }, 165 { 0UL, { 0, 0, 0 } }, 166 }, 167 .cpu_dfll_data = { 168 .tune0_low = 0x005020ff, 169 .tune0_high = 0x005040ff, 170 .tune1 = 0x00000060, 171 } 172 }, 173 }; 174 175 static const unsigned long tegra210_cpu_max_freq_table[] = { 176 [0] = 1912500000UL, 177 [1] = 1912500000UL, 178 [2] = 2218500000UL, 179 [3] = 1785000000UL, 180 [4] = 1632000000UL, 181 [5] = 1912500000UL, 182 [6] = 2014500000UL, 183 [7] = 1734000000UL, 184 [8] = 1683000000UL, 185 [9] = 1555500000UL, 186 [10] = 1504500000UL, 187 }; 188 189 #define TEGRA210_CPU_CVB_TABLE \ 190 .speedo_scale = 100, \ 191 .voltage_scale = 1000, \ 192 .entries = { \ 193 { 204000000UL, { 1007452, -23865, 370 } }, \ 194 { 306000000UL, { 1052709, -24875, 370 } }, \ 195 { 408000000UL, { 1099069, -25895, 370 } }, \ 196 { 510000000UL, { 1146534, -26905, 370 } }, \ 197 { 612000000UL, { 1195102, -27915, 370 } }, \ 198 { 714000000UL, { 1244773, -28925, 370 } }, \ 199 { 816000000UL, { 1295549, -29935, 370 } }, \ 200 { 918000000UL, { 1347428, -30955, 370 } }, \ 201 { 1020000000UL, { 1400411, -31965, 370 } }, \ 202 { 1122000000UL, { 1454497, -32975, 370 } }, \ 203 { 1224000000UL, { 1509687, -33985, 370 } }, \ 204 { 1326000000UL, { 1565981, -35005, 370 } }, \ 205 { 1428000000UL, { 1623379, -36015, 370 } }, \ 206 { 1530000000UL, { 1681880, -37025, 370 } }, \ 207 { 1632000000UL, { 1741485, -38035, 370 } }, \ 208 { 1734000000UL, { 1802194, -39055, 370 } }, \ 209 { 1836000000UL, { 1864006, -40065, 370 } }, \ 210 { 1912500000UL, { 1910780, -40815, 370 } }, \ 211 { 2014500000UL, { 1227000, 0, 0 } }, \ 212 { 2218500000UL, { 1227000, 0, 0 } }, \ 213 { 0UL, { 0, 0, 0 } }, \ 214 } 215 216 #define TEGRA210_CPU_CVB_TABLE_XA \ 217 .speedo_scale = 100, \ 218 .voltage_scale = 1000, \ 219 .entries = { \ 220 { 204000000UL, { 1250024, -39785, 565 } }, \ 221 { 306000000UL, { 1297556, -41145, 565 } }, \ 222 { 408000000UL, { 1346718, -42505, 565 } }, \ 223 { 510000000UL, { 1397511, -43855, 565 } }, \ 224 { 612000000UL, { 1449933, -45215, 565 } }, \ 225 { 714000000UL, { 1503986, -46575, 565 } }, \ 226 { 816000000UL, { 1559669, -47935, 565 } }, \ 227 { 918000000UL, { 1616982, -49295, 565 } }, \ 228 { 1020000000UL, { 1675926, -50645, 565 } }, \ 229 { 1122000000UL, { 1736500, -52005, 565 } }, \ 230 { 1224000000UL, { 1798704, -53365, 565 } }, \ 231 { 1326000000UL, { 1862538, -54725, 565 } }, \ 232 { 1428000000UL, { 1928003, -56085, 565 } }, \ 233 { 1530000000UL, { 1995097, -57435, 565 } }, \ 234 { 1606500000UL, { 2046149, -58445, 565 } }, \ 235 { 1632000000UL, { 2063822, -58795, 565 } }, \ 236 { 0UL, { 0, 0, 0 } }, \ 237 } 238 239 #define TEGRA210_CPU_CVB_TABLE_EUCM1 \ 240 .speedo_scale = 100, \ 241 .voltage_scale = 1000, \ 242 .entries = { \ 243 { 204000000UL, { 734429, 0, 0 } }, \ 244 { 306000000UL, { 768191, 0, 0 } }, \ 245 { 408000000UL, { 801953, 0, 0 } }, \ 246 { 510000000UL, { 835715, 0, 0 } }, \ 247 { 612000000UL, { 869477, 0, 0 } }, \ 248 { 714000000UL, { 903239, 0, 0 } }, \ 249 { 816000000UL, { 937001, 0, 0 } }, \ 250 { 918000000UL, { 970763, 0, 0 } }, \ 251 { 1020000000UL, { 1004525, 0, 0 } }, \ 252 { 1122000000UL, { 1038287, 0, 0 } }, \ 253 { 1224000000UL, { 1072049, 0, 0 } }, \ 254 { 1326000000UL, { 1105811, 0, 0 } }, \ 255 { 1428000000UL, { 1130000, 0, 0 } }, \ 256 { 1555500000UL, { 1130000, 0, 0 } }, \ 257 { 1632000000UL, { 1170000, 0, 0 } }, \ 258 { 1734000000UL, { 1227500, 0, 0 } }, \ 259 { 0UL, { 0, 0, 0 } }, \ 260 } 261 262 #define TEGRA210_CPU_CVB_TABLE_EUCM2 \ 263 .speedo_scale = 100, \ 264 .voltage_scale = 1000, \ 265 .entries = { \ 266 { 204000000UL, { 742283, 0, 0 } }, \ 267 { 306000000UL, { 776249, 0, 0 } }, \ 268 { 408000000UL, { 810215, 0, 0 } }, \ 269 { 510000000UL, { 844181, 0, 0 } }, \ 270 { 612000000UL, { 878147, 0, 0 } }, \ 271 { 714000000UL, { 912113, 0, 0 } }, \ 272 { 816000000UL, { 946079, 0, 0 } }, \ 273 { 918000000UL, { 980045, 0, 0 } }, \ 274 { 1020000000UL, { 1014011, 0, 0 } }, \ 275 { 1122000000UL, { 1047977, 0, 0 } }, \ 276 { 1224000000UL, { 1081943, 0, 0 } }, \ 277 { 1326000000UL, { 1090000, 0, 0 } }, \ 278 { 1479000000UL, { 1090000, 0, 0 } }, \ 279 { 1555500000UL, { 1162000, 0, 0 } }, \ 280 { 1683000000UL, { 1195000, 0, 0 } }, \ 281 { 0UL, { 0, 0, 0 } }, \ 282 } 283 284 #define TEGRA210_CPU_CVB_TABLE_EUCM2_JOINT_RAIL \ 285 .speedo_scale = 100, \ 286 .voltage_scale = 1000, \ 287 .entries = { \ 288 { 204000000UL, { 742283, 0, 0 } }, \ 289 { 306000000UL, { 776249, 0, 0 } }, \ 290 { 408000000UL, { 810215, 0, 0 } }, \ 291 { 510000000UL, { 844181, 0, 0 } }, \ 292 { 612000000UL, { 878147, 0, 0 } }, \ 293 { 714000000UL, { 912113, 0, 0 } }, \ 294 { 816000000UL, { 946079, 0, 0 } }, \ 295 { 918000000UL, { 980045, 0, 0 } }, \ 296 { 1020000000UL, { 1014011, 0, 0 } }, \ 297 { 1122000000UL, { 1047977, 0, 0 } }, \ 298 { 1224000000UL, { 1081943, 0, 0 } }, \ 299 { 1326000000UL, { 1090000, 0, 0 } }, \ 300 { 1479000000UL, { 1090000, 0, 0 } }, \ 301 { 1504500000UL, { 1120000, 0, 0 } }, \ 302 { 0UL, { 0, 0, 0 } }, \ 303 } 304 305 #define TEGRA210_CPU_CVB_TABLE_ODN \ 306 .speedo_scale = 100, \ 307 .voltage_scale = 1000, \ 308 .entries = { \ 309 { 204000000UL, { 721094, 0, 0 } }, \ 310 { 306000000UL, { 754040, 0, 0 } }, \ 311 { 408000000UL, { 786986, 0, 0 } }, \ 312 { 510000000UL, { 819932, 0, 0 } }, \ 313 { 612000000UL, { 852878, 0, 0 } }, \ 314 { 714000000UL, { 885824, 0, 0 } }, \ 315 { 816000000UL, { 918770, 0, 0 } }, \ 316 { 918000000UL, { 915716, 0, 0 } }, \ 317 { 1020000000UL, { 984662, 0, 0 } }, \ 318 { 1122000000UL, { 1017608, 0, 0 } }, \ 319 { 1224000000UL, { 1050554, 0, 0 } }, \ 320 { 1326000000UL, { 1083500, 0, 0 } }, \ 321 { 1428000000UL, { 1116446, 0, 0 } }, \ 322 { 1581000000UL, { 1130000, 0, 0 } }, \ 323 { 1683000000UL, { 1168000, 0, 0 } }, \ 324 { 1785000000UL, { 1227500, 0, 0 } }, \ 325 { 0UL, { 0, 0, 0 } }, \ 326 } 327 328 static struct cvb_table tegra210_cpu_cvb_tables[] = { 329 { 330 .speedo_id = 10, 331 .process_id = 0, 332 .min_millivolts = 840, 333 .max_millivolts = 1120, 334 TEGRA210_CPU_CVB_TABLE_EUCM2_JOINT_RAIL, 335 .cpu_dfll_data = { 336 .tune0_low = 0xffead0ff, 337 .tune0_high = 0xffead0ff, 338 .tune1 = 0x20091d9, 339 .tune_high_min_millivolts = 864, 340 } 341 }, 342 { 343 .speedo_id = 10, 344 .process_id = 1, 345 .min_millivolts = 840, 346 .max_millivolts = 1120, 347 TEGRA210_CPU_CVB_TABLE_EUCM2_JOINT_RAIL, 348 .cpu_dfll_data = { 349 .tune0_low = 0xffead0ff, 350 .tune0_high = 0xffead0ff, 351 .tune1 = 0x20091d9, 352 .tune_high_min_millivolts = 864, 353 } 354 }, 355 { 356 .speedo_id = 9, 357 .process_id = 0, 358 .min_millivolts = 900, 359 .max_millivolts = 1162, 360 TEGRA210_CPU_CVB_TABLE_EUCM2, 361 .cpu_dfll_data = { 362 .tune0_low = 0xffead0ff, 363 .tune0_high = 0xffead0ff, 364 .tune1 = 0x20091d9, 365 } 366 }, 367 { 368 .speedo_id = 9, 369 .process_id = 1, 370 .min_millivolts = 900, 371 .max_millivolts = 1162, 372 TEGRA210_CPU_CVB_TABLE_EUCM2, 373 .cpu_dfll_data = { 374 .tune0_low = 0xffead0ff, 375 .tune0_high = 0xffead0ff, 376 .tune1 = 0x20091d9, 377 } 378 }, 379 { 380 .speedo_id = 8, 381 .process_id = 0, 382 .min_millivolts = 900, 383 .max_millivolts = 1195, 384 TEGRA210_CPU_CVB_TABLE_EUCM2, 385 .cpu_dfll_data = { 386 .tune0_low = 0xffead0ff, 387 .tune0_high = 0xffead0ff, 388 .tune1 = 0x20091d9, 389 } 390 }, 391 { 392 .speedo_id = 8, 393 .process_id = 1, 394 .min_millivolts = 900, 395 .max_millivolts = 1195, 396 TEGRA210_CPU_CVB_TABLE_EUCM2, 397 .cpu_dfll_data = { 398 .tune0_low = 0xffead0ff, 399 .tune0_high = 0xffead0ff, 400 .tune1 = 0x20091d9, 401 } 402 }, 403 { 404 .speedo_id = 7, 405 .process_id = 0, 406 .min_millivolts = 841, 407 .max_millivolts = 1227, 408 TEGRA210_CPU_CVB_TABLE_EUCM1, 409 .cpu_dfll_data = { 410 .tune0_low = 0xffead0ff, 411 .tune0_high = 0xffead0ff, 412 .tune1 = 0x20091d9, 413 .tune_high_min_millivolts = 864, 414 } 415 }, 416 { 417 .speedo_id = 7, 418 .process_id = 1, 419 .min_millivolts = 841, 420 .max_millivolts = 1227, 421 TEGRA210_CPU_CVB_TABLE_EUCM1, 422 .cpu_dfll_data = { 423 .tune0_low = 0xffead0ff, 424 .tune0_high = 0xffead0ff, 425 .tune1 = 0x20091d9, 426 .tune_high_min_millivolts = 864, 427 } 428 }, 429 { 430 .speedo_id = 6, 431 .process_id = 0, 432 .min_millivolts = 870, 433 .max_millivolts = 1150, 434 TEGRA210_CPU_CVB_TABLE, 435 .cpu_dfll_data = { 436 .tune0_low = 0xffead0ff, 437 .tune1 = 0x20091d9, 438 } 439 }, 440 { 441 .speedo_id = 6, 442 .process_id = 1, 443 .min_millivolts = 870, 444 .max_millivolts = 1150, 445 TEGRA210_CPU_CVB_TABLE, 446 .cpu_dfll_data = { 447 .tune0_low = 0xffead0ff, 448 .tune1 = 0x25501d0, 449 } 450 }, 451 { 452 .speedo_id = 5, 453 .process_id = 0, 454 .min_millivolts = 818, 455 .max_millivolts = 1227, 456 TEGRA210_CPU_CVB_TABLE, 457 .cpu_dfll_data = { 458 .tune0_low = 0xffead0ff, 459 .tune0_high = 0xffead0ff, 460 .tune1 = 0x20091d9, 461 .tune_high_min_millivolts = 864, 462 } 463 }, 464 { 465 .speedo_id = 5, 466 .process_id = 1, 467 .min_millivolts = 818, 468 .max_millivolts = 1227, 469 TEGRA210_CPU_CVB_TABLE, 470 .cpu_dfll_data = { 471 .tune0_low = 0xffead0ff, 472 .tune0_high = 0xffead0ff, 473 .tune1 = 0x25501d0, 474 .tune_high_min_millivolts = 864, 475 } 476 }, 477 { 478 .speedo_id = 4, 479 .process_id = -1, 480 .min_millivolts = 918, 481 .max_millivolts = 1113, 482 TEGRA210_CPU_CVB_TABLE_XA, 483 .cpu_dfll_data = { 484 .tune0_low = 0xffead0ff, 485 .tune1 = 0x17711BD, 486 } 487 }, 488 { 489 .speedo_id = 3, 490 .process_id = 0, 491 .min_millivolts = 825, 492 .max_millivolts = 1227, 493 TEGRA210_CPU_CVB_TABLE_ODN, 494 .cpu_dfll_data = { 495 .tune0_low = 0xffead0ff, 496 .tune0_high = 0xffead0ff, 497 .tune1 = 0x20091d9, 498 .tune_high_min_millivolts = 864, 499 } 500 }, 501 { 502 .speedo_id = 3, 503 .process_id = 1, 504 .min_millivolts = 825, 505 .max_millivolts = 1227, 506 TEGRA210_CPU_CVB_TABLE_ODN, 507 .cpu_dfll_data = { 508 .tune0_low = 0xffead0ff, 509 .tune0_high = 0xffead0ff, 510 .tune1 = 0x25501d0, 511 .tune_high_min_millivolts = 864, 512 } 513 }, 514 { 515 .speedo_id = 2, 516 .process_id = 0, 517 .min_millivolts = 870, 518 .max_millivolts = 1227, 519 TEGRA210_CPU_CVB_TABLE, 520 .cpu_dfll_data = { 521 .tune0_low = 0xffead0ff, 522 .tune1 = 0x20091d9, 523 } 524 }, 525 { 526 .speedo_id = 2, 527 .process_id = 1, 528 .min_millivolts = 870, 529 .max_millivolts = 1227, 530 TEGRA210_CPU_CVB_TABLE, 531 .cpu_dfll_data = { 532 .tune0_low = 0xffead0ff, 533 .tune1 = 0x25501d0, 534 } 535 }, 536 { 537 .speedo_id = 1, 538 .process_id = 0, 539 .min_millivolts = 837, 540 .max_millivolts = 1227, 541 TEGRA210_CPU_CVB_TABLE, 542 .cpu_dfll_data = { 543 .tune0_low = 0xffead0ff, 544 .tune0_high = 0xffead0ff, 545 .tune1 = 0x20091d9, 546 .tune_high_min_millivolts = 864, 547 } 548 }, 549 { 550 .speedo_id = 1, 551 .process_id = 1, 552 .min_millivolts = 837, 553 .max_millivolts = 1227, 554 TEGRA210_CPU_CVB_TABLE, 555 .cpu_dfll_data = { 556 .tune0_low = 0xffead0ff, 557 .tune0_high = 0xffead0ff, 558 .tune1 = 0x25501d0, 559 .tune_high_min_millivolts = 864, 560 } 561 }, 562 { 563 .speedo_id = 0, 564 .process_id = 0, 565 .min_millivolts = 850, 566 .max_millivolts = 1170, 567 TEGRA210_CPU_CVB_TABLE, 568 .cpu_dfll_data = { 569 .tune0_low = 0xffead0ff, 570 .tune0_high = 0xffead0ff, 571 .tune1 = 0x20091d9, 572 .tune_high_min_millivolts = 864, 573 } 574 }, 575 { 576 .speedo_id = 0, 577 .process_id = 1, 578 .min_millivolts = 850, 579 .max_millivolts = 1170, 580 TEGRA210_CPU_CVB_TABLE, 581 .cpu_dfll_data = { 582 .tune0_low = 0xffead0ff, 583 .tune0_high = 0xffead0ff, 584 .tune1 = 0x25501d0, 585 .tune_high_min_millivolts = 864, 586 } 587 }, 588 }; 589 590 static const struct dfll_fcpu_data tegra114_dfll_fcpu_data = { 591 .cpu_max_freq_table = tegra114_cpu_max_freq_table, 592 .cpu_max_freq_table_size = ARRAY_SIZE(tegra114_cpu_max_freq_table), 593 .cpu_cvb_tables = tegra114_cpu_cvb_tables, 594 .cpu_cvb_tables_size = ARRAY_SIZE(tegra114_cpu_cvb_tables) 595 }; 596 597 static const struct dfll_fcpu_data tegra124_dfll_fcpu_data = { 598 .cpu_max_freq_table = tegra124_cpu_max_freq_table, 599 .cpu_max_freq_table_size = ARRAY_SIZE(tegra124_cpu_max_freq_table), 600 .cpu_cvb_tables = tegra124_cpu_cvb_tables, 601 .cpu_cvb_tables_size = ARRAY_SIZE(tegra124_cpu_cvb_tables) 602 }; 603 604 static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = { 605 .cpu_max_freq_table = tegra210_cpu_max_freq_table, 606 .cpu_max_freq_table_size = ARRAY_SIZE(tegra210_cpu_max_freq_table), 607 .cpu_cvb_tables = tegra210_cpu_cvb_tables, 608 .cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables), 609 }; 610 611 static const struct of_device_id tegra124_dfll_fcpu_of_match[] = { 612 { 613 .compatible = "nvidia,tegra114-dfll", 614 .data = &tegra114_dfll_fcpu_data, 615 }, 616 { 617 .compatible = "nvidia,tegra124-dfll", 618 .data = &tegra124_dfll_fcpu_data, 619 }, 620 { 621 .compatible = "nvidia,tegra210-dfll", 622 .data = &tegra210_dfll_fcpu_data 623 }, 624 { }, 625 }; 626 627 static void get_alignment_from_dt(struct device *dev, 628 struct rail_alignment *align) 629 { 630 if (of_property_read_u32(dev->of_node, 631 "nvidia,pwm-voltage-step-microvolts", 632 &align->step_uv)) 633 align->step_uv = 0; 634 635 if (of_property_read_u32(dev->of_node, 636 "nvidia,pwm-min-microvolts", 637 &align->offset_uv)) 638 align->offset_uv = 0; 639 } 640 641 static int get_alignment_from_regulator(struct device *dev, 642 struct rail_alignment *align) 643 { 644 struct regulator *reg = regulator_get(dev, "vdd-cpu"); 645 646 if (IS_ERR(reg)) 647 return PTR_ERR(reg); 648 649 align->offset_uv = regulator_list_voltage(reg, 0); 650 align->step_uv = regulator_get_linear_step(reg); 651 652 regulator_put(reg); 653 654 return 0; 655 } 656 657 static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) 658 { 659 int process_id, speedo_id, speedo_value, err; 660 struct tegra_dfll_soc_data *soc; 661 const struct dfll_fcpu_data *fcpu_data; 662 struct rail_alignment align; 663 664 fcpu_data = of_device_get_match_data(&pdev->dev); 665 if (!fcpu_data) 666 return -ENODEV; 667 668 process_id = tegra_sku_info.cpu_process_id; 669 speedo_id = tegra_sku_info.cpu_speedo_id; 670 speedo_value = tegra_sku_info.cpu_speedo_value; 671 672 if (speedo_id >= fcpu_data->cpu_max_freq_table_size) { 673 dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n", 674 speedo_id); 675 return -ENODEV; 676 } 677 678 soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL); 679 if (!soc) 680 return -ENOMEM; 681 682 soc->dev = get_cpu_device(0); 683 if (!soc->dev) { 684 dev_err(&pdev->dev, "no CPU0 device\n"); 685 return -ENODEV; 686 } 687 688 if (of_property_read_bool(pdev->dev.of_node, "nvidia,pwm-to-pmic")) { 689 get_alignment_from_dt(&pdev->dev, &align); 690 } else { 691 err = get_alignment_from_regulator(&pdev->dev, &align); 692 if (err) 693 return err; 694 } 695 696 soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id]; 697 698 soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables, 699 fcpu_data->cpu_cvb_tables_size, 700 &align, process_id, speedo_id, 701 speedo_value, soc->max_freq); 702 soc->alignment = align; 703 704 if (IS_ERR(soc->cvb)) { 705 dev_err(&pdev->dev, "couldn't add OPP table: %ld\n", 706 PTR_ERR(soc->cvb)); 707 return PTR_ERR(soc->cvb); 708 } 709 710 err = tegra_dfll_register(pdev, soc); 711 if (err < 0) { 712 tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); 713 return err; 714 } 715 716 return 0; 717 } 718 719 static void tegra124_dfll_fcpu_remove(struct platform_device *pdev) 720 { 721 struct tegra_dfll_soc_data *soc; 722 723 /* 724 * Note that exiting early here is dangerous as after this function 725 * returns *soc is freed. 726 */ 727 soc = tegra_dfll_unregister(pdev); 728 if (IS_ERR(soc)) 729 return; 730 731 tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); 732 } 733 734 static const struct dev_pm_ops tegra124_dfll_pm_ops = { 735 SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend, 736 tegra_dfll_runtime_resume, NULL) 737 SET_SYSTEM_SLEEP_PM_OPS(tegra_dfll_suspend, tegra_dfll_resume) 738 }; 739 740 static struct platform_driver tegra124_dfll_fcpu_driver = { 741 .probe = tegra124_dfll_fcpu_probe, 742 .remove = tegra124_dfll_fcpu_remove, 743 .driver = { 744 .name = "tegra124-dfll", 745 .of_match_table = tegra124_dfll_fcpu_of_match, 746 .pm = &tegra124_dfll_pm_ops, 747 }, 748 }; 749 builtin_platform_driver(tegra124_dfll_fcpu_driver); 750