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 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 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 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 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 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 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 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 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 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 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