static int __init tegra_init_pm_domain(void) { pm_genpd_init(&tegra_mc_clk.gpd, &simple_qos_governor, false); pm_genpd_init(&tegra_nvavp.gpd, &simple_qos_governor, true); tegra_pd_add_sd(&tegra_nvavp.gpd); return 0; }
static int __init cpg_mssr_add_clk_domain(struct device *dev, const unsigned int *core_pm_clks, unsigned int num_core_pm_clks) { struct device_node *np = dev->of_node; struct generic_pm_domain *genpd; struct cpg_mssr_clk_domain *pd; size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]); pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL); if (!pd) return -ENOMEM; pd->np = np; pd->num_core_pm_clks = num_core_pm_clks; memcpy(pd->core_pm_clks, core_pm_clks, pm_size); genpd = &pd->genpd; genpd->name = np->name; genpd->flags = GENPD_FLAG_PM_CLK; genpd->attach_dev = cpg_mssr_attach_dev; genpd->detach_dev = cpg_mssr_detach_dev; pm_genpd_init(genpd, &pm_domain_always_on_gov, false); cpg_mssr_clk_domain = pd; of_genpd_add_provider_simple(np, genpd); return 0; }
static void mtk_register_power_domains(struct platform_device *pdev, struct scp *scp, int num) { struct genpd_onecell_data *pd_data; int i, ret; for (i = 0; i < num; i++) { struct scp_domain *scpd = &scp->domains[i]; struct generic_pm_domain *genpd = &scpd->genpd; /* * Initially turn on all domains to make the domains usable * with !CONFIG_PM and to get the hardware in sync with the * software. The unused domains will be switched off during * late_init time. */ genpd->power_on(genpd); pm_genpd_init(genpd, NULL, false); } /* * We are not allowed to fail here since there is no way to unregister * a power domain. Once registered above we have to keep the domains * valid. */ pd_data = &scp->pd_data; ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); if (ret) dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); }
void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) { struct generic_pm_domain *genpd = &r8a7779_pd->genpd; pm_genpd_init(genpd, NULL, false); genpd->dev_ops.stop = pm_clk_suspend; genpd->dev_ops.start = pm_clk_resume; genpd->dev_ops.active_wakeup = pd_active_wakeup; genpd->dev_irq_safe = true; genpd->power_off = pd_power_down; genpd->power_on = pd_power_up; if (pd_is_off(&r8a7779_pd->genpd)) pd_power_up(&r8a7779_pd->genpd); }
static int gdsc_init(struct gdsc *sc) { u32 mask, val; int on, ret; unsigned int reg; /* * Disable HW trigger: collapse/restore occur based on registers writes. * Disable SW override: Use hardware state-machine for sequencing. * Configure wait time between states. */ mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK | EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK; val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL; ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val); if (ret) return ret; /* Force gdsc ON if only ON state is supported */ if (sc->pwrsts == PWRSTS_ON) { ret = gdsc_toggle_logic(sc, true); if (ret) return ret; } reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; on = gdsc_is_enabled(sc, reg); if (on < 0) return on; /* * Votable GDSCs can be ON due to Vote from other masters. * If a Votable GDSC is ON, make sure we have a Vote. */ if ((sc->flags & VOTABLE) && on) gdsc_enable(&sc->pd); if (on || (sc->pwrsts & PWRSTS_RET)) gdsc_force_mem_on(sc); else gdsc_clear_mem_on(sc); sc->pd.power_off = gdsc_disable; sc->pd.power_on = gdsc_enable; pm_genpd_init(&sc->pd, NULL, !on); return 0; }
static int gdsc_init(struct gdsc *sc) { u32 mask, val; int on, ret; /* * Disable HW trigger: collapse/restore occur based on registers writes. * Disable SW override: Use hardware state-machine for sequencing. * Configure wait time between states. */ mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK | EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK; val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL; ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val); if (ret) return ret; /* Force gdsc ON if only ON state is supported */ if (sc->pwrsts == PWRSTS_ON) { ret = gdsc_toggle_logic(sc, true); if (ret) return ret; } on = gdsc_is_enabled(sc); if (on < 0) return on; if (on || (sc->pwrsts & PWRSTS_RET)) gdsc_force_mem_on(sc); else gdsc_clear_mem_on(sc); sc->pd.power_off = gdsc_disable; sc->pd.power_on = gdsc_enable; sc->pd.attach_dev = gdsc_attach; sc->pd.detach_dev = gdsc_detach; sc->pd.flags = GENPD_FLAG_PM_CLK; pm_genpd_init(&sc->pd, NULL, !on); return 0; }
static int owl_sps_init_domain(struct owl_sps *sps, int index) { struct owl_sps_domain *pd; pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL); if (!pd) return -ENOMEM; pd->info = &sps->info->domains[index]; pd->sps = sps; pd->genpd.name = pd->info->name; pd->genpd.power_on = owl_sps_power_on; pd->genpd.power_off = owl_sps_power_off; pd->genpd.flags = pd->info->genpd_flags; pm_genpd_init(&pd->genpd, NULL, false); sps->genpd_data.domains[index] = &pd->genpd; return 0; }
void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) { struct generic_pm_domain *genpd = &sh7372_pd->genpd; pm_genpd_init(genpd, NULL, false); genpd->stop_device = pm_clk_suspend; genpd->start_device = pm_clk_resume; genpd->active_wakeup = pd_active_wakeup; if (sh7372_pd == &sh7372_a4lc) { genpd->power_off = pd_power_down_a4lc; genpd->power_on = pd_power_up; } else if (sh7372_pd == &sh7372_a3rv) { genpd->power_off = pd_power_down_a3rv; genpd->power_on = pd_power_up_a3rv; } else { genpd->power_off = pd_power_down; genpd->power_on = pd_power_up; } genpd->power_on(&sh7372_pd->genpd); }
void __init cpg_mstp_add_clk_domain(struct device_node *np) { struct generic_pm_domain *pd; u32 ncells; if (of_property_read_u32(np, "#power-domain-cells", &ncells)) { pr_warn("%pOF lacks #power-domain-cells\n", np); return; } pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) return; pd->name = np->name; pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; pd->attach_dev = cpg_mstp_attach_dev; pd->detach_dev = cpg_mstp_detach_dev; pm_genpd_init(pd, &pm_domain_always_on_gov, false); of_genpd_add_provider_simple(np, pd); }
static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains, int xlate_index, const char *name) { struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index]; dom->fw = rpi_domains->fw; dom->base.name = name; dom->base.power_on = rpi_domain_on; dom->base.power_off = rpi_domain_off; /* * Treat all power domains as off at boot. * * The firmware itself may be keeping some domains on, but * from Linux's perspective all we control is the refcounts * that we give to the firmware, and we can't ask the firmware * to turn off something that we haven't ourselves turned on. */ pm_genpd_init(&dom->base, NULL, true); rpi_domains->xlate.domains[xlate_index] = &dom->base; }
int __init ux500_pm_domains_init(void) { struct device_node *np; struct genpd_onecell_data *genpd_data; int i; np = of_find_matching_node(NULL, ux500_pm_domain_matches); if (!np) return -ENODEV; genpd_data = kzalloc(sizeof(*genpd_data), GFP_KERNEL); if (!genpd_data) return -ENOMEM; genpd_data->domains = ux500_pm_domains; genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains); for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i) pm_genpd_init(ux500_pm_domains[i], NULL, NULL, 0, false); of_genpd_add_provider_onecell(np, genpd_data); return 0; }
static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, struct device_node *node) { const struct rockchip_domain_info *pd_info; struct rockchip_pm_domain *pd; struct device_node *qos_node; int i, j; u32 id; int error; error = of_property_read_u32(node, "reg", &id); if (error) { dev_err(pmu->dev, "%s: failed to retrieve domain id (reg): %d\n", node->name, error); return -EINVAL; } if (id >= pmu->info->num_domains) { dev_err(pmu->dev, "%s: invalid domain id %d\n", node->name, id); return -EINVAL; } pd_info = &pmu->info->domain_info[id]; if (!pd_info) { dev_err(pmu->dev, "%s: undefined domain id %d\n", node->name, id); return -EINVAL; } pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL); if (!pd) return -ENOMEM; pd->info = pd_info; pd->pmu = pmu; pd->num_clks = of_clk_get_parent_count(node); if (pd->num_clks > 0) { pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL); if (!pd->clks) return -ENOMEM; } else { dev_dbg(pmu->dev, "%s: doesn't have clocks: %d\n", node->name, pd->num_clks); pd->num_clks = 0; } for (i = 0; i < pd->num_clks; i++) { pd->clks[i].clk = of_clk_get(node, i); if (IS_ERR(pd->clks[i].clk)) { error = PTR_ERR(pd->clks[i].clk); dev_err(pmu->dev, "%s: failed to get clk at index %d: %d\n", node->name, i, error); return error; } } error = clk_bulk_prepare(pd->num_clks, pd->clks); if (error) goto err_put_clocks; pd->num_qos = of_count_phandle_with_args(node, "pm_qos", NULL); if (pd->num_qos > 0) { pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, sizeof(*pd->qos_regmap), GFP_KERNEL); if (!pd->qos_regmap) { error = -ENOMEM; goto err_unprepare_clocks; } for (j = 0; j < MAX_QOS_REGS_NUM; j++) { pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, pd->num_qos, sizeof(u32), GFP_KERNEL); if (!pd->qos_save_regs[j]) { error = -ENOMEM; goto err_unprepare_clocks; } } for (j = 0; j < pd->num_qos; j++) { qos_node = of_parse_phandle(node, "pm_qos", j); if (!qos_node) { error = -ENODEV; goto err_unprepare_clocks; } pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); if (IS_ERR(pd->qos_regmap[j])) { error = -ENODEV; of_node_put(qos_node); goto err_unprepare_clocks; } of_node_put(qos_node); } } error = rockchip_pd_power(pd, true); if (error) { dev_err(pmu->dev, "failed to power on domain '%s': %d\n", node->name, error); goto err_unprepare_clocks; } pd->genpd.name = node->name; pd->genpd.power_off = rockchip_pd_power_off; pd->genpd.power_on = rockchip_pd_power_on; pd->genpd.attach_dev = rockchip_pd_attach_dev; pd->genpd.detach_dev = rockchip_pd_detach_dev; pd->genpd.flags = GENPD_FLAG_PM_CLK; if (pd_info->active_wakeup) pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; pm_genpd_init(&pd->genpd, NULL, false); pmu->genpd_data.domains[id] = &pd->genpd; return 0; err_unprepare_clocks: clk_bulk_unprepare(pd->num_clks, pd->clks); err_put_clocks: clk_bulk_put(pd->num_clks, pd->clks); return error; }
static int scpi_pm_domain_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct scpi_pm_domain *scpi_pd; struct genpd_onecell_data *scpi_pd_data; struct generic_pm_domain **domains; struct scpi_ops *scpi_ops; int ret, num_domains, i; scpi_ops = get_scpi_ops(); if (!scpi_ops) return -EPROBE_DEFER; if (!np) { dev_err(dev, "device tree node not found\n"); return -ENODEV; } if (!scpi_ops->device_set_power_state || !scpi_ops->device_get_power_state) { dev_err(dev, "power domains not supported in the firmware\n"); return -ENODEV; } ret = of_property_read_u32(np, "num-domains", &num_domains); if (ret) { dev_err(dev, "number of domains not found\n"); return -EINVAL; } scpi_pd = devm_kcalloc(dev, num_domains, sizeof(*scpi_pd), GFP_KERNEL); if (!scpi_pd) return -ENOMEM; scpi_pd_data = devm_kzalloc(dev, sizeof(*scpi_pd_data), GFP_KERNEL); if (!scpi_pd_data) return -ENOMEM; domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL); if (!domains) return -ENOMEM; for (i = 0; i < num_domains; i++, scpi_pd++) { domains[i] = &scpi_pd->genpd; scpi_pd->domain = i; scpi_pd->ops = scpi_ops; sprintf(scpi_pd->name, "%pOFn.%d", np, i); scpi_pd->genpd.name = scpi_pd->name; scpi_pd->genpd.power_off = scpi_pd_power_off; scpi_pd->genpd.power_on = scpi_pd_power_on; /* * Treat all power domains as off at boot. * * The SCP firmware itself may have switched on some domains, * but for reference counting purpose, keep it this way. */ pm_genpd_init(&scpi_pd->genpd, NULL, true); } scpi_pd_data->domains = domains; scpi_pd_data->num_domains = num_domains; of_genpd_add_provider_onecell(np, scpi_pd_data); return 0; }
static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, struct device_node *node) { const struct rockchip_domain_info *pd_info; struct rockchip_pm_domain *pd; struct device_node *qos_node; struct clk *clk; int clk_cnt; int i, j; u32 id; int error; error = of_property_read_u32(node, "reg", &id); if (error) { dev_err(pmu->dev, "%s: failed to retrieve domain id (reg): %d\n", node->name, error); return -EINVAL; } if (id >= pmu->info->num_domains) { dev_err(pmu->dev, "%s: invalid domain id %d\n", node->name, id); return -EINVAL; } pd_info = &pmu->info->domain_info[id]; if (!pd_info) { dev_err(pmu->dev, "%s: undefined domain id %d\n", node->name, id); return -EINVAL; } clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells"); pd = devm_kzalloc(pmu->dev, sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]), GFP_KERNEL); if (!pd) return -ENOMEM; pd->info = pd_info; pd->pmu = pmu; for (i = 0; i < clk_cnt; i++) { clk = of_clk_get(node, i); if (IS_ERR(clk)) { error = PTR_ERR(clk); dev_err(pmu->dev, "%s: failed to get clk at index %d: %d\n", node->name, i, error); goto err_out; } error = clk_prepare(clk); if (error) { dev_err(pmu->dev, "%s: failed to prepare clk %pC (index %d): %d\n", node->name, clk, i, error); clk_put(clk); goto err_out; } pd->clks[pd->num_clks++] = clk; dev_dbg(pmu->dev, "added clock '%pC' to domain '%s'\n", clk, node->name); } pd->num_qos = of_count_phandle_with_args(node, "pm_qos", NULL); if (pd->num_qos > 0) { pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, sizeof(*pd->qos_regmap), GFP_KERNEL); if (!pd->qos_regmap) { error = -ENOMEM; goto err_out; } for (j = 0; j < MAX_QOS_REGS_NUM; j++) { pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, pd->num_qos, sizeof(u32), GFP_KERNEL); if (!pd->qos_save_regs[j]) { error = -ENOMEM; goto err_out; } } for (j = 0; j < pd->num_qos; j++) { qos_node = of_parse_phandle(node, "pm_qos", j); if (!qos_node) { error = -ENODEV; goto err_out; } pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); if (IS_ERR(pd->qos_regmap[j])) { error = -ENODEV; of_node_put(qos_node); goto err_out; } of_node_put(qos_node); } } error = rockchip_pd_power(pd, true); if (error) { dev_err(pmu->dev, "failed to power on domain '%s': %d\n", node->name, error); goto err_out; } pd->genpd.name = node->name; pd->genpd.power_off = rockchip_pd_power_off; pd->genpd.power_on = rockchip_pd_power_on; pd->genpd.attach_dev = rockchip_pd_attach_dev; pd->genpd.detach_dev = rockchip_pd_detach_dev; pd->genpd.flags = GENPD_FLAG_PM_CLK; pm_genpd_init(&pd->genpd, NULL, false); pmu->genpd_data.domains[id] = &pd->genpd; return 0; err_out: while (--i >= 0) { clk_unprepare(pd->clks[i]); clk_put(pd->clks[i]); } return error; }