// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
qn->sum_avg[i] = 0;
qn->max_peak[i] = 0;
}
for (i = 0; i < qn->num_bcms; i++)
qcom_icc_bcm_voter_add(qp->voter, qn->bcms[i]);
}
EXPORT_SYMBOL_GPL(qcom_icc_pre_aggregate);
/** * qcom_icc_aggregate - aggregate bw for buckets indicated by tag * @node: node to aggregate * @tag: tag to indicate which buckets to aggregate * @avg_bw: new bw to sum aggregate * @peak_bw: new bw to max aggregate * @agg_avg: existing aggregate avg bw val * @agg_peak: existing aggregate peak bw val
*/ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
size_t i; struct qcom_icc_node *qn;
qn = node->data;
if (!tag)
tag = QCOM_ICC_TAG_ALWAYS;
for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { if (tag & BIT(i)) {
qn->sum_avg[i] += avg_bw;
qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
}
/** * qcom_icc_set - set the constraints based on path * @src: source node for the path to set constraints on * @dst: destination node for the path to set constraints on * * Return: 0 on success, or an error code otherwise
*/ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
{ struct qcom_icc_provider *qp; struct icc_node *node;
if (!src)
node = dst; else
node = src;
qp = to_qcom_provider(node->provider);
qcom_icc_bcm_voter_commit(qp->voter);
return 0;
}
EXPORT_SYMBOL_GPL(qcom_icc_set);
/** * qcom_icc_bcm_init - populates bcm aux data and connect qnodes * @bcm: bcm to be initialized * @dev: associated provider device * * Return: 0 on success, or an error code otherwise
*/ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
{ struct qcom_icc_node *qn; conststruct bcm_db *data;
size_t data_count; int i;
/* BCM is already initialised*/ if (bcm->addr) return 0;
bcm->addr = cmd_db_read_addr(bcm->name); if (!bcm->addr) {
dev_err(dev, "%s could not find RPMh address\n",
bcm->name); return -EINVAL;
}
data = cmd_db_read_aux_data(bcm->name, &data_count); if (IS_ERR(data)) {
dev_err(dev, "%s command db read error (%ld)\n",
bcm->name, PTR_ERR(data)); return PTR_ERR(data);
} if (!data_count) {
dev_err(dev, "%s command db missing or partial aux data\n",
bcm->name); return -EINVAL;
}
qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks); if (qp->num_clks == -EPROBE_DEFER) return dev_err_probe(dev, qp->num_clks, "Failed to get QoS clocks\n");
if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_requires_clocks)) {
dev_info(dev, "Skipping QoS, failed to get clk: %d\n", qp->num_clks); goto skip_qos_config;
}
ret = qcom_icc_rpmh_configure_qos(qp); if (ret)
dev_info(dev, "Failed to program QoS: %d\n", ret);
}
skip_qos_config:
ret = icc_provider_register(provider); if (ret) goto err_remove_nodes;
platform_set_drvdata(pdev, qp);
/* Populate child NoC devices if any */ if (of_get_child_count(dev->of_node) > 0) {
ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) goto err_deregister_provider;
}
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.