debugfs.c revision 6edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8c
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 */
106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/debugfs.h>
116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/fs.h>
126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/seq_file.h>
136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/stat.h>
146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/mmc/host.h>
166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include "core.h"
186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_show(struct seq_file *s, void *data)
216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	static const char *vdd_str[] = {
236edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[8]	= "2.0",
246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[9]	= "2.1",
256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[10]	= "2.2",
266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[11]	= "2.3",
276edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[12]	= "2.4",
286edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[13]	= "2.5",
296edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[14]	= "2.6",
306edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[15]	= "2.7",
316edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[16]	= "2.8",
326edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[17]	= "2.9",
336edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[18]	= "3.0",
346edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[19]	= "3.1",
356edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[20]	= "3.2",
366edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[21]	= "3.3",
376edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[22]	= "3.4",
386edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[23]	= "3.5",
396edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		[24]	= "3.6",
406edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	};
416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct mmc_host	*host = s->private;
426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct mmc_ios	*ios = &host->ios;
436edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	const char *str;
446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "vdd:\t\t%u ", ios->vdd);
476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if ((1 << ios->vdd) & MMC_VDD_165_195)
486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		seq_printf(s, "(1.65 - 1.95 V)\n");
496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1)
506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen			&& vdd_str[ios->vdd] && vdd_str[ios->vdd + 1])
516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd],
526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen				vdd_str[ios->vdd + 1]);
536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	else
546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		seq_printf(s, "(invalid)\n");
556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->bus_mode) {
576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_BUSMODE_OPENDRAIN:
586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "open drain";
596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
606edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_BUSMODE_PUSHPULL:
616edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "push-pull";
626edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
636edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
646edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
656edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
666edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
676edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str);
686edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
696edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->chip_select) {
706edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_CS_DONTCARE:
716edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "don't care";
726edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
736edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_CS_HIGH:
746edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "active high";
756edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
766edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_CS_LOW:
776edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "active low";
786edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
796edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
806edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
816edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
826edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
836edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str);
846edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
856edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->power_mode) {
866edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_POWER_OFF:
876edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "off";
886edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
896edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_POWER_UP:
906edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "up";
916edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
926edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_POWER_ON:
936edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "on";
946edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
956edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
966edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
976edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
986edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
996edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str);
1006edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "bus width:\t%u (%u bits)\n",
1016edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen			ios->bus_width, 1 << ios->bus_width);
1026edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1036edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	switch (ios->timing) {
1046edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_TIMING_LEGACY:
1056edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "legacy";
1066edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1076edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_TIMING_MMC_HS:
1086edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "mmc high-speed";
1096edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	case MMC_TIMING_SD_HS:
1116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "sd high-speed";
1126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	default:
1146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		str = "invalid";
1156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		break;
1166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	}
1176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
1186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return 0;
1206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_open(struct inode *inode, struct file *file)
1236edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
1246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return single_open(file, mmc_ios_show, inode->i_private);
1256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1276edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic const struct file_operations mmc_ios_fops = {
1286edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.open		= mmc_ios_open,
1296edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.read		= seq_read,
1306edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.llseek		= seq_lseek,
1316edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	.release	= single_release,
1326edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen};
1336edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1346edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_add_host_debugfs(struct mmc_host *host)
1356edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
1366edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	struct dentry *root;
1376edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1386edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	root = debugfs_create_dir(mmc_hostname(host), NULL);
1396edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (IS_ERR(root))
1406edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		/* Don't complain -- debugfs just isn't enabled */
1416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		return;
1426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (!root)
1436edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		/* Complain -- debugfs is enabled, but it failed to
1446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		 * create the directory. */
1456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		goto err_root;
1466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	host->debugfs_root = root;
1486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
1506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen		goto err_ios;
1516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	return;
1536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_ios:
1556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	debugfs_remove_recursive(root);
1566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	host->debugfs_root = NULL;
1576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_root:
1586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	dev_err(&host->class_dev, "failed to initialize debugfs\n");
1596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
1606edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen
1616edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_remove_host_debugfs(struct mmc_host *host)
1626edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{
1636edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen	debugfs_remove_recursive(host->debugfs_root);
1646edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}
165