hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/cpufreq/tegra186-cpufreq.c
....@@ -1,14 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
124 */
135
146 #include <linux/cpufreq.h>
....@@ -22,6 +14,7 @@
2214
2315 #define EDVD_CORE_VOLT_FREQ(core) (0x20 + (core) * 0x4)
2416 #define EDVD_CORE_VOLT_FREQ_F_SHIFT 0
17
+#define EDVD_CORE_VOLT_FREQ_F_MASK 0xffff
2518 #define EDVD_CORE_VOLT_FREQ_V_SHIFT 16
2619
2720 struct tegra186_cpufreq_cluster_info {
....@@ -49,6 +42,8 @@
4942 struct tegra186_cpufreq_cluster {
5043 const struct tegra186_cpufreq_cluster_info *info;
5144 struct cpufreq_frequency_table *table;
45
+ u32 ref_clk_khz;
46
+ u32 div;
5247 };
5348
5449 struct tegra186_cpufreq_data {
....@@ -99,9 +94,45 @@
9994 return 0;
10095 }
10196
97
+static unsigned int tegra186_cpufreq_get(unsigned int cpu)
98
+{
99
+ struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
100
+ struct cpufreq_policy *policy;
101
+ void __iomem *edvd_reg;
102
+ unsigned int i, freq = 0;
103
+ u32 ndiv;
104
+
105
+ policy = cpufreq_cpu_get(cpu);
106
+ if (!policy)
107
+ return 0;
108
+
109
+ edvd_reg = policy->driver_data;
110
+ ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK;
111
+
112
+ for (i = 0; i < data->num_clusters; i++) {
113
+ struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
114
+ int core;
115
+
116
+ for (core = 0; core < ARRAY_SIZE(cluster->info->cpus); core++) {
117
+ if (cluster->info->cpus[core] != policy->cpu)
118
+ continue;
119
+
120
+ freq = (cluster->ref_clk_khz * ndiv) / cluster->div;
121
+ goto out;
122
+ }
123
+ }
124
+
125
+out:
126
+ cpufreq_cpu_put(policy);
127
+
128
+ return freq;
129
+}
130
+
102131 static struct cpufreq_driver tegra186_cpufreq_driver = {
103132 .name = "tegra186",
104
- .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
133
+ .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
134
+ CPUFREQ_NEED_INITIAL_FREQ_CHECK,
135
+ .get = tegra186_cpufreq_get,
105136 .verify = cpufreq_generic_frequency_table_verify,
106137 .target_index = tegra186_cpufreq_set_target,
107138 .init = tegra186_cpufreq_init,
....@@ -110,7 +141,7 @@
110141
111142 static struct cpufreq_frequency_table *init_vhint_table(
112143 struct platform_device *pdev, struct tegra_bpmp *bpmp,
113
- unsigned int cluster_id)
144
+ struct tegra186_cpufreq_cluster *cluster)
114145 {
115146 struct cpufreq_frequency_table *table;
116147 struct mrq_cpu_vhint_request req;
....@@ -121,7 +152,7 @@
121152 void *virt;
122153
123154 virt = dma_alloc_coherent(bpmp->dev, sizeof(*data), &phys,
124
- GFP_KERNEL | GFP_DMA32);
155
+ GFP_KERNEL);
125156 if (!virt)
126157 return ERR_PTR(-ENOMEM);
127158
....@@ -129,7 +160,7 @@
129160
130161 memset(&req, 0, sizeof(req));
131162 req.addr = phys;
132
- req.cluster_id = cluster_id;
163
+ req.cluster_id = cluster->info->bpmp_cluster_id;
133164
134165 memset(&msg, 0, sizeof(msg));
135166 msg.mrq = MRQ_CPU_VHINT;
....@@ -162,6 +193,9 @@
162193 goto free;
163194 }
164195
196
+ cluster->ref_clk_khz = data->ref_clk_hz / 1000;
197
+ cluster->div = data->pdiv * data->mdiv;
198
+
165199 for (i = data->vfloor, j = 0; i <= data->vceil; i++) {
166200 struct cpufreq_frequency_table *point;
167201 u16 ndiv = data->ndiv[i];
....@@ -179,8 +213,7 @@
179213
180214 point = &table[j++];
181215 point->driver_data = edvd_val;
182
- point->frequency = data->ref_clk_hz * ndiv / data->pdiv /
183
- data->mdiv / 1000;
216
+ point->frequency = (cluster->ref_clk_khz * ndiv) / cluster->div;
184217 }
185218
186219 table[j].frequency = CPUFREQ_TABLE_END;
....@@ -195,7 +228,6 @@
195228 {
196229 struct tegra186_cpufreq_data *data;
197230 struct tegra_bpmp *bpmp;
198
- struct resource *res;
199231 unsigned int i = 0, err;
200232
201233 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
....@@ -213,8 +245,7 @@
213245 if (IS_ERR(bpmp))
214246 return PTR_ERR(bpmp);
215247
216
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
217
- data->regs = devm_ioremap_resource(&pdev->dev, res);
248
+ data->regs = devm_platform_ioremap_resource(pdev, 0);
218249 if (IS_ERR(data->regs)) {
219250 err = PTR_ERR(data->regs);
220251 goto put_bpmp;
....@@ -224,23 +255,16 @@
224255 struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
225256
226257 cluster->info = &tegra186_clusters[i];
227
- cluster->table = init_vhint_table(
228
- pdev, bpmp, cluster->info->bpmp_cluster_id);
258
+ cluster->table = init_vhint_table(pdev, bpmp, cluster);
229259 if (IS_ERR(cluster->table)) {
230260 err = PTR_ERR(cluster->table);
231261 goto put_bpmp;
232262 }
233263 }
234264
235
- tegra_bpmp_put(bpmp);
236
-
237265 tegra186_cpufreq_driver.driver_data = data;
238266
239267 err = cpufreq_register_driver(&tegra186_cpufreq_driver);
240
- if (err)
241
- return err;
242
-
243
- return 0;
244268
245269 put_bpmp:
246270 tegra_bpmp_put(bpmp);