in qcom/msm8974.c [648:744]
static int msm8974_icc_probe(struct platform_device *pdev)
{
const struct msm8974_icc_desc *desc;
struct msm8974_icc_node **qnodes;
struct msm8974_icc_provider *qp;
struct device *dev = &pdev->dev;
struct icc_onecell_data *data;
struct icc_provider *provider;
struct icc_node *node;
size_t num_nodes, i;
int ret;
/* wait for the RPM proxy */
if (!qcom_icc_rpm_smd_available())
return -EPROBE_DEFER;
desc = of_device_get_match_data(dev);
if (!desc)
return -EINVAL;
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
if (!qp)
return -ENOMEM;
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
GFP_KERNEL);
if (!data)
return -ENOMEM;
qp->bus_clks = devm_kmemdup(dev, msm8974_icc_bus_clocks,
sizeof(msm8974_icc_bus_clocks), GFP_KERNEL);
if (!qp->bus_clks)
return -ENOMEM;
qp->num_clks = ARRAY_SIZE(msm8974_icc_bus_clocks);
ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
if (ret)
return ret;
ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
if (ret)
return ret;
provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = msm8974_icc_set;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
provider->get_bw = msm8974_get_bw;
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
goto err_disable_clks;
}
for (i = 0; i < num_nodes; i++) {
size_t j;
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
goto err_del_icc;
}
node->name = qnodes[i]->name;
node->data = qnodes[i];
icc_node_add(node, provider);
dev_dbg(dev, "registered node %s\n", node->name);
/* populate links */
for (j = 0; j < qnodes[i]->num_links; j++)
icc_link_create(node, qnodes[i]->links[j]);
data->nodes[i] = node;
}
data->num_nodes = num_nodes;
platform_set_drvdata(pdev, qp);
return 0;
err_del_icc:
icc_nodes_remove(provider);
icc_provider_del(provider);
err_disable_clks:
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret;
}