Lines Matching +full:rpmh +full:- +full:based

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
7 #include <linux/interconnect-provider.h>
13 #include <soc/qcom/rpmh.h>
16 #include "bcm-voter.h"
17 #include "icc-rpmh.h"
23 * struct bcm_voter - Bus Clock Manager voter
47 return bcm_a->aux_data.vcd - bcm_b->aux_data.vcd; in cmp_vcd()
61 /* BCMs with enable_mask use one-hot-encoding for on/off signaling */
68 bcm->vote_x[bucket] = 0; in bcm_aggregate_mask()
69 bcm->vote_y[bucket] = 0; in bcm_aggregate_mask()
71 for (i = 0; i < bcm->num_nodes; i++) { in bcm_aggregate_mask()
72 node = bcm->nodes[i]; in bcm_aggregate_mask()
75 if (node->sum_avg[bucket] || node->max_peak[bucket]) { in bcm_aggregate_mask()
76 bcm->vote_x[bucket] = 0; in bcm_aggregate_mask()
77 bcm->vote_y[bucket] = bcm->enable_mask; in bcm_aggregate_mask()
83 if (bcm->keepalive) { in bcm_aggregate_mask()
84 bcm->vote_x[QCOM_ICC_BUCKET_AMC] = bcm->enable_mask; in bcm_aggregate_mask()
85 bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = bcm->enable_mask; in bcm_aggregate_mask()
86 bcm->vote_y[QCOM_ICC_BUCKET_AMC] = bcm->enable_mask; in bcm_aggregate_mask()
87 bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = bcm->enable_mask; in bcm_aggregate_mask()
100 for (i = 0; i < bcm->num_nodes; i++) { in bcm_aggregate()
101 node = bcm->nodes[i]; in bcm_aggregate()
102 temp = bcm_div(node->sum_avg[bucket] * bcm->aux_data.width, in bcm_aggregate()
103 node->buswidth * node->channels); in bcm_aggregate()
106 temp = bcm_div(node->max_peak[bucket] * bcm->aux_data.width, in bcm_aggregate()
107 node->buswidth); in bcm_aggregate()
111 temp = agg_avg[bucket] * bcm->vote_scale; in bcm_aggregate()
112 bcm->vote_x[bucket] = bcm_div(temp, bcm->aux_data.unit); in bcm_aggregate()
114 temp = agg_peak[bucket] * bcm->vote_scale; in bcm_aggregate()
115 bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit); in bcm_aggregate()
118 if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && in bcm_aggregate()
119 bcm->vote_y[QCOM_ICC_BUCKET_AMC] == 0) { in bcm_aggregate()
120 bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1; in bcm_aggregate()
121 bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1; in bcm_aggregate()
122 bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1; in bcm_aggregate()
123 bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1; in bcm_aggregate()
146 cmd->addr = addr; in tcs_cmd_gen()
147 cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y); in tcs_cmd_gen()
153 cmd->wait = wait; in tcs_cmd_gen()
160 struct list_head *bcm_list = &voter->commit_list; in tcs_list_gen()
170 if ((list_is_last(&bcm->list, bcm_list)) || in tcs_list_gen()
171 bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) { in tcs_list_gen()
176 wait = commit && (voter->tcs_wait & BIT(bucket)); in tcs_list_gen()
178 tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket], in tcs_list_gen()
179 bcm->vote_y[bucket], bcm->addr, commit, wait); in tcs_list_gen()
190 n[batch] -= cur_vcd_size; in tcs_list_gen()
199 * of_bcm_voter_get - gets a bcm voter handle from DT node
211 struct bcm_voter *voter = ERR_PTR(-EPROBE_DEFER); in of_bcm_voter_get()
216 if (!dev || !dev->of_node) in of_bcm_voter_get()
217 return ERR_PTR(-ENODEV); in of_bcm_voter_get()
219 np = dev->of_node; in of_bcm_voter_get()
222 idx = of_property_match_string(np, "qcom,bcm-voter-names", name); in of_bcm_voter_get()
227 node = of_parse_phandle(np, "qcom,bcm-voters", idx); in of_bcm_voter_get()
231 if (temp->np == node) { in of_bcm_voter_get()
244 * qcom_icc_bcm_voter_add - queues up the bcm nodes that require updates
253 mutex_lock(&voter->lock); in qcom_icc_bcm_voter_add()
254 if (list_empty(&bcm->list)) in qcom_icc_bcm_voter_add()
255 list_add_tail(&bcm->list, &voter->commit_list); in qcom_icc_bcm_voter_add()
257 if (list_empty(&bcm->ws_list)) in qcom_icc_bcm_voter_add()
258 list_add_tail(&bcm->ws_list, &voter->ws_list); in qcom_icc_bcm_voter_add()
260 mutex_unlock(&voter->lock); in qcom_icc_bcm_voter_add()
265 * qcom_icc_bcm_voter_commit - generates and commits tcs cmds based on bcms
270 * based on deltas between WAKE/SLEEP requirements. The ws_list persists
287 mutex_lock(&voter->lock); in qcom_icc_bcm_voter_commit()
288 list_for_each_entry(bcm, &voter->commit_list, list) { in qcom_icc_bcm_voter_commit()
289 if (bcm->enable_mask) in qcom_icc_bcm_voter_commit()
296 * Pre sort the BCMs based on VCD for ease of generating a command list in qcom_icc_bcm_voter_commit()
303 list_sort(NULL, &voter->commit_list, cmp_vcd); in qcom_icc_bcm_voter_commit()
306 * Construct the command list based on a pre ordered list of BCMs in qcom_icc_bcm_voter_commit()
307 * based on VCD. in qcom_icc_bcm_voter_commit()
313 rpmh_invalidate(voter->dev); in qcom_icc_bcm_voter_commit()
315 ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE, in qcom_icc_bcm_voter_commit()
318 pr_err("Error sending AMC RPMH requests (%d)\n", ret); in qcom_icc_bcm_voter_commit()
322 list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list) in qcom_icc_bcm_voter_commit()
323 list_del_init(&bcm->list); in qcom_icc_bcm_voter_commit()
325 list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) { in qcom_icc_bcm_voter_commit()
331 if (bcm->vote_x[QCOM_ICC_BUCKET_WAKE] != in qcom_icc_bcm_voter_commit()
332 bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] || in qcom_icc_bcm_voter_commit()
333 bcm->vote_y[QCOM_ICC_BUCKET_WAKE] != in qcom_icc_bcm_voter_commit()
334 bcm->vote_y[QCOM_ICC_BUCKET_SLEEP]) in qcom_icc_bcm_voter_commit()
335 list_add_tail(&bcm->list, &voter->commit_list); in qcom_icc_bcm_voter_commit()
337 list_del_init(&bcm->ws_list); in qcom_icc_bcm_voter_commit()
340 if (list_empty(&voter->commit_list)) in qcom_icc_bcm_voter_commit()
343 list_sort(NULL, &voter->commit_list, cmp_vcd); in qcom_icc_bcm_voter_commit()
347 ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
349 pr_err("Error sending WAKE RPMH requests (%d)\n", ret); in qcom_icc_bcm_voter_commit()
355 ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx); in qcom_icc_bcm_voter_commit()
357 pr_err("Error sending SLEEP RPMH requests (%d)\n", ret); in qcom_icc_bcm_voter_commit()
362 list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list) in qcom_icc_bcm_voter_commit()
363 list_del_init(&bcm->list); in qcom_icc_bcm_voter_commit()
365 mutex_unlock(&voter->lock); in qcom_icc_bcm_voter_commit()
372 struct device_node *np = pdev->dev.of_node; in qcom_icc_bcm_voter_probe()
375 voter = devm_kzalloc(&pdev->dev, sizeof(*voter), GFP_KERNEL); in qcom_icc_bcm_voter_probe()
377 return -ENOMEM; in qcom_icc_bcm_voter_probe()
379 voter->dev = &pdev->dev; in qcom_icc_bcm_voter_probe()
380 voter->np = np; in qcom_icc_bcm_voter_probe()
382 if (of_property_read_u32(np, "qcom,tcs-wait", &voter->tcs_wait)) in qcom_icc_bcm_voter_probe()
383 voter->tcs_wait = QCOM_ICC_TAG_ACTIVE_ONLY; in qcom_icc_bcm_voter_probe()
385 mutex_init(&voter->lock); in qcom_icc_bcm_voter_probe()
386 INIT_LIST_HEAD(&voter->commit_list); in qcom_icc_bcm_voter_probe()
387 INIT_LIST_HEAD(&voter->ws_list); in qcom_icc_bcm_voter_probe()
390 list_add_tail(&voter->voter_node, &bcm_voters); in qcom_icc_bcm_voter_probe()
397 { .compatible = "qcom,bcm-voter" },