Lines Matching +full:bcm +full:- +full:voter

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
7 #include <linux/interconnect-provider.h>
16 #include "bcm-voter.h"
17 #include "icc-rpmh.h"
23 * struct bcm_voter - Bus Clock Manager voter
24 * @dev: reference to the device that communicates with the BCM
25 * @np: reference to the device node to match bcm voters
26 * @lock: mutex to protect commit and wake/sleep lists in the voter
29 * @voter_node: list of bcm voters
49 if (bcm_a->aux_data.vcd < bcm_b->aux_data.vcd) in cmp_vcd()
50 return -1; in cmp_vcd()
51 else if (bcm_a->aux_data.vcd == bcm_b->aux_data.vcd) in cmp_vcd()
68 static void bcm_aggregate(struct qcom_icc_bcm *bcm) in bcm_aggregate() argument
77 for (i = 0; i < bcm->num_nodes; i++) { in bcm_aggregate()
78 node = bcm->nodes[i]; in bcm_aggregate()
79 temp = bcm_div(node->sum_avg[bucket] * bcm->aux_data.width, in bcm_aggregate()
80 node->buswidth * node->channels); in bcm_aggregate()
83 temp = bcm_div(node->max_peak[bucket] * bcm->aux_data.width, in bcm_aggregate()
84 node->buswidth); in bcm_aggregate()
88 temp = agg_avg[bucket] * bcm->vote_scale; in bcm_aggregate()
89 bcm->vote_x[bucket] = bcm_div(temp, bcm->aux_data.unit); in bcm_aggregate()
91 temp = agg_peak[bucket] * bcm->vote_scale; in bcm_aggregate()
92 bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit); in bcm_aggregate()
95 if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && in bcm_aggregate()
96 bcm->vote_y[QCOM_ICC_BUCKET_AMC] == 0) { in bcm_aggregate()
97 bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1; in bcm_aggregate()
98 bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1; in bcm_aggregate()
99 bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1; in bcm_aggregate()
100 bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1; in bcm_aggregate()
123 cmd->addr = addr; in tcs_cmd_gen()
124 cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y); in tcs_cmd_gen()
130 cmd->wait = wait; in tcs_cmd_gen()
133 static void tcs_list_gen(struct bcm_voter *voter, int bucket, in tcs_list_gen() argument
137 struct list_head *bcm_list = &voter->commit_list; in tcs_list_gen()
138 struct qcom_icc_bcm *bcm; in tcs_list_gen() local
144 list_for_each_entry(bcm, bcm_list, list) { in tcs_list_gen()
147 if ((list_is_last(&bcm->list, bcm_list)) || in tcs_list_gen()
148 bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) { in tcs_list_gen()
153 wait = commit && (voter->tcs_wait & BIT(bucket)); in tcs_list_gen()
155 tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket], in tcs_list_gen()
156 bcm->vote_y[bucket], bcm->addr, commit, wait); in tcs_list_gen()
162 * to ensure that every BCM is committed since we only set the in tcs_list_gen()
163 * commit bit on the last BCM request of every VCD. in tcs_list_gen()
167 n[batch] -= cur_vcd_size; in tcs_list_gen()
176 * of_bcm_voter_get - gets a bcm voter handle from DT node
178 * @name: name for the bcm voter device
184 * when matching bcm voter is yet to be found.
188 struct bcm_voter *voter = ERR_PTR(-EPROBE_DEFER); in of_bcm_voter_get() local
193 if (!dev || !dev->of_node) in of_bcm_voter_get()
194 return ERR_PTR(-ENODEV); in of_bcm_voter_get()
196 np = dev->of_node; in of_bcm_voter_get()
199 idx = of_property_match_string(np, "qcom,bcm-voter-names", name); in of_bcm_voter_get()
204 node = of_parse_phandle(np, "qcom,bcm-voters", idx); in of_bcm_voter_get()
208 if (temp->np == node) { in of_bcm_voter_get()
209 voter = temp; in of_bcm_voter_get()
216 return voter; in of_bcm_voter_get()
221 * qcom_icc_bcm_voter_add - queues up the bcm nodes that require updates
222 * @voter: voter that the bcms are being added to
223 * @bcm: bcm to add to the commit and wake sleep list
225 void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm) in qcom_icc_bcm_voter_add() argument
227 if (!voter) in qcom_icc_bcm_voter_add()
230 mutex_lock(&voter->lock); in qcom_icc_bcm_voter_add()
231 if (list_empty(&bcm->list)) in qcom_icc_bcm_voter_add()
232 list_add_tail(&bcm->list, &voter->commit_list); in qcom_icc_bcm_voter_add()
234 if (list_empty(&bcm->ws_list)) in qcom_icc_bcm_voter_add()
235 list_add_tail(&bcm->ws_list, &voter->ws_list); in qcom_icc_bcm_voter_add()
237 mutex_unlock(&voter->lock); in qcom_icc_bcm_voter_add()
242 * qcom_icc_bcm_voter_commit - generates and commits tcs cmds based on bcms
243 * @voter: voter that needs flushing
245 * This function generates a set of AMC commands and flushes to the BCM device
246 * associated with the voter. It conditionally generate WAKE and SLEEP commands
248 * through multiple commit requests and bcm nodes are removed only when the
253 int qcom_icc_bcm_voter_commit(struct bcm_voter *voter) in qcom_icc_bcm_voter_commit() argument
255 struct qcom_icc_bcm *bcm; in qcom_icc_bcm_voter_commit() local
261 if (!voter) in qcom_icc_bcm_voter_commit()
264 mutex_lock(&voter->lock); in qcom_icc_bcm_voter_commit()
265 list_for_each_entry(bcm, &voter->commit_list, list) in qcom_icc_bcm_voter_commit()
266 bcm_aggregate(bcm); in qcom_icc_bcm_voter_commit()
276 list_sort(NULL, &voter->commit_list, cmp_vcd); in qcom_icc_bcm_voter_commit()
282 tcs_list_gen(voter, QCOM_ICC_BUCKET_AMC, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
286 rpmh_invalidate(voter->dev); in qcom_icc_bcm_voter_commit()
288 ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE, in qcom_icc_bcm_voter_commit()
295 list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list) in qcom_icc_bcm_voter_commit()
296 list_del_init(&bcm->list); in qcom_icc_bcm_voter_commit()
298 list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) { in qcom_icc_bcm_voter_commit()
304 if (bcm->vote_x[QCOM_ICC_BUCKET_WAKE] != in qcom_icc_bcm_voter_commit()
305 bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] || in qcom_icc_bcm_voter_commit()
306 bcm->vote_y[QCOM_ICC_BUCKET_WAKE] != in qcom_icc_bcm_voter_commit()
307 bcm->vote_y[QCOM_ICC_BUCKET_SLEEP]) in qcom_icc_bcm_voter_commit()
308 list_add_tail(&bcm->list, &voter->commit_list); in qcom_icc_bcm_voter_commit()
310 list_del_init(&bcm->ws_list); in qcom_icc_bcm_voter_commit()
313 if (list_empty(&voter->commit_list)) in qcom_icc_bcm_voter_commit()
316 list_sort(NULL, &voter->commit_list, cmp_vcd); in qcom_icc_bcm_voter_commit()
318 tcs_list_gen(voter, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
320 ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
326 tcs_list_gen(voter, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
328 ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
335 list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list) in qcom_icc_bcm_voter_commit()
336 list_del_init(&bcm->list); in qcom_icc_bcm_voter_commit()
338 mutex_unlock(&voter->lock); in qcom_icc_bcm_voter_commit()
345 struct device_node *np = pdev->dev.of_node; in qcom_icc_bcm_voter_probe()
346 struct bcm_voter *voter; in qcom_icc_bcm_voter_probe() local
348 voter = devm_kzalloc(&pdev->dev, sizeof(*voter), GFP_KERNEL); in qcom_icc_bcm_voter_probe()
349 if (!voter) in qcom_icc_bcm_voter_probe()
350 return -ENOMEM; in qcom_icc_bcm_voter_probe()
352 voter->dev = &pdev->dev; in qcom_icc_bcm_voter_probe()
353 voter->np = np; in qcom_icc_bcm_voter_probe()
355 if (of_property_read_u32(np, "qcom,tcs-wait", &voter->tcs_wait)) in qcom_icc_bcm_voter_probe()
356 voter->tcs_wait = QCOM_ICC_TAG_ACTIVE_ONLY; in qcom_icc_bcm_voter_probe()
358 mutex_init(&voter->lock); in qcom_icc_bcm_voter_probe()
359 INIT_LIST_HEAD(&voter->commit_list); in qcom_icc_bcm_voter_probe()
360 INIT_LIST_HEAD(&voter->ws_list); in qcom_icc_bcm_voter_probe()
363 list_add_tail(&voter->voter_node, &bcm_voters); in qcom_icc_bcm_voter_probe()
370 { .compatible = "qcom,bcm-voter" },
385 MODULE_DESCRIPTION("Qualcomm BCM Voter interconnect driver");