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; 13879f7ae7c45a6ccf04e2908337461dee615f6afb0Seungwon Jeon case MMC_TIMING_MMC_DDR52: 13979f7ae7c45a6ccf04e2908337461dee615f6afb0Seungwon Jeon str = "mmc DDR52"; 14079f7ae7c45a6ccf04e2908337461dee615f6afb0Seungwon Jeon break; 141a4924c71aa43d4f8a3f342b1f71788349472e684Girish K S case MMC_TIMING_MMC_HS200: 142577fb13199b11d8cd75609183649be4b5561243fSeungwon Jeon str = "mmc HS200"; 143a4924c71aa43d4f8a3f342b1f71788349472e684Girish K S break; 1440a5b6438ee482696360bb013e67b8488f63d3e9eSeungwon Jeon case MMC_TIMING_MMC_HS400: 1450a5b6438ee482696360bb013e67b8488f63d3e9eSeungwon Jeon str = "mmc HS400"; 1460a5b6438ee482696360bb013e67b8488f63d3e9eSeungwon Jeon break; 1476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen default: 1486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "invalid"; 1496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 1506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen } 1516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str); 1526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 15342cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm switch (ios->signal_voltage) { 15442cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm case MMC_SIGNAL_VOLTAGE_330: 15542cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm str = "3.30 V"; 15642cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm break; 15742cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm case MMC_SIGNAL_VOLTAGE_180: 15842cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm str = "1.80 V"; 15942cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm break; 16042cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm case MMC_SIGNAL_VOLTAGE_120: 16142cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm str = "1.20 V"; 16242cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm break; 16342cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm default: 16442cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm str = "invalid"; 16542cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm break; 16642cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm } 16742cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str); 16842cd95a0603e0497e7221816bb5ddfe861ee9325Johan Rudholm 1696edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return 0; 1706edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 1716edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1726edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_open(struct inode *inode, struct file *file) 1736edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 1746edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return single_open(file, mmc_ios_show, inode->i_private); 1756edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 1766edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1776edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic const struct file_operations mmc_ios_fops = { 1786edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .open = mmc_ios_open, 1796edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .read = seq_read, 1806edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .llseek = seq_lseek, 1816edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .release = single_release, 1826edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}; 1836edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 184703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkostatic int mmc_clock_opt_get(void *data, u64 *val) 185703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko{ 186703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko struct mmc_host *host = data; 187703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 188703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko *val = host->ios.clock; 189703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 190703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko return 0; 191703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko} 192703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 193703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkostatic int mmc_clock_opt_set(void *data, u64 val) 194703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko{ 195703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko struct mmc_host *host = data; 196703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 197703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko /* We need this check due to input value is u64 */ 198703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko if (val > host->f_max) 199703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko return -EINVAL; 200703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 201703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko mmc_claim_host(host); 202703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko mmc_set_clock(host, (unsigned int) val); 203703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko mmc_release_host(host); 204703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 205703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko return 0; 206703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko} 207703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 208703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy ShevchenkoDEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, 209703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko "%llu\n"); 210703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 2116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_add_host_debugfs(struct mmc_host *host) 2126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 2136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen struct dentry *root; 2146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 2156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen root = debugfs_create_dir(mmc_hostname(host), NULL); 2166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if (IS_ERR(root)) 2176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen /* Don't complain -- debugfs just isn't enabled */ 2186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return; 2196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if (!root) 2206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen /* Complain -- debugfs is enabled, but it failed to 2216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * create the directory. */ 2226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen goto err_root; 2236edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 2246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen host->debugfs_root = root; 2256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 2266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) 227703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko goto err_node; 228703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko 229703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, 230703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko &mmc_clock_fops)) 231703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenko goto err_node; 2326edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 23304566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij#ifdef CONFIG_MMC_CLKGATE 23404566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), 23504566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij root, &host->clk_delay)) 23604566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij goto err_node; 23704566831a703ae3ef4b49a2deae261c9ed26e020Linus Walleij#endif 2381b676f70c108cda90cf9d114d16c677584400efcPer Forlin#ifdef CONFIG_FAIL_MMC_REQUEST 23934f5050800d600551cca9bcfb463cc6699d82d04Per Forlin if (fail_request) 24034f5050800d600551cca9bcfb463cc6699d82d04Per Forlin setup_fault_attr(&fail_default_attr, fail_request); 24134f5050800d600551cca9bcfb463cc6699d82d04Per Forlin host->fail_mmc_request = fail_default_attr; 2421b676f70c108cda90cf9d114d16c677584400efcPer Forlin if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request", 2431b676f70c108cda90cf9d114d16c677584400efcPer Forlin root, 2441b676f70c108cda90cf9d114d16c677584400efcPer Forlin &host->fail_mmc_request))) 2451b676f70c108cda90cf9d114d16c677584400efcPer Forlin goto err_node; 2461b676f70c108cda90cf9d114d16c677584400efcPer Forlin#endif 2476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return; 2486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 249703aae3d09a4b351866f1a97b2afafb905bdbf1eAndy Shevchenkoerr_node: 2506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen debugfs_remove_recursive(root); 2516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen host->debugfs_root = NULL; 2526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_root: 2536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen dev_err(&host->class_dev, "failed to initialize debugfs\n"); 2546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 2556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 2566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_remove_host_debugfs(struct mmc_host *host) 2576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 2586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen debugfs_remove_recursive(host->debugfs_root); 2596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 260f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 261f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenstatic int mmc_dbg_card_status_get(void *data, u64 *val) 262f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{ 263f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen struct mmc_card *card = data; 264f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen u32 status; 265f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen int ret; 266f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 267e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_get_card(card); 268f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 269f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen ret = mmc_send_status(data, &status); 270f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!ret) 271f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen *val = status; 272f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 273e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_put_card(card); 274f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 275f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return ret; 276f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen} 277f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard SkinnemoenDEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, 278f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen NULL, "%08llx\n"); 279f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 280736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter#define EXT_CSD_STR_LEN 1025 281736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 282736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_open(struct inode *inode, struct file *filp) 283736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{ 284736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter struct mmc_card *card = inode->i_private; 285736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter char *buf; 286736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter ssize_t n = 0; 287736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter u8 *ext_csd; 288736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter int err, i; 289736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 290736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL); 291736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (!buf) 292736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return -ENOMEM; 293736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 294736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter ext_csd = kmalloc(512, GFP_KERNEL); 295736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (!ext_csd) { 296736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter err = -ENOMEM; 297736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter goto out_free; 298736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter } 299736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 300e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_get_card(card); 301736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter err = mmc_send_ext_csd(card, ext_csd); 302e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson mmc_put_card(card); 303736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (err) 304736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter goto out_free; 305736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 3066780162c0097915dbc4e8fc11af662a270093d85Venkatraman S for (i = 0; i < 512; i++) 307736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter n += sprintf(buf + n, "%02x", ext_csd[i]); 308736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter n += sprintf(buf + n, "\n"); 309736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter BUG_ON(n != EXT_CSD_STR_LEN); 310736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 311736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter filp->private_data = buf; 312736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(ext_csd); 313736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return 0; 314736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 315736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterout_free: 316736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(buf); 317736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(ext_csd); 318736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return err; 319736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter} 320736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 321736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf, 322736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter size_t cnt, loff_t *ppos) 323736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{ 324736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter char *buf = filp->private_data; 325736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 326736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return simple_read_from_buffer(ubuf, cnt, ppos, 327736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter buf, EXT_CSD_STR_LEN); 328736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter} 329736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 330736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_release(struct inode *inode, struct file *file) 331736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{ 332736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(file->private_data); 333736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return 0; 334736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter} 335736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 336828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations mmc_dbg_ext_csd_fops = { 337736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter .open = mmc_ext_csd_open, 338736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter .read = mmc_ext_csd_read, 339736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter .release = mmc_ext_csd_release, 3406038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = default_llseek, 341736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}; 342736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 343f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_add_card_debugfs(struct mmc_card *card) 344f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{ 345f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen struct mmc_host *host = card->host; 346f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen struct dentry *root; 347f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 348f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!host->debugfs_root) 349f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return; 350f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 351f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); 352f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (IS_ERR(root)) 353f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen /* Don't complain -- debugfs just isn't enabled */ 354f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return; 355f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!root) 356f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen /* Complain -- debugfs is enabled, but it failed to 357f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen * create the directory. */ 358f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen goto err; 359f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 360f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen card->debugfs_root = root; 361f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 362f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) 363f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen goto err; 364f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 365f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (mmc_card_mmc(card) || mmc_card_sd(card)) 366f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!debugfs_create_file("status", S_IRUSR, root, card, 367f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen &mmc_dbg_card_status_fops)) 368f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen goto err; 369f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 370736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (mmc_card_mmc(card)) 371736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (!debugfs_create_file("ext_csd", S_IRUSR, root, card, 372736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter &mmc_dbg_ext_csd_fops)) 373736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter goto err; 374736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 375f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return; 376f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 377f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenerr: 378f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen debugfs_remove_recursive(root); 379f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen card->debugfs_root = NULL; 380f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen dev_err(&card->dev, "failed to initialize debugfs\n"); 381f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen} 382f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 383f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_remove_card_debugfs(struct mmc_card *card) 384f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{ 385f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen debugfs_remove_recursive(card->debugfs_root); 386f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen} 387