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

remoteproc: qcom_wcnss: Handle platforms with only single power domain

Both MSM8974 and MSM8226 have only CX as power domain with MX & PX being
handled as regulators. Handle this case by reodering pd_names to have CX
first, and handling that the driver core will already attach a single
power domain internally.

Signed-off-by: Matti Lehtimäki <matti.lehtimaki@gmail.com>
[luca: minor changes]
Signed-off-by: Luca Weiss <luca@lucaweiss.eu>
Link: https://lore.kernel.org/r/20250206-wcnss-singlepd-v2-2-9a53ee953dee@lucaweiss.eu
[bjorn: Added missing braces to else after multi-statement if]
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Matti Lehtimäki and committed by
Bjorn Andersson
65991ea8 14198a0c

+26 -7
+26 -7
drivers/remoteproc/qcom_wcnss.c
··· 117 117 .pmu_offset = 0x1004, 118 118 .spare_offset = 0x1088, 119 119 120 - .pd_names = { "mx", "cx" }, 120 + .pd_names = { "cx", "mx" }, 121 121 .vregs = (struct wcnss_vreg_info[]) { 122 - { "vddmx", 950000, 1150000, 0 }, 123 122 { "vddcx", .super_turbo = true}, 123 + { "vddmx", 950000, 1150000, 0 }, 124 124 { "vddpx", 1800000, 1800000, 0 }, 125 125 }, 126 126 .num_pd_vregs = 2, ··· 131 131 .pmu_offset = 0x1004, 132 132 .spare_offset = 0x1088, 133 133 134 - .pd_names = { "mx", "cx" }, 134 + .pd_names = { "cx", "mx" }, 135 135 .vregs = (struct wcnss_vreg_info[]) { 136 - { "vddmx", 1287500, 1287500, 0 }, 137 136 { "vddcx", .super_turbo = true }, 137 + { "vddmx", 1287500, 1287500, 0 }, 138 138 { "vddpx", 1800000, 1800000, 0 }, 139 139 }, 140 140 .num_pd_vregs = 2, ··· 397 397 static int wcnss_init_pds(struct qcom_wcnss *wcnss, 398 398 const char * const pd_names[WCNSS_MAX_PDS]) 399 399 { 400 + struct device *dev = wcnss->dev; 400 401 int i, ret; 402 + 403 + /* Handle single power domain */ 404 + if (dev->pm_domain) { 405 + wcnss->pds[0] = dev; 406 + wcnss->num_pds = 1; 407 + pm_runtime_enable(dev); 408 + return 0; 409 + } 401 410 402 411 for (i = 0; i < WCNSS_MAX_PDS; i++) { 403 412 if (!pd_names[i]) ··· 427 418 428 419 static void wcnss_release_pds(struct qcom_wcnss *wcnss) 429 420 { 421 + struct device *dev = wcnss->dev; 430 422 int i; 423 + 424 + /* Handle single power domain */ 425 + if (wcnss->num_pds == 1 && dev->pm_domain) { 426 + pm_runtime_disable(dev); 427 + return; 428 + } 431 429 432 430 for (i = 0; i < wcnss->num_pds; i++) 433 431 dev_pm_domain_detach(wcnss->pds[i], false); ··· 453 437 * the regulators for the power domains. For old device trees we need to 454 438 * reserve extra space to manage them through the regulator interface. 455 439 */ 456 - if (wcnss->num_pds) 457 - info += num_pd_vregs; 458 - else 440 + if (wcnss->num_pds) { 441 + info += wcnss->num_pds; 442 + /* Handle single power domain case */ 443 + num_vregs += num_pd_vregs - wcnss->num_pds; 444 + } else { 459 445 num_vregs += num_pd_vregs; 446 + } 460 447 461 448 bulk = devm_kcalloc(wcnss->dev, 462 449 num_vregs, sizeof(struct regulator_bulk_data),