Lines Matching +full:per +full:- +full:soc
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 - 2022, NVIDIA CORPORATION. All rights reserved
9 #include <linux/dma-mapping.h>
18 #include <soc/tegra/bpmp.h>
19 #include <soc/tegra/bpmp-abi.h>
31 #define SCRATCH_FREQ_CORE_REG(data, cpu) (data->regs + CMU_CLKS_BASE + CORE_OFFSET(cpu))
35 (data->regs + (MMCRAB_CLUSTER_BASE(cl) + data->soc->actmon_cntr_base))
69 const struct tegra_cpufreq_soc *soc; member
97 /* use physical id to get address of per core frequency register */ in tegra234_get_cpu_ndiv()
98 mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; in tegra234_get_cpu_ndiv()
113 for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) { in tegra234_set_cpu_ndiv()
114 data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); in tegra234_set_cpu_ndiv()
116 /* use physical id to get address of per core frequency register */ in tegra234_set_cpu_ndiv()
117 mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; in tegra234_set_cpu_ndiv()
126 * 64-bit read. The counter values are used to determine the average
138 data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid); in tegra234_read_counters()
142 c->last_refclk_cnt = upper_32_bits(val); in tegra234_read_counters()
143 c->last_coreclk_cnt = lower_32_bits(val); in tegra234_read_counters()
146 c->refclk_cnt = upper_32_bits(val); in tegra234_read_counters()
147 c->coreclk_cnt = lower_32_bits(val); in tegra234_read_counters()
184 * Read per-core Read-only system register NVFREQ_FEEDBACK_EL1.
204 return nltbl->ref_clk_hz / KHZ * ndiv / (nltbl->pdiv * nltbl->mdiv); in map_ndiv_to_freq()
212 c->last_refclk_cnt = lower_32_bits(val); in tegra194_read_counters()
213 c->last_coreclk_cnt = upper_32_bits(val); in tegra194_read_counters()
216 c->refclk_cnt = lower_32_bits(val); in tegra194_read_counters()
217 c->coreclk_cnt = upper_32_bits(val); in tegra194_read_counters()
240 c = &read_counters_work->c; in tegra_read_counters()
242 data->soc->ops->read_counters(c); in tegra_read_counters()
247 * Instantaneous freq is calculated as -
248 * -Takes sample on every query of getting the freq.
249 * - Read core and ref clock counters;
250 * - Delay for X us
251 * - Read above cycle counters again
252 * - Calculates freq by subtracting current and previous counters
254 * - Return Kcycles/second, freq in KHz
263 * @cpu - logical cpu whose freq to be updated
286 delta_ccnt = c.coreclk_cnt + (MAX_CNT - c.last_coreclk_cnt); in tegra194_calculate_speed()
288 delta_ccnt = c.coreclk_cnt - c.last_coreclk_cnt; in tegra194_calculate_speed()
294 delta_refcnt = c.refclk_cnt + (MAX_CNT - c.last_refclk_cnt); in tegra194_calculate_speed()
296 delta_refcnt = c.refclk_cnt - c.last_refclk_cnt; in tegra194_calculate_speed()
329 on_each_cpu_mask(policy->cpus, tegra194_set_cpu_ndiv_sysreg, &ndiv, true); in tegra194_set_cpu_ndiv()
341 data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); in tegra194_get_speed()
347 ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv); in tegra194_get_speed()
357 cpufreq_for_each_valid_entry(pos, data->tables[clusterid]) { in tegra194_get_speed()
358 if (pos->driver_data != ndiv) in tegra194_get_speed()
361 if (abs(pos->frequency - rate) > 115200) { in tegra194_get_speed()
363 cpu, rate, pos->frequency, ndiv); in tegra194_get_speed()
365 rate = pos->frequency; in tegra194_get_speed()
375 int maxcpus_per_cluster = data->soc->maxcpus_per_cluster; in tegra194_cpufreq_init()
379 data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid); in tegra194_cpufreq_init()
381 if (clusterid >= data->soc->num_clusters || !data->tables[clusterid]) in tegra194_cpufreq_init()
382 return -EINVAL; in tegra194_cpufreq_init()
384 start_cpu = rounddown(policy->cpu, maxcpus_per_cluster); in tegra194_cpufreq_init()
388 cpumask_set_cpu(cpu, policy->cpus); in tegra194_cpufreq_init()
390 policy->freq_table = data->tables[clusterid]; in tegra194_cpufreq_init()
391 policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY; in tegra194_cpufreq_init()
399 struct cpufreq_frequency_table *tbl = policy->freq_table + index; in tegra194_cpufreq_set_target()
403 * Each core writes frequency in per core register. Then both cores in tegra194_cpufreq_set_target()
407 data->soc->ops->set_cpu_ndiv(policy, (u64)tbl->driver_data); in tegra194_cpufreq_set_target()
465 if (msg.rx.ret == -BPMP_EINVAL) { in init_freq_table()
470 return ERR_PTR(-EINVAL); in init_freq_table()
479 dev_dbg(&pdev->dev, "cluster %d: frequency table step size: %d\n", in init_freq_table()
482 delta_ndiv = resp.ndiv_max - resp.ndiv_min; in init_freq_table()
493 freq_table = devm_kcalloc(&pdev->dev, num_freqs + 1, in init_freq_table()
496 return ERR_PTR(-ENOMEM); in init_freq_table()
514 const struct tegra_cpufreq_soc *soc; in tegra194_cpufreq_probe() local
519 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); in tegra194_cpufreq_probe()
521 return -ENOMEM; in tegra194_cpufreq_probe()
523 soc = of_device_get_match_data(&pdev->dev); in tegra194_cpufreq_probe()
525 if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters) { in tegra194_cpufreq_probe()
526 data->soc = soc; in tegra194_cpufreq_probe()
528 dev_err(&pdev->dev, "soc data missing\n"); in tegra194_cpufreq_probe()
529 return -EINVAL; in tegra194_cpufreq_probe()
532 data->tables = devm_kcalloc(&pdev->dev, data->soc->num_clusters, in tegra194_cpufreq_probe()
533 sizeof(*data->tables), GFP_KERNEL); in tegra194_cpufreq_probe()
534 if (!data->tables) in tegra194_cpufreq_probe()
535 return -ENOMEM; in tegra194_cpufreq_probe()
537 if (soc->actmon_cntr_base) { in tegra194_cpufreq_probe()
538 /* mmio registers are used for frequency request and re-construction */ in tegra194_cpufreq_probe()
539 data->regs = devm_platform_ioremap_resource(pdev, 0); in tegra194_cpufreq_probe()
540 if (IS_ERR(data->regs)) in tegra194_cpufreq_probe()
541 return PTR_ERR(data->regs); in tegra194_cpufreq_probe()
546 bpmp = tegra_bpmp_get(&pdev->dev); in tegra194_cpufreq_probe()
552 dev_err(&pdev->dev, "fail to create_workqueue\n"); in tegra194_cpufreq_probe()
553 err = -EINVAL; in tegra194_cpufreq_probe()
557 for (i = 0; i < data->soc->num_clusters; i++) { in tegra194_cpufreq_probe()
558 data->tables[i] = init_freq_table(pdev, bpmp, i); in tegra194_cpufreq_probe()
559 if (IS_ERR(data->tables[i])) { in tegra194_cpufreq_probe()
560 err = PTR_ERR(data->tables[i]); in tegra194_cpufreq_probe()
587 { .compatible = "nvidia,tegra194-ccplex", .data = &tegra194_cpufreq_soc },
588 { .compatible = "nvidia,tegra234-ccplex-cluster", .data = &tegra234_cpufreq_soc },
589 { .compatible = "nvidia,tegra239-ccplex-cluster", .data = &tegra239_cpufreq_soc },
596 .name = "tegra194-cpufreq",