/** * struct bcm_voter - Bus Clock Manager voter * @dev: reference to the device that communicates with the BCM * @np: reference to the device node to match bcm voters * @lock: mutex to protect commit and wake/sleep lists in the voter * @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
*/ struct bcm_voter { struct device *dev; struct device_node *np; struct mutex lock; struct list_head commit_list; struct list_head ws_list; struct list_head voter_node;
u32 tcs_wait;
};
for (i = 0; i < bcm->num_nodes; i++) {
node = bcm->nodes[i];
/* If any vote in this bucket exists, keep the BCM enabled */ if (node->sum_avg[bucket] || node->max_peak[bucket]) {
bcm->vote_x[bucket] = 0;
bcm->vote_y[bucket] = bcm->enable_mask; break;
}
}
}
tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket],
bcm->vote_y[bucket], bcm->addr, commit, wait);
idx++;
n[batch]++; /* * Batch the BCMs in such a way that we do not split them in * multiple payloads when they are under the same VCD. This is * to ensure that every BCM is committed since we only set the * commit bit on the last BCM request of every VCD.
*/ if (n[batch] >= MAX_RPMH_PAYLOAD) { if (!commit) {
n[batch] -= cur_vcd_size;
n[batch + 1] = cur_vcd_size;
}
batch++;
}
}
}
/** * of_bcm_voter_get - gets a bcm voter handle from DT node * @dev: device pointer for the consumer device * @name: name for the bcm voter device * * This function will match a device_node pointer for the phandle * specified in the device DT and return a bcm_voter handle on success. * * Returns bcm_voter pointer or ERR_PTR() on error. EPROBE_DEFER is returned * when matching bcm voter is yet to be found.
*/ struct bcm_voter *of_bcm_voter_get(struct device *dev, constchar *name)
{ struct bcm_voter *voter = ERR_PTR(-EPROBE_DEFER); struct bcm_voter *temp; struct device_node *np, *node; int idx = 0;
if (!dev || !dev->of_node) return ERR_PTR(-ENODEV);
np = dev->of_node;
if (name) {
idx = of_property_match_string(np, "qcom,bcm-voter-names", name); if (idx < 0) return ERR_PTR(idx);
}
/** * qcom_icc_bcm_voter_add - queues up the bcm nodes that require updates * @voter: voter that the bcms are being added to * @bcm: bcm to add to the commit and wake sleep list
*/ void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm)
{ if (!voter) return;
mutex_lock(&voter->lock); if (list_empty(&bcm->list))
list_add_tail(&bcm->list, &voter->commit_list);
if (list_empty(&bcm->ws_list))
list_add_tail(&bcm->ws_list, &voter->ws_list);
/** * qcom_icc_bcm_voter_commit - generates and commits tcs cmds based on bcms * @voter: voter that needs flushing * * This function generates a set of AMC commands and flushes to the BCM device * associated with the voter. It conditionally generate WAKE and SLEEP commands * based on deltas between WAKE/SLEEP requirements. The ws_list persists * through multiple commit requests and bcm nodes are removed only when the * requirements for WAKE matches SLEEP. * * Returns 0 on success, or an appropriate error code otherwise.
*/ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
{ struct qcom_icc_bcm *bcm; struct qcom_icc_bcm *bcm_tmp; int commit_idx[MAX_VCD + 1]; struct tcs_cmd cmds[MAX_BCMS]; int ret = 0;
/* * Pre sort the BCMs based on VCD for ease of generating a command list * that groups the BCMs with the same VCD together. VCDs are numbered * with lowest being the most expensive time wise, ensuring that * those commands are being sent the earliest in the queue. This needs * to be sorted every commit since we can't guarantee the order in which * the BCMs are added to the list.
*/
list_sort(NULL, &voter->commit_list, cmp_vcd);
/* * Construct the command list based on a pre ordered list of BCMs * based on VCD.
*/
tcs_list_gen(voter, QCOM_ICC_BUCKET_AMC, cmds, commit_idx); if (!commit_idx[0]) goto out;
rpmh_invalidate(voter->dev);
ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE,
cmds, commit_idx); if (ret) {
pr_err("Error sending AMC RPMH requests (%d)\n", ret); goto out;
}
list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) { /* * Only generate WAKE and SLEEP commands if a resource's * requirements change as the execution environment transitions * between different power states.
*/ if (bcm->vote_x[QCOM_ICC_BUCKET_WAKE] !=
bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] ||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] !=
bcm->vote_y[QCOM_ICC_BUCKET_SLEEP])
list_add_tail(&bcm->list, &voter->commit_list); else
list_del_init(&bcm->ws_list);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.