linux/drivers/mmc/core/debugfs.c
<<
>>
Prefs
   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
  29static DECLARE_FAULT_ATTR(fail_default_attr);
  30static char *fail_request;
  31module_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. */
  36static 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}
 199DEFINE_SHOW_ATTRIBUTE(mmc_ios);
 200
 201static 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
 210static 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
 225DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set,
 226        "%llu\n");
 227
 228void 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
 267err_node:
 268        debugfs_remove_recursive(root);
 269        host->debugfs_root = NULL;
 270err_root:
 271        dev_err(&host->class_dev, "failed to initialize debugfs\n");
 272}
 273
 274void mmc_remove_host_debugfs(struct mmc_host *host)
 275{
 276        debugfs_remove_recursive(host->debugfs_root);
 277}
 278
 279void 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
 303err:
 304        debugfs_remove_recursive(root);
 305        card->debugfs_root = NULL;
 306        dev_err(&card->dev, "failed to initialize debugfs\n");
 307}
 308
 309void mmc_remove_card_debugfs(struct mmc_card *card)
 310{
 311        debugfs_remove_recursive(card->debugfs_root);
 312        card->debugfs_root = NULL;
 313}
 314