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