static struct clk * scpi_clk_ops_init(struct device *dev, const struct of_device_id *match, struct scpi_clk *sclk, const char *name) { struct clk_init_data init; struct clk *clk; unsigned long min = 0, max = 0; init.name = name; init.flags = CLK_IS_ROOT; init.num_parents = 0; init.ops = match->data; sclk->hw.init = &init; sclk->scpi_ops = get_scpi_ops(); if (init.ops == &scpi_dvfs_ops) { sclk->info = sclk->scpi_ops->dvfs_get_info(sclk->id); if (IS_ERR(sclk->info)) return NULL; } else if (init.ops == &scpi_clk_ops) { if (sclk->scpi_ops->clk_get_range(sclk->id, &min, &max) || !max) return NULL; } else { return NULL; } clk = devm_clk_register(dev, &sclk->hw); if (!IS_ERR(clk) && max) clk_hw_set_rate_range(&sclk->hw, min, max); return clk; }
static int init_juno_opps_from_scpi(struct device *dev) { struct scpi_ops *scpi; struct scpi_dvfs_info *info; int i; scpi = get_scpi_ops(); if (!scpi) return 0; /* Really need to defer until scpi available */ /* Hard coded for Juno. 2 is GPU domain */ info = scpi->dvfs_get_info(2); if (IS_ERR_OR_NULL(info)) return PTR_ERR(info); for (i = 0; i < info->count; i++) { struct scpi_opp *e = &info->opps[i]; dev_info(dev, "Mali OPP from SCPI: %u Hz @ %u mV\n", e->freq, e->m_volt); dev_pm_opp_add(dev, e->freq, e->m_volt * 1000); } return 0; }
static int scpi_cpufreq_probe(struct platform_device *pdev) { scpi_ops = get_scpi_ops(); if (!scpi_ops) return -EIO; return bL_cpufreq_register(&scpi_cpufreq_ops); }
static int scpi_cpufreq_probe(struct platform_device *pdev) { int ret; scpi_ops = get_scpi_ops(); if (!scpi_ops) return -EIO; ret = cpufreq_register_driver(&scpi_cpufreq_driver); if (ret) dev_err(&pdev->dev, "%s: registering cpufreq failed, err: %d\n", __func__, ret); return ret; }
static int scpi_clocks_probe(struct platform_device *pdev) { int ret; struct device *dev = &pdev->dev; struct device_node *child, *np = dev->of_node; const struct of_device_id *match; if (!get_scpi_ops()) return -ENXIO; for_each_available_child_of_node(np, child) { match = of_match_node(scpi_clk_match, child); if (!match) continue; ret = scpi_clk_add(dev, child, match); if (ret) { scpi_clocks_remove(pdev); of_node_put(child); return ret; } }
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; }