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