diff options
| author | Leon Yu <leoyu@nvidia.com> | 2019-09-16 00:29:33 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-10-11 11:35:07 -0400 |
| commit | 74a8fe96ec7e89db246ddea8b6794cbbd46dda84 (patch) | |
| tree | 5a534cf809dcd79e1909dad702e0cdf93d445b0c | |
| parent | d6c7740ea2ddd9d5087d938e9ee3b3bc2c9b6d0a (diff) | |
cpufreq: t194: use CPU to EMC freq mapping helpers
This CL replaces existing CPU to EMC mapping related code with common
helpers to eliminate inconsistencies between cpufreq drivers including:
1) different implementations of same functionality
2) different formats of CPU to EMC freq. mapping table
This change also prevents one potential bug that existing code only
works for mapping table which is sorted in descending order (won't
work in ascending order). The helper function to be used don't have
such constrain.
Bug 200551611
Bug 200512604
Change-Id: I199219b9a9b0bda10f1f6b941101e7ca24f878ac
Signed-off-by: Leon Yu <leoyu@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2198539
Reviewed-by: Aaron Tian <atian@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bo Yan <byan@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
| -rw-r--r-- | drivers/cpufreq/tegra194_cpufreq.c | 80 |
1 files changed, 7 insertions, 73 deletions
diff --git a/drivers/cpufreq/tegra194_cpufreq.c b/drivers/cpufreq/tegra194_cpufreq.c index 339f923a2..64455007c 100644 --- a/drivers/cpufreq/tegra194_cpufreq.c +++ b/drivers/cpufreq/tegra194_cpufreq.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This software is licensed under the terms of the GNU General Public | 4 | * This software is licensed under the terms of the GNU General Public |
| 5 | * License version 2, as published by the Free Software Foundation, and | 5 | * License version 2, as published by the Free Software Foundation, and |
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/pm_qos.h> | 38 | #include <linux/pm_qos.h> |
| 39 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
| 40 | #include <linux/tegra-cpufreq.h> | 40 | #include <linux/tegra-cpufreq.h> |
| 41 | #include "cpufreq_cpu_emc_table.h" | ||
| 41 | 42 | ||
| 42 | /* cpufreq transisition latency */ | 43 | /* cpufreq transisition latency */ |
| 43 | #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */ | 44 | #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */ |
| @@ -53,12 +54,7 @@ | |||
| 53 | #define LOOP_FOR_EACH_CLUSTER(cl) for (cl = 0; \ | 54 | #define LOOP_FOR_EACH_CLUSTER(cl) for (cl = 0; \ |
| 54 | cl < MAX_CLUSTERS; cl++) | 55 | cl < MAX_CLUSTERS; cl++) |
| 55 | 56 | ||
| 56 | struct cpu_emc_map { | 57 | static struct cpu_emc_mapping *cpu_emc_map_ptr; |
| 57 | uint32_t cpufreq; /* unit in KHz */ | ||
| 58 | uint32_t emcfreq; /* unit in KHz */ | ||
| 59 | }; | ||
| 60 | static struct cpu_emc_map *cpu_emc_map_ptr; | ||
| 61 | static uint16_t cpu_emc_map_num; | ||
| 62 | static uint8_t tegra_hypervisor_mode; | 58 | static uint8_t tegra_hypervisor_mode; |
| 63 | 59 | ||
| 64 | static int cpufreq_single_policy; | 60 | static int cpufreq_single_policy; |
| @@ -239,29 +235,12 @@ static unsigned int tegra194_fast_get_speed(uint32_t cpu) | |||
| 239 | return tegra194_get_speed_common(cpu, US_DELAY_MIN); | 235 | return tegra194_get_speed_common(cpu, US_DELAY_MIN); |
| 240 | } | 236 | } |
| 241 | 237 | ||
| 242 | /** | ||
| 243 | * cluster_cpu_to_emc_freq - return emc freq in cpu_emc_map table corresponding | ||
| 244 | * to cpu rate input | ||
| 245 | * @cpu_rate - cpu rate in KHz | ||
| 246 | * Returns emc freq in KHz | ||
| 247 | */ | ||
| 248 | static unsigned long cluster_cpu_to_emc_freq(uint32_t cpu_rate) | ||
| 249 | { | ||
| 250 | int i; | ||
| 251 | |||
| 252 | for (i = 0; i < cpu_emc_map_num; i++) { | ||
| 253 | if (cpu_rate >= cpu_emc_map_ptr[i].cpufreq) | ||
| 254 | return cpu_emc_map_ptr[i].emcfreq; | ||
| 255 | } | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | /* Set emc clock by referring cpu_to_emc freq mapping */ | 238 | /* Set emc clock by referring cpu_to_emc freq mapping */ |
| 260 | static void set_cpufreq_to_emcfreq(enum cluster cl, uint32_t cluster_freq) | 239 | static void set_cpufreq_to_emcfreq(enum cluster cl, uint32_t cluster_freq) |
| 261 | { | 240 | { |
| 262 | unsigned long emc_freq; | 241 | unsigned long emc_freq; |
| 263 | 242 | ||
| 264 | emc_freq = cluster_cpu_to_emc_freq(cluster_freq); | 243 | emc_freq = tegra_cpu_to_emc_freq(cluster_freq, cpu_emc_map_ptr); |
| 265 | 244 | ||
| 266 | tegra_bwmgr_set_emc(tfreq_data.pcluster[cl].bwmgr, | 245 | tegra_bwmgr_set_emc(tfreq_data.pcluster[cl].bwmgr, |
| 267 | emc_freq * KHZ_TO_HZ, TEGRA_BWMGR_SET_EMC_FLOOR); | 246 | emc_freq * KHZ_TO_HZ, TEGRA_BWMGR_SET_EMC_FLOOR); |
| @@ -442,32 +421,6 @@ static int set_delay(void *data, u64 val) | |||
| 442 | DEFINE_SIMPLE_ATTRIBUTE(freq_compute_fops, get_delay, set_delay, | 421 | DEFINE_SIMPLE_ATTRIBUTE(freq_compute_fops, get_delay, set_delay, |
| 443 | "%llu\n"); | 422 | "%llu\n"); |
| 444 | 423 | ||
| 445 | static int show_cpu_emc_map(struct seq_file *s, void *data) | ||
| 446 | { | ||
| 447 | int i; | ||
| 448 | seq_printf(s, "(cpufreq, emcfreq)\n"); | ||
| 449 | |||
| 450 | for (i = 0; i < cpu_emc_map_num; i++) { | ||
| 451 | seq_printf(s, "%u %d\n", cpu_emc_map_ptr[i].cpufreq, | ||
| 452 | cpu_emc_map_ptr[i].emcfreq); | ||
| 453 | } | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | static int cpu_emc_map_open(struct inode *inode, struct file *file) | ||
| 459 | { | ||
| 460 | return single_open(file, show_cpu_emc_map, | ||
| 461 | inode->i_private); | ||
| 462 | } | ||
| 463 | |||
| 464 | static const struct file_operations cpu_emc_map_fops = { | ||
| 465 | .open = cpu_emc_map_open, | ||
| 466 | .read = seq_read, | ||
| 467 | .llseek = seq_lseek, | ||
| 468 | .release = single_release, | ||
| 469 | }; | ||
| 470 | |||
| 471 | static int freq_get(void *data, u64 *val) | 424 | static int freq_get(void *data, u64 *val) |
| 472 | { | 425 | { |
| 473 | uint64_t cpu = (uint64_t)data; | 426 | uint64_t cpu = (uint64_t)data; |
| @@ -713,10 +666,8 @@ static int __init tegra_cpufreq_debug_init(void) | |||
| 713 | &freq_compute_fops)) | 666 | &freq_compute_fops)) |
| 714 | goto err_out; | 667 | goto err_out; |
| 715 | 668 | ||
| 716 | if (!debugfs_create_file("cpu_emc_map", RO_MODE, | 669 | if (!tegra_debugfs_create_cpu_emc_map(tegra_cpufreq_debugfs_root, |
| 717 | tegra_cpufreq_debugfs_root, | 670 | cpu_emc_map_ptr)) |
| 718 | NULL, | ||
| 719 | &cpu_emc_map_fops)) | ||
| 720 | goto err_out; | 671 | goto err_out; |
| 721 | 672 | ||
| 722 | if (cc3_debug_init()) | 673 | if (cc3_debug_init()) |
| @@ -1079,23 +1030,6 @@ err_out: | |||
| 1079 | return ret; | 1030 | return ret; |
| 1080 | } | 1031 | } |
| 1081 | 1032 | ||
| 1082 | static void tegra_cpufreq_cpu_emc_map_init(struct device_node *dn) | ||
| 1083 | { | ||
| 1084 | struct property *prop; | ||
| 1085 | int len; | ||
| 1086 | |||
| 1087 | prop = of_find_property(dn, "cpu_emc_map", &len); | ||
| 1088 | if (prop) { | ||
| 1089 | len = rounddown(len, sizeof(struct cpu_emc_map)); | ||
| 1090 | cpu_emc_map_ptr = kzalloc(len, GFP_KERNEL); | ||
| 1091 | if (cpu_emc_map_ptr) { | ||
| 1092 | of_property_read_u32_array(dn, "cpu_emc_map", | ||
| 1093 | (u32 *)cpu_emc_map_ptr, len / sizeof(uint32_t)); | ||
| 1094 | cpu_emc_map_num = len / sizeof(struct cpu_emc_map); | ||
| 1095 | } | ||
| 1096 | } | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | static bool tegra_cpufreq_single_policy(struct device_node *dn) | 1033 | static bool tegra_cpufreq_single_policy(struct device_node *dn) |
| 1100 | { | 1034 | { |
| 1101 | struct property *prop; | 1035 | struct property *prop; |
| @@ -1114,7 +1048,7 @@ static int __init tegra194_cpufreq_probe(struct platform_device *pdev) | |||
| 1114 | int ret = 0, cl = 0; | 1048 | int ret = 0, cl = 0; |
| 1115 | 1049 | ||
| 1116 | dn = pdev->dev.of_node; | 1050 | dn = pdev->dev.of_node; |
| 1117 | tegra_cpufreq_cpu_emc_map_init(dn); | 1051 | cpu_emc_map_ptr = tegra_cpufreq_cpu_emc_map_dt_init(dn); |
| 1118 | cpufreq_single_policy = tegra_cpufreq_single_policy(dn); | 1052 | cpufreq_single_policy = tegra_cpufreq_single_policy(dn); |
| 1119 | 1053 | ||
| 1120 | mutex_init(&tfreq_data.mlock); | 1054 | mutex_init(&tfreq_data.mlock); |
