debugfs.c revision e94cfef698aae6b209d8918dd319312e4b02118d
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
14742cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	switch (ios->signal_voltage) {
14842cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	case MMC_SIGNAL_VOLTAGE_330:
14942cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		str = "3.30 V";
15042cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		break;
15142cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	case MMC_SIGNAL_VOLTAGE_180:
15242cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		str = "1.80 V";
15342cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		break;
15442cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	case MMC_SIGNAL_VOLTAGE_120:
15542cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		str = "1.20 V";
15642cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		break;
15742cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	default:
15842cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		str = "invalid";
15942cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm		break;
16042cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	}
16142cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm	seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str);
16242cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm
1636edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return 0;
1646edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1656edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1666edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_open(struct inode *inode, struct file *file)
1676edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
1686edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return single_open(file, mmc_ios_show, inode->i_private);
1696edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1706edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1716edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic const struct file_operations mmc_ios_fops = {
1726edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.open		= mmc_ios_open,
1736edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.read		= seq_read,
1746edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.llseek		= seq_lseek,
1756edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.release	= single_release,
1766edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen};
1776edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
178703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkostatic int mmc_clock_opt_get(void *data, u64 *val)
179703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko{
180703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	struct mmc_host *host = data;
181703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
182703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	*val = host->ios.clock;
183703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
184703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	return 0;
185703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko}
186703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
187703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkostatic int mmc_clock_opt_set(void *data, u64 val)
188703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko{
189703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	struct mmc_host *host = data;
190703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
191703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	/* We need this check due to input value is u64 */
192703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	if (val > host->f_max)
193703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko		return -EINVAL;
194703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
195703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	mmc_claim_host(host);
196703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	mmc_set_clock(host, (unsigned int) val);
197703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	mmc_release_host(host);
198703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
199703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	return 0;
200703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko}
201703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
202703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy ShevchenkoDEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
203703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	"%llu\n");
204703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
2056edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_add_host_debugfs(struct mmc_host *host)
2066edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
2076edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct dentry *root;
2086edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2096edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	root = debugfs_create_dir(mmc_hostname(host), NULL);
2106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (IS_ERR(root))
2116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		/* Don't complain -- debugfs just isn't enabled */
2126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		return;
2136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (!root)
2146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		/* Complain -- debugfs is enabled, but it failed to
2156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		 * create the directory. */
2166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		goto err_root;
2176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	host->debugfs_root = root;
2196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
221703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko		goto err_node;
222703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko
223703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko	if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host,
224703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko			&mmc_clock_fops))
225703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko		goto err_node;
2266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
22704566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij#ifdef CONFIG_MMC_CLKGATE
22804566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij	if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
22904566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij				root, &host->clk_delay))
23004566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij		goto err_node;
23104566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij#endif
2321b676f70c108cda90cf9d114d16c677584400efcPer Forlin#ifdef CONFIG_FAIL_MMC_REQUEST
23334f5050800d600551cca9bcfb463cc6699d82d04Per Forlin	if (fail_request)
23434f5050800d600551cca9bcfb463cc6699d82d04Per Forlin		setup_fault_attr(&fail_default_attr, fail_request);
23534f5050800d600551cca9bcfb463cc6699d82d04Per Forlin	host->fail_mmc_request = fail_default_attr;
2361b676f70c108cda90cf9d114d16c677584400efcPer Forlin	if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
2371b676f70c108cda90cf9d114d16c677584400efcPer Forlin					     root,
2381b676f70c108cda90cf9d114d16c677584400efcPer Forlin					     &host->fail_mmc_request)))
2391b676f70c108cda90cf9d114d16c677584400efcPer Forlin		goto err_node;
2401b676f70c108cda90cf9d114d16c677584400efcPer Forlin#endif
2416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return;
2426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
243703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkoerr_node:
2446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	debugfs_remove_recursive(root);
2456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	host->debugfs_root = NULL;
2466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_root:
2476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	dev_err(&host->class_dev, "failed to initialize debugfs\n");
2486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
2496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
2506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_remove_host_debugfs(struct mmc_host *host)
2516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
2526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	debugfs_remove_recursive(host->debugfs_root);
2536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
254f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
255f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenstatic int mmc_dbg_card_status_get(void *data, u64 *val)
256f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{
257f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	struct mmc_card	*card = data;
258f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	u32		status;
259f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	int		ret;
260f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
261e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_get_card(card);
262f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
263f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	ret = mmc_send_status(data, &status);
264f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!ret)
265f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		*val = status;
266f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
267e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_put_card(card);
268f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
269f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	return ret;
270f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen}
271f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard SkinnemoenDEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
272f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		NULL, "%08llx\n");
273f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
274736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter#define EXT_CSD_STR_LEN 1025
275736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
276736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_open(struct inode *inode, struct file *filp)
277736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{
278736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	struct mmc_card *card = inode->i_private;
279736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	char *buf;
280736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	ssize_t n = 0;
281736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	u8 *ext_csd;
282736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	int err, i;
283736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
284736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
285736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (!buf)
286736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		return -ENOMEM;
287736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
288736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	ext_csd = kmalloc(512, GFP_KERNEL);
289736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (!ext_csd) {
290736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		err = -ENOMEM;
291736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		goto out_free;
292736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	}
293736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
294e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_get_card(card);
295736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	err = mmc_send_ext_csd(card, ext_csd);
296e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_put_card(card);
297736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (err)
298736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		goto out_free;
299736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
3006780162c0097915dbc4e8fc11af662a270093d85Venkatraman S	for (i = 0; i < 512; i++)
301736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		n += sprintf(buf + n, "%02x", ext_csd[i]);
302736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	n += sprintf(buf + n, "\n");
303736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	BUG_ON(n != EXT_CSD_STR_LEN);
304736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
305736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	filp->private_data = buf;
306736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(ext_csd);
307736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return 0;
308736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
309736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterout_free:
310736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(buf);
311736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(ext_csd);
312736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return err;
313736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}
314736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
315736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
316736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter				size_t cnt, loff_t *ppos)
317736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{
318736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	char *buf = filp->private_data;
319736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
320736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return simple_read_from_buffer(ubuf, cnt, ppos,
321736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter				       buf, EXT_CSD_STR_LEN);
322736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}
323736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
324736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_release(struct inode *inode, struct file *file)
325736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{
326736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	kfree(file->private_data);
327736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	return 0;
328736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}
329736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
330828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations mmc_dbg_ext_csd_fops = {
331736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	.open		= mmc_ext_csd_open,
332736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	.read		= mmc_ext_csd_read,
333736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	.release	= mmc_ext_csd_release,
3346038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek		= default_llseek,
335736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter};
336736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
337f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_add_card_debugfs(struct mmc_card *card)
338f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{
339f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	struct mmc_host	*host = card->host;
340f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	struct dentry	*root;
341f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
342f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!host->debugfs_root)
343f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		return;
344f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
345f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
346f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (IS_ERR(root))
347f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		/* Don't complain -- debugfs just isn't enabled */
348f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		return;
349f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!root)
350f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		/* Complain -- debugfs is enabled, but it failed to
351f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		 * create the directory. */
352f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		goto err;
353f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
354f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	card->debugfs_root = root;
355f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
356f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
357f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		goto err;
358f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
359f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	if (mmc_card_mmc(card) || mmc_card_sd(card))
360f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen		if (!debugfs_create_file("status", S_IRUSR, root, card,
361f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen					&mmc_dbg_card_status_fops))
362f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen			goto err;
363f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
364736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter	if (mmc_card_mmc(card))
365736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter		if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
366736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter					&mmc_dbg_ext_csd_fops))
367736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter			goto err;
368736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter
369f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	return;
370f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
371f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenerr:
372f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	debugfs_remove_recursive(root);
373f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	card->debugfs_root = NULL;
374f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	dev_err(&card->dev, "failed to initialize debugfs\n");
375f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen}
376f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen
377f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_remove_card_debugfs(struct mmc_card *card)
378f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{
379f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen	debugfs_remove_recursive(card->debugfs_root);
380f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen}
381