1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2019 NVIDIA CORPORATION. All rights reserved.
7 #include <linux/debugfs.h>
8 #include <linux/module.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/of_platform.h>
11 #include <linux/platform_device.h>
13 #include <soc/tegra/bpmp.h>
16 struct tegra186_emc_dvfs
{
17 unsigned long latency
;
22 struct tegra_bpmp
*bpmp
;
26 struct tegra186_emc_dvfs
*dvfs
;
27 unsigned int num_dvfs
;
31 unsigned long min_rate
;
32 unsigned long max_rate
;
35 struct icc_provider provider
;
41 * The memory controller driver exposes some files in debugfs that can be used
42 * to control the EMC frequency. The top-level directory can be found here:
44 * /sys/kernel/debug/emc
46 * It contains the following files:
48 * - available_rates: This file contains a list of valid, space-separated
51 * - min_rate: Writing a value to this file sets the given frequency as the
52 * floor of the permitted range. If this is higher than the currently
53 * configured EMC frequency, this will cause the frequency to be
54 * increased so that it stays within the valid range.
56 * - max_rate: Similarily to the min_rate file, writing a value to this file
57 * sets the given frequency as the ceiling of the permitted range. If
58 * the value is lower than the currently configured EMC frequency, this
59 * will cause the frequency to be decreased so that it stays within the
63 static bool tegra186_emc_validate_rate(struct tegra186_emc
*emc
,
68 for (i
= 0; i
< emc
->num_dvfs
; i
++)
69 if (rate
== emc
->dvfs
[i
].rate
)
75 static int tegra186_emc_debug_available_rates_show(struct seq_file
*s
,
78 struct tegra186_emc
*emc
= s
->private;
79 const char *prefix
= "";
82 for (i
= 0; i
< emc
->num_dvfs
; i
++) {
83 seq_printf(s
, "%s%lu", prefix
, emc
->dvfs
[i
].rate
);
91 DEFINE_SHOW_ATTRIBUTE(tegra186_emc_debug_available_rates
);
93 static int tegra186_emc_debug_min_rate_get(void *data
, u64
*rate
)
95 struct tegra186_emc
*emc
= data
;
97 *rate
= emc
->debugfs
.min_rate
;
102 static int tegra186_emc_debug_min_rate_set(void *data
, u64 rate
)
104 struct tegra186_emc
*emc
= data
;
107 if (!tegra186_emc_validate_rate(emc
, rate
))
110 err
= clk_set_min_rate(emc
->clk
, rate
);
114 emc
->debugfs
.min_rate
= rate
;
119 DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_min_rate_fops
,
120 tegra186_emc_debug_min_rate_get
,
121 tegra186_emc_debug_min_rate_set
, "%llu\n");
123 static int tegra186_emc_debug_max_rate_get(void *data
, u64
*rate
)
125 struct tegra186_emc
*emc
= data
;
127 *rate
= emc
->debugfs
.max_rate
;
132 static int tegra186_emc_debug_max_rate_set(void *data
, u64 rate
)
134 struct tegra186_emc
*emc
= data
;
137 if (!tegra186_emc_validate_rate(emc
, rate
))
140 err
= clk_set_max_rate(emc
->clk
, rate
);
144 emc
->debugfs
.max_rate
= rate
;
149 DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops
,
150 tegra186_emc_debug_max_rate_get
,
151 tegra186_emc_debug_max_rate_set
, "%llu\n");
153 static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc
*emc
)
155 struct mrq_emc_dvfs_latency_response response
;
156 struct tegra_bpmp_message msg
;
160 memset(&msg
, 0, sizeof(msg
));
161 msg
.mrq
= MRQ_EMC_DVFS_LATENCY
;
164 msg
.rx
.data
= &response
;
165 msg
.rx
.size
= sizeof(response
);
167 err
= tegra_bpmp_transfer(emc
->bpmp
, &msg
);
169 dev_err(emc
->dev
, "failed to EMC DVFS pairs: %d\n", err
);
172 if (msg
.rx
.ret
< 0) {
173 dev_err(emc
->dev
, "EMC DVFS MRQ failed: %d (BPMP error code)\n", msg
.rx
.ret
);
177 emc
->debugfs
.min_rate
= ULONG_MAX
;
178 emc
->debugfs
.max_rate
= 0;
180 emc
->num_dvfs
= response
.num_pairs
;
182 emc
->dvfs
= devm_kmalloc_array(emc
->dev
, emc
->num_dvfs
, sizeof(*emc
->dvfs
), GFP_KERNEL
);
186 dev_dbg(emc
->dev
, "%u DVFS pairs:\n", emc
->num_dvfs
);
188 for (i
= 0; i
< emc
->num_dvfs
; i
++) {
189 emc
->dvfs
[i
].rate
= response
.pairs
[i
].freq
* 1000;
190 emc
->dvfs
[i
].latency
= response
.pairs
[i
].latency
;
192 if (emc
->dvfs
[i
].rate
< emc
->debugfs
.min_rate
)
193 emc
->debugfs
.min_rate
= emc
->dvfs
[i
].rate
;
195 if (emc
->dvfs
[i
].rate
> emc
->debugfs
.max_rate
)
196 emc
->debugfs
.max_rate
= emc
->dvfs
[i
].rate
;
198 dev_dbg(emc
->dev
, " %2u: %lu Hz -> %lu us\n", i
,
199 emc
->dvfs
[i
].rate
, emc
->dvfs
[i
].latency
);
202 err
= clk_set_rate_range(emc
->clk
, emc
->debugfs
.min_rate
, emc
->debugfs
.max_rate
);
204 dev_err(emc
->dev
, "failed to set rate range [%lu-%lu] for %pC\n",
205 emc
->debugfs
.min_rate
, emc
->debugfs
.max_rate
, emc
->clk
);
209 emc
->debugfs
.root
= debugfs_create_dir("emc", NULL
);
210 debugfs_create_file("available_rates", 0444, emc
->debugfs
.root
, emc
,
211 &tegra186_emc_debug_available_rates_fops
);
212 debugfs_create_file("min_rate", 0644, emc
->debugfs
.root
, emc
,
213 &tegra186_emc_debug_min_rate_fops
);
214 debugfs_create_file("max_rate", 0644, emc
->debugfs
.root
, emc
,
215 &tegra186_emc_debug_max_rate_fops
);
221 * tegra_emc_icc_set_bw() - Set BW api for EMC provider
222 * @src: ICC node for External Memory Controller (EMC)
223 * @dst: ICC node for External Memory (DRAM)
225 * Do nothing here as info to BPMP-FW is now passed in the BW set function
226 * of the MC driver. BPMP-FW sets the final Freq based on the passed values.
228 static int tegra_emc_icc_set_bw(struct icc_node
*src
, struct icc_node
*dst
)
233 static struct icc_node
*
234 tegra_emc_of_icc_xlate(const struct of_phandle_args
*spec
, void *data
)
236 struct icc_provider
*provider
= data
;
237 struct icc_node
*node
;
239 /* External Memory is the only possible ICC route */
240 list_for_each_entry(node
, &provider
->nodes
, node_list
) {
241 if (node
->id
!= TEGRA_ICC_EMEM
)
247 return ERR_PTR(-EPROBE_DEFER
);
250 static int tegra_emc_icc_get_init_bw(struct icc_node
*node
, u32
*avg
, u32
*peak
)
258 static int tegra_emc_interconnect_init(struct tegra186_emc
*emc
)
260 struct tegra_mc
*mc
= dev_get_drvdata(emc
->dev
->parent
);
261 const struct tegra_mc_soc
*soc
= mc
->soc
;
262 struct icc_node
*node
;
265 emc
->provider
.dev
= emc
->dev
;
266 emc
->provider
.set
= tegra_emc_icc_set_bw
;
267 emc
->provider
.data
= &emc
->provider
;
268 emc
->provider
.aggregate
= soc
->icc_ops
->aggregate
;
269 emc
->provider
.xlate
= tegra_emc_of_icc_xlate
;
270 emc
->provider
.get_bw
= tegra_emc_icc_get_init_bw
;
272 icc_provider_init(&emc
->provider
);
274 /* create External Memory Controller node */
275 node
= icc_node_create(TEGRA_ICC_EMC
);
281 node
->name
= "External Memory Controller";
282 icc_node_add(node
, &emc
->provider
);
284 /* link External Memory Controller to External Memory (DRAM) */
285 err
= icc_link_create(node
, TEGRA_ICC_EMEM
);
289 /* create External Memory node */
290 node
= icc_node_create(TEGRA_ICC_EMEM
);
296 node
->name
= "External Memory (DRAM)";
297 icc_node_add(node
, &emc
->provider
);
299 err
= icc_provider_register(&emc
->provider
);
306 icc_nodes_remove(&emc
->provider
);
308 dev_err(emc
->dev
, "failed to initialize ICC: %d\n", err
);
313 static int tegra186_emc_probe(struct platform_device
*pdev
)
315 struct tegra_mc
*mc
= dev_get_drvdata(pdev
->dev
.parent
);
316 struct tegra186_emc
*emc
;
319 emc
= devm_kzalloc(&pdev
->dev
, sizeof(*emc
), GFP_KERNEL
);
323 emc
->bpmp
= tegra_bpmp_get(&pdev
->dev
);
324 if (IS_ERR(emc
->bpmp
))
325 return dev_err_probe(&pdev
->dev
, PTR_ERR(emc
->bpmp
), "failed to get BPMP\n");
327 emc
->clk
= devm_clk_get(&pdev
->dev
, "emc");
328 if (IS_ERR(emc
->clk
)) {
329 err
= PTR_ERR(emc
->clk
);
330 dev_err(&pdev
->dev
, "failed to get EMC clock: %d\n", err
);
334 platform_set_drvdata(pdev
, emc
);
335 emc
->dev
= &pdev
->dev
;
337 if (tegra_bpmp_mrq_is_supported(emc
->bpmp
, MRQ_EMC_DVFS_LATENCY
)) {
338 err
= tegra186_emc_get_emc_dvfs_latency(emc
);
343 if (mc
&& mc
->soc
->icc_ops
) {
344 if (tegra_bpmp_mrq_is_supported(emc
->bpmp
, MRQ_BWMGR_INT
)) {
345 mc
->bwmgr_mrq_supported
= true;
348 * MC driver probe can't get BPMP reference as it gets probed
349 * earlier than BPMP. So, save the BPMP ref got from the EMC
350 * DT node in the mc->bpmp and use it in MC's icc_set hook.
352 mc
->bpmp
= emc
->bpmp
;
357 * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'.
358 * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return
359 * EINVAL instead of passing the request to BPMP-FW later when the BW
360 * request is made by client with 'icc_set_bw()' call.
362 err
= tegra_emc_interconnect_init(emc
);
372 tegra_bpmp_put(emc
->bpmp
);
376 static void tegra186_emc_remove(struct platform_device
*pdev
)
378 struct tegra_mc
*mc
= dev_get_drvdata(pdev
->dev
.parent
);
379 struct tegra186_emc
*emc
= platform_get_drvdata(pdev
);
381 debugfs_remove_recursive(emc
->debugfs
.root
);
384 tegra_bpmp_put(emc
->bpmp
);
387 static const struct of_device_id tegra186_emc_of_match
[] = {
388 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
389 { .compatible
= "nvidia,tegra186-emc" },
391 #if defined(CONFIG_ARCH_TEGRA_194_SOC)
392 { .compatible
= "nvidia,tegra194-emc" },
394 #if defined(CONFIG_ARCH_TEGRA_234_SOC)
395 { .compatible
= "nvidia,tegra234-emc" },
399 MODULE_DEVICE_TABLE(of
, tegra186_emc_of_match
);
401 static struct platform_driver tegra186_emc_driver
= {
403 .name
= "tegra186-emc",
404 .of_match_table
= tegra186_emc_of_match
,
405 .suppress_bind_attrs
= true,
406 .sync_state
= icc_sync_state
,
408 .probe
= tegra186_emc_probe
,
409 .remove
= tegra186_emc_remove
,
411 module_platform_driver(tegra186_emc_driver
);
413 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
414 MODULE_DESCRIPTION("NVIDIA Tegra186 External Memory Controller driver");