14Srgrimes// SPDX-License-Identifier: GPL-2.0-only
24Srgrimes/*
34Srgrimes * Debugfs support for hosts and cards
44Srgrimes *
54Srgrimes * Copyright (C) 2008 Atmel Corporation
64Srgrimes */
74Srgrimes#include <linux/moduleparam.h>
84Srgrimes#include <linux/export.h>
94Srgrimes#include <linux/debugfs.h>
104Srgrimes#include <linux/fs.h>
114Srgrimes#include <linux/seq_file.h>
124Srgrimes#include <linux/slab.h>
134Srgrimes#include <linux/stat.h>
144Srgrimes#include <linux/fault-inject.h>
154Srgrimes#include <linux/time.h>
164Srgrimes
174Srgrimes#include <linux/mmc/card.h>
184Srgrimes#include <linux/mmc/host.h>
194Srgrimes#include <linux/mmc/mmc.h>
204Srgrimes#include <linux/mmc/sd.h>
214Srgrimes
224Srgrimes#include "core.h"
234Srgrimes#include "card.h"
244Srgrimes#include "host.h"
254Srgrimes#include "mmc_ops.h"
264Srgrimes
274Srgrimes#ifdef CONFIG_FAIL_MMC_REQUEST
284Srgrimes
294Srgrimesstatic DECLARE_FAULT_ATTR(fail_default_attr);
304Srgrimesstatic char *fail_request;
314Srgrimesmodule_param(fail_request, charp, 0);
324SrgrimesMODULE_PARM_DESC(fail_request, "default fault injection attributes");
334Srgrimes
344Srgrimes#endif /* CONFIG_FAIL_MMC_REQUEST */
354Srgrimes
36556Srgrimes/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
371321Sdgstatic int mmc_ios_show(struct seq_file *s, void *data)
384Srgrimes{
394Srgrimes	static const char *vdd_str[] = {
404Srgrimes		[8]	= "2.0",
41757Sdg		[9]	= "2.1",
42757Sdg		[10]	= "2.2",
43757Sdg		[11]	= "2.3",
44757Sdg		[12]	= "2.4",
45757Sdg		[13]	= "2.5",
464Srgrimes		[14]	= "2.6",
474Srgrimes		[15]	= "2.7",
48757Sdg		[16]	= "2.8",
49757Sdg		[17]	= "2.9",
50757Sdg		[18]	= "3.0",
51757Sdg		[19]	= "3.1",
52757Sdg		[20]	= "3.2",
53757Sdg		[21]	= "3.3",
54757Sdg		[22]	= "3.4",
55757Sdg		[23]	= "3.5",
56757Sdg		[24]	= "3.6",
574Srgrimes	};
584Srgrimes	struct mmc_host	*host = s->private;
59757Sdg	struct mmc_ios	*ios = &host->ios;
60757Sdg	const char *str;
614Srgrimes
624Srgrimes	seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
634Srgrimes	if (host->actual_clock)
644Srgrimes		seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock);
654Srgrimes	seq_printf(s, "vdd:\t\t%u ", ios->vdd);
66200Sdg	if ((1 << ios->vdd) & MMC_VDD_165_195)
674Srgrimes		seq_printf(s, "(1.65 - 1.95 V)\n");
684Srgrimes	else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1)
694Srgrimes			&& vdd_str[ios->vdd] && vdd_str[ios->vdd + 1])
70592Srgrimes		seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd],
71592Srgrimes				vdd_str[ios->vdd + 1]);
72592Srgrimes	else
73757Sdg		seq_printf(s, "(invalid)\n");
74592Srgrimes
75757Sdg	switch (ios->bus_mode) {
76608Srgrimes	case MMC_BUSMODE_OPENDRAIN:
774Srgrimes		str = "open drain";
784Srgrimes		break;
794Srgrimes	case MMC_BUSMODE_PUSHPULL:
804Srgrimes		str = "push-pull";
814Srgrimes		break;
82592Srgrimes	default:
83592Srgrimes		str = "invalid";
84592Srgrimes		break;
85757Sdg	}
864Srgrimes	seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str);
874Srgrimes
884Srgrimes	switch (ios->chip_select) {
894Srgrimes	case MMC_CS_DONTCARE:
904Srgrimes		str = "don't care";
914Srgrimes		break;
92570Srgrimes	case MMC_CS_HIGH:
93134Sdg		str = "active high";
944Srgrimes		break;
95556Srgrimes	case MMC_CS_LOW:
96556Srgrimes		str = "active low";
97556Srgrimes		break;
98556Srgrimes	default:
99556Srgrimes		str = "invalid";
100757Sdg		break;
101134Sdg	}
102592Srgrimes	seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str);
103134Sdg
104592Srgrimes	switch (ios->power_mode) {
105757Sdg	case MMC_POWER_OFF:
106757Sdg		str = "off";
107757Sdg		break;
108757Sdg	case MMC_POWER_UP:
1094Srgrimes		str = "up";
110757Sdg		break;
111757Sdg	case MMC_POWER_ON:
112757Sdg		str = "on";
113592Srgrimes		break;
114757Sdg	default:
115757Sdg		str = "invalid";
1164Srgrimes		break;
117757Sdg	}
118757Sdg	seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str);
119718Swollman	seq_printf(s, "bus width:\t%u (%u bits)\n",
120757Sdg			ios->bus_width, 1 << ios->bus_width);
121757Sdg
122134Sdg	switch (ios->timing) {
123757Sdg	case MMC_TIMING_LEGACY:
124757Sdg		str = "legacy";
1251321Sdg		break;
126757Sdg	case MMC_TIMING_MMC_HS:
127718Swollman		str = "mmc high-speed";
128757Sdg		break;
129974Sdg	case MMC_TIMING_SD_HS:
1304Srgrimes		str = "sd high-speed";
131134Sdg		break;
132134Sdg	case MMC_TIMING_UHS_SDR12:
133556Srgrimes		str = "sd uhs SDR12";
134556Srgrimes		break;
135556Srgrimes	case MMC_TIMING_UHS_SDR25:
1364Srgrimes		str = "sd uhs SDR25";
137134Sdg		break;
138134Sdg	case MMC_TIMING_UHS_SDR50:
139200Sdg		str = "sd uhs SDR50";
140200Sdg		break;
141134Sdg	case MMC_TIMING_UHS_SDR104:
1421321Sdg		str = "sd uhs SDR104";
143757Sdg		break;
1444Srgrimes	case MMC_TIMING_UHS_DDR50:
1451321Sdg		str = "sd uhs DDR50";
1464Srgrimes		break;
1474Srgrimes	case MMC_TIMING_MMC_DDR52:
148556Srgrimes		str = "mmc DDR52";
1494Srgrimes		break;
1504Srgrimes	case MMC_TIMING_MMC_HS200:
1514Srgrimes		str = "mmc HS200";
1524Srgrimes		break;
1534Srgrimes	case MMC_TIMING_MMC_HS400:
154570Srgrimes		str = mmc_card_hs400es(host->card) ?
1554Srgrimes			"mmc HS400 enhanced strobe" : "mmc HS400";
156570Srgrimes		break;
1574Srgrimes	default:
158570Srgrimes		str = "invalid";
159556Srgrimes		break;
160570Srgrimes	}
161570Srgrimes	seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
162975Smartin
163975Smartin	switch (ios->signal_voltage) {
164975Smartin	case MMC_SIGNAL_VOLTAGE_330:
165975Smartin		str = "3.30 V";
166975Smartin		break;
167975Smartin	case MMC_SIGNAL_VOLTAGE_180:
168975Smartin		str = "1.80 V";
1694Srgrimes		break;
170556Srgrimes	case MMC_SIGNAL_VOLTAGE_120:
171556Srgrimes		str = "1.20 V";
172556Srgrimes		break;
173556Srgrimes	default:
174556Srgrimes		str = "invalid";
175556Srgrimes		break;
176556Srgrimes	}
177556Srgrimes	seq_printf(s, "signal voltage:\t%u (%s)\n", ios->signal_voltage, str);
178556Srgrimes
179556Srgrimes	switch (ios->drv_type) {
180556Srgrimes	case MMC_SET_DRIVER_TYPE_A:
181556Srgrimes		str = "driver type A";
182556Srgrimes		break;
183556Srgrimes	case MMC_SET_DRIVER_TYPE_B:
1841321Sdg		str = "driver type B";
185556Srgrimes		break;
186556Srgrimes	case MMC_SET_DRIVER_TYPE_C:
187570Srgrimes		str = "driver type C";
188556Srgrimes		break;
189570Srgrimes	case MMC_SET_DRIVER_TYPE_D:
190556Srgrimes		str = "driver type D";
191556Srgrimes		break;
1924Srgrimes	default:
1934Srgrimes		str = "invalid";
1944Srgrimes		break;
1954Srgrimes	}
1964Srgrimes	seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str);
1974Srgrimes
1984Srgrimes	return 0;
1994Srgrimes}
2004SrgrimesDEFINE_SHOW_ATTRIBUTE(mmc_ios);
2014Srgrimes
2024Srgrimesstatic int mmc_clock_opt_get(void *data, u64 *val)
2034Srgrimes{
2044Srgrimes	struct mmc_host *host = data;
2054Srgrimes
206757Sdg	*val = host->ios.clock;
2074Srgrimes
208570Srgrimes	return 0;
209570Srgrimes}
210570Srgrimes
211570Srgrimesstatic int mmc_clock_opt_set(void *data, u64 val)
212974Sdg{
213570Srgrimes	struct mmc_host *host = data;
214570Srgrimes
2154Srgrimes	/* We need this check due to input value is u64 */
216570Srgrimes	if (val != 0 && (val > host->f_max || val < host->f_min))
217757Sdg		return -EINVAL;
2184Srgrimes
2191321Sdg	mmc_claim_host(host);
220757Sdg	mmc_set_clock(host, (unsigned int) val);
2214Srgrimes	mmc_release_host(host);
222757Sdg
223570Srgrimes	return 0;
224760Srgrimes}
225757Sdg
2264SrgrimesDEFINE_DEBUGFS_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
2274Srgrimes	"%llu\n");
2284Srgrimes
2294Srgrimesstatic int mmc_err_state_get(void *data, u64 *val)
230608Srgrimes{
231974Sdg	struct mmc_host *host = data;
232974Sdg	int i;
233974Sdg
234974Sdg	if (!host)
235757Sdg		return -EINVAL;
236757Sdg
237608Srgrimes	*val = 0;
238757Sdg	for (i = 0; i < MMC_ERR_MAX; i++) {
239608Srgrimes		if (host->err_stats[i]) {
240757Sdg			*val = 1;
241757Sdg			break;
242974Sdg		}
243757Sdg	}
244757Sdg
245757Sdg	return 0;
246757Sdg}
247757Sdg
248757SdgDEFINE_DEBUGFS_ATTRIBUTE(mmc_err_state, mmc_err_state_get, NULL, "%llu\n");
249570Srgrimes
2504Srgrimesstatic int mmc_err_stats_show(struct seq_file *file, void *data)
251592Srgrimes{
252592Srgrimes	struct mmc_host *host = file->private;
253592Srgrimes	const char *desc[MMC_ERR_MAX] = {
254592Srgrimes		[MMC_ERR_CMD_TIMEOUT] = "Command Timeout Occurred",
255592Srgrimes		[MMC_ERR_CMD_CRC] = "Command CRC Errors Occurred",
256592Srgrimes		[MMC_ERR_DAT_TIMEOUT] = "Data Timeout Occurred",
2574Srgrimes		[MMC_ERR_DAT_CRC] = "Data CRC Errors Occurred",
2584Srgrimes		[MMC_ERR_AUTO_CMD] = "Auto-Cmd Error Occurred",
259570Srgrimes		[MMC_ERR_ADMA] = "ADMA Error Occurred",
2604Srgrimes		[MMC_ERR_TUNING] = "Tuning Error Occurred",
2614Srgrimes		[MMC_ERR_CMDQ_RED] = "CMDQ RED Errors",
2624Srgrimes		[MMC_ERR_CMDQ_GCE] = "CMDQ GCE Errors",
2634Srgrimes		[MMC_ERR_CMDQ_ICCE] = "CMDQ ICCE Errors",
2644Srgrimes		[MMC_ERR_REQ_TIMEOUT] = "Request Timedout",
2654Srgrimes		[MMC_ERR_CMDQ_REQ_TIMEOUT] = "CMDQ Request Timedout",
2664Srgrimes		[MMC_ERR_ICE_CFG] = "ICE Config Errors",
2674Srgrimes		[MMC_ERR_CTRL_TIMEOUT] = "Controller Timedout errors",
268757Sdg		[MMC_ERR_UNEXPECTED_IRQ] = "Unexpected IRQ errors",
269757Sdg	};
270757Sdg	int i;
271757Sdg
272757Sdg	for (i = 0; i < MMC_ERR_MAX; i++) {
273200Sdg		if (desc[i])
274200Sdg			seq_printf(file, "# %s:\t %d\n",
275200Sdg					desc[i], host->err_stats[i]);
276757Sdg	}
277757Sdg
278757Sdg	return 0;
279757Sdg}
2804Srgrimes
2814Srgrimesstatic int mmc_err_stats_open(struct inode *inode, struct file *file)
282757Sdg{
283757Sdg	return single_open(file, mmc_err_stats_show, inode->i_private);
284757Sdg}
285757Sdg
286757Sdgstatic ssize_t mmc_err_stats_write(struct file *filp, const char __user *ubuf,
287757Sdg				   size_t cnt, loff_t *ppos)
288757Sdg{
289757Sdg	struct mmc_host *host = filp->f_mapping->host->i_private;
290757Sdg
291757Sdg	pr_debug("%s: Resetting MMC error statistics\n", __func__);
292757Sdg	memset(host->err_stats, 0, sizeof(host->err_stats));
293757Sdg
294757Sdg	return cnt;
295757Sdg}
296757Sdg
297757Sdgstatic const struct file_operations mmc_err_stats_fops = {
2981321Sdg	.open	= mmc_err_stats_open,
299757Sdg	.read	= seq_read,
300757Sdg	.write	= mmc_err_stats_write,
301757Sdg	.release = single_release,
302974Sdg};
303757Sdg
304757Sdgstatic int mmc_caps_get(void *data, u64 *val)
305757Sdg{
306757Sdg	*val = *(u32 *)data;
307757Sdg	return 0;
308757Sdg}
309757Sdg
310757Sdgstatic int mmc_caps_set(void *data, u64 val)
3111321Sdg{
3124Srgrimes	u32 *caps = data;
3134Srgrimes	u32 diff = *caps ^ val;
314757Sdg	u32 allowed = MMC_CAP_AGGRESSIVE_PM |
315757Sdg		      MMC_CAP_SD_HIGHSPEED |
316757Sdg		      MMC_CAP_MMC_HIGHSPEED |
3171046Sdg		      MMC_CAP_UHS |
318757Sdg		      MMC_CAP_DDR;
3194Srgrimes
3204Srgrimes	if (diff & ~allowed)
3214Srgrimes		return -EINVAL;
3224Srgrimes
323757Sdg	*caps = val;
324757Sdg
325757Sdg	return 0;
326757Sdg}
327757Sdg
328757Sdgstatic int mmc_caps2_set(void *data, u64 val)
329757Sdg{
3304Srgrimes	u32 allowed = MMC_CAP2_HSX00_1_8V | MMC_CAP2_HSX00_1_2V;
3314Srgrimes	u32 *caps = data;
3324Srgrimes	u32 diff = *caps ^ val;
333757Sdg
3344Srgrimes	if (diff & ~allowed)
3354Srgrimes		return -EINVAL;
336757Sdg
337757Sdg	*caps = val;
338757Sdg
3394Srgrimes	return 0;
340757Sdg}
341974Sdg
342757SdgDEFINE_DEBUGFS_ATTRIBUTE(mmc_caps_fops, mmc_caps_get, mmc_caps_set,
3434Srgrimes			 "0x%08llx\n");
3444SrgrimesDEFINE_DEBUGFS_ATTRIBUTE(mmc_caps2_fops, mmc_caps_get, mmc_caps2_set,
3454Srgrimes			 "0x%08llx\n");
346757Sdg
347757Sdgvoid mmc_add_host_debugfs(struct mmc_host *host)
348757Sdg{
3494Srgrimes	struct dentry *root;
3504Srgrimes
351757Sdg	root = debugfs_create_dir(mmc_hostname(host), NULL);
352757Sdg	host->debugfs_root = root;
353757Sdg
3544Srgrimes	debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops);
355757Sdg	debugfs_create_file("caps", 0600, root, &host->caps, &mmc_caps_fops);
3564Srgrimes	debugfs_create_file("caps2", 0600, root, &host->caps2,
3574Srgrimes			    &mmc_caps2_fops);
358757Sdg	debugfs_create_file_unsafe("clock", S_IRUSR | S_IWUSR, root, host,
3594Srgrimes				   &mmc_clock_fops);
360570Srgrimes
3614Srgrimes	debugfs_create_file_unsafe("err_state", 0600, root, host,
3624Srgrimes			    &mmc_err_state);
3634Srgrimes	debugfs_create_file("err_stats", 0600, root, host,
3644Srgrimes			    &mmc_err_stats_fops);
3654Srgrimes
366757Sdg#ifdef CONFIG_FAIL_MMC_REQUEST
367570Srgrimes	if (fail_request)
3684Srgrimes		setup_fault_attr(&fail_default_attr, fail_request);
3694Srgrimes	host->fail_mmc_request = fail_default_attr;
370757Sdg	fault_create_debugfs_attr("fail_mmc_request", root,
3714Srgrimes				  &host->fail_mmc_request);
372570Srgrimes#endif
3734Srgrimes}
3744Srgrimes
3754Srgrimesvoid mmc_remove_host_debugfs(struct mmc_host *host)
376757Sdg{
377757Sdg	debugfs_remove_recursive(host->debugfs_root);
3784Srgrimes}
379570Srgrimes
3804Srgrimesvoid mmc_add_card_debugfs(struct mmc_card *card)
381570Srgrimes{
382757Sdg	struct mmc_host	*host = card->host;
3834Srgrimes	struct dentry	*root;
384570Srgrimes
3854Srgrimes	if (!host->debugfs_root)
386570Srgrimes		return;
3874Srgrimes
388570Srgrimes	root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
3894Srgrimes	card->debugfs_root = root;
3904Srgrimes
391757Sdg	debugfs_create_x32("state", S_IRUSR, root, &card->state);
3924Srgrimes}
3934Srgrimes
3944Srgrimesvoid mmc_remove_card_debugfs(struct mmc_card *card)
3954Srgrimes{
3964Srgrimes	debugfs_remove_recursive(card->debugfs_root);
3974Srgrimes	card->debugfs_root = NULL;
3984Srgrimes}
3991321Sdg