diff options
| -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); |
