From dd27df6115319a3fea7e8c2f282a7dcf1f855549 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Wed, 11 Mar 2020 18:20:08 -0700 Subject: [PATCH] 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);