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