debugfs.c revision a4924c71aa43d4f8a3f342b1f71788349472e684
16edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen/*
26edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * Debugfs support for hosts and cards
36edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen *
46edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * Copyright (C) 2008 Atmel Corporation
56edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen *
66edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * This program is free software; you can redistribute it and/or modify
76edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * it under the terms of the GNU General Public License version 2 as
86edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * published by the Free Software Foundation.
96edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen */
103f102ae926c01bccc9520a62cff833fde889ed6aStephen Rothwell#include <linux/moduleparam.h>
113ef77af154b03776c6c662c68c6332719e9eecacPaul Gortmaker#include <linux/export.h>
126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/debugfs.h>
136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/fs.h>
146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/seq_file.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/stat.h>
171b676f70c108cda90cf9d114d16c677584400efcPer Forlin#include <linux/fault-inject.h>
186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
19f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen#include <linux/mmc/card.h>
206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/mmc/host.h>
216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include "core.h"
23f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen#include "mmc_ops.h"
246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2534f5050800d600551cca9bcfb463cc6699d82d04Per Forlin#ifdef CONFIG_FAIL_MMC_REQUEST
2634f5050800d600551cca9bcfb463cc6699d82d04Per Forlin
2734f5050800d600551cca9bcfb463cc6699d82d04Per Forlinstatic DECLARE_FAULT_ATTR(fail_default_attr);
2834f5050800d600551cca9bcfb463cc6699d82d04Per Forlinstatic char *fail_request;
2934f5050800d600551cca9bcfb463cc6699d82d04Per Forlinmodule_param(fail_request, charp, 0);
3034f5050800d600551cca9bcfb463cc6699d82d04Per Forlin
3134f5050800d600551cca9bcfb463cc6699d82d04Per Forlin#endif /* CONFIG_FAIL_MMC_REQUEST */
3234f5050800d600551cca9bcfb463cc6699d82d04Per Forlin
336edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
346edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_show(struct seq_file *s, void *data)
356edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
366edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	static const char *vdd_str[] = {
376edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[8]	= "2.0",
386edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[9]	= "2.1",
396edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[10]	= "2.2",
406edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[11]	= "2.3",
416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[12]	= "2.4",
426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[13]	= "2.5",
436edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[14]	= "2.6",
446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[15]	= "2.7",
456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[16]	= "2.8",
466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[17]	= "2.9",
476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[18]	= "3.0",
486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[19]	= "3.1",
496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[20]	= "3.2",
506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[21]	= "3.3",
516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[22]	= "3.4",
526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[23]	= "3.5",
536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[24]	= "3.6",
546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	};
556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct mmc_host	*host = s->private;
566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct mmc_ios	*ios = &host->ios;
576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	const char *str;
586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
60df16219f365f7f5a2d88a6e123251d57255cca3fGiuseppe CAVALLARO	if (host->actual_clock)
61df16219f365f7f5a2d88a6e123251d57255cca3fGiuseppe CAVALLARO		seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock);
626edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "vdd:\t\t%u ", ios->vdd);
636edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if ((1 << ios->vdd) & MMC_VDD_165_195)
646edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		seq_printf(s, "(1.65 - 1.95 V)\n");
656edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1)
666edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen			&& vdd_str[ios->vdd] && vdd_str[ios->vdd + 1])
676edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd],
686edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen				vdd_str[ios->vdd + 1]);
696edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	else
706edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		seq_printf(s, "(invalid)\n");
716edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
726edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->bus_mode) {
736edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_BUSMODE_OPENDRAIN:
746edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "open drain";
756edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
766edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_BUSMODE_PUSHPULL:
776edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "push-pull";
786edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
796edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
806edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
816edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
826edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
836edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str);
846edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
856edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->chip_select) {
866edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_CS_DONTCARE:
876edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "don't care";
886edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
896edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_CS_HIGH:
906edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "active high";
916edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
926edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_CS_LOW:
936edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "active low";
946edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
956edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
966edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
976edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
986edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
996edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str);
1006edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1016edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->power_mode) {
1026edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_POWER_OFF:
1036edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "off";
1046edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1056edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_POWER_UP:
1066edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "up";
1076edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1086edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_POWER_ON:
1096edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "on";
1106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
1126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
1136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
1156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str);
1166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "bus width:\t%u (%u bits)\n",
1176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen			ios->bus_width, 1 << ios->bus_width);
1186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->timing) {
1206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_TIMING_LEGACY:
1216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "legacy";
1226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1236edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_TIMING_MMC_HS:
1246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "mmc high-speed";
1256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_TIMING_SD_HS:
1276edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "sd high-speed";
1286edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
129cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu	case MMC_TIMING_UHS_SDR50:
130cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu		str = "sd uhs SDR50";
131cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu		break;
132cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu	case MMC_TIMING_UHS_SDR104:
133cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu		str = "sd uhs SDR104";
134cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu		break;
135cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu	case MMC_TIMING_UHS_DDR50:
136cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu		str = "sd uhs DDR50";
137cd8a3666987ba20908bbeb7c78ed9ba82b365643Aaron Lu		break;
138a4924c71aa43d4f8a3f342b1f71788349472e684Girish K S	case MMC_TIMING_MMC_HS200:
139a4924c71aa43d4f8a3f342b1f71788349472e684Girish K S		str = "mmc high-speed SDR200";
140a4924c71aa43d4f8a3f342b1f71788349472e684Girish K S		break;
1416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
1426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
1436edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
1456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
1466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return 0;
1486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_open(struct inode *inode, struct file *file)
1516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
1526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return single_open(file, mmc_ios_show, inode->i_private);
1536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic const struct file_operations mmc_ios_fops = {
1566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.open		= mmc_ios_open,
1576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.read		= seq_read,
1586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.llseek		= seq_lseek,
1596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.release	= single_release,
1606edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen};
1616edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
162703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkostatic int mmc_clock_opt_get(void *data, u64 *val)
163703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko{
164703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	struct mmc_host *host = data;
165703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
166703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	*val = host->ios.clock;
167703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
168703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	return 0;
169703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko}
170703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
171703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkostatic int mmc_clock_opt_set(void *data, u64 val)
172703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko{
173703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	struct mmc_host *host = data;
174703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
175703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	/* We need this check due to input value is u64 */
176703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	if (val > host->f_max)
177703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko		return -EINVAL;
178703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
179703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	mmc_claim_host(host);
180703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	mmc_set_clock(host, (unsigned int) val);
181703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	mmc_release_host(host);
182703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
183703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	return 0;
184703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko}
185703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
186703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy ShevchenkoDEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
187703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	"%llu\n");
188703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
1896edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_add_host_debugfs(struct mmc_host *host)
1906edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
1916edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct dentry *root;
1926edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1936edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	root = debugfs_create_dir(mmc_hostname(host), NULL);
1946edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (IS_ERR(root))
1956edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		/* Don't complain -- debugfs just isn't enabled */
1966edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		return;
1976edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (!root)
1986edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		/* Complain -- debugfs is enabled, but it failed to
1996edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		 * create the directory. */
2006edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		goto err_root;
2016edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2026edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	host->debugfs_root = root;
2036edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2046edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
205703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko		goto err_node;
206703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
207703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host,
208703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko			&mmc_clock_fops))
209703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko		goto err_node;
2106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
21104566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij#ifdef CONFIG_MMC_CLKGATE
21204566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij	if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
21304566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij				root, &host->clk_delay))
21404566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij		goto err_node;
21504566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij#endif
2161b676f70c108cda90cf9d114d16c677584400efcPer Forlin#ifdef CONFIG_FAIL_MMC_REQUEST
21734f5050800d600551cca9bcfb463cc6699d82d04Per Forlin	if (fail_request)
21834f5050800d600551cca9bcfb463cc6699d82d04Per Forlin		setup_fault_attr(&fail_default_attr, fail_request);
21934f5050800d600551cca9bcfb463cc6699d82d04Per Forlin	host->fail_mmc_request = fail_default_attr;
2201b676f70c108cda90cf9d114d16c677584400efcPer Forlin	if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
2211b676f70c108cda90cf9d114d16c677584400efcPer Forlin					     root,
2221b676f70c108cda90cf9d114d16c677584400efcPer Forlin					     &host->fail_mmc_request)))
2231b676f70c108cda90cf9d114d16c677584400efcPer Forlin		goto err_node;
2241b676f70c108cda90cf9d114d16c677584400efcPer Forlin#endif
2256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return;
2266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
227703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkoerr_node:
2286edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	debugfs_remove_recursive(root);
2296edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	host->debugfs_root = NULL;
2306edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_root:
2316edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	dev_err(&host->class_dev, "failed to initialize debugfs\n");
2326edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
2336edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2346edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_remove_host_debugfs(struct mmc_host *host)
2356edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
2366edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	debugfs_remove_recursive(host->debugfs_root);
2376edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
238f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
239f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenstatic int mmc_dbg_card_status_get(void *data, u64 *val)
240f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{
241f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	struct mmc_card	*card = data;
242f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	u32		status;
243f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	int		ret;
244f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
245f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	mmc_claim_host(card->host);
246f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
247f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	ret = mmc_send_status(data, &status);
248f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!ret)
249f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		*val = status;
250f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
251f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	mmc_release_host(card->host);
252f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
253f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	return ret;
254f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen}
255f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard SkinnemoenDEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
256f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		NULL, "%08llx\n");
257f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
258736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter#define EXT_CSD_STR_LEN 1025
259736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
260736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_open(struct inode *inode, struct file *filp)
261736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{
262736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	struct mmc_card *card = inode->i_private;
263736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	char *buf;
264736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	ssize_t n = 0;
265736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	u8 *ext_csd;
266736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	int err, i;
267736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
268736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
269736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (!buf)
270736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		return -ENOMEM;
271736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
272736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	ext_csd = kmalloc(512, GFP_KERNEL);
273736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (!ext_csd) {
274736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		err = -ENOMEM;
275736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		goto out_free;
276736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	}
277736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
278736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	mmc_claim_host(card->host);
279736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	err = mmc_send_ext_csd(card, ext_csd);
280736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	mmc_release_host(card->host);
281736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (err)
282736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		goto out_free;
283736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
284736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	for (i = 511; i >= 0; i--)
285736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		n += sprintf(buf + n, "%02x", ext_csd[i]);
286736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	n += sprintf(buf + n, "\n");
287736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	BUG_ON(n != EXT_CSD_STR_LEN);
288736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
289736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	filp->private_data = buf;
290736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(ext_csd);
291736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return 0;
292736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
293736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterout_free:
294736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(buf);
295736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(ext_csd);
296736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return err;
297736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}
298736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
299736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
300736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter				size_t cnt, loff_t *ppos)
301736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{
302736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	char *buf = filp->private_data;
303736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
304736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return simple_read_from_buffer(ubuf, cnt, ppos,
305736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter				       buf, EXT_CSD_STR_LEN);
306736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}
307736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
308736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_release(struct inode *inode, struct file *file)
309736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{
310736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(file->private_data);
311736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return 0;
312736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}
313736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
314828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations mmc_dbg_ext_csd_fops = {
315736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	.open		= mmc_ext_csd_open,
316736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	.read		= mmc_ext_csd_read,
317736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	.release	= mmc_ext_csd_release,
3186038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek		= default_llseek,
319736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter};
320736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
321f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_add_card_debugfs(struct mmc_card *card)
322f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{
323f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	struct mmc_host	*host = card->host;
324f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	struct dentry	*root;
325f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
326f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!host->debugfs_root)
327f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		return;
328f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
329f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
330f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (IS_ERR(root))
331f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		/* Don't complain -- debugfs just isn't enabled */
332f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		return;
333f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!root)
334f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		/* Complain -- debugfs is enabled, but it failed to
335f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		 * create the directory. */
336f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		goto err;
337f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
338f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	card->debugfs_root = root;
339f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
340f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
341f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		goto err;
342f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
343f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (mmc_card_mmc(card) || mmc_card_sd(card))
344f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		if (!debugfs_create_file("status", S_IRUSR, root, card,
345f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen					&mmc_dbg_card_status_fops))
346f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen			goto err;
347f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
348736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (mmc_card_mmc(card))
349736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
350736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter					&mmc_dbg_ext_csd_fops))
351736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter			goto err;
352736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
353f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	return;
354f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
355f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenerr:
356f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	debugfs_remove_recursive(root);
357f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	card->debugfs_root = NULL;
358f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	dev_err(&card->dev, "failed to initialize debugfs\n");
359f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen}
360f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
361f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_remove_card_debugfs(struct mmc_card *card)
362f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{
363f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	debugfs_remove_recursive(card->debugfs_root);
364f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen}
365