1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2019-2025 NVIDIA CORPORATION. All rights reserved.
4 */
5
6 #include <linux/cleanup.h>
7 #include <linux/clk.h>
8 #include <linux/debugfs.h>
9 #include <linux/fs.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
14
15 #include <soc/tegra/bpmp.h>
16 #include "mc.h"
17
18 static DEFINE_MUTEX(tegra_emc_debugfs_root_lock);
19 static struct dentry *tegra_emc_debugfs_root;
20
21 struct tegra186_emc_dvfs {
22 unsigned long latency;
23 unsigned long rate;
24 };
25
26 struct tegra186_emc {
27 struct tegra_bpmp *bpmp;
28 struct device *dev;
29 struct clk *clk;
30 struct clk *clk_dbb;
31
32 struct tegra186_emc_dvfs *dvfs;
33 unsigned int num_dvfs;
34
35 struct {
36 struct dentry *root;
37 unsigned long min_rate;
38 unsigned long max_rate;
39 } debugfs;
40
41 struct icc_provider provider;
42 };
43
44 /*
45 * debugfs interface
46 *
47 * The memory controller driver exposes some files in debugfs that can be used
48 * to control the EMC frequency. The top-level directory can be found here:
49 *
50 * /sys/kernel/debug/emc
51 *
52 * It contains the following files:
53 *
54 * - available_rates: This file contains a list of valid, space-separated
55 * EMC frequencies.
56 *
57 * - min_rate: Writing a value to this file sets the given frequency as the
58 * floor of the permitted range. If this is higher than the currently
59 * configured EMC frequency, this will cause the frequency to be
60 * increased so that it stays within the valid range.
61 *
62 * - max_rate: Similarily to the min_rate file, writing a value to this file
63 * sets the given frequency as the ceiling of the permitted range. If
64 * the value is lower than the currently configured EMC frequency, this
65 * will cause the frequency to be decreased so that it stays within the
66 * valid range.
67 */
68
tegra186_emc_validate_rate(struct tegra186_emc * emc,unsigned long rate)69 static bool tegra186_emc_validate_rate(struct tegra186_emc *emc,
70 unsigned long rate)
71 {
72 unsigned int i;
73
74 for (i = 0; i < emc->num_dvfs; i++)
75 if (rate == emc->dvfs[i].rate)
76 return true;
77
78 return false;
79 }
80
tegra186_emc_debug_available_rates_show(struct seq_file * s,void * data)81 static int tegra186_emc_debug_available_rates_show(struct seq_file *s,
82 void *data)
83 {
84 struct tegra186_emc *emc = s->private;
85 const char *prefix = "";
86 unsigned int i;
87
88 for (i = 0; i < emc->num_dvfs; i++) {
89 seq_printf(s, "%s%lu", prefix, emc->dvfs[i].rate);
90 prefix = " ";
91 }
92
93 seq_puts(s, "\n");
94
95 return 0;
96 }
97 DEFINE_SHOW_ATTRIBUTE(tegra186_emc_debug_available_rates);
98
tegra186_emc_debug_min_rate_get(void * data,u64 * rate)99 static int tegra186_emc_debug_min_rate_get(void *data, u64 *rate)
100 {
101 struct tegra186_emc *emc = data;
102
103 *rate = emc->debugfs.min_rate;
104
105 return 0;
106 }
107
tegra186_emc_debug_min_rate_set(void * data,u64 rate)108 static int tegra186_emc_debug_min_rate_set(void *data, u64 rate)
109 {
110 struct tegra186_emc *emc = data;
111 int err;
112
113 if (!tegra186_emc_validate_rate(emc, rate))
114 return -EINVAL;
115
116 err = clk_set_min_rate(emc->clk, rate);
117 if (err < 0)
118 return err;
119
120 emc->debugfs.min_rate = rate;
121
122 return 0;
123 }
124
125 DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_min_rate_fops,
126 tegra186_emc_debug_min_rate_get,
127 tegra186_emc_debug_min_rate_set, "%llu\n");
128
tegra186_emc_debug_max_rate_get(void * data,u64 * rate)129 static int tegra186_emc_debug_max_rate_get(void *data, u64 *rate)
130 {
131 struct tegra186_emc *emc = data;
132
133 *rate = emc->debugfs.max_rate;
134
135 return 0;
136 }
137
tegra186_emc_debug_max_rate_set(void * data,u64 rate)138 static int tegra186_emc_debug_max_rate_set(void *data, u64 rate)
139 {
140 struct tegra186_emc *emc = data;
141 int err;
142
143 if (!tegra186_emc_validate_rate(emc, rate))
144 return -EINVAL;
145
146 err = clk_set_max_rate(emc->clk, rate);
147 if (err < 0)
148 return err;
149
150 emc->debugfs.max_rate = rate;
151
152 return 0;
153 }
154
155 DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops,
156 tegra186_emc_debug_max_rate_get,
157 tegra186_emc_debug_max_rate_set, "%llu\n");
158
tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc * emc)159 static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
160 {
161 struct mrq_emc_dvfs_latency_response response;
162 struct tegra_bpmp_message msg;
163 unsigned int i;
164 int err;
165
166 memset(&msg, 0, sizeof(msg));
167 msg.mrq = MRQ_EMC_DVFS_LATENCY;
168 msg.tx.data = NULL;
169 msg.tx.size = 0;
170 msg.rx.data = &response;
171 msg.rx.size = sizeof(response);
172
173 err = tegra_bpmp_transfer(emc->bpmp, &msg);
174 if (err < 0) {
175 dev_err(emc->dev, "failed to EMC DVFS pairs: %d\n", err);
176 return err;
177 }
178 if (msg.rx.ret < 0) {
179 dev_err(emc->dev, "EMC DVFS MRQ failed: %d (BPMP error code)\n", msg.rx.ret);
180 return -EINVAL;
181 }
182
183 emc->debugfs.min_rate = ULONG_MAX;
184 emc->debugfs.max_rate = 0;
185
186 emc->num_dvfs = response.num_pairs;
187
188 emc->dvfs = devm_kmalloc_array(emc->dev, emc->num_dvfs, sizeof(*emc->dvfs), GFP_KERNEL);
189 if (!emc->dvfs)
190 return -ENOMEM;
191
192 dev_dbg(emc->dev, "%u DVFS pairs:\n", emc->num_dvfs);
193
194 for (i = 0; i < emc->num_dvfs; i++) {
195 emc->dvfs[i].rate = response.pairs[i].freq * 1000;
196 emc->dvfs[i].latency = response.pairs[i].latency;
197
198 if (emc->dvfs[i].rate < emc->debugfs.min_rate)
199 emc->debugfs.min_rate = emc->dvfs[i].rate;
200
201 if (emc->dvfs[i].rate > emc->debugfs.max_rate)
202 emc->debugfs.max_rate = emc->dvfs[i].rate;
203
204 dev_dbg(emc->dev, " %2u: %lu Hz -> %lu us\n", i,
205 emc->dvfs[i].rate, emc->dvfs[i].latency);
206 }
207
208 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate, emc->debugfs.max_rate);
209 if (err < 0) {
210 dev_err(emc->dev, "failed to set rate range [%lu-%lu] for %pC\n",
211 emc->debugfs.min_rate, emc->debugfs.max_rate, emc->clk);
212 return err;
213 }
214
215 scoped_guard(mutex, &tegra_emc_debugfs_root_lock) {
216 if (!tegra_emc_debugfs_root)
217 tegra_emc_debugfs_root = debugfs_create_dir("emc", NULL);
218
219 if (dev_to_node(emc->dev) == NUMA_NO_NODE)
220 emc->debugfs.root = tegra_emc_debugfs_root;
221 else
222 emc->debugfs.root = debugfs_create_dir(dev_name(emc->dev),
223 tegra_emc_debugfs_root);
224 }
225
226 debugfs_create_file("available_rates", 0444, emc->debugfs.root, emc,
227 &tegra186_emc_debug_available_rates_fops);
228 debugfs_create_file("min_rate", 0644, emc->debugfs.root, emc,
229 &tegra186_emc_debug_min_rate_fops);
230 debugfs_create_file("max_rate", 0644, emc->debugfs.root, emc,
231 &tegra186_emc_debug_max_rate_fops);
232
233 return 0;
234 }
235
236 /*
237 * tegra186_emc_icc_set_bw() - Set BW api for EMC provider
238 * @src: ICC node for External Memory Controller (EMC)
239 * @dst: ICC node for External Memory (DRAM)
240 *
241 * Do nothing here as info to BPMP-FW is now passed in the BW set function
242 * of the MC driver. BPMP-FW sets the final Freq based on the passed values.
243 */
tegra186_emc_icc_set_bw(struct icc_node * src,struct icc_node * dst)244 static int tegra186_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
245 {
246 return 0;
247 }
248
249 static struct icc_node *
tegra186_emc_of_icc_xlate(const struct of_phandle_args * spec,void * data)250 tegra186_emc_of_icc_xlate(const struct of_phandle_args *spec, void *data)
251 {
252 struct icc_provider *provider = data;
253 struct icc_node *node;
254
255 /* External Memory is the only possible ICC route */
256 list_for_each_entry(node, &provider->nodes, node_list) {
257 if (tegra_mc_client_id_from_node(node) != TEGRA_ICC_EMEM)
258 continue;
259
260 return node;
261 }
262
263 return ERR_PTR(-EPROBE_DEFER);
264 }
265
tegra186_emc_icc_get_init_bw(struct icc_node * node,u32 * avg,u32 * peak)266 static int tegra186_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
267 {
268 *avg = 0;
269 *peak = 0;
270
271 return 0;
272 }
273
tegra186_emc_interconnect_init(struct tegra186_emc * emc)274 static int tegra186_emc_interconnect_init(struct tegra186_emc *emc)
275 {
276 int node_id = dev_to_node(emc->dev->parent);
277 struct icc_node *node;
278 int err;
279
280 emc->provider.dev = emc->dev;
281 emc->provider.set = tegra186_emc_icc_set_bw;
282 emc->provider.data = &emc->provider;
283 emc->provider.aggregate = icc_std_aggregate;
284 emc->provider.xlate = tegra186_emc_of_icc_xlate;
285 emc->provider.get_bw = tegra186_emc_icc_get_init_bw;
286
287 icc_provider_init(&emc->provider);
288
289 /* create External Memory Controller node */
290 node = tegra_mc_icc_node_create(node_id, TEGRA_ICC_EMC);
291 if (IS_ERR(node)) {
292 err = PTR_ERR(node);
293 goto remove_nodes;
294 }
295
296 if (node_id == NUMA_NO_NODE)
297 node->name = "External Memory Controller";
298 else
299 node->name = dev_name(emc->dev);
300
301 icc_node_add(node, &emc->provider);
302
303 /* link External Memory Controller to External Memory (DRAM) */
304 err = tegra_mc_icc_link_create(node, node_id, TEGRA_ICC_EMEM);
305 if (err)
306 goto remove_nodes;
307
308 /* create External Memory node */
309 node = tegra_mc_icc_node_create(node_id, TEGRA_ICC_EMEM);
310 if (IS_ERR(node)) {
311 err = PTR_ERR(node);
312 goto remove_nodes;
313 }
314
315 if (node_id == NUMA_NO_NODE)
316 node->name = "External Memory (DRAM)";
317 else
318 node->name = devm_kasprintf(emc->dev, GFP_KERNEL, "%d-dram", node_id);
319
320 icc_node_add(node, &emc->provider);
321
322 err = icc_provider_register(&emc->provider);
323 if (err)
324 goto remove_nodes;
325
326 return 0;
327
328 remove_nodes:
329 icc_nodes_remove(&emc->provider);
330
331 return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
332 }
333
tegra186_emc_probe(struct platform_device * pdev)334 static int tegra186_emc_probe(struct platform_device *pdev)
335 {
336 struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
337 struct tegra186_emc *emc;
338 int err;
339
340 emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
341 if (!emc)
342 return -ENOMEM;
343
344 emc->bpmp = tegra_bpmp_get(&pdev->dev);
345 if (IS_ERR(emc->bpmp))
346 return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp),
347 "failed to get BPMP\n");
348
349 emc->clk = devm_clk_get(&pdev->dev, "emc");
350 if (IS_ERR(emc->clk)) {
351 err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk),
352 "failed to get EMC clock\n");
353 goto put_bpmp;
354 }
355
356 emc->clk_dbb = devm_clk_get_optional_enabled(&pdev->dev, "dbb");
357 if (IS_ERR(emc->clk_dbb)) {
358 err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk_dbb),
359 "failed to get DBB clock\n");
360 goto put_bpmp;
361 }
362
363 platform_set_drvdata(pdev, emc);
364 emc->dev = &pdev->dev;
365
366 if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_EMC_DVFS_LATENCY)) {
367 err = tegra186_emc_get_emc_dvfs_latency(emc);
368 if (err)
369 goto put_bpmp;
370 }
371
372 if (mc && mc->soc->icc_ops) {
373 if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) {
374 mc->bwmgr_mrq_supported = true;
375
376 /*
377 * MC driver probe can't get BPMP reference as it gets probed
378 * earlier than BPMP. So, save the BPMP ref got from the EMC
379 * DT node in the mc->bpmp and use it in MC's icc_set hook.
380 */
381 mc->bpmp = emc->bpmp;
382 barrier();
383 }
384
385 /*
386 * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'.
387 * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return
388 * EINVAL instead of passing the request to BPMP-FW later when the BW
389 * request is made by client with 'icc_set_bw()' call.
390 */
391 err = tegra186_emc_interconnect_init(emc);
392 if (err) {
393 mc->bpmp = NULL;
394 goto put_bpmp;
395 }
396 }
397
398 return 0;
399
400 put_bpmp:
401 tegra_bpmp_put(emc->bpmp);
402 return err;
403 }
404
tegra186_emc_remove(struct platform_device * pdev)405 static void tegra186_emc_remove(struct platform_device *pdev)
406 {
407 struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
408 struct tegra186_emc *emc = platform_get_drvdata(pdev);
409
410 debugfs_remove_recursive(emc->debugfs.root);
411
412 scoped_guard(mutex, &tegra_emc_debugfs_root_lock) {
413 if (emc->debugfs.root == tegra_emc_debugfs_root) {
414 tegra_emc_debugfs_root = NULL;
415 } else if (tegra_emc_debugfs_root &&
416 simple_empty(tegra_emc_debugfs_root)) {
417 debugfs_remove(tegra_emc_debugfs_root);
418 tegra_emc_debugfs_root = NULL;
419 }
420 }
421
422 mc->bpmp = NULL;
423 tegra_bpmp_put(emc->bpmp);
424 }
425
426 static const struct of_device_id tegra186_emc_of_match[] = {
427 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
428 { .compatible = "nvidia,tegra186-emc" },
429 #endif
430 #if defined(CONFIG_ARCH_TEGRA_194_SOC)
431 { .compatible = "nvidia,tegra194-emc" },
432 #endif
433 #if defined(CONFIG_ARCH_TEGRA_234_SOC)
434 { .compatible = "nvidia,tegra234-emc" },
435 #endif
436 #if defined(CONFIG_ARCH_TEGRA_264_SOC)
437 { .compatible = "nvidia,tegra264-emc" },
438 #endif
439 { /* sentinel */ }
440 };
441 MODULE_DEVICE_TABLE(of, tegra186_emc_of_match);
442
443 static struct platform_driver tegra186_emc_driver = {
444 .driver = {
445 .name = "tegra186-emc",
446 .of_match_table = tegra186_emc_of_match,
447 .suppress_bind_attrs = true,
448 .sync_state = icc_sync_state,
449 },
450 .probe = tegra186_emc_probe,
451 .remove = tegra186_emc_remove,
452 };
453 module_platform_driver(tegra186_emc_driver);
454
455 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
456 MODULE_DESCRIPTION("NVIDIA Tegra186 External Memory Controller driver");
457