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