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

Merge tag 'cpufreq-arm-updates-6.18-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Merge CPUFreq fixes for 6.18 from Viresh Kumar:

"- Update frequency for all tegra CPUs (Aaron Kling).

 - Fix device leak in mediatek driver (Johan Hovold).

 - Rust cpufreq helper cleanup (Thorsten Blum)."

* tag 'cpufreq-arm-updates-6.18-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: tegra186: Initialize all cores to max frequencies
  cpufreq: tegra186: Set target frequency for all cpus in policy
  rust: cpufreq: streamline find_supply_names
  cpufreq: mediatek: fix device leak on probe failure
parents 950c6451 ba601892
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -403,9 +403,11 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
	}

	info->cpu_clk = clk_get(cpu_dev, "cpu");
	if (IS_ERR(info->cpu_clk))
		return dev_err_probe(cpu_dev, PTR_ERR(info->cpu_clk),
				     "cpu%d: failed to get cpu clk\n", cpu);
	if (IS_ERR(info->cpu_clk)) {
		ret = PTR_ERR(info->cpu_clk);
		dev_err_probe(cpu_dev, ret, "cpu%d: failed to get cpu clk\n", cpu);
		goto out_put_cci_dev;
	}

	info->inter_clk = clk_get(cpu_dev, "intermediate");
	if (IS_ERR(info->inter_clk)) {
@@ -551,6 +553,10 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
out_free_mux_clock:
	clk_put(info->cpu_clk);

out_put_cci_dev:
	if (info->soc_data->ccifreq_supported)
		put_device(info->cci_dev);

	return ret;
}

@@ -568,6 +574,8 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
	clk_put(info->inter_clk);
	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
	dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb);
	if (info->soc_data->ccifreq_supported)
		put_device(info->cci_dev);
}

static int mtk_cpufreq_init(struct cpufreq_policy *policy)
+3 −7
Original line number Diff line number Diff line
@@ -28,15 +28,11 @@ fn find_supply_name_exact(dev: &Device, name: &str) -> Option<CString> {
/// Finds supply name for the CPU from DT.
fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option<KVec<CString>> {
    // Try "cpu0" for older DTs, fallback to "cpu".
    let name = (cpu.as_u32() == 0)
    (cpu.as_u32() == 0)
        .then(|| find_supply_name_exact(dev, "cpu0"))
        .flatten()
        .or_else(|| find_supply_name_exact(dev, "cpu"))?;

    let mut list = KVec::with_capacity(1, GFP_KERNEL).ok()?;
    list.push(name, GFP_KERNEL).ok()?;

    Some(list)
        .or_else(|| find_supply_name_exact(dev, "cpu"))
        .and_then(|name| kernel::kvec![name].ok())
}

/// Represents the cpufreq dt device.
+27 −8
Original line number Diff line number Diff line
@@ -93,10 +93,14 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy,
{
	struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
	struct cpufreq_frequency_table *tbl = policy->freq_table + index;
	unsigned int edvd_offset = data->cpus[policy->cpu].edvd_offset;
	unsigned int edvd_offset;
	u32 edvd_val = tbl->driver_data;
	u32 cpu;

	for_each_cpu(cpu, policy->cpus) {
		edvd_offset = data->cpus[cpu].edvd_offset;
		writel(edvd_val, data->regs + edvd_offset);
	}

	return 0;
}
@@ -132,13 +136,14 @@ static struct cpufreq_driver tegra186_cpufreq_driver = {

static struct cpufreq_frequency_table *init_vhint_table(
	struct platform_device *pdev, struct tegra_bpmp *bpmp,
	struct tegra186_cpufreq_cluster *cluster, unsigned int cluster_id)
	struct tegra186_cpufreq_cluster *cluster, unsigned int cluster_id,
	int *num_rates)
{
	struct cpufreq_frequency_table *table;
	struct mrq_cpu_vhint_request req;
	struct tegra_bpmp_message msg;
	struct cpu_vhint_data *data;
	int err, i, j, num_rates = 0;
	int err, i, j;
	dma_addr_t phys;
	void *virt;

@@ -168,6 +173,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
		goto free;
	}

	*num_rates = 0;
	for (i = data->vfloor; i <= data->vceil; i++) {
		u16 ndiv = data->ndiv[i];

@@ -178,10 +184,10 @@ static struct cpufreq_frequency_table *init_vhint_table(
		if (i > 0 && ndiv == data->ndiv[i - 1])
			continue;

		num_rates++;
		(*num_rates)++;
	}

	table = devm_kcalloc(&pdev->dev, num_rates + 1, sizeof(*table),
	table = devm_kcalloc(&pdev->dev, *num_rates + 1, sizeof(*table),
			     GFP_KERNEL);
	if (!table) {
		table = ERR_PTR(-ENOMEM);
@@ -223,7 +229,9 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
{
	struct tegra186_cpufreq_data *data;
	struct tegra_bpmp *bpmp;
	unsigned int i = 0, err;
	unsigned int i = 0, err, edvd_offset;
	int num_rates = 0;
	u32 edvd_val, cpu;

	data = devm_kzalloc(&pdev->dev,
			    struct_size(data, clusters, TEGRA186_NUM_CLUSTERS),
@@ -246,10 +254,21 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
	for (i = 0; i < TEGRA186_NUM_CLUSTERS; i++) {
		struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];

		cluster->table = init_vhint_table(pdev, bpmp, cluster, i);
		cluster->table = init_vhint_table(pdev, bpmp, cluster, i, &num_rates);
		if (IS_ERR(cluster->table)) {
			err = PTR_ERR(cluster->table);
			goto put_bpmp;
		} else if (!num_rates) {
			err = -EINVAL;
			goto put_bpmp;
		}

		for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) {
			if (data->cpus[cpu].bpmp_cluster_id == i) {
				edvd_val = cluster->table[num_rates - 1].driver_data;
				edvd_offset = data->cpus[cpu].edvd_offset;
				writel(edvd_val, data->regs + edvd_offset);
			}
		}
	}