Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.16-rc1 612 lines 17 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */ 3 4#include <linux/err.h> 5#include <linux/init.h> 6#include <linux/kernel.h> 7#include <linux/module.h> 8#include <linux/mutex.h> 9#include <linux/pm_domain.h> 10#include <linux/of.h> 11#include <linux/of_device.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/* Resource types: 21 * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */ 22#define RPMPD_SMPA 0x61706d73 23#define RPMPD_LDOA 0x616f646c 24#define RPMPD_SMPB 0x62706d73 25#define RPMPD_LDOB 0x626f646c 26#define RPMPD_RWCX 0x78637772 27#define RPMPD_RWMX 0x786d7772 28#define RPMPD_RWLC 0x636c7772 29#define RPMPD_RWLM 0x6d6c7772 30#define RPMPD_RWSC 0x63737772 31#define RPMPD_RWSM 0x6d737772 32 33/* Operation Keys */ 34#define KEY_CORNER 0x6e726f63 /* corn */ 35#define KEY_ENABLE 0x6e657773 /* swen */ 36#define KEY_FLOOR_CORNER 0x636676 /* vfc */ 37#define KEY_FLOOR_LEVEL 0x6c6676 /* vfl */ 38#define KEY_LEVEL 0x6c766c76 /* vlvl */ 39 40#define MAX_CORNER_RPMPD_STATE 6 41 42#define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key, \ 43 r_id) \ 44 static struct rpmpd _platform##_##_active; \ 45 static struct rpmpd _platform##_##_name = { \ 46 .pd = { .name = #_name, }, \ 47 .peer = &_platform##_##_active, \ 48 .res_type = RPMPD_##r_type, \ 49 .res_id = r_id, \ 50 .key = KEY_##r_key, \ 51 }; \ 52 static struct rpmpd _platform##_##_active = { \ 53 .pd = { .name = #_active, }, \ 54 .peer = &_platform##_##_name, \ 55 .active_only = true, \ 56 .res_type = RPMPD_##r_type, \ 57 .res_id = r_id, \ 58 .key = KEY_##r_key, \ 59 } 60 61#define DEFINE_RPMPD_CORNER(_platform, _name, r_type, r_id) \ 62 static struct rpmpd _platform##_##_name = { \ 63 .pd = { .name = #_name, }, \ 64 .res_type = RPMPD_##r_type, \ 65 .res_id = r_id, \ 66 .key = KEY_CORNER, \ 67 } 68 69#define DEFINE_RPMPD_LEVEL(_platform, _name, r_type, r_id) \ 70 static struct rpmpd _platform##_##_name = { \ 71 .pd = { .name = #_name, }, \ 72 .res_type = RPMPD_##r_type, \ 73 .res_id = r_id, \ 74 .key = KEY_LEVEL, \ 75 } 76 77#define DEFINE_RPMPD_VFC(_platform, _name, r_type, r_id) \ 78 static struct rpmpd _platform##_##_name = { \ 79 .pd = { .name = #_name, }, \ 80 .res_type = RPMPD_##r_type, \ 81 .res_id = r_id, \ 82 .key = KEY_FLOOR_CORNER, \ 83 } 84 85#define DEFINE_RPMPD_VFL(_platform, _name, r_type, r_id) \ 86 static struct rpmpd _platform##_##_name = { \ 87 .pd = { .name = #_name, }, \ 88 .res_type = RPMPD_##r_type, \ 89 .res_id = r_id, \ 90 .key = KEY_FLOOR_LEVEL, \ 91 } 92 93struct rpmpd_req { 94 __le32 key; 95 __le32 nbytes; 96 __le32 value; 97}; 98 99struct rpmpd { 100 struct generic_pm_domain pd; 101 struct rpmpd *peer; 102 const bool active_only; 103 unsigned int corner; 104 bool enabled; 105 const char *res_name; 106 const int res_type; 107 const int res_id; 108 struct qcom_smd_rpm *rpm; 109 unsigned int max_state; 110 __le32 key; 111}; 112 113struct rpmpd_desc { 114 struct rpmpd **rpmpds; 115 size_t num_pds; 116 unsigned int max_state; 117}; 118 119static DEFINE_MUTEX(rpmpd_lock); 120 121/* mdm9607 RPM Power Domains */ 122DEFINE_RPMPD_PAIR(mdm9607, vddcx, vddcx_ao, SMPA, LEVEL, 3); 123DEFINE_RPMPD_VFL(mdm9607, vddcx_vfl, SMPA, 3); 124 125DEFINE_RPMPD_PAIR(mdm9607, vddmx, vddmx_ao, LDOA, LEVEL, 12); 126DEFINE_RPMPD_VFL(mdm9607, vddmx_vfl, LDOA, 12); 127static struct rpmpd *mdm9607_rpmpds[] = { 128 [MDM9607_VDDCX] = &mdm9607_vddcx, 129 [MDM9607_VDDCX_AO] = &mdm9607_vddcx_ao, 130 [MDM9607_VDDCX_VFL] = &mdm9607_vddcx_vfl, 131 [MDM9607_VDDMX] = &mdm9607_vddmx, 132 [MDM9607_VDDMX_AO] = &mdm9607_vddmx_ao, 133 [MDM9607_VDDMX_VFL] = &mdm9607_vddmx_vfl, 134}; 135 136static const struct rpmpd_desc mdm9607_desc = { 137 .rpmpds = mdm9607_rpmpds, 138 .num_pds = ARRAY_SIZE(mdm9607_rpmpds), 139 .max_state = RPM_SMD_LEVEL_TURBO, 140}; 141 142/* msm8939 RPM Power Domains */ 143DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1); 144DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1); 145 146DEFINE_RPMPD_PAIR(msm8939, vddcx, vddcx_ao, SMPA, CORNER, 2); 147DEFINE_RPMPD_VFC(msm8939, vddcx_vfc, SMPA, 2); 148 149DEFINE_RPMPD_PAIR(msm8939, vddmx, vddmx_ao, LDOA, CORNER, 3); 150 151static struct rpmpd *msm8939_rpmpds[] = { 152 [MSM8939_VDDMDCX] = &msm8939_vddmd, 153 [MSM8939_VDDMDCX_AO] = &msm8939_vddmd_ao, 154 [MSM8939_VDDMDCX_VFC] = &msm8939_vddmd_vfc, 155 [MSM8939_VDDCX] = &msm8939_vddcx, 156 [MSM8939_VDDCX_AO] = &msm8939_vddcx_ao, 157 [MSM8939_VDDCX_VFC] = &msm8939_vddcx_vfc, 158 [MSM8939_VDDMX] = &msm8939_vddmx, 159 [MSM8939_VDDMX_AO] = &msm8939_vddmx_ao, 160}; 161 162static const struct rpmpd_desc msm8939_desc = { 163 .rpmpds = msm8939_rpmpds, 164 .num_pds = ARRAY_SIZE(msm8939_rpmpds), 165 .max_state = MAX_CORNER_RPMPD_STATE, 166}; 167 168/* msm8916 RPM Power Domains */ 169DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1); 170DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3); 171 172DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1); 173 174static struct rpmpd *msm8916_rpmpds[] = { 175 [MSM8916_VDDCX] = &msm8916_vddcx, 176 [MSM8916_VDDCX_AO] = &msm8916_vddcx_ao, 177 [MSM8916_VDDCX_VFC] = &msm8916_vddcx_vfc, 178 [MSM8916_VDDMX] = &msm8916_vddmx, 179 [MSM8916_VDDMX_AO] = &msm8916_vddmx_ao, 180}; 181 182static const struct rpmpd_desc msm8916_desc = { 183 .rpmpds = msm8916_rpmpds, 184 .num_pds = ARRAY_SIZE(msm8916_rpmpds), 185 .max_state = MAX_CORNER_RPMPD_STATE, 186}; 187 188/* msm8953 RPM Power Domains */ 189DEFINE_RPMPD_PAIR(msm8953, vddmd, vddmd_ao, SMPA, LEVEL, 1); 190DEFINE_RPMPD_PAIR(msm8953, vddcx, vddcx_ao, SMPA, LEVEL, 2); 191DEFINE_RPMPD_PAIR(msm8953, vddmx, vddmx_ao, SMPA, LEVEL, 7); 192 193DEFINE_RPMPD_VFL(msm8953, vddcx_vfl, SMPA, 2); 194 195static struct rpmpd *msm8953_rpmpds[] = { 196 [MSM8953_VDDMD] = &msm8953_vddmd, 197 [MSM8953_VDDMD_AO] = &msm8953_vddmd_ao, 198 [MSM8953_VDDCX] = &msm8953_vddcx, 199 [MSM8953_VDDCX_AO] = &msm8953_vddcx_ao, 200 [MSM8953_VDDCX_VFL] = &msm8953_vddcx_vfl, 201 [MSM8953_VDDMX] = &msm8953_vddmx, 202 [MSM8953_VDDMX_AO] = &msm8953_vddmx_ao, 203}; 204 205static const struct rpmpd_desc msm8953_desc = { 206 .rpmpds = msm8953_rpmpds, 207 .num_pds = ARRAY_SIZE(msm8953_rpmpds), 208 .max_state = RPM_SMD_LEVEL_TURBO, 209}; 210 211/* msm8976 RPM Power Domains */ 212DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2); 213DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6); 214 215DEFINE_RPMPD_VFL(msm8976, vddcx_vfl, RWSC, 2); 216DEFINE_RPMPD_VFL(msm8976, vddmx_vfl, RWSM, 6); 217 218static struct rpmpd *msm8976_rpmpds[] = { 219 [MSM8976_VDDCX] = &msm8976_vddcx, 220 [MSM8976_VDDCX_AO] = &msm8976_vddcx_ao, 221 [MSM8976_VDDCX_VFL] = &msm8976_vddcx_vfl, 222 [MSM8976_VDDMX] = &msm8976_vddmx, 223 [MSM8976_VDDMX_AO] = &msm8976_vddmx_ao, 224 [MSM8976_VDDMX_VFL] = &msm8976_vddmx_vfl, 225}; 226 227static const struct rpmpd_desc msm8976_desc = { 228 .rpmpds = msm8976_rpmpds, 229 .num_pds = ARRAY_SIZE(msm8976_rpmpds), 230 .max_state = RPM_SMD_LEVEL_TURBO_HIGH, 231}; 232 233/* msm8994 RPM Power domains */ 234DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1); 235DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2); 236/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */ 237DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2); 238 239DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1); 240DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2); 241 242static struct rpmpd *msm8994_rpmpds[] = { 243 [MSM8994_VDDCX] = &msm8994_vddcx, 244 [MSM8994_VDDCX_AO] = &msm8994_vddcx_ao, 245 [MSM8994_VDDCX_VFC] = &msm8994_vddcx_vfc, 246 [MSM8994_VDDMX] = &msm8994_vddmx, 247 [MSM8994_VDDMX_AO] = &msm8994_vddmx_ao, 248 [MSM8994_VDDGFX] = &msm8994_vddgfx, 249 [MSM8994_VDDGFX_VFC] = &msm8994_vddgfx_vfc, 250}; 251 252static const struct rpmpd_desc msm8994_desc = { 253 .rpmpds = msm8994_rpmpds, 254 .num_pds = ARRAY_SIZE(msm8994_rpmpds), 255 .max_state = MAX_CORNER_RPMPD_STATE, 256}; 257 258/* msm8996 RPM Power domains */ 259DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1); 260DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2); 261DEFINE_RPMPD_CORNER(msm8996, vddsscx, LDOA, 26); 262 263DEFINE_RPMPD_VFC(msm8996, vddcx_vfc, SMPA, 1); 264DEFINE_RPMPD_VFC(msm8996, vddsscx_vfc, LDOA, 26); 265 266static struct rpmpd *msm8996_rpmpds[] = { 267 [MSM8996_VDDCX] = &msm8996_vddcx, 268 [MSM8996_VDDCX_AO] = &msm8996_vddcx_ao, 269 [MSM8996_VDDCX_VFC] = &msm8996_vddcx_vfc, 270 [MSM8996_VDDMX] = &msm8996_vddmx, 271 [MSM8996_VDDMX_AO] = &msm8996_vddmx_ao, 272 [MSM8996_VDDSSCX] = &msm8996_vddsscx, 273 [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc, 274}; 275 276static const struct rpmpd_desc msm8996_desc = { 277 .rpmpds = msm8996_rpmpds, 278 .num_pds = ARRAY_SIZE(msm8996_rpmpds), 279 .max_state = MAX_CORNER_RPMPD_STATE, 280}; 281 282/* msm8998 RPM Power domains */ 283DEFINE_RPMPD_PAIR(msm8998, vddcx, vddcx_ao, RWCX, LEVEL, 0); 284DEFINE_RPMPD_VFL(msm8998, vddcx_vfl, RWCX, 0); 285 286DEFINE_RPMPD_PAIR(msm8998, vddmx, vddmx_ao, RWMX, LEVEL, 0); 287DEFINE_RPMPD_VFL(msm8998, vddmx_vfl, RWMX, 0); 288 289DEFINE_RPMPD_LEVEL(msm8998, vdd_ssccx, RWSC, 0); 290DEFINE_RPMPD_VFL(msm8998, vdd_ssccx_vfl, RWSC, 0); 291 292DEFINE_RPMPD_LEVEL(msm8998, vdd_sscmx, RWSM, 0); 293DEFINE_RPMPD_VFL(msm8998, vdd_sscmx_vfl, RWSM, 0); 294 295static struct rpmpd *msm8998_rpmpds[] = { 296 [MSM8998_VDDCX] = &msm8998_vddcx, 297 [MSM8998_VDDCX_AO] = &msm8998_vddcx_ao, 298 [MSM8998_VDDCX_VFL] = &msm8998_vddcx_vfl, 299 [MSM8998_VDDMX] = &msm8998_vddmx, 300 [MSM8998_VDDMX_AO] = &msm8998_vddmx_ao, 301 [MSM8998_VDDMX_VFL] = &msm8998_vddmx_vfl, 302 [MSM8998_SSCCX] = &msm8998_vdd_ssccx, 303 [MSM8998_SSCCX_VFL] = &msm8998_vdd_ssccx_vfl, 304 [MSM8998_SSCMX] = &msm8998_vdd_sscmx, 305 [MSM8998_SSCMX_VFL] = &msm8998_vdd_sscmx_vfl, 306}; 307 308static const struct rpmpd_desc msm8998_desc = { 309 .rpmpds = msm8998_rpmpds, 310 .num_pds = ARRAY_SIZE(msm8998_rpmpds), 311 .max_state = RPM_SMD_LEVEL_BINNING, 312}; 313 314/* qcs404 RPM Power domains */ 315DEFINE_RPMPD_PAIR(qcs404, vddmx, vddmx_ao, RWMX, LEVEL, 0); 316DEFINE_RPMPD_VFL(qcs404, vddmx_vfl, RWMX, 0); 317 318DEFINE_RPMPD_LEVEL(qcs404, vdd_lpicx, RWLC, 0); 319DEFINE_RPMPD_VFL(qcs404, vdd_lpicx_vfl, RWLC, 0); 320 321DEFINE_RPMPD_LEVEL(qcs404, vdd_lpimx, RWLM, 0); 322DEFINE_RPMPD_VFL(qcs404, vdd_lpimx_vfl, RWLM, 0); 323 324static struct rpmpd *qcs404_rpmpds[] = { 325 [QCS404_VDDMX] = &qcs404_vddmx, 326 [QCS404_VDDMX_AO] = &qcs404_vddmx_ao, 327 [QCS404_VDDMX_VFL] = &qcs404_vddmx_vfl, 328 [QCS404_LPICX] = &qcs404_vdd_lpicx, 329 [QCS404_LPICX_VFL] = &qcs404_vdd_lpicx_vfl, 330 [QCS404_LPIMX] = &qcs404_vdd_lpimx, 331 [QCS404_LPIMX_VFL] = &qcs404_vdd_lpimx_vfl, 332}; 333 334static const struct rpmpd_desc qcs404_desc = { 335 .rpmpds = qcs404_rpmpds, 336 .num_pds = ARRAY_SIZE(qcs404_rpmpds), 337 .max_state = RPM_SMD_LEVEL_BINNING, 338}; 339 340/* sdm660 RPM Power domains */ 341DEFINE_RPMPD_PAIR(sdm660, vddcx, vddcx_ao, RWCX, LEVEL, 0); 342DEFINE_RPMPD_VFL(sdm660, vddcx_vfl, RWCX, 0); 343 344DEFINE_RPMPD_PAIR(sdm660, vddmx, vddmx_ao, RWMX, LEVEL, 0); 345DEFINE_RPMPD_VFL(sdm660, vddmx_vfl, RWMX, 0); 346 347DEFINE_RPMPD_LEVEL(sdm660, vdd_ssccx, RWLC, 0); 348DEFINE_RPMPD_VFL(sdm660, vdd_ssccx_vfl, RWLC, 0); 349 350DEFINE_RPMPD_LEVEL(sdm660, vdd_sscmx, RWLM, 0); 351DEFINE_RPMPD_VFL(sdm660, vdd_sscmx_vfl, RWLM, 0); 352 353static struct rpmpd *sdm660_rpmpds[] = { 354 [SDM660_VDDCX] = &sdm660_vddcx, 355 [SDM660_VDDCX_AO] = &sdm660_vddcx_ao, 356 [SDM660_VDDCX_VFL] = &sdm660_vddcx_vfl, 357 [SDM660_VDDMX] = &sdm660_vddmx, 358 [SDM660_VDDMX_AO] = &sdm660_vddmx_ao, 359 [SDM660_VDDMX_VFL] = &sdm660_vddmx_vfl, 360 [SDM660_SSCCX] = &sdm660_vdd_ssccx, 361 [SDM660_SSCCX_VFL] = &sdm660_vdd_ssccx_vfl, 362 [SDM660_SSCMX] = &sdm660_vdd_sscmx, 363 [SDM660_SSCMX_VFL] = &sdm660_vdd_sscmx_vfl, 364}; 365 366static const struct rpmpd_desc sdm660_desc = { 367 .rpmpds = sdm660_rpmpds, 368 .num_pds = ARRAY_SIZE(sdm660_rpmpds), 369 .max_state = RPM_SMD_LEVEL_TURBO, 370}; 371 372/* sm4250/6115 RPM Power domains */ 373DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0); 374DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0); 375 376DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0); 377DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0); 378 379DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0); 380DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0); 381 382static struct rpmpd *sm6115_rpmpds[] = { 383 [SM6115_VDDCX] = &sm6115_vddcx, 384 [SM6115_VDDCX_AO] = &sm6115_vddcx_ao, 385 [SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl, 386 [SM6115_VDDMX] = &sm6115_vddmx, 387 [SM6115_VDDMX_AO] = &sm6115_vddmx_ao, 388 [SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl, 389 [SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, 390 [SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, 391}; 392 393static const struct rpmpd_desc sm6115_desc = { 394 .rpmpds = sm6115_rpmpds, 395 .num_pds = ARRAY_SIZE(sm6115_rpmpds), 396 .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, 397}; 398 399static const struct of_device_id rpmpd_match_table[] = { 400 { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, 401 { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, 402 { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, 403 { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc }, 404 { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc }, 405 { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc }, 406 { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, 407 { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, 408 { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, 409 { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, 410 { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, 411 { } 412}; 413MODULE_DEVICE_TABLE(of, rpmpd_match_table); 414 415static int rpmpd_send_enable(struct rpmpd *pd, bool enable) 416{ 417 struct rpmpd_req req = { 418 .key = KEY_ENABLE, 419 .nbytes = cpu_to_le32(sizeof(u32)), 420 .value = cpu_to_le32(enable), 421 }; 422 423 return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE, 424 pd->res_type, pd->res_id, &req, sizeof(req)); 425} 426 427static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner) 428{ 429 struct rpmpd_req req = { 430 .key = pd->key, 431 .nbytes = cpu_to_le32(sizeof(u32)), 432 .value = cpu_to_le32(corner), 433 }; 434 435 return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id, 436 &req, sizeof(req)); 437}; 438 439static void to_active_sleep(struct rpmpd *pd, unsigned int corner, 440 unsigned int *active, unsigned int *sleep) 441{ 442 *active = corner; 443 444 if (pd->active_only) 445 *sleep = 0; 446 else 447 *sleep = *active; 448} 449 450static int rpmpd_aggregate_corner(struct rpmpd *pd) 451{ 452 int ret; 453 struct rpmpd *peer = pd->peer; 454 unsigned int active_corner, sleep_corner; 455 unsigned int this_active_corner = 0, this_sleep_corner = 0; 456 unsigned int peer_active_corner = 0, peer_sleep_corner = 0; 457 458 to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner); 459 460 if (peer && peer->enabled) 461 to_active_sleep(peer, peer->corner, &peer_active_corner, 462 &peer_sleep_corner); 463 464 active_corner = max(this_active_corner, peer_active_corner); 465 466 ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner); 467 if (ret) 468 return ret; 469 470 sleep_corner = max(this_sleep_corner, peer_sleep_corner); 471 472 return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner); 473} 474 475static int rpmpd_power_on(struct generic_pm_domain *domain) 476{ 477 int ret; 478 struct rpmpd *pd = domain_to_rpmpd(domain); 479 480 mutex_lock(&rpmpd_lock); 481 482 ret = rpmpd_send_enable(pd, true); 483 if (ret) 484 goto out; 485 486 pd->enabled = true; 487 488 if (pd->corner) 489 ret = rpmpd_aggregate_corner(pd); 490 491out: 492 mutex_unlock(&rpmpd_lock); 493 494 return ret; 495} 496 497static int rpmpd_power_off(struct generic_pm_domain *domain) 498{ 499 int ret; 500 struct rpmpd *pd = domain_to_rpmpd(domain); 501 502 mutex_lock(&rpmpd_lock); 503 504 ret = rpmpd_send_enable(pd, false); 505 if (!ret) 506 pd->enabled = false; 507 508 mutex_unlock(&rpmpd_lock); 509 510 return ret; 511} 512 513static int rpmpd_set_performance(struct generic_pm_domain *domain, 514 unsigned int state) 515{ 516 int ret = 0; 517 struct rpmpd *pd = domain_to_rpmpd(domain); 518 519 if (state > pd->max_state) 520 state = pd->max_state; 521 522 mutex_lock(&rpmpd_lock); 523 524 pd->corner = state; 525 526 /* Always send updates for vfc and vfl */ 527 if (!pd->enabled && pd->key != KEY_FLOOR_CORNER && 528 pd->key != KEY_FLOOR_LEVEL) 529 goto out; 530 531 ret = rpmpd_aggregate_corner(pd); 532 533out: 534 mutex_unlock(&rpmpd_lock); 535 536 return ret; 537} 538 539static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd, 540 struct dev_pm_opp *opp) 541{ 542 return dev_pm_opp_get_level(opp); 543} 544 545static int rpmpd_probe(struct platform_device *pdev) 546{ 547 int i; 548 size_t num; 549 struct genpd_onecell_data *data; 550 struct qcom_smd_rpm *rpm; 551 struct rpmpd **rpmpds; 552 const struct rpmpd_desc *desc; 553 554 rpm = dev_get_drvdata(pdev->dev.parent); 555 if (!rpm) { 556 dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); 557 return -ENODEV; 558 } 559 560 desc = of_device_get_match_data(&pdev->dev); 561 if (!desc) 562 return -EINVAL; 563 564 rpmpds = desc->rpmpds; 565 num = desc->num_pds; 566 567 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 568 if (!data) 569 return -ENOMEM; 570 571 data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains), 572 GFP_KERNEL); 573 data->num_domains = num; 574 575 for (i = 0; i < num; i++) { 576 if (!rpmpds[i]) { 577 dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n", 578 i); 579 continue; 580 } 581 582 rpmpds[i]->rpm = rpm; 583 rpmpds[i]->max_state = desc->max_state; 584 rpmpds[i]->pd.power_off = rpmpd_power_off; 585 rpmpds[i]->pd.power_on = rpmpd_power_on; 586 rpmpds[i]->pd.set_performance_state = rpmpd_set_performance; 587 rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance; 588 pm_genpd_init(&rpmpds[i]->pd, NULL, true); 589 590 data->domains[i] = &rpmpds[i]->pd; 591 } 592 593 return of_genpd_add_provider_onecell(pdev->dev.of_node, data); 594} 595 596static struct platform_driver rpmpd_driver = { 597 .driver = { 598 .name = "qcom-rpmpd", 599 .of_match_table = rpmpd_match_table, 600 .suppress_bind_attrs = true, 601 }, 602 .probe = rpmpd_probe, 603}; 604 605static int __init rpmpd_init(void) 606{ 607 return platform_driver_register(&rpmpd_driver); 608} 609core_initcall(rpmpd_init); 610 611MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver"); 612MODULE_LICENSE("GPL v2");