xref: /linux/drivers/memory/tegra/tegra186-emc.c (revision fab183d632628381b466a41479489541ac0e29a0)
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