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