Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd27df61 authored by Mike Tipton's avatar Mike Tipton
Browse files

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: default avatarMike Tipton <mdtipton@codeaurora.org>
parent d76fc9c6
Loading
Loading
Loading
Loading
+15 −10
Original line number Diff line number Diff line
@@ -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);