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