1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2019 NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/debugfs.h> 8 #include <linux/module.h> 9 #include <linux/mod_devicetable.h> 10 #include <linux/platform_device.h> 11 12 #include <soc/tegra/bpmp.h> 13 14 struct tegra186_emc_dvfs { 15 unsigned long latency; 16 unsigned long rate; 17 }; 18 19 struct tegra186_emc { 20 struct tegra_bpmp *bpmp; 21 struct device *dev; 22 struct clk *clk; 23 24 struct tegra186_emc_dvfs *dvfs; 25 unsigned int num_dvfs; 26 27 struct { 28 struct dentry *root; 29 unsigned long min_rate; 30 unsigned long max_rate; 31 } debugfs; 32 }; 33 34 /* 35 * debugfs interface 36 * 37 * The memory controller driver exposes some files in debugfs that can be used 38 * to control the EMC frequency. The top-level directory can be found here: 39 * 40 * /sys/kernel/debug/emc 41 * 42 * It contains the following files: 43 * 44 * - available_rates: This file contains a list of valid, space-separated 45 * EMC frequencies. 46 * 47 * - min_rate: Writing a value to this file sets the given frequency as the 48 * floor of the permitted range. If this is higher than the currently 49 * configured EMC frequency, this will cause the frequency to be 50 * increased so that it stays within the valid range. 51 * 52 * - max_rate: Similarily to the min_rate file, writing a value to this file 53 * sets the given frequency as the ceiling of the permitted range. If 54 * the value is lower than the currently configured EMC frequency, this 55 * will cause the frequency to be decreased so that it stays within the 56 * valid range. 57 */ 58 59 static bool tegra186_emc_validate_rate(struct tegra186_emc *emc, 60 unsigned long rate) 61 { 62 unsigned int i; 63 64 for (i = 0; i < emc->num_dvfs; i++) 65 if (rate == emc->dvfs[i].rate) 66 return true; 67 68 return false; 69 } 70 71 static int tegra186_emc_debug_available_rates_show(struct seq_file *s, 72 void *data) 73 { 74 struct tegra186_emc *emc = s->private; 75 const char *prefix = ""; 76 unsigned int i; 77 78 for (i = 0; i < emc->num_dvfs; i++) { 79 seq_printf(s, "%s%lu", prefix, emc->dvfs[i].rate); 80 prefix = " "; 81 } 82 83 seq_puts(s, "\n"); 84 85 return 0; 86 } 87 88 static int tegra186_emc_debug_available_rates_open(struct inode *inode, 89 struct file *file) 90 { 91 return single_open(file, tegra186_emc_debug_available_rates_show, 92 inode->i_private); 93 } 94 95 static const struct file_operations tegra186_emc_debug_available_rates_fops = { 96 .open = tegra186_emc_debug_available_rates_open, 97 .read = seq_read, 98 .llseek = seq_lseek, 99 .release = single_release, 100 }; 101 102 static int tegra186_emc_debug_min_rate_get(void *data, u64 *rate) 103 { 104 struct tegra186_emc *emc = data; 105 106 *rate = emc->debugfs.min_rate; 107 108 return 0; 109 } 110 111 static int tegra186_emc_debug_min_rate_set(void *data, u64 rate) 112 { 113 struct tegra186_emc *emc = data; 114 int err; 115 116 if (!tegra186_emc_validate_rate(emc, rate)) 117 return -EINVAL; 118 119 err = clk_set_min_rate(emc->clk, rate); 120 if (err < 0) 121 return err; 122 123 emc->debugfs.min_rate = rate; 124 125 return 0; 126 } 127 128 DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_min_rate_fops, 129 tegra186_emc_debug_min_rate_get, 130 tegra186_emc_debug_min_rate_set, "%llu\n"); 131 132 static int tegra186_emc_debug_max_rate_get(void *data, u64 *rate) 133 { 134 struct tegra186_emc *emc = data; 135 136 *rate = emc->debugfs.max_rate; 137 138 return 0; 139 } 140 141 static int tegra186_emc_debug_max_rate_set(void *data, u64 rate) 142 { 143 struct tegra186_emc *emc = data; 144 int err; 145 146 if (!tegra186_emc_validate_rate(emc, rate)) 147 return -EINVAL; 148 149 err = clk_set_max_rate(emc->clk, rate); 150 if (err < 0) 151 return err; 152 153 emc->debugfs.max_rate = rate; 154 155 return 0; 156 } 157 158 DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, 159 tegra186_emc_debug_max_rate_get, 160 tegra186_emc_debug_max_rate_set, "%llu\n"); 161 162 static int tegra186_emc_probe(struct platform_device *pdev) 163 { 164 struct mrq_emc_dvfs_latency_response response; 165 struct tegra_bpmp_message msg; 166 struct tegra186_emc *emc; 167 unsigned int i; 168 int err; 169 170 emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL); 171 if (!emc) 172 return -ENOMEM; 173 174 emc->bpmp = tegra_bpmp_get(&pdev->dev); 175 if (IS_ERR(emc->bpmp)) 176 return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp), "failed to get BPMP\n"); 177 178 emc->clk = devm_clk_get(&pdev->dev, "emc"); 179 if (IS_ERR(emc->clk)) { 180 err = PTR_ERR(emc->clk); 181 dev_err(&pdev->dev, "failed to get EMC clock: %d\n", err); 182 goto put_bpmp; 183 } 184 185 platform_set_drvdata(pdev, emc); 186 emc->dev = &pdev->dev; 187 188 memset(&msg, 0, sizeof(msg)); 189 msg.mrq = MRQ_EMC_DVFS_LATENCY; 190 msg.tx.data = NULL; 191 msg.tx.size = 0; 192 msg.rx.data = &response; 193 msg.rx.size = sizeof(response); 194 195 err = tegra_bpmp_transfer(emc->bpmp, &msg); 196 if (err < 0) { 197 dev_err(&pdev->dev, "failed to EMC DVFS pairs: %d\n", err); 198 goto put_bpmp; 199 } 200 201 emc->debugfs.min_rate = ULONG_MAX; 202 emc->debugfs.max_rate = 0; 203 204 emc->num_dvfs = response.num_pairs; 205 206 emc->dvfs = devm_kmalloc_array(&pdev->dev, emc->num_dvfs, 207 sizeof(*emc->dvfs), GFP_KERNEL); 208 if (!emc->dvfs) { 209 err = -ENOMEM; 210 goto put_bpmp; 211 } 212 213 dev_dbg(&pdev->dev, "%u DVFS pairs:\n", emc->num_dvfs); 214 215 for (i = 0; i < emc->num_dvfs; i++) { 216 emc->dvfs[i].rate = response.pairs[i].freq * 1000; 217 emc->dvfs[i].latency = response.pairs[i].latency; 218 219 if (emc->dvfs[i].rate < emc->debugfs.min_rate) 220 emc->debugfs.min_rate = emc->dvfs[i].rate; 221 222 if (emc->dvfs[i].rate > emc->debugfs.max_rate) 223 emc->debugfs.max_rate = emc->dvfs[i].rate; 224 225 dev_dbg(&pdev->dev, " %2u: %lu Hz -> %lu us\n", i, 226 emc->dvfs[i].rate, emc->dvfs[i].latency); 227 } 228 229 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate, 230 emc->debugfs.max_rate); 231 if (err < 0) { 232 dev_err(&pdev->dev, 233 "failed to set rate range [%lu-%lu] for %pC\n", 234 emc->debugfs.min_rate, emc->debugfs.max_rate, 235 emc->clk); 236 goto put_bpmp; 237 } 238 239 emc->debugfs.root = debugfs_create_dir("emc", NULL); 240 debugfs_create_file("available_rates", S_IRUGO, emc->debugfs.root, 241 emc, &tegra186_emc_debug_available_rates_fops); 242 debugfs_create_file("min_rate", S_IRUGO | S_IWUSR, emc->debugfs.root, 243 emc, &tegra186_emc_debug_min_rate_fops); 244 debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root, 245 emc, &tegra186_emc_debug_max_rate_fops); 246 247 return 0; 248 249 put_bpmp: 250 tegra_bpmp_put(emc->bpmp); 251 return err; 252 } 253 254 static int tegra186_emc_remove(struct platform_device *pdev) 255 { 256 struct tegra186_emc *emc = platform_get_drvdata(pdev); 257 258 debugfs_remove_recursive(emc->debugfs.root); 259 tegra_bpmp_put(emc->bpmp); 260 261 return 0; 262 } 263 264 static const struct of_device_id tegra186_emc_of_match[] = { 265 #if defined(CONFIG_ARCH_TEGRA_186_SOC) 266 { .compatible = "nvidia,tegra186-emc" }, 267 #endif 268 #if defined(CONFIG_ARCH_TEGRA_194_SOC) 269 { .compatible = "nvidia,tegra194-emc" }, 270 #endif 271 { /* sentinel */ } 272 }; 273 MODULE_DEVICE_TABLE(of, tegra186_emc_of_match); 274 275 static struct platform_driver tegra186_emc_driver = { 276 .driver = { 277 .name = "tegra186-emc", 278 .of_match_table = tegra186_emc_of_match, 279 .suppress_bind_attrs = true, 280 }, 281 .probe = tegra186_emc_probe, 282 .remove = tegra186_emc_remove, 283 }; 284 module_platform_driver(tegra186_emc_driver); 285 286 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 287 MODULE_DESCRIPTION("NVIDIA Tegra186 External Memory Controller driver"); 288 MODULE_LICENSE("GPL v2"); 289