in power/domain.c [2288:2356]
int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data)
{
struct generic_pm_domain *genpd;
unsigned int i;
int ret = -EINVAL;
if (!np || !data)
return -EINVAL;
if (!data->xlate)
data->xlate = genpd_xlate_onecell;
for (i = 0; i < data->num_domains; i++) {
genpd = data->domains[i];
if (!genpd)
continue;
if (!genpd_present(genpd))
goto error;
genpd->dev.of_node = np;
/* Parse genpd OPP table */
if (genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(&genpd->dev, "Failed to add OPP table for index %d: %d\n",
i, ret);
goto error;
}
/*
* Save table for faster processing while setting
* performance state.
*/
genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev);
WARN_ON(IS_ERR(genpd->opp_table));
}
genpd->provider = &np->fwnode;
genpd->has_provider = true;
}
ret = genpd_add_provider(np, data->xlate, data);
if (ret < 0)
goto error;
return 0;
error:
while (i--) {
genpd = data->domains[i];
if (!genpd)
continue;
genpd->provider = NULL;
genpd->has_provider = false;
if (genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
}
return ret;
}