* [PATCH RFC 1/2] dt-bindings: interconnect: qcom,sdm845: Add MASTER_ALC
2026-10-13 20:26 [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC yoxcu
@ 2026-10-13 20:26 ` yoxcu
2026-10-13 20:26 ` [PATCH RFC 2/2] interconnect: qcom: sdm845: Own the ALC BCM to drop its boot vote yoxcu
2026-10-19 12:22 ` [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC Konrad Dybcio
2 siblings, 0 replies; 5+ messages in thread
From: yoxcu @ 2026-10-13 20:26 UTC (permalink / raw)
To: Georgi Djakov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, linux-arm-msm, linux-pm, devicetree, linux-kernel,
Michael Auer
From: Michael Auer <mick@yoxcu.de>
Add an ID for the ALC node on mem_noc. The node has no consumers, so
no DTS is expected to use the ID. The driver needs it to own the ALC
BCM.
Assisted-by: LLM
Signed-off-by: Michael Auer <mick@yoxcu.de>
---
include/dt-bindings/interconnect/qcom,sdm845.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/dt-bindings/interconnect/qcom,sdm845.h b/include/dt-bindings/interconnect/qcom,sdm845.h
index 67b500e24915..fda8e367359e 100644
--- a/include/dt-bindings/interconnect/qcom,sdm845.h
+++ b/include/dt-bindings/interconnect/qcom,sdm845.h
@@ -108,6 +108,7 @@
#define SLAVE_SERVICE_MEM_NOC 12
#define MASTER_LLCC 13
#define SLAVE_EBI1 14
+#define MASTER_ALC 15
#define MASTER_CNOC_MNOC_CFG 0
#define MASTER_CAMNOC_HF0 1
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH RFC 2/2] interconnect: qcom: sdm845: Own the ALC BCM to drop its boot vote
2026-10-13 20:26 [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC yoxcu
2026-10-13 20:26 ` [PATCH RFC 1/2] dt-bindings: interconnect: qcom,sdm845: Add MASTER_ALC yoxcu
@ 2026-10-13 20:26 ` yoxcu
2026-10-19 12:22 ` [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC Konrad Dybcio
2 siblings, 0 replies; 5+ messages in thread
From: yoxcu @ 2026-10-13 20:26 UTC (permalink / raw)
To: Georgi Djakov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, linux-arm-msm, linux-pm, devicetree, linux-kernel,
Michael Auer
From: Michael Auer <mick@yoxcu.de>
On the OnePlus 6 the bootloader leaves a vote on the ALC BCM
(rpmh_read() on the APPS DRV returns 0x2000000f). No driver owns this
BCM, so the vote is never removed and the SoC never reaches AOSS sleep
or CX collapse (qcom_stats aosd and cxsd stay at 0).
Add a node without consumers for the ALC BCM on mem_noc. The provider
then owns the BCM and drops the vote at sync_state.
With this change ALC reads 0 after boot and suspend reaches CX
collapse. The average current in an idle push standby test (Wi-Fi on)
was 35.6 mA, against 43.7 mA with the ALC vote kept in the sleep set.
Assisted-by: LLM
Signed-off-by: Michael Auer <mick@yoxcu.de>
---
drivers/interconnect/qcom/sdm845.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index 1c434fd12ead..2a35ed7fce49 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -1114,6 +1114,13 @@ static struct qcom_icc_node ebi = {
.buswidth = 4,
};
+/* No consumers, owns the ALC BCM so sync_state drops the boot vote */
+static struct qcom_icc_node alc = {
+ .name = "alc",
+ .channels = 1,
+ .buswidth = 1,
+};
+
static struct qcom_icc_node qhs_mdsp_ms_mpu_cfg = {
.name = "qhs_mdsp_ms_mpu_cfg",
.channels = 1,
@@ -1250,6 +1257,14 @@ static struct qcom_icc_bcm bcm_acv = {
.nodes = { &ebi },
};
+static struct qcom_icc_bcm bcm_alc = {
+ .name = "ALC",
+ .enable_mask = BIT(0),
+ .keepalive = false,
+ .num_nodes = 1,
+ .nodes = { &alc },
+};
+
static struct qcom_icc_bcm bcm_mc0 = {
.name = "MC0",
.keepalive = true,
@@ -1646,6 +1661,7 @@ static const struct qcom_icc_desc sdm845_gladiator_noc = {
static struct qcom_icc_bcm * const mem_noc_bcms[] = {
&bcm_mc0,
&bcm_acv,
+ &bcm_alc,
&bcm_sh0,
&bcm_sh1,
&bcm_sh2,
@@ -1669,6 +1685,7 @@ static struct qcom_icc_node * const mem_noc_nodes[] = {
[SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc,
[MASTER_LLCC] = &llcc_mc,
[SLAVE_EBI1] = &ebi,
+ [MASTER_ALC] = &alc,
};
static const struct qcom_icc_desc sdm845_mem_noc = {
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC
2026-10-13 20:26 [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC yoxcu
2026-10-13 20:26 ` [PATCH RFC 1/2] dt-bindings: interconnect: qcom,sdm845: Add MASTER_ALC yoxcu
2026-10-13 20:26 ` [PATCH RFC 2/2] interconnect: qcom: sdm845: Own the ALC BCM to drop its boot vote yoxcu
@ 2026-10-19 12:22 ` Konrad Dybcio
2026-10-23 20:02 ` Michael Auer
2 siblings, 1 reply; 5+ messages in thread
From: Konrad Dybcio @ 2026-10-19 12:22 UTC (permalink / raw)
To: yoxcu, Georgi Djakov, Mike Tipton
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, linux-arm-msm, linux-pm, devicetree, linux-kernel
On 10/13/26 10:26 PM, yoxcu wrote:
> From: Michael Auer <mick@yoxcu.de>
>
> On sdm845 the bootloader can leave a vote on the ALC BCM. No icc node
> uses this BCM, so Linux never writes it and the vote stays in force
> through sleep: the SoC never reaches CX collapse or AOSS sleep. Found
> on a OnePlus 6 (rpmh_read() of ALC on the APPS DRV returns 0x2000000f).
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.
> This RFC adds a node without consumers on mem_noc that owns the ALC
> BCM, so the provider drops the vote at sync_state like for any other
> BCM. The node needs a new ID in the dt-bindings header. Android's
> sdm845 bus DT has ALC as a node on mc_virt. Mainline has no mc_virt,
> so the node goes on mem_noc next to ACV and MC0.
>
> On icc-next the provider reads the boot vote back
> (qcom_icc_bcm_get_bw()). The vote seen here has y = 0xf, so with
> enable_mask BIT(0) the node keeps an initial vote until sync_state and
> then votes 0. A boot vote with bit 0 clear would not be seen and would
> stay. GENMASK(3, 0) would match the vote seen here; I do not know
> which value ALC expects.
On msm-4.9, the downstream kernel for sdm845, the driver unconditionally
writes a (x, y) = (12, 0) on the active-only context and (0, 0) on the
remaining ones and that seems to be the right set of values. I don't
know how secret their meaning is, maybe +Mike can help.
Konrad
> Questions:
> - Is a node without consumers and a new binding ID acceptable for
> this? No other qcom icc driver models ALC.
> - Or should the node use a driver-local index past the binding IDs,
> so the header is not touched?
> - Or should the bcm-voter clear bootloader votes on BCMs that no node
> owns? It has no list of such BCMs, and cmd-db has no API to list
> them.
>
> Tested on a OnePlus 6 with an sdm845-mainline 7.1-rc1 based kernel.
> That kernel has no vote read-back, so the node started at INT_MAX:
> ALC was voted with y = 1 until sync_state and 0 after it. ALC reads 0
> after boot and suspend reaches CX collapse (qcom_stats cxsd counts).
> The average current in an idle push standby test (Wi-Fi on) was
> 35.6 mA, against 43.7 mA with the ALC vote kept in the sleep set. With
> ALC off in all sets the phone has been in daily use for two weeks with
> no side effects seen. On icc-next both patches were only build tested
> (W=1).
>
> This is my first kernel submission, feedback on the process is welcome.
>
> Michael Auer (2):
> dt-bindings: interconnect: qcom,sdm845: Add MASTER_ALC
> interconnect: qcom: sdm845: Own the ALC BCM to drop its boot vote
>
> drivers/interconnect/qcom/sdm845.c | 17 +++++++++++++++++
> include/dt-bindings/interconnect/qcom,sdm845.h | 1 +
> 2 files changed, 18 insertions(+)
>
>
> base-commit: 3fd56a2833c22f62eb84297d0dbd47739632f1a0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC
2026-10-19 12:22 ` [PATCH RFC 0/2] interconnect: qcom: sdm845: Drop the bootloader vote on ALC Konrad Dybcio
@ 2026-10-23 20:02 ` Michael Auer
0 siblings, 0 replies; 5+ messages in thread
From: Michael Auer @ 2026-10-23 20:02 UTC (permalink / raw)
To: Konrad Dybcio, Georgi Djakov, Mike Tipton
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, linux-arm-msm, linux-pm, devicetree, linux-kernel
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.
> On msm-4.9, the downstream kernel for sdm845, the driver unconditionally
> writes a (x, y) = (12, 0) on the active-only context and (0, 0) on the
> remaining ones and that seems to be the right set of values. I don't
> know how secret their meaning is, maybe +Mike can help.
That fits what I measured: the cost is the vote in the sleep set. With
the boot value kept in the wake set and 0 only in the sleep set, the
SoC also reached CX collapse.
I could only find the (12, 0) write for clients marked with
qcom,msm-bus,alc-voter (update_client_alc()), and I found no such client
in the sdm845 DTs (CAF LA.UM.7.3 and 10.3, and the OnePlus tree). Did I
miss something? If not, the only ALC write I see is the handoff removal
at late_initcall_sync, which writes 0, so downstream would end up with
ALC off, like this RFC.
Would it be acceptable for v2 to drop the dummy node and the binding
change, and instead let sdm845 list ALC as a BCM without nodes, which
icc-rpmh votes off once at probe? Or is there a better place for this?
Mike, is off the right state for ALC when nothing asks for low latency?
Or should Linux vote (12, 0) on the active-only set, the way msm_bus
does for an ALC client?
Thanks,
Michael
^ permalink raw reply [flat|nested] 5+ messages in thread