Re: [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC
From: Konrad Dybcio
Date: Fri Nov 13 2026 - 09:01:39 EST
On 10/23/26 10:02 PM, Michael Auer wrote:
> On 10/19/26 2:22 PM, Konrad Dybcio wrote:
>> ALC essentially translates into "prevent DDR from sleeping to reduce
>> latency", I don't know what a good framework for that func would be,
>> but interconnect (even though it has the plumbing for BCMs) doesn't
>> seem like it.
>
> Thanks, that explains why the vote is so expensive in suspend.
>
> I don't really want to add a consumer API for that.
> I only want to get rid of the vote the bootloader leaves behind.
For a start, let's do something like:
diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c
index 0880a287b0c0..f9d51f3d586d 100644
--- a/drivers/interconnect/qcom/bcm-voter.c
+++ b/drivers/interconnect/qcom/bcm-voter.c
@@ -390,6 +390,46 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
}
EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_commit);
+/*
+ * ALC is not modeled by any icc node, but the bootloader may leave it voted,
+ * which prevents the SoC from reaching CX collapse and AOSS shutdown.
+ */
+static void bcm_voter_clear_alc(struct bcm_voter *voter)
+{
+ struct tcs_cmd cmd;
+ u32 addr;
+ int ret;
+
+ addr = cmd_db_read_addr("ALC");
+ if (!addr)
+ return;
+
+ tcs_cmd_gen(&cmd, 12, 0, addr, true,
+ voter->tcs_wait & BIT(QCOM_ICC_BUCKET_AMC));
+
+ ret = rpmh_write(voter->dev, RPMH_ACTIVE_ONLY_STATE, &cmd, 1);
+ if (ret) {
+ dev_err(voter->dev, "Error sending ALC AMC RPMH request (%d)\n", ret);
+ return;
+ }
+
+ tcs_cmd_gen(&cmd, 0, 0, addr, true,
+ voter->tcs_wait & BIT(QCOM_ICC_BUCKET_WAKE));
+
+ ret = rpmh_write(voter->dev, RPMH_WAKE_ONLY_STATE, &cmd, 1);
+ if (ret) {
+ dev_err(voter->dev, "Error sending ALC WAKE RPMH request (%d)\n", ret);
+ return;
+ }
+
+ tcs_cmd_gen(&cmd, 0, 0, addr, true,
+ voter->tcs_wait & BIT(QCOM_ICC_BUCKET_SLEEP));
+
+ ret = rpmh_write(voter->dev, RPMH_SLEEP_STATE, &cmd, 1);
+ if (ret)
+ dev_err(voter->dev, "Error sending ALC SLEEP RPMH request (%d)\n", ret);
+}
+
static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -409,6 +449,8 @@ static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&voter->commit_list);
INIT_LIST_HEAD(&voter->ws_list);
+ bcm_voter_clear_alc(voter);
+
mutex_lock(&bcm_voter_lock);
list_add_tail(&voter->voter_node, &bcm_voters);
mutex_unlock(&bcm_voter_lock);
Konrad