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
get_alignment_from_dt(struct device * dev,struct rail_alignment * align)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
get_alignment_from_regulator(struct device * dev,struct rail_alignment * align)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
tegra124_dfll_fcpu_probe(struct platform_device * pdev)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
tegra124_dfll_fcpu_remove(struct platform_device * pdev)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