1 // SPDX-License-Identifier: GPL-2.0-only
3 * Debugfs support for hosts and cards
5 * Copyright (C) 2008 Atmel Corporation
7 #include <linux/moduleparam.h>
8 #include <linux/export.h>
9 #include <linux/debugfs.h>
11 #include <linux/seq_file.h>
12 #include <linux/slab.h>
13 #include <linux/stat.h>
14 #include <linux/fault-inject.h>
16 #include <linux/mmc/card.h>
17 #include <linux/mmc/host.h>
24 #ifdef CONFIG_FAIL_MMC_REQUEST
26 static DECLARE_FAULT_ATTR(fail_default_attr
);
27 static char *fail_request
;
28 module_param(fail_request
, charp
, 0);
30 #endif /* CONFIG_FAIL_MMC_REQUEST */
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
)
35 static const char *vdd_str
[] = {
54 struct mmc_host
*host
= s
->private;
55 struct mmc_ios
*ios
= &host
->ios
;
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]);
69 seq_printf(s
, "(invalid)\n");
71 switch (ios
->bus_mode
) {
72 case MMC_BUSMODE_OPENDRAIN
:
75 case MMC_BUSMODE_PUSHPULL
:
82 seq_printf(s
, "bus mode:\t%u (%s)\n", ios
->bus_mode
, str
);
84 switch (ios
->chip_select
) {
98 seq_printf(s
, "chip select:\t%u (%s)\n", ios
->chip_select
, str
);
100 switch (ios
->power_mode
) {
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
);
118 switch (ios
->timing
) {
119 case MMC_TIMING_LEGACY
:
122 case MMC_TIMING_MMC_HS
:
123 str
= "mmc high-speed";
125 case MMC_TIMING_SD_HS
:
126 str
= "sd high-speed";
128 case MMC_TIMING_UHS_SDR12
:
129 str
= "sd uhs SDR12";
131 case MMC_TIMING_UHS_SDR25
:
132 str
= "sd uhs SDR25";
134 case MMC_TIMING_UHS_SDR50
:
135 str
= "sd uhs SDR50";
137 case MMC_TIMING_UHS_SDR104
:
138 str
= "sd uhs SDR104";
140 case MMC_TIMING_UHS_DDR50
:
141 str
= "sd uhs DDR50";
143 case MMC_TIMING_MMC_DDR52
:
146 case MMC_TIMING_MMC_HS200
:
149 case MMC_TIMING_MMC_HS400
:
150 str
= mmc_card_hs400es(host
->card
) ?
151 "mmc HS400 enhanced strobe" : "mmc HS400";
157 seq_printf(s
, "timing spec:\t%u (%s)\n", ios
->timing
, str
);
159 switch (ios
->signal_voltage
) {
160 case MMC_SIGNAL_VOLTAGE_330
:
163 case MMC_SIGNAL_VOLTAGE_180
:
166 case MMC_SIGNAL_VOLTAGE_120
:
173 seq_printf(s
, "signal voltage:\t%u (%s)\n", ios
->signal_voltage
, str
);
175 switch (ios
->drv_type
) {
176 case MMC_SET_DRIVER_TYPE_A
:
177 str
= "driver type A";
179 case MMC_SET_DRIVER_TYPE_B
:
180 str
= "driver type B";
182 case MMC_SET_DRIVER_TYPE_C
:
183 str
= "driver type C";
185 case MMC_SET_DRIVER_TYPE_D
:
186 str
= "driver type D";
192 seq_printf(s
, "driver type:\t%u (%s)\n", ios
->drv_type
, str
);
196 DEFINE_SHOW_ATTRIBUTE(mmc_ios
);
198 static int mmc_clock_opt_get(void *data
, u64
*val
)
200 struct mmc_host
*host
= data
;
202 *val
= host
->ios
.clock
;
207 static int mmc_clock_opt_set(void *data
, u64 val
)
209 struct mmc_host
*host
= data
;
211 /* We need this check due to input value is u64 */
212 if (val
!= 0 && (val
> host
->f_max
|| val
< host
->f_min
))
215 mmc_claim_host(host
);
216 mmc_set_clock(host
, (unsigned int) val
);
217 mmc_release_host(host
);
222 DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops
, mmc_clock_opt_get
, mmc_clock_opt_set
,
225 void mmc_add_host_debugfs(struct mmc_host
*host
)
229 root
= debugfs_create_dir(mmc_hostname(host
), NULL
);
230 host
->debugfs_root
= root
;
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
,
238 #ifdef CONFIG_FAIL_MMC_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
);
247 void mmc_remove_host_debugfs(struct mmc_host
*host
)
249 debugfs_remove_recursive(host
->debugfs_root
);
252 void mmc_add_card_debugfs(struct mmc_card
*card
)
254 struct mmc_host
*host
= card
->host
;
257 if (!host
->debugfs_root
)
260 root
= debugfs_create_dir(mmc_card_id(card
), host
->debugfs_root
);
261 card
->debugfs_root
= root
;
263 debugfs_create_x32("state", S_IRUSR
, root
, &card
->state
);
266 void mmc_remove_card_debugfs(struct mmc_card
*card
)
268 debugfs_remove_recursive(card
->debugfs_root
);
269 card
->debugfs_root
= NULL
;