From 2f622be7ab27709278a64ae442e5ab4423e393a2 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Sun, 15 Mar 2020 13:52:54 -0700 Subject: [PATCH 1/3] dt-bindings: interconnect: Add generic qcom bindings Add generic qcom interconnect bindings that are common across platforms. Change-Id: Iffe00699c52cbb7d0566eebb252234bd4597ed0a Signed-off-by: Mike Tipton --- include/dt-bindings/interconnect/qcom,icc.h | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 include/dt-bindings/interconnect/qcom,icc.h diff --git a/include/dt-bindings/interconnect/qcom,icc.h b/include/dt-bindings/interconnect/qcom,icc.h new file mode 100644 index 000000000000..cd34f36daaaa --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,icc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_ICC_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_ICC_H + +/* + * The AMC bucket denotes constraints that are applied to hardware when + * icc_set_bw() completes, whereas the WAKE and SLEEP constraints are applied + * when the execution environment transitions between active and low power mode. + */ +#define QCOM_ICC_BUCKET_AMC 0 +#define QCOM_ICC_BUCKET_WAKE 1 +#define QCOM_ICC_BUCKET_SLEEP 2 +#define QCOM_ICC_NUM_BUCKETS 3 + +#define QCOM_ICC_TAG_AMC (1 << QCOM_ICC_BUCKET_AMC) +#define QCOM_ICC_TAG_WAKE (1 << QCOM_ICC_BUCKET_WAKE) +#define QCOM_ICC_TAG_SLEEP (1 << QCOM_ICC_BUCKET_SLEEP) +#define QCOM_ICC_TAG_ACTIVE_ONLY (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE) +#define QCOM_ICC_TAG_ALWAYS (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\ + QCOM_ICC_TAG_SLEEP) + +#endif From d76fc9c630dff9914b8530315f90941dc9e09240 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Wed, 11 Mar 2020 18:20:08 -0700 Subject: [PATCH 2/3] interconnect: qcom: Don't redefine bucket/tag macros Replace internal bucket/tag macros with those defined in dt-bindings. Change-Id: Id91dacaeb6b45174ee9e59056fe4bc497951a27a Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/icc-rpmh.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index 0ad1fd5cf55e..67ef15811228 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -8,6 +8,7 @@ #define __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__ #include +#include #define to_qcom_provider(_provider) \ container_of(_provider, struct qcom_icc_provider, provider) @@ -51,22 +52,6 @@ struct bcm_db { #define MAX_BCM_PER_NODE 3 #define MAX_VCD 10 -/* - * The AMC bucket denotes constraints that are applied to hardware when - * icc_set_bw() completes, whereas the WAKE and SLEEP constraints are applied - * when the execution environment transitions between active and low power mode. - */ -#define QCOM_ICC_BUCKET_AMC 0 -#define QCOM_ICC_BUCKET_WAKE 1 -#define QCOM_ICC_BUCKET_SLEEP 2 -#define QCOM_ICC_NUM_BUCKETS 3 -#define QCOM_ICC_TAG_AMC BIT(QCOM_ICC_BUCKET_AMC) -#define QCOM_ICC_TAG_WAKE BIT(QCOM_ICC_BUCKET_WAKE) -#define QCOM_ICC_TAG_SLEEP BIT(QCOM_ICC_BUCKET_SLEEP) -#define QCOM_ICC_TAG_ACTIVE_ONLY (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE) -#define QCOM_ICC_TAG_ALWAYS (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\ - QCOM_ICC_TAG_SLEEP) - /** * struct qcom_icc_node - QTI specific interconnect nodes * @name: the node name used in debugfs From dd27df6115319a3fea7e8c2f282a7dcf1f855549 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Wed, 11 Mar 2020 18:20:08 -0700 Subject: [PATCH 3/3] interconnect: qcom: Support bcm-voter-specific TCS wait behavior Currently, all bcm-voters follow the same logic for when a tcs_cmd needs to wait for completion. This logic sets tcs_cmd::wait = true for the last command in each TCS (AMC, WAKE, and SLEEP). However, this isn't necessarily the desired behavior for each bcm-voter, so allow which TCS's require wait-for-completion to be specified in devicetree. Additionally, change the default behavior to only wait for completion in AMC and WAKE sets. The SLEEP set generally does not require this, since in essentially all cases resources are only being disabled in the sleep set and that can happen asynchronously in parallel with the rest of the power collapse sequence. Change-Id: If782f88c2748f018863fe1cdbc8c82ad427c3e9f Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/bcm-voter.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c index b17818d1e490..4b4e1b3028b4 100644 --- a/drivers/interconnect/qcom/bcm-voter.c +++ b/drivers/interconnect/qcom/bcm-voter.c @@ -26,6 +26,7 @@ static LIST_HEAD(bcm_voters); * @commit_list: list containing bcms to be committed to hardware * @ws_list: list containing bcms that have different wake/sleep votes * @voter_node: list of bcm voters + * @tcs_wait: mask for which buckets require TCS completion * @init: flag to determine when init has completed. */ struct bcm_voter { @@ -35,6 +36,7 @@ struct bcm_voter { struct list_head commit_list; struct list_head ws_list; struct list_head voter_node; + u32 tcs_wait; bool init; }; @@ -127,11 +129,12 @@ static inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y, cmd->wait = true; } -static void tcs_list_gen(struct list_head *bcm_list, int bucket, +static void tcs_list_gen(struct bcm_voter *voter, int bucket, struct tcs_cmd tcs_list[MAX_VCD], int n[MAX_VCD]) { struct qcom_icc_bcm *bcm; + struct list_head *bcm_list = &voter->commit_list; bool commit; size_t idx = 0, batch = 0, cur_vcd_size = 0; @@ -143,8 +146,9 @@ static void tcs_list_gen(struct list_head *bcm_list, int bucket, if ((list_is_last(&bcm->list, bcm_list)) || bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) { - commit = true; cur_vcd_size = 0; + if (voter->tcs_wait & BIT(bucket)) + commit = true; } tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket], bcm->vote_y[bucket], bcm->addr, commit); @@ -271,9 +275,7 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter) * Construct the command list based on a pre ordered list of BCMs * based on VCD. */ - tcs_list_gen(&voter->commit_list, QCOM_ICC_BUCKET_AMC, cmds, - commit_idx); - + tcs_list_gen(voter, QCOM_ICC_BUCKET_AMC, cmds, commit_idx); if (!commit_idx[0]) goto out; @@ -327,8 +329,7 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter) list_sort(NULL, &voter->commit_list, cmp_vcd); - tcs_list_gen(&voter->commit_list, QCOM_ICC_BUCKET_WAKE, cmds, - commit_idx); + tcs_list_gen(voter, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx); ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx); @@ -337,8 +338,7 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter) goto out; } - tcs_list_gen(&voter->commit_list, QCOM_ICC_BUCKET_SLEEP, cmds, - commit_idx); + tcs_list_gen(voter, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx); ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx); if (ret) { @@ -373,6 +373,7 @@ EXPORT_SYMBOL(qcom_icc_bcm_voter_clear_init); static int qcom_icc_bcm_voter_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct bcm_voter *voter; voter = devm_kzalloc(&pdev->dev, sizeof(*voter), GFP_KERNEL); @@ -380,8 +381,12 @@ static int qcom_icc_bcm_voter_probe(struct platform_device *pdev) return -ENOMEM; voter->dev = &pdev->dev; - voter->np = pdev->dev.of_node; + voter->np = np; voter->init = true; + + if (of_property_read_u32(np, "qcom,tcs-wait", &voter->tcs_wait)) + voter->tcs_wait = QCOM_ICC_TAG_ACTIVE_ONLY; + mutex_init(&voter->lock); INIT_LIST_HEAD(&voter->commit_list); INIT_LIST_HEAD(&voter->ws_list);