Commit c4f5a40b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-opp'

Merge operating performance points (OPP) updates for 5.20-rc1.

* pm-opp: (43 commits)
  venus: pm_helpers: Fix warning in OPP during probe
  OPP: Don't drop opp->np reference while it is still in use
  OPP: Don't drop opp_table->np reference while it is still in use
  OPP: Remove dev{m}_pm_opp_of_add_table_noclk()
  PM / devfreq: tegra30: Register config_clks helper
  OPP: Allow config_clks helper for single clk case
  OPP: Provide a simple implementation to configure multiple clocks
  OPP: Assert clk_count == 1 for single clk helpers
  OPP: Add key specific assert() method to key finding helpers
  OPP: Compare bandwidths for all paths in _opp_compare_key()
  OPP: Allow multiple clocks for a device
  dt-bindings: opp: accept array of frequencies
  OPP: Make dev_pm_opp_set_opp() independent of frequency
  OPP: Reuse _opp_compare_key() in _opp_add_static_v2()
  OPP: Remove rate_not_available parameter to _opp_add()
  OPP: Use consistent names for OPP table instances
  OPP: Use generic key finding helpers for bandwidth key
  OPP: Use generic key finding helpers for level key
  OPP: Add generic key finding helpers and use them for freq APIs
  OPP: Remove dev_pm_opp_find_freq_ceil_by_volt()
  ...
parents 6ab4b199 f6e0b468
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -50,6 +50,16 @@ patternProperties:
          property to uniquely identify the OPP nodes exists. Devices like power
          domains must have another (implementation dependent) property.

          Entries for multiple clocks shall be provided in the same field, as
          array of frequencies.  The OPP binding doesn't provide any provisions
          to relate the values to their clocks or the order in which the clocks
          need to be configured and that is left for the implementation
          specific binding.
        minItems: 1
        maxItems: 16
        items:
          maxItems: 1

      opp-microvolt:
        description: |
          Voltage for the OPP
+9 −10
Original line number Diff line number Diff line
@@ -29,9 +29,9 @@ struct private_data {

	cpumask_var_t cpus;
	struct device *cpu_dev;
	struct opp_table *opp_table;
	struct cpufreq_frequency_table *freq_table;
	bool have_static_opps;
	int opp_token;
};

static LIST_HEAD(priv_list);
@@ -193,7 +193,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
	struct private_data *priv;
	struct device *cpu_dev;
	bool fallback = false;
	const char *reg_name;
	const char *reg_name[] = { NULL, NULL };
	int ret;

	/* Check if this CPU is already covered by some other policy */
