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