xref: /linux/drivers/pmdomain/qcom/rpmpd.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
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 	[MDM9607_VDDCX] =	&cx_s3a_lvl,
635 	[MDM9607_VDDCX_AO] =	&cx_s3a_lvl_ao,
636 	[MDM9607_VDDCX_VFL] =	&cx_s3a_vfl,
637 	[MDM9607_VDDMX] =	&mx_l12a_lvl,
638 	[MDM9607_VDDMX_AO] =	&mx_l12a_lvl_ao,
639 	[MDM9607_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 	[MSM8226_VDDCX] =	&cx_s1a_corner,
650 	[MSM8226_VDDCX_AO] =	&cx_s1a_corner_ao,
651 	[MSM8226_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 	[MSM8916_VDDCX] =	&cx_s1a_corner,
679 	[MSM8916_VDDCX_AO] =	&cx_s1a_corner_ao,
680 	[MSM8916_VDDCX_VFC] =	&cx_s1a_vfc,
681 	[MSM8916_VDDMX] =	&mx_l3a_corner,
682 	[MSM8916_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 	[MSM8917_VDDCX] =	&cx_s2a_lvl,
693 	[MSM8917_VDDCX_AO] =	&cx_s2a_lvl_ao,
694 	[MSM8917_VDDCX_VFL] =	&cx_s2a_vfl,
695 	[MSM8917_VDDMX] =	&mx_l3a_lvl,
696 	[MSM8917_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 	[MSM8976_VDDCX] =	&cx_s2a_lvl,
751 	[MSM8976_VDDCX_AO] =	&cx_s2a_lvl_ao,
752 	[MSM8976_VDDCX_VFL] =	&cx_rwsc2_vfl,
753 	[MSM8976_VDDMX] =	&mx_s6a_lvl,
754 	[MSM8976_VDDMX_AO] =	&mx_s6a_lvl_ao,
755 	[MSM8976_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 	[MSM8998_VDDCX] =	&cx_rwcx0_lvl,
800 	[MSM8998_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
801 	[MSM8998_VDDCX_VFL] =	&cx_rwcx0_vfl,
802 	[MSM8998_VDDMX] =	&mx_rwmx0_lvl,
803 	[MSM8998_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
804 	[MSM8998_VDDMX_VFL] =	&mx_rwmx0_vfl,
805 	[MSM8998_SSCCX] =	&ssc_cx_rwsc0_lvl,
806 	[MSM8998_SSCCX_VFL] =	&ssc_cx_rwsc0_vfl,
807 	[MSM8998_SSCMX] =	&ssc_mx_rwsm0_lvl,
808 	[MSM8998_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 	[QM215_VDDCX] =		&cx_s1a_lvl,
835 	[QM215_VDDCX_AO] =	&cx_s1a_lvl_ao,
836 	[QM215_VDDCX_VFL] =	&cx_s1a_vfl,
837 	[QM215_VDDMX] =		&mx_l2a_lvl,
838 	[QM215_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 	[SDM660_VDDCX] =	&cx_rwcx0_lvl,
849 	[SDM660_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
850 	[SDM660_VDDCX_VFL] =	&cx_rwcx0_vfl,
851 	[SDM660_VDDMX] =	&mx_rwmx0_lvl,
852 	[SDM660_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
853 	[SDM660_VDDMX_VFL] =	&mx_rwmx0_vfl,
854 	[SDM660_SSCCX] =	&ssc_cx_rwlc0_lvl,
855 	[SDM660_SSCCX_VFL] =	&ssc_cx_rwlc0_vfl,
856 	[SDM660_SSCMX] =	&ssc_mx_rwlm0_lvl,
857 	[SDM660_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 	[SM6125_VDDCX] =	&cx_rwcx0_lvl,
885 	[SM6125_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
886 	[SM6125_VDDCX_VFL] =	&cx_rwcx0_vfl,
887 	[SM6125_VDDMX] =	&mx_rwmx0_lvl,
888 	[SM6125_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
889 	[SM6125_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 struct rpmpd *sm6375_rpmpds[] = {
899 	[SM6375_VDDCX] =	&cx_rwcx0_lvl,
900 	[SM6375_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
901 	[SM6375_VDDCX_VFL] =	&cx_rwcx0_vfl,
902 	[SM6375_VDDMX] =	&mx_rwmx0_lvl,
903 	[SM6375_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
904 	[SM6375_VDDMX_VFL] =	&mx_rwmx0_vfl,
905 	[SM6375_VDDGX] =	&gx_rwgx0_lvl,
906 	[SM6375_VDDGX_AO] =	&gx_rwgx0_lvl_ao,
907 	[SM6375_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
908 	[SM6375_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
909 };
910 
911 static const struct rpmpd_desc sm6375_desc = {
912 	.rpmpds = sm6375_rpmpds,
913 	.num_pds = ARRAY_SIZE(sm6375_rpmpds),
914 	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
915 };
916 
917 static struct rpmpd *qcm2290_rpmpds[] = {
918 	[QCM2290_VDDCX] =	&cx_rwcx0_lvl,
919 	[QCM2290_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
920 	[QCM2290_VDDCX_VFL] =	&cx_rwcx0_vfl,
921 	[QCM2290_VDDMX] =	&mx_rwmx0_lvl,
922 	[QCM2290_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
923 	[QCM2290_VDDMX_VFL] =	&mx_rwmx0_vfl,
924 	[QCM2290_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
925 	[QCM2290_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
926 };
927 
928 static const struct rpmpd_desc qcm2290_desc = {
929 	.rpmpds = qcm2290_rpmpds,
930 	.num_pds = ARRAY_SIZE(qcm2290_rpmpds),
931 	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
932 };
933 
934 static const struct of_device_id rpmpd_match_table[] = {
935 	{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
936 	{ .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
937 	{ .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
938 	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
939 	{ .compatible = "qcom,msm8917-rpmpd", .data = &msm8917_desc },
940 	{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
941 	{ .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
942 	{ .compatible = "qcom,msm8974-rpmpd", .data = &msm8974_desc },
943 	{ .compatible = "qcom,msm8974pro-pma8084-rpmpd", .data = &msm8974pro_pma8084_desc },
944 	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
945 	{ .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
946 	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
947 	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
948 	{ .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
949 	{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
950 	{ .compatible = "qcom,qm215-rpmpd", .data = &qm215_desc },
951 	{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
952 	{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
953 	{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
954 	{ .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
955 	{ }
956 };
957 MODULE_DEVICE_TABLE(of, rpmpd_match_table);
958 
rpmpd_send_enable(struct rpmpd * pd,bool enable)959 static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
960 {
961 	struct rpmpd_req req = {
962 		.key = KEY_ENABLE,
963 		.nbytes = cpu_to_le32(sizeof(u32)),
964 		.value = cpu_to_le32(enable),
965 	};
966 
967 	return qcom_rpm_smd_write(rpmpd_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE,
968 				  pd->res_type, pd->res_id, &req, sizeof(req));
969 }
970 
rpmpd_send_corner(struct rpmpd * pd,int state,unsigned int corner)971 static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
972 {
973 	struct rpmpd_req req = {
974 		.key = pd->key,
975 		.nbytes = cpu_to_le32(sizeof(u32)),
976 		.value = cpu_to_le32(corner),
977 	};
978 
979 	return qcom_rpm_smd_write(rpmpd_smd_rpm, state, pd->res_type, pd->res_id,
980 				  &req, sizeof(req));
981 };
982 
to_active_sleep(struct rpmpd * pd,unsigned int corner,unsigned int * active,unsigned int * sleep)983 static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
984 			    unsigned int *active, unsigned int *sleep)
985 {
986 	*active = corner;
987 
988 	if (pd->active_only)
989 		*sleep = 0;
990 	else
991 		*sleep = *active;
992 }
993 
rpmpd_aggregate_corner(struct rpmpd * pd)994 static int rpmpd_aggregate_corner(struct rpmpd *pd)
995 {
996 	int ret;
997 	struct rpmpd *peer = pd->peer;
998 	unsigned int active_corner, sleep_corner;
999 	unsigned int this_active_corner = 0, this_sleep_corner = 0;
1000 	unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
1001 
1002 	/* Clamp to the highest corner/level if sync_state isn't done yet */
1003 	if (!pd->state_synced)
1004 		this_active_corner = this_sleep_corner = pd->max_state - 1;
1005 	else
1006 		to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
1007 
1008 	if (peer && peer->enabled)
1009 		to_active_sleep(peer, peer->corner, &peer_active_corner,
1010 				&peer_sleep_corner);
1011 
1012 	active_corner = max(this_active_corner, peer_active_corner);
1013 
1014 	ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
1015 	if (ret)
1016 		return ret;
1017 
1018 	sleep_corner = max(this_sleep_corner, peer_sleep_corner);
1019 
1020 	return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
1021 }
1022 
rpmpd_power_on(struct generic_pm_domain * domain)1023 static int rpmpd_power_on(struct generic_pm_domain *domain)
1024 {
1025 	int ret;
1026 	struct rpmpd *pd = domain_to_rpmpd(domain);
1027 
1028 	guard(mutex)(&rpmpd_lock);
1029 
1030 	ret = rpmpd_send_enable(pd, true);
1031 	if (ret)
1032 		return ret;
1033 
1034 	pd->enabled = true;
1035 
1036 	if (pd->corner)
1037 		ret = rpmpd_aggregate_corner(pd);
1038 
1039 	return ret;
1040 }
1041 
rpmpd_power_off(struct generic_pm_domain * domain)1042 static int rpmpd_power_off(struct generic_pm_domain *domain)
1043 {
1044 	int ret;
1045 	struct rpmpd *pd = domain_to_rpmpd(domain);
1046 
1047 	mutex_lock(&rpmpd_lock);
1048 
1049 	ret = rpmpd_send_enable(pd, false);
1050 	if (!ret)
1051 		pd->enabled = false;
1052 
1053 	mutex_unlock(&rpmpd_lock);
1054 
1055 	return ret;
1056 }
1057 
rpmpd_set_performance(struct generic_pm_domain * domain,unsigned int state)1058 static int rpmpd_set_performance(struct generic_pm_domain *domain,
1059 				 unsigned int state)
1060 {
1061 	struct rpmpd *pd = domain_to_rpmpd(domain);
1062 
1063 	if (state > pd->max_state)
1064 		state = pd->max_state;
1065 
1066 	guard(mutex)(&rpmpd_lock);
1067 
1068 	pd->corner = state;
1069 
1070 	/* Always send updates for vfc and vfl */
1071 	if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
1072 	    pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
1073 		return 0;
1074 
1075 	return rpmpd_aggregate_corner(pd);
1076 }
1077 
rpmpd_probe(struct platform_device * pdev)1078 static int rpmpd_probe(struct platform_device *pdev)
1079 {
1080 	int i;
1081 	size_t num;
1082 	struct genpd_onecell_data *data;
1083 	struct rpmpd **rpmpds;
1084 	const struct rpmpd_desc *desc;
1085 
1086 	rpmpd_smd_rpm = dev_get_drvdata(pdev->dev.parent);
1087 	if (!rpmpd_smd_rpm) {
1088 		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
1089 		return -ENODEV;
1090 	}
1091 
1092 	desc = of_device_get_match_data(&pdev->dev);
1093 	if (!desc)
1094 		return -EINVAL;
1095 
1096 	rpmpds = desc->rpmpds;
1097 	num = desc->num_pds;
1098 
1099 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
1100 	if (!data)
1101 		return -ENOMEM;
1102 
1103 	data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
1104 				     GFP_KERNEL);
1105 	if (!data->domains)
1106 		return -ENOMEM;
1107 
1108 	data->num_domains = num;
1109 
1110 	for (i = 0; i < num; i++) {
1111 		if (!rpmpds[i]) {
1112 			dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
1113 				 i);
1114 			continue;
1115 		}
1116 
1117 		rpmpds[i]->max_state = desc->max_state;
1118 		rpmpds[i]->pd.power_off = rpmpd_power_off;
1119 		rpmpds[i]->pd.power_on = rpmpd_power_on;
1120 		rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
1121 		rpmpds[i]->pd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
1122 		pm_genpd_init(&rpmpds[i]->pd, NULL, true);
1123 
1124 		data->domains[i] = &rpmpds[i]->pd;
1125 	}
1126 
1127 	/* Add subdomains */
1128 	for (i = 0; i < num; i++) {
1129 		if (!rpmpds[i])
1130 			continue;
1131 
1132 		if (rpmpds[i]->parent)
1133 			pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
1134 	}
1135 
1136 	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
1137 }
1138 
rpmpd_sync_state(struct device * dev)1139 static void rpmpd_sync_state(struct device *dev)
1140 {
1141 	const struct rpmpd_desc *desc = of_device_get_match_data(dev);
1142 	struct rpmpd **rpmpds = desc->rpmpds;
1143 	struct rpmpd *pd;
1144 	unsigned int i;
1145 	int ret;
1146 
1147 	mutex_lock(&rpmpd_lock);
1148 	for (i = 0; i < desc->num_pds; i++) {
1149 		pd = rpmpds[i];
1150 		if (!pd)
1151 			continue;
1152 
1153 		pd->state_synced = true;
1154 
1155 		if (!pd->enabled)
1156 			pd->corner = 0;
1157 
1158 		ret = rpmpd_aggregate_corner(pd);
1159 		if (ret)
1160 			dev_err(dev, "failed to sync %s: %d\n", pd->pd.name, ret);
1161 	}
1162 	mutex_unlock(&rpmpd_lock);
1163 }
1164 
1165 static struct platform_driver rpmpd_driver = {
1166 	.driver = {
1167 		.name = "qcom-rpmpd",
1168 		.of_match_table = rpmpd_match_table,
1169 		.suppress_bind_attrs = true,
1170 		.sync_state = rpmpd_sync_state,
1171 	},
1172 	.probe = rpmpd_probe,
1173 };
1174 
rpmpd_init(void)1175 static int __init rpmpd_init(void)
1176 {
1177 	return platform_driver_register(&rpmpd_driver);
1178 }
1179 core_initcall(rpmpd_init);
1180 
1181 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
1182 MODULE_LICENSE("GPL v2");
1183