0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/cpu.h>
0012 #include <linux/err.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/of_device.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regulator/consumer.h>
0018 #include <soc/tegra/fuse.h>
0019
0020 #include "clk.h"
0021 #include "clk-dfll.h"
0022 #include "cvb.h"
0023
0024 struct dfll_fcpu_data {
0025 const unsigned long *cpu_max_freq_table;
0026 unsigned int cpu_max_freq_table_size;
0027 const struct cvb_table *cpu_cvb_tables;
0028 unsigned int cpu_cvb_tables_size;
0029 };
0030
0031
0032 static const unsigned long tegra124_cpu_max_freq_table[] = {
0033 [0] = 2014500000UL,
0034 [1] = 2320500000UL,
0035 [2] = 2116500000UL,
0036 [3] = 2524500000UL,
0037 };
0038
0039 static const struct cvb_table tegra124_cpu_cvb_tables[] = {
0040 {
0041 .speedo_id = -1,
0042 .process_id = -1,
0043 .min_millivolts = 900,
0044 .max_millivolts = 1260,
0045 .speedo_scale = 100,
0046 .voltage_scale = 1000,
0047 .entries = {
0048 { 204000000UL, { 1112619, -29295, 402 } },
0049 { 306000000UL, { 1150460, -30585, 402 } },
0050 { 408000000UL, { 1190122, -31865, 402 } },
0051 { 510000000UL, { 1231606, -33155, 402 } },
0052 { 612000000UL, { 1274912, -34435, 402 } },
0053 { 714000000UL, { 1320040, -35725, 402 } },
0054 { 816000000UL, { 1366990, -37005, 402 } },
0055 { 918000000UL, { 1415762, -38295, 402 } },
0056 { 1020000000UL, { 1466355, -39575, 402 } },
0057 { 1122000000UL, { 1518771, -40865, 402 } },
0058 { 1224000000UL, { 1573009, -42145, 402 } },
0059 { 1326000000UL, { 1629068, -43435, 402 } },
0060 { 1428000000UL, { 1686950, -44715, 402 } },
0061 { 1530000000UL, { 1746653, -46005, 402 } },
0062 { 1632000000UL, { 1808179, -47285, 402 } },
0063 { 1734000000UL, { 1871526, -48575, 402 } },
0064 { 1836000000UL, { 1936696, -49855, 402 } },
0065 { 1938000000UL, { 2003687, -51145, 402 } },
0066 { 2014500000UL, { 2054787, -52095, 402 } },
0067 { 2116500000UL, { 2124957, -53385, 402 } },
0068 { 2218500000UL, { 2196950, -54665, 402 } },
0069 { 2320500000UL, { 2270765, -55955, 402 } },
0070 { 2422500000UL, { 2346401, -57235, 402 } },
0071 { 2524500000UL, { 2437299, -58535, 402 } },
0072 { 0UL, { 0, 0, 0 } },
0073 },
0074 .cpu_dfll_data = {
0075 .tune0_low = 0x005020ff,
0076 .tune0_high = 0x005040ff,
0077 .tune1 = 0x00000060,
0078 }
0079 },
0080 };
0081
0082 static const unsigned long tegra210_cpu_max_freq_table[] = {
0083 [0] = 1912500000UL,
0084 [1] = 1912500000UL,
0085 [2] = 2218500000UL,
0086 [3] = 1785000000UL,
0087 [4] = 1632000000UL,
0088 [5] = 1912500000UL,
0089 [6] = 2014500000UL,
0090 [7] = 1734000000UL,
0091 [8] = 1683000000UL,
0092 [9] = 1555500000UL,
0093 [10] = 1504500000UL,
0094 };
0095
0096 #define CPU_CVB_TABLE \
0097 .speedo_scale = 100, \
0098 .voltage_scale = 1000, \
0099 .entries = { \
0100 { 204000000UL, { 1007452, -23865, 370 } }, \
0101 { 306000000UL, { 1052709, -24875, 370 } }, \
0102 { 408000000UL, { 1099069, -25895, 370 } }, \
0103 { 510000000UL, { 1146534, -26905, 370 } }, \
0104 { 612000000UL, { 1195102, -27915, 370 } }, \
0105 { 714000000UL, { 1244773, -28925, 370 } }, \
0106 { 816000000UL, { 1295549, -29935, 370 } }, \
0107 { 918000000UL, { 1347428, -30955, 370 } }, \
0108 { 1020000000UL, { 1400411, -31965, 370 } }, \
0109 { 1122000000UL, { 1454497, -32975, 370 } }, \
0110 { 1224000000UL, { 1509687, -33985, 370 } }, \
0111 { 1326000000UL, { 1565981, -35005, 370 } }, \
0112 { 1428000000UL, { 1623379, -36015, 370 } }, \
0113 { 1530000000UL, { 1681880, -37025, 370 } }, \
0114 { 1632000000UL, { 1741485, -38035, 370 } }, \
0115 { 1734000000UL, { 1802194, -39055, 370 } }, \
0116 { 1836000000UL, { 1864006, -40065, 370 } }, \
0117 { 1912500000UL, { 1910780, -40815, 370 } }, \
0118 { 2014500000UL, { 1227000, 0, 0 } }, \
0119 { 2218500000UL, { 1227000, 0, 0 } }, \
0120 { 0UL, { 0, 0, 0 } }, \
0121 }
0122
0123 #define CPU_CVB_TABLE_XA \
0124 .speedo_scale = 100, \
0125 .voltage_scale = 1000, \
0126 .entries = { \
0127 { 204000000UL, { 1250024, -39785, 565 } }, \
0128 { 306000000UL, { 1297556, -41145, 565 } }, \
0129 { 408000000UL, { 1346718, -42505, 565 } }, \
0130 { 510000000UL, { 1397511, -43855, 565 } }, \
0131 { 612000000UL, { 1449933, -45215, 565 } }, \
0132 { 714000000UL, { 1503986, -46575, 565 } }, \
0133 { 816000000UL, { 1559669, -47935, 565 } }, \
0134 { 918000000UL, { 1616982, -49295, 565 } }, \
0135 { 1020000000UL, { 1675926, -50645, 565 } }, \
0136 { 1122000000UL, { 1736500, -52005, 565 } }, \
0137 { 1224000000UL, { 1798704, -53365, 565 } }, \
0138 { 1326000000UL, { 1862538, -54725, 565 } }, \
0139 { 1428000000UL, { 1928003, -56085, 565 } }, \
0140 { 1530000000UL, { 1995097, -57435, 565 } }, \
0141 { 1606500000UL, { 2046149, -58445, 565 } }, \
0142 { 1632000000UL, { 2063822, -58795, 565 } }, \
0143 { 0UL, { 0, 0, 0 } }, \
0144 }
0145
0146 #define CPU_CVB_TABLE_EUCM1 \
0147 .speedo_scale = 100, \
0148 .voltage_scale = 1000, \
0149 .entries = { \
0150 { 204000000UL, { 734429, 0, 0 } }, \
0151 { 306000000UL, { 768191, 0, 0 } }, \
0152 { 408000000UL, { 801953, 0, 0 } }, \
0153 { 510000000UL, { 835715, 0, 0 } }, \
0154 { 612000000UL, { 869477, 0, 0 } }, \
0155 { 714000000UL, { 903239, 0, 0 } }, \
0156 { 816000000UL, { 937001, 0, 0 } }, \
0157 { 918000000UL, { 970763, 0, 0 } }, \
0158 { 1020000000UL, { 1004525, 0, 0 } }, \
0159 { 1122000000UL, { 1038287, 0, 0 } }, \
0160 { 1224000000UL, { 1072049, 0, 0 } }, \
0161 { 1326000000UL, { 1105811, 0, 0 } }, \
0162 { 1428000000UL, { 1130000, 0, 0 } }, \
0163 { 1555500000UL, { 1130000, 0, 0 } }, \
0164 { 1632000000UL, { 1170000, 0, 0 } }, \
0165 { 1734000000UL, { 1227500, 0, 0 } }, \
0166 { 0UL, { 0, 0, 0 } }, \
0167 }
0168
0169 #define CPU_CVB_TABLE_EUCM2 \
0170 .speedo_scale = 100, \
0171 .voltage_scale = 1000, \
0172 .entries = { \
0173 { 204000000UL, { 742283, 0, 0 } }, \
0174 { 306000000UL, { 776249, 0, 0 } }, \
0175 { 408000000UL, { 810215, 0, 0 } }, \
0176 { 510000000UL, { 844181, 0, 0 } }, \
0177 { 612000000UL, { 878147, 0, 0 } }, \
0178 { 714000000UL, { 912113, 0, 0 } }, \
0179 { 816000000UL, { 946079, 0, 0 } }, \
0180 { 918000000UL, { 980045, 0, 0 } }, \
0181 { 1020000000UL, { 1014011, 0, 0 } }, \
0182 { 1122000000UL, { 1047977, 0, 0 } }, \
0183 { 1224000000UL, { 1081943, 0, 0 } }, \
0184 { 1326000000UL, { 1090000, 0, 0 } }, \
0185 { 1479000000UL, { 1090000, 0, 0 } }, \
0186 { 1555500000UL, { 1162000, 0, 0 } }, \
0187 { 1683000000UL, { 1195000, 0, 0 } }, \
0188 { 0UL, { 0, 0, 0 } }, \
0189 }
0190
0191 #define CPU_CVB_TABLE_EUCM2_JOINT_RAIL \
0192 .speedo_scale = 100, \
0193 .voltage_scale = 1000, \
0194 .entries = { \
0195 { 204000000UL, { 742283, 0, 0 } }, \
0196 { 306000000UL, { 776249, 0, 0 } }, \
0197 { 408000000UL, { 810215, 0, 0 } }, \
0198 { 510000000UL, { 844181, 0, 0 } }, \
0199 { 612000000UL, { 878147, 0, 0 } }, \
0200 { 714000000UL, { 912113, 0, 0 } }, \
0201 { 816000000UL, { 946079, 0, 0 } }, \
0202 { 918000000UL, { 980045, 0, 0 } }, \
0203 { 1020000000UL, { 1014011, 0, 0 } }, \
0204 { 1122000000UL, { 1047977, 0, 0 } }, \
0205 { 1224000000UL, { 1081943, 0, 0 } }, \
0206 { 1326000000UL, { 1090000, 0, 0 } }, \
0207 { 1479000000UL, { 1090000, 0, 0 } }, \
0208 { 1504500000UL, { 1120000, 0, 0 } }, \
0209 { 0UL, { 0, 0, 0 } }, \
0210 }
0211
0212 #define CPU_CVB_TABLE_ODN \
0213 .speedo_scale = 100, \
0214 .voltage_scale = 1000, \
0215 .entries = { \
0216 { 204000000UL, { 721094, 0, 0 } }, \
0217 { 306000000UL, { 754040, 0, 0 } }, \
0218 { 408000000UL, { 786986, 0, 0 } }, \
0219 { 510000000UL, { 819932, 0, 0 } }, \
0220 { 612000000UL, { 852878, 0, 0 } }, \
0221 { 714000000UL, { 885824, 0, 0 } }, \
0222 { 816000000UL, { 918770, 0, 0 } }, \
0223 { 918000000UL, { 915716, 0, 0 } }, \
0224 { 1020000000UL, { 984662, 0, 0 } }, \
0225 { 1122000000UL, { 1017608, 0, 0 } }, \
0226 { 1224000000UL, { 1050554, 0, 0 } }, \
0227 { 1326000000UL, { 1083500, 0, 0 } }, \
0228 { 1428000000UL, { 1116446, 0, 0 } }, \
0229 { 1581000000UL, { 1130000, 0, 0 } }, \
0230 { 1683000000UL, { 1168000, 0, 0 } }, \
0231 { 1785000000UL, { 1227500, 0, 0 } }, \
0232 { 0UL, { 0, 0, 0 } }, \
0233 }
0234
0235 static struct cvb_table tegra210_cpu_cvb_tables[] = {
0236 {
0237 .speedo_id = 10,
0238 .process_id = 0,
0239 .min_millivolts = 840,
0240 .max_millivolts = 1120,
0241 CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
0242 .cpu_dfll_data = {
0243 .tune0_low = 0xffead0ff,
0244 .tune0_high = 0xffead0ff,
0245 .tune1 = 0x20091d9,
0246 .tune_high_min_millivolts = 864,
0247 }
0248 },
0249 {
0250 .speedo_id = 10,
0251 .process_id = 1,
0252 .min_millivolts = 840,
0253 .max_millivolts = 1120,
0254 CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
0255 .cpu_dfll_data = {
0256 .tune0_low = 0xffead0ff,
0257 .tune0_high = 0xffead0ff,
0258 .tune1 = 0x20091d9,
0259 .tune_high_min_millivolts = 864,
0260 }
0261 },
0262 {
0263 .speedo_id = 9,
0264 .process_id = 0,
0265 .min_millivolts = 900,
0266 .max_millivolts = 1162,
0267 CPU_CVB_TABLE_EUCM2,
0268 .cpu_dfll_data = {
0269 .tune0_low = 0xffead0ff,
0270 .tune0_high = 0xffead0ff,
0271 .tune1 = 0x20091d9,
0272 }
0273 },
0274 {
0275 .speedo_id = 9,
0276 .process_id = 1,
0277 .min_millivolts = 900,
0278 .max_millivolts = 1162,
0279 CPU_CVB_TABLE_EUCM2,
0280 .cpu_dfll_data = {
0281 .tune0_low = 0xffead0ff,
0282 .tune0_high = 0xffead0ff,
0283 .tune1 = 0x20091d9,
0284 }
0285 },
0286 {
0287 .speedo_id = 8,
0288 .process_id = 0,
0289 .min_millivolts = 900,
0290 .max_millivolts = 1195,
0291 CPU_CVB_TABLE_EUCM2,
0292 .cpu_dfll_data = {
0293 .tune0_low = 0xffead0ff,
0294 .tune0_high = 0xffead0ff,
0295 .tune1 = 0x20091d9,
0296 }
0297 },
0298 {
0299 .speedo_id = 8,
0300 .process_id = 1,
0301 .min_millivolts = 900,
0302 .max_millivolts = 1195,
0303 CPU_CVB_TABLE_EUCM2,
0304 .cpu_dfll_data = {
0305 .tune0_low = 0xffead0ff,
0306 .tune0_high = 0xffead0ff,
0307 .tune1 = 0x20091d9,
0308 }
0309 },
0310 {
0311 .speedo_id = 7,
0312 .process_id = 0,
0313 .min_millivolts = 841,
0314 .max_millivolts = 1227,
0315 CPU_CVB_TABLE_EUCM1,
0316 .cpu_dfll_data = {
0317 .tune0_low = 0xffead0ff,
0318 .tune0_high = 0xffead0ff,
0319 .tune1 = 0x20091d9,
0320 .tune_high_min_millivolts = 864,
0321 }
0322 },
0323 {
0324 .speedo_id = 7,
0325 .process_id = 1,
0326 .min_millivolts = 841,
0327 .max_millivolts = 1227,
0328 CPU_CVB_TABLE_EUCM1,
0329 .cpu_dfll_data = {
0330 .tune0_low = 0xffead0ff,
0331 .tune0_high = 0xffead0ff,
0332 .tune1 = 0x20091d9,
0333 .tune_high_min_millivolts = 864,
0334 }
0335 },
0336 {
0337 .speedo_id = 6,
0338 .process_id = 0,
0339 .min_millivolts = 870,
0340 .max_millivolts = 1150,
0341 CPU_CVB_TABLE,
0342 .cpu_dfll_data = {
0343 .tune0_low = 0xffead0ff,
0344 .tune1 = 0x20091d9,
0345 }
0346 },
0347 {
0348 .speedo_id = 6,
0349 .process_id = 1,
0350 .min_millivolts = 870,
0351 .max_millivolts = 1150,
0352 CPU_CVB_TABLE,
0353 .cpu_dfll_data = {
0354 .tune0_low = 0xffead0ff,
0355 .tune1 = 0x25501d0,
0356 }
0357 },
0358 {
0359 .speedo_id = 5,
0360 .process_id = 0,
0361 .min_millivolts = 818,
0362 .max_millivolts = 1227,
0363 CPU_CVB_TABLE,
0364 .cpu_dfll_data = {
0365 .tune0_low = 0xffead0ff,
0366 .tune0_high = 0xffead0ff,
0367 .tune1 = 0x20091d9,
0368 .tune_high_min_millivolts = 864,
0369 }
0370 },
0371 {
0372 .speedo_id = 5,
0373 .process_id = 1,
0374 .min_millivolts = 818,
0375 .max_millivolts = 1227,
0376 CPU_CVB_TABLE,
0377 .cpu_dfll_data = {
0378 .tune0_low = 0xffead0ff,
0379 .tune0_high = 0xffead0ff,
0380 .tune1 = 0x25501d0,
0381 .tune_high_min_millivolts = 864,
0382 }
0383 },
0384 {
0385 .speedo_id = 4,
0386 .process_id = -1,
0387 .min_millivolts = 918,
0388 .max_millivolts = 1113,
0389 CPU_CVB_TABLE_XA,
0390 .cpu_dfll_data = {
0391 .tune0_low = 0xffead0ff,
0392 .tune1 = 0x17711BD,
0393 }
0394 },
0395 {
0396 .speedo_id = 3,
0397 .process_id = 0,
0398 .min_millivolts = 825,
0399 .max_millivolts = 1227,
0400 CPU_CVB_TABLE_ODN,
0401 .cpu_dfll_data = {
0402 .tune0_low = 0xffead0ff,
0403 .tune0_high = 0xffead0ff,
0404 .tune1 = 0x20091d9,
0405 .tune_high_min_millivolts = 864,
0406 }
0407 },
0408 {
0409 .speedo_id = 3,
0410 .process_id = 1,
0411 .min_millivolts = 825,
0412 .max_millivolts = 1227,
0413 CPU_CVB_TABLE_ODN,
0414 .cpu_dfll_data = {
0415 .tune0_low = 0xffead0ff,
0416 .tune0_high = 0xffead0ff,
0417 .tune1 = 0x25501d0,
0418 .tune_high_min_millivolts = 864,
0419 }
0420 },
0421 {
0422 .speedo_id = 2,
0423 .process_id = 0,
0424 .min_millivolts = 870,
0425 .max_millivolts = 1227,
0426 CPU_CVB_TABLE,
0427 .cpu_dfll_data = {
0428 .tune0_low = 0xffead0ff,
0429 .tune1 = 0x20091d9,
0430 }
0431 },
0432 {
0433 .speedo_id = 2,
0434 .process_id = 1,
0435 .min_millivolts = 870,
0436 .max_millivolts = 1227,
0437 CPU_CVB_TABLE,
0438 .cpu_dfll_data = {
0439 .tune0_low = 0xffead0ff,
0440 .tune1 = 0x25501d0,
0441 }
0442 },
0443 {
0444 .speedo_id = 1,
0445 .process_id = 0,
0446 .min_millivolts = 837,
0447 .max_millivolts = 1227,
0448 CPU_CVB_TABLE,
0449 .cpu_dfll_data = {
0450 .tune0_low = 0xffead0ff,
0451 .tune0_high = 0xffead0ff,
0452 .tune1 = 0x20091d9,
0453 .tune_high_min_millivolts = 864,
0454 }
0455 },
0456 {
0457 .speedo_id = 1,
0458 .process_id = 1,
0459 .min_millivolts = 837,
0460 .max_millivolts = 1227,
0461 CPU_CVB_TABLE,
0462 .cpu_dfll_data = {
0463 .tune0_low = 0xffead0ff,
0464 .tune0_high = 0xffead0ff,
0465 .tune1 = 0x25501d0,
0466 .tune_high_min_millivolts = 864,
0467 }
0468 },
0469 {
0470 .speedo_id = 0,
0471 .process_id = 0,
0472 .min_millivolts = 850,
0473 .max_millivolts = 1170,
0474 CPU_CVB_TABLE,
0475 .cpu_dfll_data = {
0476 .tune0_low = 0xffead0ff,
0477 .tune0_high = 0xffead0ff,
0478 .tune1 = 0x20091d9,
0479 .tune_high_min_millivolts = 864,
0480 }
0481 },
0482 {
0483 .speedo_id = 0,
0484 .process_id = 1,
0485 .min_millivolts = 850,
0486 .max_millivolts = 1170,
0487 CPU_CVB_TABLE,
0488 .cpu_dfll_data = {
0489 .tune0_low = 0xffead0ff,
0490 .tune0_high = 0xffead0ff,
0491 .tune1 = 0x25501d0,
0492 .tune_high_min_millivolts = 864,
0493 }
0494 },
0495 };
0496
0497 static const struct dfll_fcpu_data tegra124_dfll_fcpu_data = {
0498 .cpu_max_freq_table = tegra124_cpu_max_freq_table,
0499 .cpu_max_freq_table_size = ARRAY_SIZE(tegra124_cpu_max_freq_table),
0500 .cpu_cvb_tables = tegra124_cpu_cvb_tables,
0501 .cpu_cvb_tables_size = ARRAY_SIZE(tegra124_cpu_cvb_tables)
0502 };
0503
0504 static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = {
0505 .cpu_max_freq_table = tegra210_cpu_max_freq_table,
0506 .cpu_max_freq_table_size = ARRAY_SIZE(tegra210_cpu_max_freq_table),
0507 .cpu_cvb_tables = tegra210_cpu_cvb_tables,
0508 .cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables),
0509 };
0510
0511 static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
0512 {
0513 .compatible = "nvidia,tegra124-dfll",
0514 .data = &tegra124_dfll_fcpu_data,
0515 },
0516 {
0517 .compatible = "nvidia,tegra210-dfll",
0518 .data = &tegra210_dfll_fcpu_data
0519 },
0520 { },
0521 };
0522
0523 static void get_alignment_from_dt(struct device *dev,
0524 struct rail_alignment *align)
0525 {
0526 if (of_property_read_u32(dev->of_node,
0527 "nvidia,pwm-voltage-step-microvolts",
0528 &align->step_uv))
0529 align->step_uv = 0;
0530
0531 if (of_property_read_u32(dev->of_node,
0532 "nvidia,pwm-min-microvolts",
0533 &align->offset_uv))
0534 align->offset_uv = 0;
0535 }
0536
0537 static int get_alignment_from_regulator(struct device *dev,
0538 struct rail_alignment *align)
0539 {
0540 struct regulator *reg = regulator_get(dev, "vdd-cpu");
0541
0542 if (IS_ERR(reg))
0543 return PTR_ERR(reg);
0544
0545 align->offset_uv = regulator_list_voltage(reg, 0);
0546 align->step_uv = regulator_get_linear_step(reg);
0547
0548 regulator_put(reg);
0549
0550 return 0;
0551 }
0552
0553 static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
0554 {
0555 int process_id, speedo_id, speedo_value, err;
0556 struct tegra_dfll_soc_data *soc;
0557 const struct dfll_fcpu_data *fcpu_data;
0558 struct rail_alignment align;
0559
0560 fcpu_data = of_device_get_match_data(&pdev->dev);
0561 if (!fcpu_data)
0562 return -ENODEV;
0563
0564 process_id = tegra_sku_info.cpu_process_id;
0565 speedo_id = tegra_sku_info.cpu_speedo_id;
0566 speedo_value = tegra_sku_info.cpu_speedo_value;
0567
0568 if (speedo_id >= fcpu_data->cpu_max_freq_table_size) {
0569 dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
0570 speedo_id);
0571 return -ENODEV;
0572 }
0573
0574 soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL);
0575 if (!soc)
0576 return -ENOMEM;
0577
0578 soc->dev = get_cpu_device(0);
0579 if (!soc->dev) {
0580 dev_err(&pdev->dev, "no CPU0 device\n");
0581 return -ENODEV;
0582 }
0583
0584 if (of_property_read_bool(pdev->dev.of_node, "nvidia,pwm-to-pmic")) {
0585 get_alignment_from_dt(&pdev->dev, &align);
0586 } else {
0587 err = get_alignment_from_regulator(&pdev->dev, &align);
0588 if (err)
0589 return err;
0590 }
0591
0592 soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id];
0593
0594 soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
0595 fcpu_data->cpu_cvb_tables_size,
0596 &align, process_id, speedo_id,
0597 speedo_value, soc->max_freq);
0598 soc->alignment = align;
0599
0600 if (IS_ERR(soc->cvb)) {
0601 dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
0602 PTR_ERR(soc->cvb));
0603 return PTR_ERR(soc->cvb);
0604 }
0605
0606 err = tegra_dfll_register(pdev, soc);
0607 if (err < 0) {
0608 tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
0609 return err;
0610 }
0611
0612 return 0;
0613 }
0614
0615 static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
0616 {
0617 struct tegra_dfll_soc_data *soc;
0618
0619 soc = tegra_dfll_unregister(pdev);
0620 if (IS_ERR(soc)) {
0621 dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n",
0622 PTR_ERR(soc));
0623 return PTR_ERR(soc);
0624 }
0625
0626 tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
0627
0628 return 0;
0629 }
0630
0631 static const struct dev_pm_ops tegra124_dfll_pm_ops = {
0632 SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
0633 tegra_dfll_runtime_resume, NULL)
0634 SET_SYSTEM_SLEEP_PM_OPS(tegra_dfll_suspend, tegra_dfll_resume)
0635 };
0636
0637 static struct platform_driver tegra124_dfll_fcpu_driver = {
0638 .probe = tegra124_dfll_fcpu_probe,
0639 .remove = tegra124_dfll_fcpu_remove,
0640 .driver = {
0641 .name = "tegra124-dfll",
0642 .of_match_table = tegra124_dfll_fcpu_of_match,
0643 .pm = &tegra124_dfll_pm_ops,
0644 },
0645 };
0646 builtin_platform_driver(tegra124_dfll_fcpu_driver);