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 DEFINE_SHOW_ATTRIBUTE(mmc_ios); 200 201 static int mmc_clock_opt_get(void *data, u64 *val) 202 { 203 struct mmc_host *host = data; 204 205 *val = host->ios.clock; 206 207 return 0; 208 } 209 210 static int mmc_clock_opt_set(void *data, u64 val) 211 { 212 struct mmc_host *host = data; 213 214 /* We need this check due to input value is u64 */ 215 if (val != 0 && (val > host->f_max || val < host->f_min)) 216 return -EINVAL; 217 218 mmc_claim_host(host); 219 mmc_set_clock(host, (unsigned int) val); 220 mmc_release_host(host); 221 222 return 0; 223 } 224 225 DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, 226 "%llu\n"); 227 228 void mmc_add_host_debugfs(struct mmc_host *host) 229 { 230 struct dentry *root; 231 232 root = debugfs_create_dir(mmc_hostname(host), NULL); 233 if (IS_ERR(root)) 234 /* Don't complain -- debugfs just isn't enabled */ 235 return; 236 if (!root) 237 /* Complain -- debugfs is enabled, but it failed to 238 * create the directory. */ 239 goto err_root; 240 241 host->debugfs_root = root; 242 243 if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) 244 goto err_node; 245 246 if (!debugfs_create_x32("caps", S_IRUSR, root, &host->caps)) 247 goto err_node; 248 249 if (!debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2)) 250 goto err_node; 251 252 if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, 253 &mmc_clock_fops)) 254 goto err_node; 255 256 #ifdef CONFIG_FAIL_MMC_REQUEST 257 if (fail_request) 258 setup_fault_attr(&fail_default_attr, fail_request); 259 host->fail_mmc_request = fail_default_attr; 260 if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request", 261 root, 262 &host->fail_mmc_request))) 263 goto err_node; 264 #endif 265 return; 266 267 err_node: 268 debugfs_remove_recursive(root); 269 host->debugfs_root = NULL; 270 err_root: 271 dev_err(&host->class_dev, "failed to initialize debugfs\n"); 272 } 273 274 void mmc_remove_host_debugfs(struct mmc_host *host) 275 { 276 debugfs_remove_recursive(host->debugfs_root); 277 } 278 279 void mmc_add_card_debugfs(struct mmc_card *card) 280 { 281 struct mmc_host *host = card->host; 282 struct dentry *root; 283 284 if (!host->debugfs_root) 285 return; 286 287 root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); 288 if (IS_ERR(root)) 289 /* Don't complain -- debugfs just isn't enabled */ 290 return; 291 if (!root) 292 /* Complain -- debugfs is enabled, but it failed to 293 * create the directory. */ 294 goto err; 295 296 card->debugfs_root = root; 297 298 if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) 299 goto err; 300 301 return; 302 303 err: 304 debugfs_remove_recursive(root); 305 card->debugfs_root = NULL; 306 dev_err(&card->dev, "failed to initialize debugfs\n"); 307 } 308 309 void mmc_remove_card_debugfs(struct mmc_card *card) 310 { 311 debugfs_remove_recursive(card->debugfs_root); 312 card->debugfs_root = NULL; 313 } 314