Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
62a8a094 TT |
2 | /* |
3 | * Tegra124 DFLL FCPU clock source driver | |
4 | * | |
b0dcfb78 | 5 | * Copyright (C) 2012-2019 NVIDIA Corporation. All rights reserved. |
62a8a094 TT |
6 | * |
7 | * Aleksandr Frid <afrid@nvidia.com> | |
8 | * Paul Walmsley <pwalmsley@nvidia.com> | |
62a8a094 TT |
9 | */ |
10 | ||
11 | #include <linux/cpu.h> | |
12 | #include <linux/err.h> | |
13 | #include <linux/kernel.h> | |
33996b02 | 14 | #include <linux/init.h> |
b0dcfb78 | 15 | #include <linux/of_device.h> |
62a8a094 | 16 | #include <linux/platform_device.h> |
b3cf8d06 | 17 | #include <linux/regulator/consumer.h> |
62a8a094 TT |
18 | #include <soc/tegra/fuse.h> |
19 | ||
20 | #include "clk.h" | |
21 | #include "clk-dfll.h" | |
22 | #include "cvb.h" | |
23 | ||
b0dcfb78 PDS |
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 | ||
62a8a094 | 31 | /* Maximum CPU frequency, indexed by CPU speedo id */ |
b0dcfb78 | 32 | static const unsigned long tegra124_cpu_max_freq_table[] = { |
62a8a094 TT |
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, | |
62a8a094 TT |
45 | .speedo_scale = 100, |
46 | .voltage_scale = 1000, | |
e8f6a68c | 47 | .entries = { |
2690e912 TR |
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 } }, | |
62a8a094 TT |
73 | }, |
74 | .cpu_dfll_data = { | |
75 | .tune0_low = 0x005020ff, | |
76 | .tune0_high = 0x005040ff, | |
77 | .tune1 = 0x00000060, | |
78 | } | |
79 | }, | |
80 | }; | |
81 | ||
2b2dbc2f JL |
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 | ||
bb872709 | 235 | static struct cvb_table tegra210_cpu_cvb_tables[] = { |
2b2dbc2f JL |
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 | ||
b0dcfb78 PDS |
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 | ||
2b2dbc2f JL |
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 | ||
b0dcfb78 PDS |
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 | }, | |
2b2dbc2f JL |
516 | { |
517 | .compatible = "nvidia,tegra210-dfll", | |
518 | .data = &tegra210_dfll_fcpu_data | |
519 | }, | |
b0dcfb78 PDS |
520 | { }, |
521 | }; | |
522 | ||
b3cf8d06 JL |
523 | static 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 | ||
537 | static int get_alignment_from_regulator(struct device *dev, | |
538 | struct rail_alignment *align) | |
539 | { | |
2f0d67bf | 540 | struct regulator *reg = regulator_get(dev, "vdd-cpu"); |
b3cf8d06 JL |
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 | ||
2f0d67bf | 548 | regulator_put(reg); |
b3cf8d06 JL |
549 | |
550 | return 0; | |
551 | } | |
552 | ||
62a8a094 TT |
553 | static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) |
554 | { | |
f7c42d98 | 555 | int process_id, speedo_id, speedo_value, err; |
62a8a094 | 556 | struct tegra_dfll_soc_data *soc; |
b0dcfb78 | 557 | const struct dfll_fcpu_data *fcpu_data; |
b3cf8d06 | 558 | struct rail_alignment align; |
b0dcfb78 PDS |
559 | |
560 | fcpu_data = of_device_get_match_data(&pdev->dev); | |
561 | if (!fcpu_data) | |
562 | return -ENODEV; | |
62a8a094 TT |
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 | ||
b0dcfb78 | 568 | if (speedo_id >= fcpu_data->cpu_max_freq_table_size) { |
62a8a094 TT |
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 | ||
b3cf8d06 JL |
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 | ||
b0dcfb78 | 592 | soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id]; |
f7c42d98 | 593 | |
b0dcfb78 PDS |
594 | soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables, |
595 | fcpu_data->cpu_cvb_tables_size, | |
b3cf8d06 JL |
596 | &align, process_id, speedo_id, |
597 | speedo_value, soc->max_freq); | |
598 | soc->alignment = align; | |
f7c42d98 | 599 | |
27ed2f7e TR |
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); | |
62a8a094 TT |
604 | } |
605 | ||
f7c42d98 TR |
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 | ||
f7c42d98 TR |
612 | return 0; |
613 | } | |
614 | ||
615 | static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) | |
616 | { | |
1752c9ee | 617 | struct tegra_dfll_soc_data *soc; |
f7c42d98 | 618 | |
c73e435e UKK |
619 | /* |
620 | * Note that exiting early here is dangerous as after this function | |
621 | * returns *soc is freed. | |
622 | */ | |
1752c9ee | 623 | soc = tegra_dfll_unregister(pdev); |
c73e435e UKK |
624 | if (IS_ERR(soc)) |
625 | return 0; | |
f7c42d98 TR |
626 | |
627 | tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); | |
62a8a094 | 628 | |
f7c42d98 | 629 | return 0; |
62a8a094 TT |
630 | } |
631 | ||
62a8a094 TT |
632 | static const struct dev_pm_ops tegra124_dfll_pm_ops = { |
633 | SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend, | |
634 | tegra_dfll_runtime_resume, NULL) | |
a99d744d | 635 | SET_SYSTEM_SLEEP_PM_OPS(tegra_dfll_suspend, tegra_dfll_resume) |
62a8a094 TT |
636 | }; |
637 | ||
638 | static struct platform_driver tegra124_dfll_fcpu_driver = { | |
639 | .probe = tegra124_dfll_fcpu_probe, | |
f7c42d98 | 640 | .remove = tegra124_dfll_fcpu_remove, |
62a8a094 TT |
641 | .driver = { |
642 | .name = "tegra124-dfll", | |
643 | .of_match_table = tegra124_dfll_fcpu_of_match, | |
644 | .pm = &tegra124_dfll_pm_ops, | |
645 | }, | |
646 | }; | |
6f877e79 | 647 | builtin_platform_driver(tegra124_dfll_fcpu_driver); |