1 /* 2 * Debugfs support for hosts and cards 3 * 4 * Copyright (C) 2008 Atmel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 #include <linux/moduleparam.h> 11 #include <linux/export.h> 12 #include <linux/debugfs.h> 13 #include <linux/fs.h> 14 #include <linux/seq_file.h> 15 #include <linux/slab.h> 16 #include <linux/stat.h> 17 #include <linux/fault-inject.h> 18 19 #include <linux/mmc/card.h> 20 #include <linux/mmc/host.h> 21 22 #include "core.h" 23 #include "card.h" 24 #include "host.h" 25 #include "mmc_ops.h" 26 27 #ifdef CONFIG_FAIL_MMC_REQUEST 28 29 static DECLARE_FAULT_ATTR(fail_default_attr); 30 static char *fail_request; 31 module_param(fail_request, charp, 0); 32 33 #endif /* CONFIG_FAIL_MMC_REQUEST */ 34 35 /* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */ 36 static int mmc_ios_show(struct seq_file *s, void *data) 37 { 38 static const char *vdd_str[] = { 39 [8] = "2.0", 40 [9] = "2.1", 41 [10] = "2.2", 42 [11] = "2.3", 43 [12] = "2.4", 44 [13] = "2.5", 45 [14] = "2.6", 46 [15] = "2.7", 47 [16] = "2.8", 48 [17] = "2.9", 49 [18] = "3.0", 50 [19] = "3.1", 51 [20] = "3.2", 52 [21] = "3.3", 53 [22] = "3.4", 54 [23] = "3.5", 55 [24] = "3.6", 56 }; 57 struct mmc_host *host = s->private; 58 struct mmc_ios *ios = &host->ios; 59 const char *str; 60 61 seq_printf(s, "clock:\t\t%u Hz\n", ios->clock); 62 if (host->actual_clock) 63 seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock); 64 seq_printf(s, "vdd:\t\t%u ", ios->vdd); 65 if ((1 << ios->vdd) & MMC_VDD_165_195) 66 seq_printf(s, "(1.65 - 1.95 V)\n"); 67 else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1) 68 && vdd_str[ios->vdd] && vdd_str[ios->vdd + 1]) 69 seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd], 70 vdd_str[ios->vdd + 1]); 71 else 72 seq_printf(s, "(invalid)\n"); 73 74 switch (ios->bus_mode) { 75 case MMC_BUSMODE_OPENDRAIN: 76 str = "open drain"; 77 break; 78 case MMC_BUSMODE_PUSHPULL: 79 str = "push-pull"; 80 break; 81 default: 82 str = "invalid"; 83 break; 84 } 85 seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str); 86 87 switch (ios->chip_select) { 88 case MMC_CS_DONTCARE: 89 str = "don't care"; 90 break; 91 case MMC_CS_HIGH: 92 str = "active high"; 93 break; 94 case MMC_CS_LOW: 95 str = "active low"; 96 break; 97 default: 98 str = "invalid"; 99 break; 100 } 101 seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str); 102 103 switch (ios->power_mode) { 104 case MMC_POWER_OFF: 105 str = "off"; 106 break; 107 case MMC_POWER_UP: 108 str = "up"; 109 break; 110 case MMC_POWER_ON: 111 str = "on"; 112 break; 113 default: 114 str = "invalid"; 115 break; 116 } 117 seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str); 118 seq_printf(s, "bus width:\t%u (%u bits)\n", 119 ios->bus_width, 1 << ios->bus_width); 120 121 switch (ios->timing) { 122 case MMC_TIMING_LEGACY: 123 str = "legacy"; 124 break; 125 case MMC_TIMING_MMC_HS: 126 str = "mmc high-speed"; 127 break; 128 case MMC_TIMING_SD_HS: 129 str = "sd high-speed"; 130 break; 131 case MMC_TIMING_UHS_SDR12: 132 str = "sd uhs SDR12"; 133 break; 134 case MMC_TIMING_UHS_SDR25: 135 str = "sd uhs SDR25"; 136 break; 137 case MMC_TIMING_UHS_SDR50: 138 str = "sd uhs SDR50"; 139 break; 140 case MMC_TIMING_UHS_SDR104: 141 str = "sd uhs SDR104"; 142 break; 143 case MMC_TIMING_UHS_DDR50: 144 str = "sd uhs DDR50"; 145 break; 146 case MMC_TIMING_MMC_DDR52: 147 str = "mmc DDR52"; 148 break; 149 case MMC_TIMING_MMC_HS200: 150 str = "mmc HS200"; 151 break; 152 case MMC_TIMING_MMC_HS400: 153 str = mmc_card_hs400es(host->card) ? 154 "mmc HS400 enhanced strobe" : "mmc HS400"; 155 break; 156 default: 157 str = "invalid"; 158 break; 159 } 160 seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str); 161 162 switch (ios->signal_voltage) { 163 case MMC_SIGNAL_VOLTAGE_330: 164 str = "3.30 V"; 165 break; 166 case MMC_SIGNAL_VOLTAGE_180: 167 str = "1.80 V"; 168 break; 169 case MMC_SIGNAL_VOLTAGE_120: 170 str = "1.20 V"; 171 break; 172 default: 173 str = "invalid"; 174 break; 175 } 176 seq_printf(s, "signal voltage:\t%u (%s)\n", ios->signal_voltage, str); 177 178 switch (ios->drv_type) { 179 case MMC_SET_DRIVER_TYPE_A: 180 str = "driver type A"; 181 break; 182 case MMC_SET_DRIVER_TYPE_B: 183 str = "driver type B"; 184 break; 185 case MMC_SET_DRIVER_TYPE_C: 186 str = "driver type C"; 187 break; 188 case MMC_SET_DRIVER_TYPE_D: 189 str = "driver type D"; 190 break; 191 default: 192 str = "invalid"; 193 break; 194 } 195 seq_printf(s, "driver type:\t%u (%s)\n", ios->drv_type, str); 196 197 return 0; 198 } 199 200 static int mmc_ios_open(struct inode *inode, struct file *file) 201 { 202 return single_open(file, mmc_ios_show, inode->i_private); 203 } 204 205 static const struct file_operations mmc_ios_fops = { 206 .open = mmc_ios_open, 207 .read = seq_read, 208 .llseek = seq_lseek, 209 .release = single_release, 210 }; 211 212 static int mmc_clock_opt_get(void *data, u64 *val) 213 { 214 struct mmc_host *host = data; 215 216 *val = host->ios.clock; 217 218 return 0; 219 } 220 221 static int mmc_clock_opt_set(void *data, u64 val) 222 { 223 struct mmc_host *host = data; 224 225 /* We need this check due to input value is u64 */ 226 if (val != 0 && (val > host->f_max || val < host->f_min)) 227 return -EINVAL; 228 229 mmc_claim_host(host); 230 mmc_set_clock(host, (unsigned int) val); 231 mmc_release_host(host); 232 233 return 0; 234 } 235 236 DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, 237 "%llu\n"); 238 239 void mmc_add_host_debugfs(struct mmc_host *host) 240 { 241 struct dentry *root; 242 243 root = debugfs_create_dir(mmc_hostname(host), NULL); 244 if (IS_ERR(root)) 245 /* Don't complain -- debugfs just isn't enabled */ 246 return; 247 if (!root) 248 /* Complain -- debugfs is enabled, but it failed to 249 * create the directory. */ 250 goto err_root; 251 252 host->debugfs_root = root; 253 254 if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) 255 goto err_node; 256 257 if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, 258 &mmc_clock_fops)) 259 goto err_node; 260 261 #ifdef CONFIG_FAIL_MMC_REQUEST 262 if (fail_request) 263 setup_fault_attr(&fail_default_attr, fail_request); 264 host->fail_mmc_request = fail_default_attr; 265 if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request", 266 root, 267 &host->fail_mmc_request))) 268 goto err_node; 269 #endif 270 return; 271 272 err_node: 273 debugfs_remove_recursive(root); 274 host->debugfs_root = NULL; 275 err_root: 276 dev_err(&host->class_dev, "failed to initialize debugfs\n"); 277 } 278 279 void mmc_remove_host_debugfs(struct mmc_host *host) 280 { 281 debugfs_remove_recursive(host->debugfs_root); 282 } 283 284 void mmc_add_card_debugfs(struct mmc_card *card) 285 { 286 struct mmc_host *host = card->host; 287 struct dentry *root; 288 289 if (!host->debugfs_root) 290 return; 291 292 root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); 293 if (IS_ERR(root)) 294 /* Don't complain -- debugfs just isn't enabled */ 295 return; 296 if (!root) 297 /* Complain -- debugfs is enabled, but it failed to 298 * create the directory. */ 299 goto err; 300 301 card->debugfs_root = root; 302 303 if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) 304 goto err; 305 306 return; 307 308 err: 309 debugfs_remove_recursive(root); 310 card->debugfs_root = NULL; 311 dev_err(&card->dev, "failed to initialize debugfs\n"); 312 } 313 314 void mmc_remove_card_debugfs(struct mmc_card *card) 315 { 316 debugfs_remove_recursive(card->debugfs_root); 317 card->debugfs_root = NULL; 318 } 319