xref: /openbmc/linux/drivers/mmc/core/debugfs.c (revision aad7ebb5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Debugfs support for hosts and cards
4  *
5  * Copyright (C) 2008 Atmel Corporation
6  */
7 #include <linux/moduleparam.h>
8 #include <linux/export.h>
9 #include <linux/debugfs.h>
10 #include <linux/fs.h>
11 #include <linux/seq_file.h>
12 #include <linux/slab.h>
13 #include <linux/stat.h>
14 #include <linux/fault-inject.h>
15 
16 #include <linux/mmc/card.h>
17 #include <linux/mmc/host.h>
18 
19 #include "core.h"
20 #include "card.h"
21 #include "host.h"
22 #include "mmc_ops.h"
23 
24 #ifdef CONFIG_FAIL_MMC_REQUEST
25 
26 static DECLARE_FAULT_ATTR(fail_default_attr);
27 static char *fail_request;
28 module_param(fail_request, charp, 0);
29 
30 #endif /* CONFIG_FAIL_MMC_REQUEST */
31 
32 /* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
33 static int mmc_ios_show(struct seq_file *s, void *data)
34 {
35 	static const char *vdd_str[] = {
36 		[8]	= "2.0",
37 		[9]	= "2.1",
38 		[10]	= "2.2",
39 		[11]	= "2.3",
40 		[12]	= "2.4",
41 		[13]	= "2.5",
42 		[14]	= "2.6",
43 		[15]	= "2.7",
44 		[16]	= "2.8",
45 		[17]	= "2.9",
46 		[18]	= "3.0",
47 		[19]	= "3.1",
48 		[20]	= "3.2",
49 		[21]	= "3.3",
50 		[22]	= "3.4",
51 		[23]	= "3.5",
52 		[24]	= "3.6",
53 	};
54 	struct mmc_host	*host = s->private;
55 	struct mmc_ios	*ios = &host->ios;
56 	const char *str;
57 
58 	seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
59 	if (host->actual_clock)
60 		seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock);
61 	seq_printf(s, "vdd:\t\t%u ", ios->vdd);
62 	if ((1 << ios->vdd) & MMC_VDD_165_195)
63 		seq_printf(s, "(1.65 - 1.95 V)\n");
64 	else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1)
65 			&& vdd_str[ios->vdd] && vdd_str[ios->vdd + 1])
66 		seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd],
67 				vdd_str[ios->vdd + 1]);
68 	else
69 		seq_printf(s, "(invalid)\n");
70 
71 	switch (ios->bus_mode) {
72 	case MMC_BUSMODE_OPENDRAIN:
73 		str = "open drain";
74 		break;
75 	case MMC_BUSMODE_PUSHPULL:
76 		str = "push-pull";
77 		break;
78 	default:
79 		str = "invalid";
80 		break;
81 	}
82 	seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str);
83 
84 	switch (ios->chip_select) {
85 	case MMC_CS_DONTCARE:
86 		str = "don't care";
87 		break;
88 	case MMC_CS_HIGH:
89 		str = "active high";
90 		break;
91 	case MMC_CS_LOW:
92 		str = "active low";
93 		break;
94 	default:
95 		str = "invalid";
96 		break;
97 	}
98 	seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str);
99 
100 	switch (ios->power_mode) {
101 	case MMC_POWER_OFF:
102 		str = "off";
103 		break;
104 	case MMC_POWER_UP:
105 		str = "up";
106 		break;
107 	case MMC_POWER_ON:
108 		str = "on";
109 		break;
110 	default:
111 		str = "invalid";
112 		break;
113 	}
114 	seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str);
115 	seq_printf(s, "bus width:\t%u (%u bits)\n",
116 			ios->bus_width, 1 << ios->bus_width);
117 
118 	switch (ios->timing) {
119 	case MMC_TIMING_LEGACY:
120 		str = "legacy";
121 		break;
122 	case MMC_TIMING_MMC_HS:
123 		str = "mmc high-speed";
124 		break;
125 	case MMC_TIMING_SD_HS:
126 		str = "sd high-speed";
127 		break;
128 	case MMC_TIMING_UHS_SDR12:
129 		str = "sd uhs SDR12";
130 		break;
131 	case MMC_TIMING_UHS_SDR25:
132 		str = "sd uhs SDR25";
133 		break;
134 	case MMC_TIMING_UHS_SDR50:
135 		str = "sd uhs SDR50";
136 		break;
137 	case MMC_TIMING_UHS_SDR104:
138 		str = "sd uhs SDR104";
139 		break;
140 	case MMC_TIMING_UHS_DDR50:
141 		str = "sd uhs DDR50";
142 		break;
143 	case MMC_TIMING_MMC_DDR52:
144 		str = "mmc DDR52";
145 		break;
146 	case MMC_TIMING_MMC_HS200:
147 		str = "mmc HS200";
148 		break;
149 	case MMC_TIMING_MMC_HS400:
150 		str = mmc_card_hs400es(host->card) ?
151 			"mmc HS400 enhanced strobe" : "mmc HS400";
152 		break;
153 	default:
154 		str = "invalid";
155 		break;
156 	}
157 	seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
158 
159 	switch (ios->signal_voltage) {
160 	case MMC_SIGNAL_VOLTAGE_330:
161 		str = "3.30 V";
162 		break;
163 	case MMC_SIGNAL_VOLTAGE_180:
164 		str = "1.80 V";
165 		break;
166 	case MMC_SIGNAL_VOLTAGE_120:
167 		str = "1.20 V";
168 		break;
169 	default:
170 		str = "invalid";
171 		break;
172 	}
173 	seq_printf(s, "signal voltage:\t%u (%s)\n", ios->signal_voltage, str);
174 
175 	switch (ios->drv_type) {
176 	case MMC_SET_DRIVER_TYPE_A:
177 		str = "driver type A";
178 		break;
179 	case MMC_SET_DRIVER_TYPE_B:
180 		str = "driver type B";
181 		break;
182 	case MMC_SET_DRIVER_TYPE_C:
183 		str = "driver type C";
184 		break;
185 	case MMC_SET_DRIVER_TYPE_D:
186 		str = "driver type D";
187 		break;
188 	default:
189 		str = "invalid";
190 		break;
191 	}
192 	seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str);
193 
194 	return 0;
195 }
196 DEFINE_SHOW_ATTRIBUTE(mmc_ios);
197 
198 static int mmc_clock_opt_get(void *data, u64 *val)
199 {
200 	struct mmc_host *host = data;
201 
202 	*val = host->ios.clock;
203 
204 	return 0;
205 }
206 
207 static int mmc_clock_opt_set(void *data, u64 val)
208 {
209 	struct mmc_host *host = data;
210 
211 	/* We need this check due to input value is u64 */
212 	if (val != 0 && (val > host->f_max || val < host->f_min))
213 		return -EINVAL;
214 
215 	mmc_claim_host(host);
216 	mmc_set_clock(host, (unsigned int) val);
217 	mmc_release_host(host);
218 
219 	return 0;
220 }
221 
222 DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
223 	"%llu\n");
224 
225 void mmc_add_host_debugfs(struct mmc_host *host)
226 {
227 	struct dentry *root;
228 
229 	root = debugfs_create_dir(mmc_hostname(host), NULL);
230 	host->debugfs_root = root;
231 
232 	debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops);
233 	debugfs_create_x32("caps", S_IRUSR, root, &host->caps);
234 	debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2);
235 	debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host,
236 			    &mmc_clock_fops);
237 
238 #ifdef CONFIG_FAIL_MMC_REQUEST
239 	if (fail_request)
240 		setup_fault_attr(&fail_default_attr, fail_request);
241 	host->fail_mmc_request = fail_default_attr;
242 	fault_create_debugfs_attr("fail_mmc_request", root,
243 				  &host->fail_mmc_request);
244 #endif
245 }
246 
247 void mmc_remove_host_debugfs(struct mmc_host *host)
248 {
249 	debugfs_remove_recursive(host->debugfs_root);
250 }
251 
252 void mmc_add_card_debugfs(struct mmc_card *card)
253 {
254 	struct mmc_host	*host = card->host;
255 	struct dentry	*root;
256 
257 	if (!host->debugfs_root)
258 		return;
259 
260 	root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
261 	card->debugfs_root = root;
262 
263 	debugfs_create_x32("state", S_IRUSR, root, &card->state);
264 }
265 
266 void mmc_remove_card_debugfs(struct mmc_card *card)
267 {
268 	debugfs_remove_recursive(card->debugfs_root);
269 	card->debugfs_root = NULL;
270 }
271