• Home
  • Raw
  • Download

Lines Matching +full:per +full:- +full:cpu +full:- +full:cluster

1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/cpu.h>
9 #include <linux/dma-mapping.h>
19 #include <soc/tegra/bpmp-abi.h>
31 enum cluster { enum
46 u32 cpu; member
59 static void get_cpu_cluster(void *cluster) in get_cpu_cluster() argument
63 *((uint32_t *)cluster) = MPIDR_AFFINITY_LEVEL(mpidr, 1); in get_cpu_cluster()
67 * Read per-core Read-only system register NVFREQ_FEEDBACK_EL1.
87 return nltbl->ref_clk_hz / KHZ * ndiv / (nltbl->pdiv * nltbl->mdiv); in map_ndiv_to_freq()
104 * freq of cluster. Assuming max cluster clock ~2000MHz, in tegra_read_counters()
110 c = &read_counters_work->c; in tegra_read_counters()
113 c->last_refclk_cnt = lower_32_bits(val); in tegra_read_counters()
114 c->last_coreclk_cnt = upper_32_bits(val); in tegra_read_counters()
115 udelay(c->delay); in tegra_read_counters()
117 c->refclk_cnt = lower_32_bits(val); in tegra_read_counters()
118 c->coreclk_cnt = upper_32_bits(val); in tegra_read_counters()
122 * Return instantaneous cpu speed
123 * Instantaneous freq is calculated as -
124 * -Takes sample on every query of getting the freq.
125 * - Read core and ref clock counters;
126 * - Delay for X us
127 * - Read above cycle counters again
128 * - Calculates freq by subtracting current and previous counters
130 * - Return Kcycles/second, freq in KHz
139 * @cpu - logical cpu whose freq to be updated
140 * Returns freq in KHz on success, 0 if cpu is offline
142 static unsigned int tegra194_get_speed_common(u32 cpu, u32 delay) in tegra194_get_speed_common() argument
151 * udelay() is required to reconstruct cpu frequency over an in tegra194_get_speed_common()
155 read_counters_work.c.cpu = cpu; in tegra194_get_speed_common()
158 queue_work_on(cpu, read_counters_wq, &read_counters_work.work); in tegra194_get_speed_common()
163 delta_ccnt = c.coreclk_cnt + (MAX_CNT - c.last_coreclk_cnt); in tegra194_get_speed_common()
165 delta_ccnt = c.coreclk_cnt - c.last_coreclk_cnt; in tegra194_get_speed_common()
171 delta_refcnt = c.refclk_cnt + (MAX_CNT - c.last_refclk_cnt); in tegra194_get_speed_common()
173 delta_refcnt = c.refclk_cnt - c.last_refclk_cnt; in tegra194_get_speed_common()
175 pr_debug("cpufreq: %d is idle, delta_refcnt: 0\n", cpu); in tegra194_get_speed_common()
183 static unsigned int tegra194_get_speed(u32 cpu) in tegra194_get_speed() argument
185 return tegra194_get_speed_common(cpu, US_DELAY); in tegra194_get_speed()
191 u32 cpu; in tegra194_cpufreq_init() local
194 smp_call_function_single(policy->cpu, get_cpu_cluster, &cl, true); in tegra194_cpufreq_init()
196 if (cl >= data->num_clusters) in tegra194_cpufreq_init()
197 return -EINVAL; in tegra194_cpufreq_init()
200 policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY_MIN); in tegra194_cpufreq_init()
202 /* set same policy for all cpus in a cluster */ in tegra194_cpufreq_init()
203 for (cpu = (cl * 2); cpu < ((cl + 1) * 2); cpu++) in tegra194_cpufreq_init()
204 cpumask_set_cpu(cpu, policy->cpus); in tegra194_cpufreq_init()
206 policy->freq_table = data->tables[cl]; in tegra194_cpufreq_init()
207 policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY; in tegra194_cpufreq_init()
215 u64 ndiv_val = (u64)tbl->driver_data; in set_cpu_ndiv()
223 struct cpufreq_frequency_table *tbl = policy->freq_table + index; in tegra194_cpufreq_set_target()
226 * Each core writes frequency in per core register. Then both cores in tegra194_cpufreq_set_target()
227 * in a cluster run at same frequency which is the maximum frequency in tegra194_cpufreq_set_target()
228 * request out of the values requested by both cores in that cluster. in tegra194_cpufreq_set_target()
230 on_each_cpu_mask(policy->cpus, set_cpu_ndiv, tbl, true); in tegra194_cpufreq_set_target()
284 dev_dbg(&pdev->dev, "cluster %d: frequency table step size: %d\n", in init_freq_table()
287 delta_ndiv = resp.ndiv_max - resp.ndiv_min; in init_freq_table()
298 freq_table = devm_kcalloc(&pdev->dev, num_freqs + 1, in init_freq_table()
301 return ERR_PTR(-ENOMEM); in init_freq_table()
323 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); in tegra194_cpufreq_probe()
325 return -ENOMEM; in tegra194_cpufreq_probe()
327 data->num_clusters = MAX_CLUSTERS; in tegra194_cpufreq_probe()
328 data->tables = devm_kcalloc(&pdev->dev, data->num_clusters, in tegra194_cpufreq_probe()
329 sizeof(*data->tables), GFP_KERNEL); in tegra194_cpufreq_probe()
330 if (!data->tables) in tegra194_cpufreq_probe()
331 return -ENOMEM; in tegra194_cpufreq_probe()
335 bpmp = tegra_bpmp_get(&pdev->dev); in tegra194_cpufreq_probe()
341 dev_err(&pdev->dev, "fail to create_workqueue\n"); in tegra194_cpufreq_probe()
342 err = -EINVAL; in tegra194_cpufreq_probe()
346 for (i = 0; i < data->num_clusters; i++) { in tegra194_cpufreq_probe()
347 data->tables[i] = init_freq_table(pdev, bpmp, i); in tegra194_cpufreq_probe()
348 if (IS_ERR(data->tables[i])) { in tegra194_cpufreq_probe()
349 err = PTR_ERR(data->tables[i]); in tegra194_cpufreq_probe()
376 { .compatible = "nvidia,tegra194-ccplex", },
383 .name = "tegra194-cpufreq",