@@ -218,12 +218,11 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
	 * OPP layer will be taking care of regulators now, but it needs to know
	 * the name of the regulator first.
	 */
	reg_name = find_supply_name(cpu_dev);
	if (reg_name) {
		priv->opp_table = dev_pm_opp_set_regulators(cpu_dev, &reg_name,
							    1);
		if (IS_ERR(priv->opp_table)) {
			ret = PTR_ERR(priv->opp_table);
	reg_name[0] = find_supply_name(cpu_dev);
	if (reg_name[0]) {
		priv->opp_token = dev_pm_opp_set_regulators(cpu_dev, reg_name);
		if (priv->opp_token < 0) {
			ret = priv->opp_token;
			if (ret != -EPROBE_DEFER)
				dev_err(cpu_dev, "failed to set regulators: %d\n",
					ret);
@@ -295,7 +294,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
out:
	if (priv->have_static_opps)
		dev_pm_opp_of_cpumask_remove_table(priv->cpus);
	dev_pm_opp_put_regulators(priv->opp_table);
	dev_pm_opp_put_regulators(priv->opp_token);
free_cpumask:
	free_cpumask_var(priv->cpus);
	return ret;
@@ -309,7 +308,7 @@ static void dt_cpufreq_release(void)
		dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
		if (priv->have_static_opps)
			dev_pm_opp_of_cpumask_remove_table(priv->cpus);
		dev_pm_opp_put_regulators(priv->opp_table);
		dev_pm_opp_put_regulators(priv->opp_token);
		free_cpumask_var(priv->cpus);
		list_del(&priv->node);
	}
+6 −6
Original line number Diff line number Diff line
@@ -31,8 +31,8 @@

/* cpufreq-dt device registered by imx-cpufreq-dt */
static struct platform_device *cpufreq_dt_pdev;
static struct opp_table *cpufreq_opp_table;
static struct device *cpu_dev;
static int cpufreq_opp_token;

enum IMX7ULP_CPUFREQ_CLKS {
	ARM,
@@ -153,9 +153,9 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
	dev_info(&pdev->dev, "cpu speed grade %d mkt segment %d supported-hw %#x %#x\n",
			speed_grade, mkt_segment, supported_hw[0], supported_hw[1]);

	cpufreq_opp_table = dev_pm_opp_set_supported_hw(cpu_dev, supported_hw, 2);
	if (IS_ERR(cpufreq_opp_table)) {
		ret = PTR_ERR(cpufreq_opp_table);
	cpufreq_opp_token = dev_pm_opp_set_supported_hw(cpu_dev, supported_hw, 2);
	if (cpufreq_opp_token < 0) {
		ret = cpufreq_opp_token;
		dev_err(&pdev->dev, "Failed to set supported opp: %d\n", ret);
		return ret;
	}
@@ -163,7 +163,7 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
	cpufreq_dt_pdev = platform_device_register_data(
			&pdev->dev, "cpufreq-dt", -1, NULL, 0);
	if (IS_ERR(cpufreq_dt_pdev)) {
		dev_pm_opp_put_supported_hw(cpufreq_opp_table);
		dev_pm_opp_put_supported_hw(cpufreq_opp_token);
		ret = PTR_ERR(cpufreq_dt_pdev);
		dev_err(&pdev->dev, "Failed to register cpufreq-dt: %d\n", ret);
		return ret;
@@ -176,7 +176,7 @@ static int imx_cpufreq_dt_remove(struct platform_device *pdev)
{
	platform_device_unregister(cpufreq_dt_pdev);
	if (!of_machine_is_compatible("fsl,imx7ulp"))
		dev_pm_opp_put_supported_hw(cpufreq_opp_table);
		dev_pm_opp_put_supported_hw(cpufreq_opp_token);
	else
		clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks);

+28 −81
Original line number Diff line number Diff line
@@ -55,9 +55,7 @@ struct qcom_cpufreq_match_data {
};

struct qcom_cpufreq_drv {
	struct opp_table **names_opp_tables;
	struct opp_table **hw_opp_tables;
	struct opp_table **genpd_opp_tables;
	int *opp_tokens;
	u32 versions;
	const struct qcom_cpufreq_match_data *data;
};
@@ -315,72 +313,43 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
	}
	of_node_put(np);

	drv->names_opp_tables = kcalloc(num_possible_cpus(),
				  sizeof(*drv->names_opp_tables),
	drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens),
				  GFP_KERNEL);
	if (!drv->names_opp_tables) {
	if (!drv->opp_tokens) {
		ret = -ENOMEM;
		goto free_drv;
	}
	drv->hw_opp_tables = kcalloc(num_possible_cpus(),
				  sizeof(*drv->hw_opp_tables),
				  GFP_KERNEL);
	if (!drv->hw_opp_tables) {
		ret = -ENOMEM;
		goto free_opp_names;
	}

	drv->genpd_opp_tables = kcalloc(num_possible_cpus(),
					sizeof(*drv->genpd_opp_tables),
					GFP_KERNEL);
	if (!drv->genpd_opp_tables) {
		ret = -ENOMEM;
		goto free_opp;
	}

	for_each_possible_cpu(cpu) {
		struct dev_pm_opp_config config = {
			.supported_hw = NULL,
		};

		cpu_dev = get_cpu_device(cpu);
		if (NULL == cpu_dev) {
			ret = -ENODEV;
			goto free_genpd_opp;
			goto free_opp;
		}

		if (drv->data->get_version) {
			config.supported_hw = &drv->versions;
			config.supported_hw_count = 1;

			if (pvs_name) {
				drv->names_opp_tables[cpu] = dev_pm_opp_set_prop_name(
								     cpu_dev,
								     pvs_name);
				if (IS_ERR(drv->names_opp_tables[cpu])) {
					ret = PTR_ERR(drv->names_opp_tables[cpu]);
					dev_err(cpu_dev, "Failed to add OPP name %s\n",
						pvs_name);
					goto free_opp;
				}
			if (pvs_name)
				config.prop_name = pvs_name;
		}

			drv->hw_opp_tables[cpu] = dev_pm_opp_set_supported_hw(
									 cpu_dev, &drv->versions, 1);
			if (IS_ERR(drv->hw_opp_tables[cpu])) {
				ret = PTR_ERR(drv->hw_opp_tables[cpu]);
				dev_err(cpu_dev,
					"Failed to set supported hardware\n");
				goto free_genpd_opp;
			}
		if (drv->data->genpd_names) {
			config.genpd_names = drv->data->genpd_names;
			config.virt_devs = NULL;
		}

		if (drv->data->genpd_names) {
			drv->genpd_opp_tables[cpu] =
				dev_pm_opp_attach_genpd(cpu_dev,
							drv->data->genpd_names,
							NULL);
			if (IS_ERR(drv->genpd_opp_tables[cpu])) {
				ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
				if (ret != -EPROBE_DEFER)
					dev_err(cpu_dev,
						"Could not attach to pm_domain: %d\n",
						ret);
				goto free_genpd_opp;
		if (config.supported_hw || config.genpd_names) {
			drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config);
			if (drv->opp_tokens[cpu] < 0) {
				ret = drv->opp_tokens[cpu];
				dev_err(cpu_dev, "Failed to set OPP config\n");
				goto free_opp;
			}
		}
	}
@@ -395,27 +364,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
	ret = PTR_ERR(cpufreq_dt_pdev);
	dev_err(cpu_dev, "Failed to register platform device\n");

free_genpd_opp:
	for_each_possible_cpu(cpu) {
		if (IS_ERR(drv->genpd_opp_tables[cpu]))
			break;
		dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
	}
	kfree(drv->genpd_opp_tables);
free_opp:
	for_each_possible_cpu(cpu) {
		if (IS_ERR(drv->names_opp_tables[cpu]))
			break;
		dev_pm_opp_put_prop_name(drv->names_opp_tables[cpu]);
	}
	for_each_possible_cpu(cpu) {
		if (IS_ERR(drv->hw_opp_tables[cpu]))
			break;
		dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
	}
	kfree(drv->hw_opp_tables);
free_opp_names:
	kfree(drv->names_opp_tables);
	for_each_possible_cpu(cpu)
		dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
	kfree(drv->opp_tokens);
free_drv:
	kfree(drv);

@@ -429,15 +381,10 @@ static int qcom_cpufreq_remove(struct platform_device *pdev)

	platform_device_unregister(cpufreq_dt_pdev);

	for_each_possible_cpu(cpu) {
		dev_pm_opp_put_supported_hw(drv->names_opp_tables[cpu]);
		dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
		dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
	}
	for_each_possible_cpu(cpu)
		dev_pm_opp_clear_config(drv->opp_tokens[cpu]);

	kfree(drv->names_opp_tables);
	kfree(drv->hw_opp_tables);
	kfree(drv->genpd_opp_tables);
	kfree(drv->opp_tokens);
	kfree(drv);

	return 0;
+10 −17
Original line number Diff line number Diff line
@@ -156,9 +156,13 @@ static int sti_cpufreq_set_opp_info(void)
	unsigned int hw_info_offset;
	unsigned int version[VERSION_ELEMENTS];
	int pcode, substrate, major, minor;
	int ret;
	int opp_token, ret;
	char name[MAX_PCODE_NAME_LEN];
	struct opp_table *opp_table;
	struct dev_pm_opp_config config = {
		.supported_hw = version,
		.supported_hw_count = ARRAY_SIZE(version),
		.prop_name = name,
	};

	reg_fields = sti_cpufreq_match();
	if (!reg_fields) {
@@ -210,21 +214,14 @@ static int sti_cpufreq_set_opp_info(void)

	snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode);

	opp_table = dev_pm_opp_set_prop_name(dev, name);
	if (IS_ERR(opp_table)) {
		dev_err(dev, "Failed to set prop name\n");
		return PTR_ERR(opp_table);
	}

	version[0] = BIT(major);
	version[1] = BIT(minor);
	version[2] = BIT(substrate);

	opp_table = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS);
	if (IS_ERR(opp_table)) {
		dev_err(dev, "Failed to set supported hardware\n");
		ret = PTR_ERR(opp_table);
		goto err_put_prop_name;
	opp_token = dev_pm_opp_set_config(dev, &config);
	if (opp_token < 0) {
		dev_err(dev, "Failed to set OPP config\n");
		return opp_token;
	}

	dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n",
@@ -233,10 +230,6 @@ static int sti_cpufreq_set_opp_info(void)
		version[0], version[1], version[2]);

	return 0;

err_put_prop_name:
	dev_pm_opp_put_prop_name(opp_table);
	return ret;
}

static int sti_cpufreq_fetch_syscon_registers(void)
Loading