Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
atmel-mci: debugfs support
mmc: Add per-card debugfs support
mmc: Export internal host state through debugfs
imxmmc: fix crash when no platform data is provided
imxmmc: fix platform resources
imxmmc: remove DEBUG definition
mmc_spi: put signals to low power off fix

+461 -36
+1
drivers/mmc/core/Makefile
··· 12 12 sdio.o sdio_ops.o sdio_bus.o \ 13 13 sdio_cis.o sdio_io.o sdio_irq.o 14 14 15 + mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
+8
drivers/mmc/core/bus.c
··· 252 252 if (ret) 253 253 return ret; 254 254 255 + #ifdef CONFIG_DEBUG_FS 256 + mmc_add_card_debugfs(card); 257 + #endif 258 + 255 259 mmc_card_set_present(card); 256 260 257 261 return 0; ··· 267 263 */ 268 264 void mmc_remove_card(struct mmc_card *card) 269 265 { 266 + #ifdef CONFIG_DEBUG_FS 267 + mmc_remove_card_debugfs(card); 268 + #endif 269 + 270 270 if (mmc_card_present(card)) { 271 271 if (mmc_host_is_spi(card->host)) { 272 272 printk(KERN_INFO "%s: SPI card removed\n",
+7
drivers/mmc/core/core.h
··· 52 52 53 53 extern int use_spi_crc; 54 54 55 + /* Debugfs information for hosts and cards */ 56 + void mmc_add_host_debugfs(struct mmc_host *host); 57 + void mmc_remove_host_debugfs(struct mmc_host *host); 58 + 59 + void mmc_add_card_debugfs(struct mmc_card *card); 60 + void mmc_remove_card_debugfs(struct mmc_card *card); 61 + 55 62 #endif 56 63
+225
drivers/mmc/core/debugfs.c
··· 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/debugfs.h> 11 + #include <linux/fs.h> 12 + #include <linux/seq_file.h> 13 + #include <linux/stat.h> 14 + 15 + #include <linux/mmc/card.h> 16 + #include <linux/mmc/host.h> 17 + 18 + #include "core.h" 19 + #include "mmc_ops.h" 20 + 21 + /* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */ 22 + static int mmc_ios_show(struct seq_file *s, void *data) 23 + { 24 + static const char *vdd_str[] = { 25 + [8] = "2.0", 26 + [9] = "2.1", 27 + [10] = "2.2", 28 + [11] = "2.3", 29 + [12] = "2.4", 30 + [13] = "2.5", 31 + [14] = "2.6", 32 + [15] = "2.7", 33 + [16] = "2.8", 34 + [17] = "2.9", 35 + [18] = "3.0", 36 + [19] = "3.1", 37 + [20] = "3.2", 38 + [21] = "3.3", 39 + [22] = "3.4", 40 + [23] = "3.5", 41 + [24] = "3.6", 42 + }; 43 + struct mmc_host *host = s->private; 44 + struct mmc_ios *ios = &host->ios; 45 + const char *str; 46 + 47 + seq_printf(s, "clock:\t\t%u Hz\n", ios->clock); 48 + seq_printf(s, "vdd:\t\t%u ", ios->vdd); 49 + if ((1 << ios->vdd) & MMC_VDD_165_195) 50 + seq_printf(s, "(1.65 - 1.95 V)\n"); 51 + else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1) 52 + && vdd_str[ios->vdd] && vdd_str[ios->vdd + 1]) 53 + seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd], 54 + vdd_str[ios->vdd + 1]); 55 + else 56 + seq_printf(s, "(invalid)\n"); 57 + 58 + switch (ios->bus_mode) { 59 + case MMC_BUSMODE_OPENDRAIN: 60 + str = "open drain"; 61 + break; 62 + case MMC_BUSMODE_PUSHPULL: 63 + str = "push-pull"; 64 + break; 65 + default: 66 + str = "invalid"; 67 + break; 68 + } 69 + seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str); 70 + 71 + switch (ios->chip_select) { 72 + case MMC_CS_DONTCARE: 73 + str = "don't care"; 74 + break; 75 + case MMC_CS_HIGH: 76 + str = "active high"; 77 + break; 78 + case MMC_CS_LOW: 79 + str = "active low"; 80 + break; 81 + default: 82 + str = "invalid"; 83 + break; 84 + } 85 + seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str); 86 + 87 + switch (ios->power_mode) { 88 + case MMC_POWER_OFF: 89 + str = "off"; 90 + break; 91 + case MMC_POWER_UP: 92 + str = "up"; 93 + break; 94 + case MMC_POWER_ON: 95 + str = "on"; 96 + break; 97 + default: 98 + str = "invalid"; 99 + break; 100 + } 101 + seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str); 102 + seq_printf(s, "bus width:\t%u (%u bits)\n", 103 + ios->bus_width, 1 << ios->bus_width); 104 + 105 + switch (ios->timing) { 106 + case MMC_TIMING_LEGACY: 107 + str = "legacy"; 108 + break; 109 + case MMC_TIMING_MMC_HS: 110 + str = "mmc high-speed"; 111 + break; 112 + case MMC_TIMING_SD_HS: 113 + str = "sd high-speed"; 114 + break; 115 + default: 116 + str = "invalid"; 117 + break; 118 + } 119 + seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str); 120 + 121 + return 0; 122 + } 123 + 124 + static int mmc_ios_open(struct inode *inode, struct file *file) 125 + { 126 + return single_open(file, mmc_ios_show, inode->i_private); 127 + } 128 + 129 + static const struct file_operations mmc_ios_fops = { 130 + .open = mmc_ios_open, 131 + .read = seq_read, 132 + .llseek = seq_lseek, 133 + .release = single_release, 134 + }; 135 + 136 + void mmc_add_host_debugfs(struct mmc_host *host) 137 + { 138 + struct dentry *root; 139 + 140 + root = debugfs_create_dir(mmc_hostname(host), NULL); 141 + if (IS_ERR(root)) 142 + /* Don't complain -- debugfs just isn't enabled */ 143 + return; 144 + if (!root) 145 + /* Complain -- debugfs is enabled, but it failed to 146 + * create the directory. */ 147 + goto err_root; 148 + 149 + host->debugfs_root = root; 150 + 151 + if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) 152 + goto err_ios; 153 + 154 + return; 155 + 156 + err_ios: 157 + debugfs_remove_recursive(root); 158 + host->debugfs_root = NULL; 159 + err_root: 160 + dev_err(&host->class_dev, "failed to initialize debugfs\n"); 161 + } 162 + 163 + void mmc_remove_host_debugfs(struct mmc_host *host) 164 + { 165 + debugfs_remove_recursive(host->debugfs_root); 166 + } 167 + 168 + static int mmc_dbg_card_status_get(void *data, u64 *val) 169 + { 170 + struct mmc_card *card = data; 171 + u32 status; 172 + int ret; 173 + 174 + mmc_claim_host(card->host); 175 + 176 + ret = mmc_send_status(data, &status); 177 + if (!ret) 178 + *val = status; 179 + 180 + mmc_release_host(card->host); 181 + 182 + return ret; 183 + } 184 + DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, 185 + NULL, "%08llx\n"); 186 + 187 + void mmc_add_card_debugfs(struct mmc_card *card) 188 + { 189 + struct mmc_host *host = card->host; 190 + struct dentry *root; 191 + 192 + if (!host->debugfs_root) 193 + return; 194 + 195 + root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); 196 + if (IS_ERR(root)) 197 + /* Don't complain -- debugfs just isn't enabled */ 198 + return; 199 + if (!root) 200 + /* Complain -- debugfs is enabled, but it failed to 201 + * create the directory. */ 202 + goto err; 203 + 204 + card->debugfs_root = root; 205 + 206 + if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) 207 + goto err; 208 + 209 + if (mmc_card_mmc(card) || mmc_card_sd(card)) 210 + if (!debugfs_create_file("status", S_IRUSR, root, card, 211 + &mmc_dbg_card_status_fops)) 212 + goto err; 213 + 214 + return; 215 + 216 + err: 217 + debugfs_remove_recursive(root); 218 + card->debugfs_root = NULL; 219 + dev_err(&card->dev, "failed to initialize debugfs\n"); 220 + } 221 + 222 + void mmc_remove_card_debugfs(struct mmc_card *card) 223 + { 224 + debugfs_remove_recursive(card->debugfs_root); 225 + }
+8
drivers/mmc/core/host.c
··· 127 127 if (err) 128 128 return err; 129 129 130 + #ifdef CONFIG_DEBUG_FS 131 + mmc_add_host_debugfs(host); 132 + #endif 133 + 130 134 mmc_start_host(host); 131 135 132 136 return 0; ··· 149 145 void mmc_remove_host(struct mmc_host *host) 150 146 { 151 147 mmc_stop_host(host); 148 + 149 + #ifdef CONFIG_DEBUG_FS 150 + mmc_remove_host_debugfs(host); 151 + #endif 152 152 153 153 device_del(&host->class_dev); 154 154
+2
drivers/mmc/host/atmel-mci-regs.h
··· 82 82 # define MCI_OVRE ( 1 << 30) /* RX Overrun Error */ 83 83 # define MCI_UNRE ( 1 << 31) /* TX Underrun Error */ 84 84 85 + #define MCI_REGS_SIZE 0x100 86 + 85 87 /* Register access macros */ 86 88 #define mci_readl(port,reg) \ 87 89 __raw_readl((port)->regs + MCI_##reg)
+189
drivers/mmc/host/atmel-mci.c
··· 9 9 */ 10 10 #include <linux/blkdev.h> 11 11 #include <linux/clk.h> 12 + #include <linux/debugfs.h> 12 13 #include <linux/device.h> 13 14 #include <linux/init.h> 14 15 #include <linux/interrupt.h> ··· 17 16 #include <linux/module.h> 18 17 #include <linux/platform_device.h> 19 18 #include <linux/scatterlist.h> 19 + #include <linux/seq_file.h> 20 + #include <linux/stat.h> 20 21 21 22 #include <linux/mmc/host.h> 22 23 ··· 91 88 #define atmci_clear_pending(host, event) \ 92 89 clear_bit(event, &host->pending_events) 93 90 91 + /* 92 + * The debugfs stuff below is mostly optimized away when 93 + * CONFIG_DEBUG_FS is not set. 94 + */ 95 + static int atmci_req_show(struct seq_file *s, void *v) 96 + { 97 + struct atmel_mci *host = s->private; 98 + struct mmc_request *mrq = host->mrq; 99 + struct mmc_command *cmd; 100 + struct mmc_command *stop; 101 + struct mmc_data *data; 102 + 103 + /* Make sure we get a consistent snapshot */ 104 + spin_lock_irq(&host->mmc->lock); 105 + 106 + if (mrq) { 107 + cmd = mrq->cmd; 108 + data = mrq->data; 109 + stop = mrq->stop; 110 + 111 + if (cmd) 112 + seq_printf(s, 113 + "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", 114 + cmd->opcode, cmd->arg, cmd->flags, 115 + cmd->resp[0], cmd->resp[1], cmd->resp[2], 116 + cmd->resp[2], cmd->error); 117 + if (data) 118 + seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", 119 + data->bytes_xfered, data->blocks, 120 + data->blksz, data->flags, data->error); 121 + if (stop) 122 + seq_printf(s, 123 + "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", 124 + stop->opcode, stop->arg, stop->flags, 125 + stop->resp[0], stop->resp[1], stop->resp[2], 126 + stop->resp[2], stop->error); 127 + } 128 + 129 + spin_unlock_irq(&host->mmc->lock); 130 + 131 + return 0; 132 + } 133 + 134 + static int atmci_req_open(struct inode *inode, struct file *file) 135 + { 136 + return single_open(file, atmci_req_show, inode->i_private); 137 + } 138 + 139 + static const struct file_operations atmci_req_fops = { 140 + .owner = THIS_MODULE, 141 + .open = atmci_req_open, 142 + .read = seq_read, 143 + .llseek = seq_lseek, 144 + .release = single_release, 145 + }; 146 + 147 + static void atmci_show_status_reg(struct seq_file *s, 148 + const char *regname, u32 value) 149 + { 150 + static const char *sr_bit[] = { 151 + [0] = "CMDRDY", 152 + [1] = "RXRDY", 153 + [2] = "TXRDY", 154 + [3] = "BLKE", 155 + [4] = "DTIP", 156 + [5] = "NOTBUSY", 157 + [8] = "SDIOIRQA", 158 + [9] = "SDIOIRQB", 159 + [16] = "RINDE", 160 + [17] = "RDIRE", 161 + [18] = "RCRCE", 162 + [19] = "RENDE", 163 + [20] = "RTOE", 164 + [21] = "DCRCE", 165 + [22] = "DTOE", 166 + [30] = "OVRE", 167 + [31] = "UNRE", 168 + }; 169 + unsigned int i; 170 + 171 + seq_printf(s, "%s:\t0x%08x", regname, value); 172 + for (i = 0; i < ARRAY_SIZE(sr_bit); i++) { 173 + if (value & (1 << i)) { 174 + if (sr_bit[i]) 175 + seq_printf(s, " %s", sr_bit[i]); 176 + else 177 + seq_puts(s, " UNKNOWN"); 178 + } 179 + } 180 + seq_putc(s, '\n'); 181 + } 182 + 183 + static int atmci_regs_show(struct seq_file *s, void *v) 184 + { 185 + struct atmel_mci *host = s->private; 186 + u32 *buf; 187 + 188 + buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL); 189 + if (!buf) 190 + return -ENOMEM; 191 + 192 + /* Grab a more or less consistent snapshot */ 193 + spin_lock_irq(&host->mmc->lock); 194 + memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); 195 + spin_unlock_irq(&host->mmc->lock); 196 + 197 + seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", 198 + buf[MCI_MR / 4], 199 + buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "", 200 + buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "", 201 + buf[MCI_MR / 4] & 0xff); 202 + seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]); 203 + seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]); 204 + seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]); 205 + seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n", 206 + buf[MCI_BLKR / 4], 207 + buf[MCI_BLKR / 4] & 0xffff, 208 + (buf[MCI_BLKR / 4] >> 16) & 0xffff); 209 + 210 + /* Don't read RSPR and RDR; it will consume the data there */ 211 + 212 + atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); 213 + atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); 214 + 215 + return 0; 216 + } 217 + 218 + static int atmci_regs_open(struct inode *inode, struct file *file) 219 + { 220 + return single_open(file, atmci_regs_show, inode->i_private); 221 + } 222 + 223 + static const struct file_operations atmci_regs_fops = { 224 + .owner = THIS_MODULE, 225 + .open = atmci_regs_open, 226 + .read = seq_read, 227 + .llseek = seq_lseek, 228 + .release = single_release, 229 + }; 230 + 231 + static void atmci_init_debugfs(struct atmel_mci *host) 232 + { 233 + struct mmc_host *mmc; 234 + struct dentry *root; 235 + struct dentry *node; 236 + struct resource *res; 237 + 238 + mmc = host->mmc; 239 + root = mmc->debugfs_root; 240 + if (!root) 241 + return; 242 + 243 + node = debugfs_create_file("regs", S_IRUSR, root, host, 244 + &atmci_regs_fops); 245 + if (IS_ERR(node)) 246 + return; 247 + if (!node) 248 + goto err; 249 + 250 + res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); 251 + node->d_inode->i_size = res->end - res->start + 1; 252 + 253 + node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops); 254 + if (!node) 255 + goto err; 256 + 257 + node = debugfs_create_x32("pending_events", S_IRUSR, root, 258 + (u32 *)&host->pending_events); 259 + if (!node) 260 + goto err; 261 + 262 + node = debugfs_create_x32("completed_events", S_IRUSR, root, 263 + (u32 *)&host->completed_events); 264 + if (!node) 265 + goto err; 266 + 267 + return; 268 + 269 + err: 270 + dev_err(&host->pdev->dev, 271 + "failed to initialize debugfs for controller\n"); 272 + } 94 273 95 274 static void atmci_enable(struct atmel_mci *host) 96 275 { ··· 1090 905 "Atmel MCI controller at 0x%08lx irq %d\n", 1091 906 host->mapbase, irq); 1092 907 908 + atmci_init_debugfs(host); 909 + 1093 910 return 0; 1094 911 1095 912 err_request_irq: ··· 1110 923 platform_set_drvdata(pdev, NULL); 1111 924 1112 925 if (host) { 926 + /* Debugfs stuff is cleaned up by mmc core */ 927 + 1113 928 if (host->detect_pin >= 0) { 1114 929 int pin = host->detect_pin; 1115 930
+15 -35
drivers/mmc/host/imxmmc.c
··· 26 26 * 27 27 */ 28 28 29 - #ifdef CONFIG_MMC_DEBUG 30 - #define DEBUG 31 - #else 32 - #undef DEBUG 33 - #endif 34 - 35 29 #include <linux/module.h> 36 30 #include <linux/init.h> 37 31 #include <linux/ioport.h> ··· 901 907 .get_ro = imxmci_get_ro, 902 908 }; 903 909 904 - static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr) 905 - { 906 - int i; 907 - 908 - for (i = 0; i < dev->num_resources; i++) 909 - if (dev->resource[i].flags == mask && nr-- == 0) 910 - return &dev->resource[i]; 911 - return NULL; 912 - } 913 - 914 - static int platform_device_irq(struct platform_device *dev, int nr) 915 - { 916 - int i; 917 - 918 - for (i = 0; i < dev->num_resources; i++) 919 - if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0) 920 - return dev->resource[i].start; 921 - return NO_IRQ; 922 - } 923 - 924 910 static void imxmci_check_status(unsigned long data) 925 911 { 926 912 struct imxmci_host *host = (struct imxmci_host *)data; 927 913 928 - if( host->pdata->card_present(mmc_dev(host->mmc)) != host->present ) { 914 + if (host->pdata && host->pdata->card_present && 915 + host->pdata->card_present(mmc_dev(host->mmc)) != host->present) { 929 916 host->present ^= 1; 930 917 dev_info(mmc_dev(host->mmc), "card %s\n", 931 918 host->present ? "inserted" : "removed"); ··· 937 962 938 963 printk(KERN_INFO "i.MX mmc driver\n"); 939 964 940 - r = platform_device_resource(pdev, IORESOURCE_MEM, 0); 941 - irq = platform_device_irq(pdev, 0); 942 - if (!r || irq == NO_IRQ) 965 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 966 + irq = platform_get_irq(pdev, 0); 967 + if (!r || irq < 0) 943 968 return -ENXIO; 944 969 945 - r = request_mem_region(r->start, 0x100, "IMXMCI"); 946 - if (!r) 970 + if (!request_mem_region(r->start, 0x100, pdev->name)) 947 971 return -EBUSY; 948 972 949 973 mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev); ··· 969 995 host->mmc = mmc; 970 996 host->dma_allocated = 0; 971 997 host->pdata = pdev->dev.platform_data; 998 + if (!host->pdata) 999 + dev_warn(&pdev->dev, "No platform data provided!\n"); 972 1000 973 1001 spin_lock_init(&host->lock); 974 1002 host->res = r; ··· 1023 1047 if (ret) 1024 1048 goto out; 1025 1049 1026 - host->present = host->pdata->card_present(mmc_dev(mmc)); 1050 + if (host->pdata && host->pdata->card_present) 1051 + host->present = host->pdata->card_present(mmc_dev(mmc)); 1052 + else /* if there is no way to detect assume that card is present */ 1053 + host->present = 1; 1054 + 1027 1055 init_timer(&host->timer); 1028 1056 host->timer.data = (unsigned long)host; 1029 1057 host->timer.function = imxmci_check_status; ··· 1053 1073 } 1054 1074 if (mmc) 1055 1075 mmc_free_host(mmc); 1056 - release_resource(r); 1076 + release_mem_region(r->start, 0x100); 1057 1077 return ret; 1058 1078 } 1059 1079 ··· 1082 1102 clk_disable(host->clk); 1083 1103 clk_put(host->clk); 1084 1104 1085 - release_resource(host->res); 1105 + release_mem_region(host->res->start, 0x100); 1086 1106 1087 1107 mmc_free_host(mmc); 1088 1108 }
+2 -1
drivers/mmc/host/mmc_spi.c
··· 1076 1076 */ 1077 1077 if (canpower && ios->power_mode == MMC_POWER_OFF) { 1078 1078 int mres; 1079 + u8 nullbyte = 0; 1079 1080 1080 1081 host->spi->mode &= ~(SPI_CPOL|SPI_CPHA); 1081 1082 mres = spi_setup(host->spi); ··· 1084 1083 dev_dbg(&host->spi->dev, 1085 1084 "switch to SPI mode 0 failed\n"); 1086 1085 1087 - if (spi_w8r8(host->spi, 0x00) < 0) 1086 + if (spi_write(host->spi, &nullbyte, 1) < 0) 1088 1087 dev_dbg(&host->spi->dev, 1089 1088 "put spi signals to low failed\n"); 1090 1089
+2
include/linux/mmc/card.h
··· 111 111 unsigned num_info; /* number of info strings */ 112 112 const char **info; /* info strings */ 113 113 struct sdio_func_tuple *tuples; /* unknown common tuples */ 114 + 115 + struct dentry *debugfs_root; 114 116 }; 115 117 116 118 #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC)
+2
include/linux/mmc/host.h
··· 157 157 struct led_trigger *led; /* activity led */ 158 158 #endif 159 159 160 + struct dentry *debugfs_root; 161 + 160 162 unsigned long private[0] ____cacheline_aligned; 161 163 }; 162 164