static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, struct device_node *parent) { struct device_node *np; struct generic_pm_domain *child_domain, *parent_domain; int error; for_each_child_of_node(parent, np) { u32 idx; error = of_property_read_u32(parent, "reg", &idx); if (error) { dev_err(pmu->dev, "%s: failed to retrieve domain id (reg): %d\n", parent->name, error); goto err_out; } parent_domain = pmu->genpd_data.domains[idx]; error = rockchip_pm_add_one_domain(pmu, np); if (error) { dev_err(pmu->dev, "failed to handle node %s: %d\n", np->name, error); goto err_out; } error = of_property_read_u32(np, "reg", &idx); if (error) { dev_err(pmu->dev, "%s: failed to retrieve domain id (reg): %d\n", np->name, error); goto err_out; } child_domain = pmu->genpd_data.domains[idx]; error = pm_genpd_add_subdomain(parent_domain, child_domain); if (error) { dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n", parent_domain->name, child_domain->name, error); goto err_out; } else { dev_dbg(pmu->dev, "%s add subdomain: %s\n", parent_domain->name, child_domain->name); } rockchip_pm_add_subdomain(pmu, np); }
static int rockchip_pm_domain_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device_node *node; struct device *parent; struct rockchip_pmu *pmu; const struct of_device_id *match; const struct rockchip_pmu_info *pmu_info; int error; if (!np) { dev_err(dev, "device tree node not found\n"); return -ENODEV; } match = of_match_device(dev->driver->of_match_table, dev); if (!match || !match->data) { dev_err(dev, "missing pmu data\n"); return -EINVAL; } pmu_info = match->data; pmu = devm_kzalloc(dev, sizeof(*pmu) + pmu_info->num_domains * sizeof(pmu->domains[0]), GFP_KERNEL); if (!pmu) return -ENOMEM; pmu->dev = &pdev->dev; mutex_init(&pmu->mutex); pmu->info = pmu_info; pmu->genpd_data.domains = pmu->domains; pmu->genpd_data.num_domains = pmu_info->num_domains; parent = dev->parent; if (!parent) { dev_err(dev, "no parent for syscon devices\n"); return -ENODEV; } pmu->regmap = syscon_node_to_regmap(parent->of_node); /* * Configure power up and down transition delays for CORE * and GPU domains. */ rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset, pmu_info->core_power_transition_time); rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset, pmu_info->gpu_power_transition_time); error = -ENODEV; for_each_available_child_of_node(np, node) { error = rockchip_pm_add_one_domain(pmu, node); if (error) { dev_err(dev, "failed to handle node %s: %d\n", node->name, error); goto err_out; } }