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 tegra124_cpu_max_freq_table[] = { |
33 | [0] = 2014500000UL, |
34 | [1] = 2320500000UL, |
35 | [2] = 2116500000UL, |
36 | [3] = 2524500000UL, |
37 | }; |
38 | |
39 | static 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 | |
82 | static 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 | |
235 | static 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 | |
497 | static 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 | |
504 | static 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 | |
511 | static 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_data |
519 | }, |
520 | { }, |
521 | }; |
522 | |
523 | static void get_alignment_from_dt(struct device *dev, |
524 | struct rail_alignment *align) |
525 | { |
526 | if (of_property_read_u32(np: dev->of_node, |
527 | propname: "nvidia,pwm-voltage-step-microvolts" , |
528 | out_value: &align->step_uv)) |
529 | align->step_uv = 0; |
530 | |
531 | if (of_property_read_u32(np: dev->of_node, |
532 | propname: "nvidia,pwm-min-microvolts" , |
533 | out_value: &align->offset_uv)) |
534 | align->offset_uv = 0; |
535 | } |
536 | |
537 | static int get_alignment_from_regulator(struct device *dev, |
538 | struct rail_alignment *align) |
539 | { |
540 | struct regulator *reg = regulator_get(dev, id: "vdd-cpu" ); |
541 | |
542 | if (IS_ERR(ptr: reg)) |
543 | return PTR_ERR(ptr: reg); |
544 | |
545 | align->offset_uv = regulator_list_voltage(regulator: reg, selector: 0); |
546 | align->step_uv = regulator_get_linear_step(regulator: reg); |
547 | |
548 | regulator_put(regulator: reg); |
549 | |
550 | return 0; |
551 | } |
552 | |
553 | static 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(dev: &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(dev: &pdev->dev, size: sizeof(*soc), GFP_KERNEL); |
575 | if (!soc) |
576 | return -ENOMEM; |
577 | |
578 | soc->dev = get_cpu_device(cpu: 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(np: pdev->dev.of_node, propname: "nvidia,pwm-to-pmic" )) { |
585 | get_alignment_from_dt(dev: &pdev->dev, align: &align); |
586 | } else { |
587 | err = get_alignment_from_regulator(dev: &pdev->dev, align: &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(dev: soc->dev, cvb_tables: fcpu_data->cpu_cvb_tables, |
595 | count: fcpu_data->cpu_cvb_tables_size, |
596 | align: &align, process_id, speedo_id, |
597 | speedo_value, max_freq: soc->max_freq); |
598 | soc->alignment = align; |
599 | |
600 | if (IS_ERR(ptr: soc->cvb)) { |
601 | dev_err(&pdev->dev, "couldn't add OPP table: %ld\n" , |
602 | PTR_ERR(soc->cvb)); |
603 | return PTR_ERR(ptr: soc->cvb); |
604 | } |
605 | |
606 | err = tegra_dfll_register(pdev, soc); |
607 | if (err < 0) { |
608 | tegra_cvb_remove_opp_table(dev: soc->dev, table: soc->cvb, max_freq: soc->max_freq); |
609 | return err; |
610 | } |
611 | |
612 | return 0; |
613 | } |
614 | |
615 | static 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 function |
621 | * returns *soc is freed. |
622 | */ |
623 | soc = tegra_dfll_unregister(pdev); |
624 | if (IS_ERR(ptr: soc)) |
625 | return; |
626 | |
627 | tegra_cvb_remove_opp_table(dev: soc->dev, table: soc->cvb, max_freq: soc->max_freq); |
628 | } |
629 | |
630 | static 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 | |
636 | static struct platform_driver tegra124_dfll_fcpu_driver = { |
637 | .probe = tegra124_dfll_fcpu_probe, |
638 | .remove_new = 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 | }; |
645 | builtin_platform_driver(tegra124_dfll_fcpu_driver); |
646 | |