14Srgrimes// SPDX-License-Identifier: GPL-2.0-only 24Srgrimes/* 34Srgrimes * Debugfs support for hosts and cards 44Srgrimes * 54Srgrimes * Copyright (C) 2008 Atmel Corporation 64Srgrimes */ 74Srgrimes#include <linux/moduleparam.h> 84Srgrimes#include <linux/export.h> 94Srgrimes#include <linux/debugfs.h> 104Srgrimes#include <linux/fs.h> 114Srgrimes#include <linux/seq_file.h> 124Srgrimes#include <linux/slab.h> 134Srgrimes#include <linux/stat.h> 144Srgrimes#include <linux/fault-inject.h> 154Srgrimes#include <linux/time.h> 164Srgrimes 174Srgrimes#include <linux/mmc/card.h> 184Srgrimes#include <linux/mmc/host.h> 194Srgrimes#include <linux/mmc/mmc.h> 204Srgrimes#include <linux/mmc/sd.h> 214Srgrimes 224Srgrimes#include "core.h" 234Srgrimes#include "card.h" 244Srgrimes#include "host.h" 254Srgrimes#include "mmc_ops.h" 264Srgrimes 274Srgrimes#ifdef CONFIG_FAIL_MMC_REQUEST 284Srgrimes 294Srgrimesstatic DECLARE_FAULT_ATTR(fail_default_attr); 304Srgrimesstatic char *fail_request; 314Srgrimesmodule_param(fail_request, charp, 0); 324SrgrimesMODULE_PARM_DESC(fail_request, "default fault injection attributes"); 334Srgrimes 344Srgrimes#endif /* CONFIG_FAIL_MMC_REQUEST */ 354Srgrimes 36556Srgrimes/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */ 371321Sdgstatic int mmc_ios_show(struct seq_file *s, void *data) 384Srgrimes{ 394Srgrimes static const char *vdd_str[] = { 404Srgrimes [8] = "2.0", 41757Sdg [9] = "2.1", 42757Sdg [10] = "2.2", 43757Sdg [11] = "2.3", 44757Sdg [12] = "2.4", 45757Sdg [13] = "2.5", 464Srgrimes [14] = "2.6", 474Srgrimes [15] = "2.7", 48757Sdg [16] = "2.8", 49757Sdg [17] = "2.9", 50757Sdg [18] = "3.0", 51757Sdg [19] = "3.1", 52757Sdg [20] = "3.2", 53757Sdg [21] = "3.3", 54757Sdg [22] = "3.4", 55757Sdg [23] = "3.5", 56757Sdg [24] = "3.6", 574Srgrimes }; 584Srgrimes struct mmc_host *host = s->private; 59757Sdg struct mmc_ios *ios = &host->ios; 60757Sdg const char *str; 614Srgrimes 624Srgrimes seq_printf(s, "clock:\t\t%u Hz\n", ios->clock); 634Srgrimes if (host->actual_clock) 644Srgrimes seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock); 654Srgrimes seq_printf(s, "vdd:\t\t%u ", ios->vdd); 66200Sdg if ((1 << ios->vdd) & MMC_VDD_165_195) 674Srgrimes seq_printf(s, "(1.65 - 1.95 V)\n"); 684Srgrimes else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1) 694Srgrimes && vdd_str[ios->vdd] && vdd_str[ios->vdd + 1]) 70592Srgrimes seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd], 71592Srgrimes vdd_str[ios->vdd + 1]); 72592Srgrimes else 73757Sdg seq_printf(s, "(invalid)\n"); 74592Srgrimes 75757Sdg switch (ios->bus_mode) { 76608Srgrimes case MMC_BUSMODE_OPENDRAIN: 774Srgrimes str = "open drain"; 784Srgrimes break; 794Srgrimes case MMC_BUSMODE_PUSHPULL: 804Srgrimes str = "push-pull"; 814Srgrimes break; 82592Srgrimes default: 83592Srgrimes str = "invalid"; 84592Srgrimes break; 85757Sdg } 864Srgrimes seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str); 874Srgrimes 884Srgrimes switch (ios->chip_select) { 894Srgrimes case MMC_CS_DONTCARE: 904Srgrimes str = "don't care"; 914Srgrimes break; 92570Srgrimes case MMC_CS_HIGH: 93134Sdg str = "active high"; 944Srgrimes break; 95556Srgrimes case MMC_CS_LOW: 96556Srgrimes str = "active low"; 97556Srgrimes break; 98556Srgrimes default: 99556Srgrimes str = "invalid"; 100757Sdg break; 101134Sdg } 102592Srgrimes seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str); 103134Sdg 104592Srgrimes switch (ios->power_mode) { 105757Sdg case MMC_POWER_OFF: 106757Sdg str = "off"; 107757Sdg break; 108757Sdg case MMC_POWER_UP: 1094Srgrimes str = "up"; 110757Sdg break; 111757Sdg case MMC_POWER_ON: 112757Sdg str = "on"; 113592Srgrimes break; 114757Sdg default: 115757Sdg str = "invalid"; 1164Srgrimes break; 117757Sdg } 118757Sdg seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str); 119718Swollman seq_printf(s, "bus width:\t%u (%u bits)\n", 120757Sdg ios->bus_width, 1 << ios->bus_width); 121757Sdg 122134Sdg switch (ios->timing) { 123757Sdg case MMC_TIMING_LEGACY: 124757Sdg str = "legacy"; 1251321Sdg break; 126757Sdg case MMC_TIMING_MMC_HS: 127718Swollman str = "mmc high-speed"; 128757Sdg break; 129974Sdg case MMC_TIMING_SD_HS: 1304Srgrimes str = "sd high-speed"; 131134Sdg break; 132134Sdg case MMC_TIMING_UHS_SDR12: 133556Srgrimes str = "sd uhs SDR12"; 134556Srgrimes break; 135556Srgrimes case MMC_TIMING_UHS_SDR25: 1364Srgrimes str = "sd uhs SDR25"; 137134Sdg break; 138134Sdg case MMC_TIMING_UHS_SDR50: 139200Sdg str = "sd uhs SDR50"; 140200Sdg break; 141134Sdg case MMC_TIMING_UHS_SDR104: 1421321Sdg str = "sd uhs SDR104"; 143757Sdg break; 1444Srgrimes case MMC_TIMING_UHS_DDR50: 1451321Sdg str = "sd uhs DDR50"; 1464Srgrimes break; 1474Srgrimes case MMC_TIMING_MMC_DDR52: 148556Srgrimes str = "mmc DDR52"; 1494Srgrimes break; 1504Srgrimes case MMC_TIMING_MMC_HS200: 1514Srgrimes str = "mmc HS200"; 1524Srgrimes break; 1534Srgrimes case MMC_TIMING_MMC_HS400: 154570Srgrimes str = mmc_card_hs400es(host->card) ? 1554Srgrimes "mmc HS400 enhanced strobe" : "mmc HS400"; 156570Srgrimes break; 1574Srgrimes default: 158570Srgrimes str = "invalid"; 159556Srgrimes break; 160570Srgrimes } 161570Srgrimes seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str); 162975Smartin 163975Smartin switch (ios->signal_voltage) { 164975Smartin case MMC_SIGNAL_VOLTAGE_330: 165975Smartin str = "3.30 V"; 166975Smartin break; 167975Smartin case MMC_SIGNAL_VOLTAGE_180: 168975Smartin str = "1.80 V"; 1694Srgrimes break; 170556Srgrimes case MMC_SIGNAL_VOLTAGE_120: 171556Srgrimes str = "1.20 V"; 172556Srgrimes break; 173556Srgrimes default: 174556Srgrimes str = "invalid"; 175556Srgrimes break; 176556Srgrimes } 177556Srgrimes seq_printf(s, "signal voltage:\t%u (%s)\n", ios->signal_voltage, str); 178556Srgrimes 179556Srgrimes switch (ios->drv_type) { 180556Srgrimes case MMC_SET_DRIVER_TYPE_A: 181556Srgrimes str = "driver type A"; 182556Srgrimes break; 183556Srgrimes case MMC_SET_DRIVER_TYPE_B: 1841321Sdg str = "driver type B"; 185556Srgrimes break; 186556Srgrimes case MMC_SET_DRIVER_TYPE_C: 187570Srgrimes str = "driver type C"; 188556Srgrimes break; 189570Srgrimes case MMC_SET_DRIVER_TYPE_D: 190556Srgrimes str = "driver type D"; 191556Srgrimes break; 1924Srgrimes default: 1934Srgrimes str = "invalid"; 1944Srgrimes break; 1954Srgrimes } 1964Srgrimes seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str); 1974Srgrimes 1984Srgrimes return 0; 1994Srgrimes} 2004SrgrimesDEFINE_SHOW_ATTRIBUTE(mmc_ios); 2014Srgrimes 2024Srgrimesstatic int mmc_clock_opt_get(void *data, u64 *val) 2034Srgrimes{ 2044Srgrimes struct mmc_host *host = data; 2054Srgrimes 206757Sdg *val = host->ios.clock; 2074Srgrimes 208570Srgrimes return 0; 209570Srgrimes} 210570Srgrimes 211570Srgrimesstatic int mmc_clock_opt_set(void *data, u64 val) 212974Sdg{ 213570Srgrimes struct mmc_host *host = data; 214570Srgrimes 2154Srgrimes /* We need this check due to input value is u64 */ 216570Srgrimes if (val != 0 && (val > host->f_max || val < host->f_min)) 217757Sdg return -EINVAL; 2184Srgrimes 2191321Sdg mmc_claim_host(host); 220757Sdg mmc_set_clock(host, (unsigned int) val); 2214Srgrimes mmc_release_host(host); 222757Sdg 223570Srgrimes return 0; 224760Srgrimes} 225757Sdg 2264SrgrimesDEFINE_DEBUGFS_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, 2274Srgrimes "%llu\n"); 2284Srgrimes 2294Srgrimesstatic int mmc_err_state_get(void *data, u64 *val) 230608Srgrimes{ 231974Sdg struct mmc_host *host = data; 232974Sdg int i; 233974Sdg 234974Sdg if (!host) 235757Sdg return -EINVAL; 236757Sdg 237608Srgrimes *val = 0; 238757Sdg for (i = 0; i < MMC_ERR_MAX; i++) { 239608Srgrimes if (host->err_stats[i]) { 240757Sdg *val = 1; 241757Sdg break; 242974Sdg } 243757Sdg } 244757Sdg 245757Sdg return 0; 246757Sdg} 247757Sdg 248757SdgDEFINE_DEBUGFS_ATTRIBUTE(mmc_err_state, mmc_err_state_get, NULL, "%llu\n"); 249570Srgrimes 2504Srgrimesstatic int mmc_err_stats_show(struct seq_file *file, void *data) 251592Srgrimes{ 252592Srgrimes struct mmc_host *host = file->private; 253592Srgrimes const char *desc[MMC_ERR_MAX] = { 254592Srgrimes [MMC_ERR_CMD_TIMEOUT] = "Command Timeout Occurred", 255592Srgrimes [MMC_ERR_CMD_CRC] = "Command CRC Errors Occurred", 256592Srgrimes [MMC_ERR_DAT_TIMEOUT] = "Data Timeout Occurred", 2574Srgrimes [MMC_ERR_DAT_CRC] = "Data CRC Errors Occurred", 2584Srgrimes [MMC_ERR_AUTO_CMD] = "Auto-Cmd Error Occurred", 259570Srgrimes [MMC_ERR_ADMA] = "ADMA Error Occurred", 2604Srgrimes [MMC_ERR_TUNING] = "Tuning Error Occurred", 2614Srgrimes [MMC_ERR_CMDQ_RED] = "CMDQ RED Errors", 2624Srgrimes [MMC_ERR_CMDQ_GCE] = "CMDQ GCE Errors", 2634Srgrimes [MMC_ERR_CMDQ_ICCE] = "CMDQ ICCE Errors", 2644Srgrimes [MMC_ERR_REQ_TIMEOUT] = "Request Timedout", 2654Srgrimes [MMC_ERR_CMDQ_REQ_TIMEOUT] = "CMDQ Request Timedout", 2664Srgrimes [MMC_ERR_ICE_CFG] = "ICE Config Errors", 2674Srgrimes [MMC_ERR_CTRL_TIMEOUT] = "Controller Timedout errors", 268757Sdg [MMC_ERR_UNEXPECTED_IRQ] = "Unexpected IRQ errors", 269757Sdg }; 270757Sdg int i; 271757Sdg 272757Sdg for (i = 0; i < MMC_ERR_MAX; i++) { 273200Sdg if (desc[i]) 274200Sdg seq_printf(file, "# %s:\t %d\n", 275200Sdg desc[i], host->err_stats[i]); 276757Sdg } 277757Sdg 278757Sdg return 0; 279757Sdg} 2804Srgrimes 2814Srgrimesstatic int mmc_err_stats_open(struct inode *inode, struct file *file) 282757Sdg{ 283757Sdg return single_open(file, mmc_err_stats_show, inode->i_private); 284757Sdg} 285757Sdg 286757Sdgstatic ssize_t mmc_err_stats_write(struct file *filp, const char __user *ubuf, 287757Sdg size_t cnt, loff_t *ppos) 288757Sdg{ 289757Sdg struct mmc_host *host = filp->f_mapping->host->i_private; 290757Sdg 291757Sdg pr_debug("%s: Resetting MMC error statistics\n", __func__); 292757Sdg memset(host->err_stats, 0, sizeof(host->err_stats)); 293757Sdg 294757Sdg return cnt; 295757Sdg} 296757Sdg 297757Sdgstatic const struct file_operations mmc_err_stats_fops = { 2981321Sdg .open = mmc_err_stats_open, 299757Sdg .read = seq_read, 300757Sdg .write = mmc_err_stats_write, 301757Sdg .release = single_release, 302974Sdg}; 303757Sdg 304757Sdgstatic int mmc_caps_get(void *data, u64 *val) 305757Sdg{ 306757Sdg *val = *(u32 *)data; 307757Sdg return 0; 308757Sdg} 309757Sdg 310757Sdgstatic int mmc_caps_set(void *data, u64 val) 3111321Sdg{ 3124Srgrimes u32 *caps = data; 3134Srgrimes u32 diff = *caps ^ val; 314757Sdg u32 allowed = MMC_CAP_AGGRESSIVE_PM | 315757Sdg MMC_CAP_SD_HIGHSPEED | 316757Sdg MMC_CAP_MMC_HIGHSPEED | 3171046Sdg MMC_CAP_UHS | 318757Sdg MMC_CAP_DDR; 3194Srgrimes 3204Srgrimes if (diff & ~allowed) 3214Srgrimes return -EINVAL; 3224Srgrimes 323757Sdg *caps = val; 324757Sdg 325757Sdg return 0; 326757Sdg} 327757Sdg 328757Sdgstatic int mmc_caps2_set(void *data, u64 val) 329757Sdg{ 3304Srgrimes u32 allowed = MMC_CAP2_HSX00_1_8V | MMC_CAP2_HSX00_1_2V; 3314Srgrimes u32 *caps = data; 3324Srgrimes u32 diff = *caps ^ val; 333757Sdg 3344Srgrimes if (diff & ~allowed) 3354Srgrimes return -EINVAL; 336757Sdg 337757Sdg *caps = val; 338757Sdg 3394Srgrimes return 0; 340757Sdg} 341974Sdg 342757SdgDEFINE_DEBUGFS_ATTRIBUTE(mmc_caps_fops, mmc_caps_get, mmc_caps_set, 3434Srgrimes "0x%08llx\n"); 3444SrgrimesDEFINE_DEBUGFS_ATTRIBUTE(mmc_caps2_fops, mmc_caps_get, mmc_caps2_set, 3454Srgrimes "0x%08llx\n"); 346757Sdg 347757Sdgvoid mmc_add_host_debugfs(struct mmc_host *host) 348757Sdg{ 3494Srgrimes struct dentry *root; 3504Srgrimes 351757Sdg root = debugfs_create_dir(mmc_hostname(host), NULL); 352757Sdg host->debugfs_root = root; 353757Sdg 3544Srgrimes debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops); 355757Sdg debugfs_create_file("caps", 0600, root, &host->caps, &mmc_caps_fops); 3564Srgrimes debugfs_create_file("caps2", 0600, root, &host->caps2, 3574Srgrimes &mmc_caps2_fops); 358757Sdg debugfs_create_file_unsafe("clock", S_IRUSR | S_IWUSR, root, host, 3594Srgrimes &mmc_clock_fops); 360570Srgrimes 3614Srgrimes debugfs_create_file_unsafe("err_state", 0600, root, host, 3624Srgrimes &mmc_err_state); 3634Srgrimes debugfs_create_file("err_stats", 0600, root, host, 3644Srgrimes &mmc_err_stats_fops); 3654Srgrimes 366757Sdg#ifdef CONFIG_FAIL_MMC_REQUEST 367570Srgrimes if (fail_request) 3684Srgrimes setup_fault_attr(&fail_default_attr, fail_request); 3694Srgrimes host->fail_mmc_request = fail_default_attr; 370757Sdg fault_create_debugfs_attr("fail_mmc_request", root, 3714Srgrimes &host->fail_mmc_request); 372570Srgrimes#endif 3734Srgrimes} 3744Srgrimes 3754Srgrimesvoid mmc_remove_host_debugfs(struct mmc_host *host) 376757Sdg{ 377757Sdg debugfs_remove_recursive(host->debugfs_root); 3784Srgrimes} 379570Srgrimes 3804Srgrimesvoid mmc_add_card_debugfs(struct mmc_card *card) 381570Srgrimes{ 382757Sdg struct mmc_host *host = card->host; 3834Srgrimes struct dentry *root; 384570Srgrimes 3854Srgrimes if (!host->debugfs_root) 386570Srgrimes return; 3874Srgrimes 388570Srgrimes root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); 3894Srgrimes card->debugfs_root = root; 3904Srgrimes 391757Sdg debugfs_create_x32("state", S_IRUSR, root, &card->state); 3924Srgrimes} 3934Srgrimes 3944Srgrimesvoid mmc_remove_card_debugfs(struct mmc_card *card) 3954Srgrimes{ 3964Srgrimes debugfs_remove_recursive(card->debugfs_root); 3974Srgrimes card->debugfs_root = NULL; 3984Srgrimes} 3991321Sdg