xref: /linux/drivers/pmdomain/qcom/rpmpd.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
3 
4 #include <linux/cleanup.h>
5 #include <linux/err.h>
6 #include <linux/init.h>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/mutex.h>
10 #include <linux/pm_domain.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_opp.h>
14 #include <linux/soc/qcom/smd-rpm.h>
15 
16 #include <dt-bindings/power/qcom-rpmpd.h>
17 
18 #define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
19 
20 static struct qcom_smd_rpm *rpmpd_smd_rpm;
21 
22 /* Resource types:
23  * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
24 #define RPMPD_SMPA 0x61706d73
25 #define RPMPD_LDOA 0x616f646c
26 #define RPMPD_SMPB 0x62706d73
27 #define RPMPD_LDOB 0x626f646c
28 #define RPMPD_RWCX 0x78637772
29 #define RPMPD_RWMX 0x786d7772
30 #define RPMPD_RWLC 0x636c7772
31 #define RPMPD_RWLM 0x6d6c7772
32 #define RPMPD_RWSC 0x63737772
33 #define RPMPD_RWSM 0x6d737772
34 #define RPMPD_RWGX 0x78677772
35 
36 /* Operation Keys */
37 #define KEY_CORNER		0x6e726f63 /* corn */
38 #define KEY_ENABLE		0x6e657773 /* swen */
39 #define KEY_FLOOR_CORNER	0x636676   /* vfc */
40 #define KEY_FLOOR_LEVEL		0x6c6676   /* vfl */
41 #define KEY_LEVEL		0x6c766c76 /* vlvl */
42 
43 #define MAX_CORNER_RPMPD_STATE	6
44 
45 struct rpmpd_req {
46 	__le32 key;
47 	__le32 nbytes;
48 	__le32 value;
49 };
50 
51 struct rpmpd {
52 	struct generic_pm_domain pd;
53 	struct generic_pm_domain *parent;
54 	struct rpmpd *peer;
55 	const bool active_only;
56 	unsigned int corner;
57 	bool enabled;
58 	const int res_type;
59 	const int res_id;
60 	unsigned int max_state;
61 	__le32 key;
62 	bool state_synced;
63 };
64 
65 struct rpmpd_desc {
66 	struct rpmpd **rpmpds;
67 	size_t num_pds;
68 	unsigned int max_state;
69 };
70 
71 static DEFINE_MUTEX(rpmpd_lock);
72 
73 /* CX */
74 static struct rpmpd cx_rwcx0_lvl_ao;
75 static struct rpmpd cx_rwcx0_lvl = {
76 	.pd = { .name = "cx", },
77 	.peer = &cx_rwcx0_lvl_ao,
78 	.res_type = RPMPD_RWCX,
79 	.res_id = 0,
80 	.key = KEY_LEVEL,
81 };
82 
83 static struct rpmpd cx_rwcx0_lvl_ao = {
84 	.pd = { .name = "cx_ao", },
85 	.peer = &cx_rwcx0_lvl,
86 	.active_only = true,
87 	.res_type = RPMPD_RWCX,
88 	.res_id = 0,
89 	.key = KEY_LEVEL,
90 };
91 
92 static struct rpmpd cx_s1a_corner_ao;
93 static struct rpmpd cx_s1a_corner = {
94 	.pd = { .name = "cx", },
95 	.peer = &cx_s1a_corner_ao,
96 	.res_type = RPMPD_SMPA,
97 	.res_id = 1,
98 	.key = KEY_CORNER,
99 };
100 
101 static struct rpmpd cx_s1a_corner_ao = {
102 	.pd = { .name = "cx_ao", },
103 	.peer = &cx_s1a_corner,
104 	.active_only = true,
105 	.res_type = RPMPD_SMPA,
106 	.res_id = 1,
107 	.key = KEY_CORNER,
108 };
109 
110 static struct rpmpd cx_s1a_lvl_ao;
111 static struct rpmpd cx_s1a_lvl = {
112 	.pd = { .name = "cx", },
113 	.peer = &cx_s1a_lvl_ao,
114 	.res_type = RPMPD_SMPA,
115 	.res_id = 1,
116 	.key = KEY_LEVEL,
117 };
118 
119 static struct rpmpd cx_s1a_lvl_ao = {
120 	.pd = { .name = "cx_ao", },
121 	.peer = &cx_s1a_lvl,
122 	.active_only = true,
123 	.res_type = RPMPD_SMPA,
124 	.res_id = 1,
125 	.key = KEY_LEVEL,
126 };
127 
128 static struct rpmpd cx_s2a_corner_ao;
129 static struct rpmpd cx_s2a_corner = {
130 	.pd = { .name = "cx", },
131 	.peer = &cx_s2a_corner_ao,
132 	.res_type = RPMPD_SMPA,
133 	.res_id = 2,
134 	.key = KEY_CORNER,
135 };
136 
137 static struct rpmpd cx_s2a_corner_ao = {
138 	.pd = { .name = "cx_ao", },
139 	.peer = &cx_s2a_corner,
140 	.active_only = true,
141 	.res_type = RPMPD_SMPA,
142 	.res_id = 2,
143 	.key = KEY_CORNER,
144 };
145 
146 static struct rpmpd cx_s2a_lvl_ao;
147 static struct rpmpd cx_s2a_lvl = {
148 	.pd = { .name = "cx", },
149 	.peer = &cx_s2a_lvl_ao,
150 	.res_type = RPMPD_SMPA,
151 	.res_id = 2,
152 	.key = KEY_LEVEL,
153 };
154 
155 static struct rpmpd cx_s2a_lvl_ao = {
156 	.pd = { .name = "cx_ao", },
157 	.peer = &cx_s2a_lvl,
158 	.active_only = true,
159 	.res_type = RPMPD_SMPA,
160 	.res_id = 2,
161 	.key = KEY_LEVEL,
162 };
163 
164 static struct rpmpd cx_s3a_lvl_ao;
165 static struct rpmpd cx_s3a_lvl = {
166 	.pd = { .name = "cx", },
167 	.peer = &cx_s3a_lvl_ao,
168 	.res_type = RPMPD_SMPA,
169 	.res_id = 3,
170 	.key = KEY_LEVEL,
171 };
172 
173 static struct rpmpd cx_s3a_lvl_ao = {
174 	.pd = { .name = "cx_ao", },
175 	.peer = &cx_s3a_lvl,
176 	.active_only = true,
177 	.res_type = RPMPD_SMPA,
178 	.res_id = 3,
179 	.key = KEY_LEVEL,
180 };
181 
182 static struct rpmpd cx_rwcx0_vfl = {
183 	.pd = { .name = "cx_vfl", },
184 	.res_type = RPMPD_RWCX,
185 	.res_id = 0,
186 	.key = KEY_FLOOR_LEVEL,
187 };
188 
189 static struct rpmpd cx_rwsc2_vfl = {
190 	.pd = { .name = "cx_vfl", },
191 	.res_type = RPMPD_RWSC,
192 	.res_id = 2,
193 	.key = KEY_FLOOR_LEVEL,
194 };
195 
196 static struct rpmpd cx_s1a_vfc = {
197 	.pd = { .name = "cx_vfc", },
198 	.res_type = RPMPD_SMPA,
199 	.res_id = 1,
200 	.key = KEY_FLOOR_CORNER,
201 };
202 
203 static struct rpmpd cx_s1a_vfl = {
204 	.pd = { .name = "cx_vfl", },
205 	.res_type = RPMPD_SMPA,
206 	.res_id = 1,
207 	.key = KEY_FLOOR_LEVEL,
208 };
209 
210 static struct rpmpd cx_s2a_vfc = {
211 	.pd = { .name = "cx_vfc", },
212 	.res_type = RPMPD_SMPA,
213 	.res_id = 2,
214 	.key = KEY_FLOOR_CORNER,
215 };
216 
217 static struct rpmpd cx_s2a_vfl = {
218 	.pd = { .name = "cx_vfl", },
219 	.res_type = RPMPD_SMPA,
220 	.res_id = 2,
221 	.key = KEY_FLOOR_LEVEL,
222 };
223 
224 static struct rpmpd cx_s3a_vfl = {
225 	.pd = { .name = "cx_vfl", },
226 	.res_type = RPMPD_SMPA,
227 	.res_id = 3,
228 	.key = KEY_FLOOR_LEVEL,
229 };
230 
231 static struct rpmpd cx_s2b_corner_ao;
232 static struct rpmpd cx_s2b_corner = {
233 	.pd = { .name = "cx", },
234 	.peer = &cx_s2b_corner_ao,
235 	.res_type = RPMPD_SMPB,
236 	.res_id = 2,
237 	.key = KEY_CORNER,
238 };
239 
240 static struct rpmpd cx_s2b_corner_ao = {
241 	.pd = { .name = "cx_ao", },
242 	.peer = &cx_s2b_corner,
243 	.active_only = true,
244 	.res_type = RPMPD_SMPB,
245 	.res_id = 2,
246 	.key = KEY_CORNER,
247 };
248 
249 static struct rpmpd cx_s2b_vfc = {
250 	.pd = { .name = "cx_vfc", },
251 	.res_type = RPMPD_SMPB,
252 	.res_id = 2,
253 	.key = KEY_FLOOR_CORNER,
254 };
255 
256 /* G(F)X */
257 static struct rpmpd gfx_s7a_corner = {
258 	.pd = { .name = "gfx", },
259 	.res_type = RPMPD_SMPA,
260 	.res_id = 7,
261 	.key = KEY_CORNER,
262 };
263 
264 static struct rpmpd gfx_s7a_vfc = {
265 	.pd = { .name = "gfx_vfc", },
266 	.res_type = RPMPD_SMPA,
267 	.res_id = 7,
268 	.key = KEY_FLOOR_CORNER,
269 };
270 
271 static struct rpmpd gfx_s2b_corner = {
272 	.pd = { .name = "gfx", },
273 	.res_type = RPMPD_SMPB,
274 	.res_id = 2,
275 	.key = KEY_CORNER,
276 };
277 
278 static struct rpmpd gfx_s2b_vfc = {
279 	.pd = { .name = "gfx_vfc", },
280 	.res_type = RPMPD_SMPB,
281 	.res_id = 2,
282 	.key = KEY_FLOOR_CORNER,
283 };
284 
285 static struct rpmpd gfx_s4b_corner = {
286 	.pd = { .name = "gfx", },
287 	.res_type = RPMPD_SMPB,
288 	.res_id = 4,
289 	.key = KEY_CORNER,
290 };
291 
292 static struct rpmpd gfx_s4b_vfc = {
293 	.pd = { .name = "gfx_vfc", },
294 	.res_type = RPMPD_SMPB,
295 	.res_id = 4,
296 	.key = KEY_FLOOR_CORNER,
297 };
298 
299 static struct rpmpd mx_rwmx0_lvl;
300 static struct rpmpd gx_rwgx0_lvl_ao;
301 static struct rpmpd gx_rwgx0_lvl = {
302 	.pd = { .name = "gx", },
303 	.peer = &gx_rwgx0_lvl_ao,
304 	.res_type = RPMPD_RWGX,
305 	.parent = &mx_rwmx0_lvl.pd,
306 	.res_id = 0,
307 	.key = KEY_LEVEL,
308 };
309 
310 static struct rpmpd mx_rwmx0_lvl_ao;
311 static struct rpmpd gx_rwgx0_lvl_ao = {
312 	.pd = { .name = "gx_ao", },
313 	.peer = &gx_rwgx0_lvl,
314 	.parent = &mx_rwmx0_lvl_ao.pd,
315 	.active_only = true,
316 	.res_type = RPMPD_RWGX,
317 	.res_id = 0,
318 	.key = KEY_LEVEL,
319 };
320 
321 /* MX */
322 static struct rpmpd mx_l2a_lvl_ao;
323 static struct rpmpd mx_l2a_lvl = {
324 	.pd = { .name = "mx", },
325 	.peer = &mx_l2a_lvl_ao,
326 	.res_type = RPMPD_LDOA,
327 	.res_id = 2,
328 	.key = KEY_LEVEL,
329 };
330 
331 static struct rpmpd mx_l2a_lvl_ao = {
332 	.pd = { .name = "mx_ao", },
333 	.peer = &mx_l2a_lvl,
334 	.active_only = true,
335 	.res_type = RPMPD_LDOA,
336 	.res_id = 2,
337 	.key = KEY_LEVEL,
338 };
339 
340 static struct rpmpd mx_l3a_corner_ao;
341 static struct rpmpd mx_l3a_corner = {
342 	.pd = { .name = "mx", },
343 	.peer = &mx_l3a_corner_ao,
344 	.res_type = RPMPD_LDOA,
345 	.res_id = 3,
346 	.key = KEY_CORNER,
347 };
348 
349 static struct rpmpd mx_l3a_corner_ao = {
350 	.pd = { .name = "mx_ao", },
351 	.peer = &mx_l3a_corner,
352 	.active_only = true,
353 	.res_type = RPMPD_LDOA,
354 	.res_id = 3,
355 	.key = KEY_CORNER,
356 };
357 
358 static struct rpmpd mx_l3a_lvl_ao;
359 static struct rpmpd mx_l3a_lvl = {
360 	.pd = { .name = "mx", },
361 	.peer = &mx_l3a_lvl_ao,
362 	.res_type = RPMPD_LDOA,
363 	.res_id = 3,
364 	.key = KEY_LEVEL,
365 };
366 
367 static struct rpmpd mx_l3a_lvl_ao = {
368 	.pd = { .name = "mx_ao", },
369 	.peer = &mx_l3a_lvl,
370 	.active_only = true,
371 	.res_type = RPMPD_LDOA,
372 	.res_id = 3,
373 	.key = KEY_LEVEL,
374 };
375 
376 static struct rpmpd mx_l12a_lvl_ao;
377 static struct rpmpd mx_l12a_lvl = {
378 	.pd = { .name = "mx", },
379 	.peer = &mx_l12a_lvl_ao,
380 	.res_type = RPMPD_LDOA,
381 	.res_id = 12,
382 	.key = KEY_LEVEL,
383 };
384 
385 static struct rpmpd mx_l12a_lvl_ao = {
386 	.pd = { .name = "mx_ao", },
387 	.peer = &mx_l12a_lvl,
388 	.active_only = true,
389 	.res_type = RPMPD_LDOA,
390 	.res_id = 12,
391 	.key = KEY_LEVEL,
392 };
393 
394 static struct rpmpd mx_s2a_corner_ao;
395 static struct rpmpd mx_s2a_corner = {
396 	.pd = { .name = "mx", },
397 	.peer = &mx_s2a_corner_ao,
398 	.res_type = RPMPD_SMPA,
399 	.res_id = 2,
400 	.key = KEY_CORNER,
401 };
402 
403 static struct rpmpd mx_s2a_corner_ao = {
404 	.pd = { .name = "mx_ao", },
405 	.peer = &mx_s2a_corner,
406 	.active_only = true,
407 	.res_type = RPMPD_SMPA,
408 	.res_id = 2,
409 	.key = KEY_CORNER,
410 };
411 
412 static struct rpmpd mx_rwmx0_lvl_ao;
413 static struct rpmpd mx_rwmx0_lvl = {
414 	.pd = { .name = "mx", },
415 	.peer = &mx_rwmx0_lvl_ao,
416 	.res_type = RPMPD_RWMX,
417 	.res_id = 0,
418 	.key = KEY_LEVEL,
419 };
420 
421 static struct rpmpd mx_rwmx0_lvl_ao = {
422 	.pd = { .name = "mx_ao", },
423 	.peer = &mx_rwmx0_lvl,
424 	.active_only = true,
425 	.res_type = RPMPD_RWMX,
426 	.res_id = 0,
427 	.key = KEY_LEVEL,
428 };
429 
430 static struct rpmpd mx_s6a_lvl_ao;
431 static struct rpmpd mx_s6a_lvl = {
432 	.pd = { .name = "mx", },
433 	.peer = &mx_s6a_lvl_ao,
434 	.res_type = RPMPD_SMPA,
435 	.res_id = 6,
436 	.key = KEY_LEVEL,
437 };
438 
439 static struct rpmpd mx_s6a_lvl_ao = {
440 	.pd = { .name = "mx_ao", },
441 	.peer = &mx_s6a_lvl,
442 	.active_only = true,
443 	.res_type = RPMPD_SMPA,
444 	.res_id = 6,
445 	.key = KEY_LEVEL,
446 };
447 
448 static struct rpmpd mx_s7a_lvl_ao;
449 static struct rpmpd mx_s7a_lvl = {
450 	.pd = { .name = "mx", },
451 	.peer = &mx_s7a_lvl_ao,
452 	.res_type = RPMPD_SMPA,
453 	.res_id = 7,
454 	.key = KEY_LEVEL,
455 };
456 
457 static struct rpmpd mx_s7a_lvl_ao = {
458 	.pd = { .name = "mx_ao", },
459 	.peer = &mx_s7a_lvl,
460 	.active_only = true,
461 	.res_type = RPMPD_SMPA,
462 	.res_id = 7,
463 	.key = KEY_LEVEL,
464 };
465 
466 static struct rpmpd mx_l12a_vfl = {
467 	.pd = { .name = "mx_vfl", },
468 	.res_type = RPMPD_LDOA,
469 	.res_id = 12,
470 	.key = KEY_FLOOR_LEVEL,
471 };
472 
473 static struct rpmpd mx_rwmx0_vfl = {
474 	.pd = { .name = "mx_vfl", },
475 	.res_type = RPMPD_RWMX,
476 	.res_id = 0,
477 	.key = KEY_FLOOR_LEVEL,
478 };
479 
480 static struct rpmpd mx_rwsm6_vfl = {
481 	.pd = { .name = "mx_vfl", },
482 	.res_type = RPMPD_RWSM,
483 	.res_id = 6,
484 	.key = KEY_FLOOR_LEVEL,
485 };
486 
487 /* MD */
488 static struct rpmpd md_s1a_corner_ao;
489 static struct rpmpd md_s1a_corner = {
490 	.pd = { .name = "md", },
491 	.peer = &md_s1a_corner_ao,
492 	.res_type = RPMPD_SMPA,
493 	.res_id = 1,
494 	.key = KEY_CORNER,
495 };
496 
497 static struct rpmpd md_s1a_corner_ao = {
498 	.pd = { .name = "md_ao", },
499 	.peer = &md_s1a_corner,
500 	.active_only = true,
501 	.res_type = RPMPD_SMPA,
502 	.res_id = 1,
503 	.key = KEY_CORNER,
504 };
505 
506 static struct rpmpd md_s1a_lvl_ao;
507 static struct rpmpd md_s1a_lvl = {
508 	.pd = { .name = "md", },
509 	.peer = &md_s1a_lvl_ao,
510 	.res_type = RPMPD_SMPA,
511 	.res_id = 1,
512 	.key = KEY_LEVEL,
513 };
514 
515 static struct rpmpd md_s1a_lvl_ao = {
516 	.pd = { .name = "md_ao", },
517 	.peer = &md_s1a_lvl,
518 	.active_only = true,
519 	.res_type = RPMPD_SMPA,
520 	.res_id = 1,
521 	.key = KEY_LEVEL,
522 };
523 
524 static struct rpmpd md_s1a_vfc = {
525 	.pd = { .name = "md_vfc", },
526 	.res_type = RPMPD_SMPA,
527 	.res_id = 1,
528 	.key = KEY_FLOOR_CORNER,
529 };
530 
531 /* LPI_CX */
532 static struct rpmpd lpi_cx_rwlc0_lvl = {
533 	.pd = { .name = "lpi_cx", },
534 	.res_type = RPMPD_RWLC,
535 	.res_id = 0,
536 	.key = KEY_LEVEL,
537 };
538 
539 static struct rpmpd lpi_cx_rwlc0_vfl = {
540 	.pd = { .name = "lpi_cx_vfl", },
541 	.res_type = RPMPD_RWLC,
542 	.res_id = 0,
543 	.key = KEY_FLOOR_LEVEL,
544 };
545 
546 /* LPI_MX */
547 static struct rpmpd lpi_mx_rwlm0_lvl = {
548 	.pd = { .name = "lpi_mx", },
549 	.res_type = RPMPD_RWLM,
550 	.res_id = 0,
551 	.key = KEY_LEVEL,
552 };
553 
554 static struct rpmpd lpi_mx_rwlm0_vfl = {
555 	.pd = { .name = "lpi_mx_vfl", },
556 	.res_type = RPMPD_RWLM,
557 	.res_id = 0,
558 	.key = KEY_FLOOR_LEVEL,
559 };
560 
561 /* SSC_CX */
562 static struct rpmpd ssc_cx_l26a_corner = {
563 	.pd = { .name = "ssc_cx", },
564 	.res_type = RPMPD_LDOA,
565 	.res_id = 26,
566 	.key = KEY_CORNER,
567 };
568 
569 static struct rpmpd ssc_cx_rwlc0_lvl = {
570 	.pd = { .name = "ssc_cx", },
571 	.res_type = RPMPD_RWLC,
572 	.res_id = 0,
573 	.key = KEY_LEVEL,
574 };
575 
576 static struct rpmpd ssc_cx_rwsc0_lvl = {
577 	.pd = { .name = "ssc_cx", },
578 	.res_type = RPMPD_RWSC,
579 	.res_id = 0,
580 	.key = KEY_LEVEL,
581 };
582 
583 static struct rpmpd ssc_cx_l26a_vfc = {
584 	.pd = { .name = "ssc_cx_vfc", },
585 	.res_type = RPMPD_LDOA,
586 	.res_id = 26,
587 	.key = KEY_FLOOR_CORNER,
588 };
589 
590 static struct rpmpd ssc_cx_rwlc0_vfl = {
591 	.pd = { .name = "ssc_cx_vfl", },
592 	.res_type = RPMPD_RWLC,
593 	.res_id = 0,
594 	.key = KEY_FLOOR_LEVEL,
595 };
596 
597 static struct rpmpd ssc_cx_rwsc0_vfl = {
598 	.pd = { .name = "ssc_cx_vfl", },
599 	.res_type = RPMPD_RWSC,
600 	.res_id = 0,
601 	.key = KEY_FLOOR_LEVEL,
602 };
603 
604 /* SSC_MX */
605 static struct rpmpd ssc_mx_rwlm0_lvl = {
606 	.pd = { .name = "ssc_mx", },
607 	.res_type = RPMPD_RWLM,
608 	.res_id = 0,
609 	.key = KEY_LEVEL,
610 };
611 
612 static struct rpmpd ssc_mx_rwsm0_lvl = {
613 	.pd = { .name = "ssc_mx", },
614 	.res_type = RPMPD_RWSM,
615 	.res_id = 0,
616 	.key = KEY_LEVEL,
617 };
618 
619 static struct rpmpd ssc_mx_rwlm0_vfl = {
620 	.pd = { .name = "ssc_mx_vfl", },
621 	.res_type = RPMPD_RWLM,
622 	.res_id = 0,
623 	.key = KEY_FLOOR_LEVEL,
624 };
625 
626 static struct rpmpd ssc_mx_rwsm0_vfl = {
627 	.pd = { .name = "ssc_mx_vfl", },
628 	.res_type = RPMPD_RWSM,
629 	.res_id = 0,
630 	.key = KEY_FLOOR_LEVEL,
631 };
632 
633 static struct rpmpd *mdm9607_rpmpds[] = {
634 	[RPMPD_VDDCX] =		&cx_s3a_lvl,
635 	[RPMPD_VDDCX_AO] =	&cx_s3a_lvl_ao,
636 	[RPMPD_VDDCX_VFL] =	&cx_s3a_vfl,
637 	[RPMPD_VDDMX] =		&mx_l12a_lvl,
638 	[RPMPD_VDDMX_AO] =	&mx_l12a_lvl_ao,
639 	[RPMPD_VDDMX_VFL] =	&mx_l12a_vfl,
640 };
641 
642 static const struct rpmpd_desc mdm9607_desc = {
643 	.rpmpds = mdm9607_rpmpds,
644 	.num_pds = ARRAY_SIZE(mdm9607_rpmpds),
645 	.max_state = RPM_SMD_LEVEL_TURBO,
646 };
647 
648 static struct rpmpd *msm8226_rpmpds[] = {
649 	[RPMPD_VDDCX] =		&cx_s1a_corner,
650 	[RPMPD_VDDCX_AO] =	&cx_s1a_corner_ao,
651 	[RPMPD_VDDCX_VFC] =	&cx_s1a_vfc,
652 };
653 
654 static const struct rpmpd_desc msm8226_desc = {
655 	.rpmpds = msm8226_rpmpds,
656 	.num_pds = ARRAY_SIZE(msm8226_rpmpds),
657 	.max_state = MAX_CORNER_RPMPD_STATE,
658 };
659 
660 static struct rpmpd *msm8939_rpmpds[] = {
661 	[MSM8939_VDDMDCX] =	&md_s1a_corner,
662 	[MSM8939_VDDMDCX_AO] =	&md_s1a_corner_ao,
663 	[MSM8939_VDDMDCX_VFC] =	&md_s1a_vfc,
664 	[MSM8939_VDDCX] =	&cx_s2a_corner,
665 	[MSM8939_VDDCX_AO] =	&cx_s2a_corner_ao,
666 	[MSM8939_VDDCX_VFC] =	&cx_s2a_vfc,
667 	[MSM8939_VDDMX] =	&mx_l3a_corner,
668 	[MSM8939_VDDMX_AO] =	&mx_l3a_corner_ao,
669 };
670 
671 static const struct rpmpd_desc msm8939_desc = {
672 	.rpmpds = msm8939_rpmpds,
673 	.num_pds = ARRAY_SIZE(msm8939_rpmpds),
674 	.max_state = MAX_CORNER_RPMPD_STATE,
675 };
676 
677 static struct rpmpd *msm8916_rpmpds[] = {
678 	[RPMPD_VDDCX] =		&cx_s1a_corner,
679 	[RPMPD_VDDCX_AO] =	&cx_s1a_corner_ao,
680 	[RPMPD_VDDCX_VFC] =	&cx_s1a_vfc,
681 	[RPMPD_VDDMX] =		&mx_l3a_corner,
682 	[RPMPD_VDDMX_AO] =	&mx_l3a_corner_ao,
683 };
684 
685 static const struct rpmpd_desc msm8916_desc = {
686 	.rpmpds = msm8916_rpmpds,
687 	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
688 	.max_state = MAX_CORNER_RPMPD_STATE,
689 };
690 
691 static struct rpmpd *msm8917_rpmpds[] = {
692 	[RPMPD_VDDCX] =		&cx_s2a_lvl,
693 	[RPMPD_VDDCX_AO] =	&cx_s2a_lvl_ao,
694 	[RPMPD_VDDCX_VFL] =	&cx_s2a_vfl,
695 	[RPMPD_VDDMX] =		&mx_l3a_lvl,
696 	[RPMPD_VDDMX_AO] =	&mx_l3a_lvl_ao,
697 };
698 
699 static const struct rpmpd_desc msm8917_desc = {
700 	.rpmpds = msm8917_rpmpds,
701 	.num_pds = ARRAY_SIZE(msm8917_rpmpds),
702 	.max_state = RPM_SMD_LEVEL_TURBO,
703 };
704 
705 static struct rpmpd *msm8953_rpmpds[] = {
706 	[MSM8953_VDDMD] =	&md_s1a_lvl,
707 	[MSM8953_VDDMD_AO] =	&md_s1a_lvl_ao,
708 	[MSM8953_VDDCX] =	&cx_s2a_lvl,
709 	[MSM8953_VDDCX_AO] =	&cx_s2a_lvl_ao,
710 	[MSM8953_VDDCX_VFL] =	&cx_s2a_vfl,
711 	[MSM8953_VDDMX] =	&mx_s7a_lvl,
712 	[MSM8953_VDDMX_AO] =	&mx_s7a_lvl_ao,
713 };
714 
715 static const struct rpmpd_desc msm8953_desc = {
716 	.rpmpds = msm8953_rpmpds,
717 	.num_pds = ARRAY_SIZE(msm8953_rpmpds),
718 	.max_state = RPM_SMD_LEVEL_TURBO,
719 };
720 
721 static struct rpmpd *msm8974_rpmpds[] = {
722 	[MSM8974_VDDCX] =	&cx_s2b_corner,
723 	[MSM8974_VDDCX_AO] =	&cx_s2b_corner_ao,
724 	[MSM8974_VDDCX_VFC] =	&cx_s2b_vfc,
725 	[MSM8974_VDDGFX] =	&gfx_s4b_corner,
726 	[MSM8974_VDDGFX_VFC] =	&gfx_s4b_vfc,
727 };
728 
729 static const struct rpmpd_desc msm8974_desc = {
730 	.rpmpds = msm8974_rpmpds,
731 	.num_pds = ARRAY_SIZE(msm8974_rpmpds),
732 	.max_state = MAX_CORNER_RPMPD_STATE,
733 };
734 
735 static struct rpmpd *msm8974pro_pma8084_rpmpds[] = {
736 	[MSM8974_VDDCX] =	&cx_s2a_corner,
737 	[MSM8974_VDDCX_AO] =	&cx_s2a_corner_ao,
738 	[MSM8974_VDDCX_VFC] =	&cx_s2a_vfc,
739 	[MSM8974_VDDGFX] =	&gfx_s7a_corner,
740 	[MSM8974_VDDGFX_VFC] =	&gfx_s7a_vfc,
741 };
742 
743 static const struct rpmpd_desc msm8974pro_pma8084_desc = {
744 	.rpmpds = msm8974pro_pma8084_rpmpds,
745 	.num_pds = ARRAY_SIZE(msm8974pro_pma8084_rpmpds),
746 	.max_state = MAX_CORNER_RPMPD_STATE,
747 };
748 
749 static struct rpmpd *msm8976_rpmpds[] = {
750 	[RPMPD_VDDCX] =		&cx_s2a_lvl,
751 	[RPMPD_VDDCX_AO] =	&cx_s2a_lvl_ao,
752 	[RPMPD_VDDCX_VFL] =	&cx_rwsc2_vfl,
753 	[RPMPD_VDDMX] =		&mx_s6a_lvl,
754 	[RPMPD_VDDMX_AO] =	&mx_s6a_lvl_ao,
755 	[RPMPD_VDDMX_VFL] =	&mx_rwsm6_vfl,
756 };
757 
758 static const struct rpmpd_desc msm8976_desc = {
759 	.rpmpds = msm8976_rpmpds,
760 	.num_pds = ARRAY_SIZE(msm8976_rpmpds),
761 	.max_state = RPM_SMD_LEVEL_TURBO_HIGH,
762 };
763 
764 static struct rpmpd *msm8994_rpmpds[] = {
765 	[MSM8994_VDDCX] =	&cx_s1a_corner,
766 	[MSM8994_VDDCX_AO] =	&cx_s1a_corner_ao,
767 	[MSM8994_VDDCX_VFC] =	&cx_s1a_vfc,
768 	[MSM8994_VDDMX] =	&mx_s2a_corner,
769 	[MSM8994_VDDMX_AO] =	&mx_s2a_corner_ao,
770 
771 	/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
772 	[MSM8994_VDDGFX] =	&gfx_s2b_corner,
773 	[MSM8994_VDDGFX_VFC] =	&gfx_s2b_vfc,
774 };
775 
776 static const struct rpmpd_desc msm8994_desc = {
777 	.rpmpds = msm8994_rpmpds,
778 	.num_pds = ARRAY_SIZE(msm8994_rpmpds),
779 	.max_state = MAX_CORNER_RPMPD_STATE,
780 };
781 
782 static struct rpmpd *msm8996_rpmpds[] = {
783 	[MSM8996_VDDCX] =	&cx_s1a_corner,
784 	[MSM8996_VDDCX_AO] =	&cx_s1a_corner_ao,
785 	[MSM8996_VDDCX_VFC] =	&cx_s1a_vfc,
786 	[MSM8996_VDDMX] =	&mx_s2a_corner,
787 	[MSM8996_VDDMX_AO] =	&mx_s2a_corner_ao,
788 	[MSM8996_VDDSSCX] =	&ssc_cx_l26a_corner,
789 	[MSM8996_VDDSSCX_VFC] =	&ssc_cx_l26a_vfc,
790 };
791 
792 static const struct rpmpd_desc msm8996_desc = {
793 	.rpmpds = msm8996_rpmpds,
794 	.num_pds = ARRAY_SIZE(msm8996_rpmpds),
795 	.max_state = MAX_CORNER_RPMPD_STATE,
796 };
797 
798 static struct rpmpd *msm8998_rpmpds[] = {
799 	[RPMPD_VDDCX] =		&cx_rwcx0_lvl,
800 	[RPMPD_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
801 	[RPMPD_VDDCX_VFL] =	&cx_rwcx0_vfl,
802 	[RPMPD_VDDMX] =		&mx_rwmx0_lvl,
803 	[RPMPD_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
804 	[RPMPD_VDDMX_VFL] =	&mx_rwmx0_vfl,
805 	[RPMPD_SSCCX] =		&ssc_cx_rwsc0_lvl,
806 	[RPMPD_SSCCX_VFL] =	&ssc_cx_rwsc0_vfl,
807 	[RPMPD_SSCMX] =		&ssc_mx_rwsm0_lvl,
808 	[RPMPD_SSCMX_VFL] =	&ssc_mx_rwsm0_vfl,
809 };
810 
811 static const struct rpmpd_desc msm8998_desc = {
812 	.rpmpds = msm8998_rpmpds,
813 	.num_pds = ARRAY_SIZE(msm8998_rpmpds),
814 	.max_state = RPM_SMD_LEVEL_BINNING,
815 };
816 
817 static struct rpmpd *qcs404_rpmpds[] = {
818 	[QCS404_VDDMX] =	&mx_rwmx0_lvl,
819 	[QCS404_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
820 	[QCS404_VDDMX_VFL] =	&mx_rwmx0_vfl,
821 	[QCS404_LPICX] =	&lpi_cx_rwlc0_lvl,
822 	[QCS404_LPICX_VFL] =	&lpi_cx_rwlc0_vfl,
823 	[QCS404_LPIMX] =	&lpi_mx_rwlm0_lvl,
824 	[QCS404_LPIMX_VFL] =	&lpi_mx_rwlm0_vfl,
825 };
826 
827 static const struct rpmpd_desc qcs404_desc = {
828 	.rpmpds = qcs404_rpmpds,
829 	.num_pds = ARRAY_SIZE(qcs404_rpmpds),
830 	.max_state = RPM_SMD_LEVEL_BINNING,
831 };
832 
833 static struct rpmpd *qm215_rpmpds[] = {
834 	[RPMPD_VDDCX] =		&cx_s1a_lvl,
835 	[RPMPD_VDDCX_AO] =	&cx_s1a_lvl_ao,
836 	[RPMPD_VDDCX_VFL] =	&cx_s1a_vfl,
837 	[RPMPD_VDDMX] =		&mx_l2a_lvl,
838 	[RPMPD_VDDMX_AO] =	&mx_l2a_lvl_ao,
839 };
840 
841 static const struct rpmpd_desc qm215_desc = {
842 	.rpmpds = qm215_rpmpds,
843 	.num_pds = ARRAY_SIZE(qm215_rpmpds),
844 	.max_state = RPM_SMD_LEVEL_TURBO,
845 };
846 
847 static struct rpmpd *sdm660_rpmpds[] = {
848 	[RPMPD_VDDCX] =		&cx_rwcx0_lvl,
849 	[RPMPD_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
850 	[RPMPD_VDDCX_VFL] =	&cx_rwcx0_vfl,
851 	[RPMPD_VDDMX] =		&mx_rwmx0_lvl,
852 	[RPMPD_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
853 	[RPMPD_VDDMX_VFL] =	&mx_rwmx0_vfl,
854 	[RPMPD_SSCCX] =		&ssc_cx_rwlc0_lvl,
855 	[RPMPD_SSCCX_VFL] =	&ssc_cx_rwlc0_vfl,
856 	[RPMPD_SSCMX] =		&ssc_mx_rwlm0_lvl,
857 	[RPMPD_SSCMX_VFL] =	&ssc_mx_rwlm0_vfl,
858 };
859 
860 static const struct rpmpd_desc sdm660_desc = {
861 	.rpmpds = sdm660_rpmpds,
862 	.num_pds = ARRAY_SIZE(sdm660_rpmpds),
863 	.max_state = RPM_SMD_LEVEL_TURBO,
864 };
865 
866 static struct rpmpd *sm6115_rpmpds[] = {
867 	[SM6115_VDDCX] =	&cx_rwcx0_lvl,
868 	[SM6115_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
869 	[SM6115_VDDCX_VFL] =	&cx_rwcx0_vfl,
870 	[SM6115_VDDMX] =	&mx_rwmx0_lvl,
871 	[SM6115_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
872 	[SM6115_VDDMX_VFL] =	&mx_rwmx0_vfl,
873 	[SM6115_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
874 	[SM6115_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
875 };
876 
877 static const struct rpmpd_desc sm6115_desc = {
878 	.rpmpds = sm6115_rpmpds,
879 	.num_pds = ARRAY_SIZE(sm6115_rpmpds),
880 	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
881 };
882 
883 static struct rpmpd *sm6125_rpmpds[] = {
884 	[RPMPD_VDDCX] =		&cx_rwcx0_lvl,
885 	[RPMPD_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
886 	[RPMPD_VDDCX_VFL] =	&cx_rwcx0_vfl,
887 	[RPMPD_VDDMX] =		&mx_rwmx0_lvl,
888 	[RPMPD_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
889 	[RPMPD_VDDMX_VFL] =	&mx_rwmx0_vfl,
890 };
891 
892 static const struct rpmpd_desc sm6125_desc = {
893 	.rpmpds = sm6125_rpmpds,
894 	.num_pds = ARRAY_SIZE(sm6125_rpmpds),
895 	.max_state = RPM_SMD_LEVEL_BINNING,
896 };
897 
898 static const struct rpmpd_desc shikra_desc = {
899 	.rpmpds = sm6125_rpmpds,
900 	.num_pds = ARRAY_SIZE(sm6125_rpmpds),
901 	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
902 };
903 
904 static struct rpmpd *sm6375_rpmpds[] = {
905 	[SM6375_VDDCX] =	&cx_rwcx0_lvl,
906 	[SM6375_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
907 	[SM6375_VDDCX_VFL] =	&cx_rwcx0_vfl,
908 	[SM6375_VDDMX] =	&mx_rwmx0_lvl,
909 	[SM6375_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
910 	[SM6375_VDDMX_VFL] =	&mx_rwmx0_vfl,
911 	[SM6375_VDDGX] =	&gx_rwgx0_lvl,
912 	[SM6375_VDDGX_AO] =	&gx_rwgx0_lvl_ao,
913 	[SM6375_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
914 	[SM6375_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
915 };
916 
917 static const struct rpmpd_desc sm6375_desc = {
918 	.rpmpds = sm6375_rpmpds,
919 	.num_pds = ARRAY_SIZE(sm6375_rpmpds),
920 	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
921 };
922 
923 static struct rpmpd *qcm2290_rpmpds[] = {
924 	[QCM2290_VDDCX] =	&cx_rwcx0_lvl,
925 	[QCM2290_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
926 	[QCM2290_VDDCX_VFL] =	&cx_rwcx0_vfl,
927 	[QCM2290_VDDMX] =	&mx_rwmx0_lvl,
928 	[QCM2290_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
929 	[QCM2290_VDDMX_VFL] =	&mx_rwmx0_vfl,
930 	[QCM2290_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
931 	[QCM2290_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
932 };
933 
934 static const struct rpmpd_desc qcm2290_desc = {
935 	.rpmpds = qcm2290_rpmpds,
936 	.num_pds = ARRAY_SIZE(qcm2290_rpmpds),
937 	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
938 };
939 
940 static const struct of_device_id rpmpd_match_table[] = {
941 	{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
942 	{ .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
943 	{ .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
944 	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
945 	{ .compatible = "qcom,msm8917-rpmpd", .data = &msm8917_desc },
946 	{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
947 	{ .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
948 	{ .compatible = "qcom,msm8974-rpmpd", .data = &msm8974_desc },
949 	{ .compatible = "qcom,msm8974pro-pma8084-rpmpd", .data = &msm8974pro_pma8084_desc },
950 	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
951 	{ .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
952 	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
953 	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
954 	{ .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
955 	{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
956 	{ .compatible = "qcom,qm215-rpmpd", .data = &qm215_desc },
957 	{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
958 	{ .compatible = "qcom,shikra-rpmpd", .data = &shikra_desc },
959 	{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
960 	{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
961 	{ .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
962 	{ }
963 };
964 MODULE_DEVICE_TABLE(of, rpmpd_match_table);
965 
966 static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
967 {
968 	struct rpmpd_req req = {
969 		.key = KEY_ENABLE,
970 		.nbytes = cpu_to_le32(sizeof(u32)),
971 		.value = cpu_to_le32(enable),
972 	};
973 
974 	return qcom_rpm_smd_write(rpmpd_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE,
975 				  pd->res_type, pd->res_id, &req, sizeof(req));
976 }
977 
978 static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
979 {
980 	struct rpmpd_req req = {
981 		.key = pd->key,
982 		.nbytes = cpu_to_le32(sizeof(u32)),
983 		.value = cpu_to_le32(corner),
984 	};
985 
986 	return qcom_rpm_smd_write(rpmpd_smd_rpm, state, pd->res_type, pd->res_id,
987 				  &req, sizeof(req));
988 }
989 
990 static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
991 			    unsigned int *active, unsigned int *sleep)
992 {
993 	*active = corner;
994 
995 	if (pd->active_only)
996 		*sleep = 0;
997 	else
998 		*sleep = *active;
999 }
1000 
1001 static int rpmpd_aggregate_corner(struct rpmpd *pd)
1002 {
1003 	int ret;
1004 	struct rpmpd *peer = pd->peer;
1005 	unsigned int active_corner, sleep_corner;
1006 	unsigned int this_active_corner = 0, this_sleep_corner = 0;
1007 	unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
1008 
1009 	/* Clamp to the highest corner/level if sync_state isn't done yet */
1010 	if (!pd->state_synced)
1011 		this_active_corner = this_sleep_corner = pd->max_state;
1012 	else
1013 		to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
1014 
1015 	if (peer && peer->enabled)
1016 		to_active_sleep(peer, peer->corner, &peer_active_corner,
1017 				&peer_sleep_corner);
1018 
1019 	active_corner = max(this_active_corner, peer_active_corner);
1020 
1021 	ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
1022 	if (ret)
1023 		return ret;
1024 
1025 	sleep_corner = max(this_sleep_corner, peer_sleep_corner);
1026 
1027 	return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
1028 }
1029 
1030 static int rpmpd_power_on(struct generic_pm_domain *domain)
1031 {
1032 	int ret;
1033 	struct rpmpd *pd = domain_to_rpmpd(domain);
1034 
1035 	guard(mutex)(&rpmpd_lock);
1036 
1037 	ret = rpmpd_send_enable(pd, true);
1038 	if (ret)
1039 		return ret;
1040 
1041 	pd->enabled = true;
1042 
1043 	if (pd->corner)
1044 		ret = rpmpd_aggregate_corner(pd);
1045 
1046 	return ret;
1047 }
1048 
1049 static int rpmpd_power_off(struct generic_pm_domain *domain)
1050 {
1051 	int ret;
1052 	struct rpmpd *pd = domain_to_rpmpd(domain);
1053 
1054 	mutex_lock(&rpmpd_lock);
1055 
1056 	ret = rpmpd_send_enable(pd, false);
1057 	if (!ret)
1058 		pd->enabled = false;
1059 
1060 	mutex_unlock(&rpmpd_lock);
1061 
1062 	return ret;
1063 }
1064 
1065 static int rpmpd_set_performance(struct generic_pm_domain *domain,
1066 				 unsigned int state)
1067 {
1068 	struct rpmpd *pd = domain_to_rpmpd(domain);
1069 
1070 	if (state > pd->max_state)
1071 		state = pd->max_state;
1072 
1073 	guard(mutex)(&rpmpd_lock);
1074 
1075 	pd->corner = state;
1076 
1077 	/* Always send updates for vfc and vfl */
1078 	if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
1079 	    pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
1080 		return 0;
1081 
1082 	return rpmpd_aggregate_corner(pd);
1083 }
1084 
1085 static int rpmpd_probe(struct platform_device *pdev)
1086 {
1087 	int i;
1088 	size_t num;
1089 	struct genpd_onecell_data *data;
1090 	struct rpmpd **rpmpds;
1091 	const struct rpmpd_desc *desc;
1092 
1093 	rpmpd_smd_rpm = dev_get_drvdata(pdev->dev.parent);
1094 	if (!rpmpd_smd_rpm) {
1095 		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
1096 		return -ENODEV;
1097 	}
1098 
1099 	desc = of_device_get_match_data(&pdev->dev);
1100 	if (!desc)
1101 		return -EINVAL;
1102 
1103 	rpmpds = desc->rpmpds;
1104 	num = desc->num_pds;
1105 
1106 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
1107 	if (!data)
1108 		return -ENOMEM;
1109 
1110 	data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
1111 				     GFP_KERNEL);
1112 	if (!data->domains)
1113 		return -ENOMEM;
1114 
1115 	data->num_domains = num;
1116 
1117 	for (i = 0; i < num; i++) {
1118 		if (!rpmpds[i]) {
1119 			dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
1120 				 i);
1121 			continue;
1122 		}
1123 
1124 		rpmpds[i]->max_state = desc->max_state;
1125 		rpmpds[i]->pd.power_off = rpmpd_power_off;
1126 		rpmpds[i]->pd.power_on = rpmpd_power_on;
1127 		rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
1128 		rpmpds[i]->pd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
1129 		pm_genpd_init(&rpmpds[i]->pd, NULL, true);
1130 
1131 		data->domains[i] = &rpmpds[i]->pd;
1132 	}
1133 
1134 	/* Add subdomains */
1135 	for (i = 0; i < num; i++) {
1136 		if (!rpmpds[i])
1137 			continue;
1138 
1139 		if (rpmpds[i]->parent)
1140 			pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
1141 	}
1142 
1143 	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
1144 }
1145 
1146 static void rpmpd_sync_state(struct device *dev)
1147 {
1148 	const struct rpmpd_desc *desc = of_device_get_match_data(dev);
1149 	struct rpmpd **rpmpds = desc->rpmpds;
1150 	struct rpmpd *pd;
1151 	unsigned int i;
1152 	int ret;
1153 
1154 	of_genpd_sync_state(dev->of_node);
1155 
1156 	mutex_lock(&rpmpd_lock);
1157 	for (i = 0; i < desc->num_pds; i++) {
1158 		pd = rpmpds[i];
1159 		if (!pd)
1160 			continue;
1161 
1162 		pd->state_synced = true;
1163 
1164 		if (!pd->enabled)
1165 			pd->corner = 0;
1166 
1167 		ret = rpmpd_aggregate_corner(pd);
1168 		if (ret)
1169 			dev_err(dev, "failed to sync %s: %d\n", pd->pd.name, ret);
1170 	}
1171 	mutex_unlock(&rpmpd_lock);
1172 }
1173 
1174 static struct platform_driver rpmpd_driver = {
1175 	.driver = {
1176 		.name = "qcom-rpmpd",
1177 		.of_match_table = rpmpd_match_table,
1178 		.suppress_bind_attrs = true,
1179 		.sync_state = rpmpd_sync_state,
1180 	},
1181 	.probe = rpmpd_probe,
1182 };
1183 
1184 static int __init rpmpd_init(void)
1185 {
1186 	return platform_driver_register(&rpmpd_driver);
1187 }
1188 core_initcall(rpmpd_init);
1189 
1190 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
1191 MODULE_LICENSE("GPL v2");
1192