ret = clk_set_rate(clk[new_cluster], new_rate * 1000); if (!ret) { /* * FIXME: clk_set_rate hasn't returned an error here however it * may be that clk_change_rate failed due to hardware or * firmware issues and wasn't able to report that due to the * current design of the clk core layer. To work around this * problem we will read back the clock rate and check it is * correct. This needs to be removed once clk core is fixed.
*/ if (clk_get_rate(clk[new_cluster]) != new_rate * 1000)
ret = -EIO;
}
if (WARN_ON(ret)) { if (bLs) {
per_cpu(cpu_last_req_freq, cpu) = prev_rate;
per_cpu(physical_cluster, cpu) = old_cluster;
}
mutex_unlock(&cluster_lock[new_cluster]);
return ret;
}
mutex_unlock(&cluster_lock[new_cluster]);
/* Recalc freq for old cluster when switching clusters */ if (old_cluster != new_cluster) { /* Switch cluster */
bL_switch_request(cpu, new_cluster);
mutex_lock(&cluster_lock[old_cluster]);
/* Set freq of old cluster if there are cpus left on it */
new_rate = find_cluster_maxfreq(old_cluster);
new_rate = ACTUAL_FREQ(old_cluster, new_rate);
staticinline u32 get_table_count(struct cpufreq_frequency_table *table)
{ int count;
for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
;
return count;
}
/* get the minimum frequency in the cpufreq_frequency_table */ staticinline u32 get_table_min(struct cpufreq_frequency_table *table)
{ struct cpufreq_frequency_table *pos;
u32 min_freq = ~0;
/* get the maximum frequency in the cpufreq_frequency_table */ staticinline u32 get_table_max(struct cpufreq_frequency_table *table)
{ struct cpufreq_frequency_table *pos;
u32 max_freq = 0;
staticbool search_frequency(struct cpufreq_frequency_table *table, int size, unsignedint freq)
{ int count;
for (count = 0; count < size; count++) { if (table[count].frequency == freq) returntrue;
}
returnfalse;
}
staticint merge_cluster_tables(void)
{ int i, j, k = 0, count = 1; struct cpufreq_frequency_table *table;
for (i = 0; i < MAX_CLUSTERS; i++)
count += get_table_count(freq_table[i]);
table = kcalloc(count, sizeof(*table), GFP_KERNEL); if (!table) return -ENOMEM;
freq_table[MAX_CLUSTERS] = table;
/* Add in reverse order to get freqs in increasing order */ for (i = MAX_CLUSTERS - 1; i >= 0; i--, count = k) { for (j = 0; freq_table[i][j].frequency != CPUFREQ_TABLE_END;
j++) { if (i == A15_CLUSTER &&
search_frequency(table, count, freq_table[i][j].frequency)) continue; /* skip duplicates */
table[k++].frequency =
VIRT_FREQ(i, freq_table[i][j].frequency);
}
}
/* * platform specific SPC code must initialise the opp table * so just check if the OPP count is non-zero
*/
ret = dev_pm_opp_get_opp_count(cpu_dev) <= 0; if (ret) goto out;
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]); if (ret) goto out;
clk[cluster] = clk_get(cpu_dev, NULL); if (!IS_ERR(clk[cluster])) return 0;
dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d, cluster: %d\n",
__func__, cpu_dev->id, cluster);
ret = PTR_ERR(clk[cluster]);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
out:
dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__,
cluster); return ret;
}
staticint get_cluster_clk_and_freq_table(struct device *cpu_dev, conststruct cpumask *cpumask)
{
u32 cluster = cpu_to_cluster(cpu_dev->id); int i, ret;
if (atomic_inc_return(&cluster_usage[cluster]) != 1) return 0;
if (cluster < MAX_CLUSTERS) {
ret = _get_cluster_clk_and_freq_table(cpu_dev, cpumask); if (ret)
atomic_dec(&cluster_usage[cluster]); return ret;
}
/* * Get data for all clusters and fill virtual cluster with a merge of * both
*/
for_each_present_cpu(i) { struct device *cdev = get_cpu_device(i);
if (!cdev) return -ENODEV;
ret = _get_cluster_clk_and_freq_table(cdev, cpumask); if (ret) goto put_clusters;
}
ret = merge_cluster_tables(); if (ret) goto put_clusters;
/* Assuming 2 cluster, set clk_big_min and clk_little_max */
clk_big_min = get_table_min(freq_table[A15_CLUSTER]);
clk_little_max = VIRT_FREQ(A7_CLUSTER,
get_table_max(freq_table[A7_CLUSTER]));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.