aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-05 13:18:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-05 13:18:21 -0400
commit0a053e8c71d666daf30da2d407147b1293923d8b (patch)
tree9ba3967845db9053cb2ca045f01a9454eb5e6230 /drivers/mmc/core
parent601cc11d054ae4b5e9b5babec3d8e4667a2cb9b5 (diff)
parent32ab83a56fdf42f543b86c349143c2a86ead9707 (diff)
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: (42 commits) atmel-mci: fix sdc_reg typo tmio_mmc: add maintainer mmc: Add OpenFirmware bindings for SDHCI driver sdhci: Add quirk for forcing maximum block size to 2048 bytes sdhci: Add quirk for controllers that need IRQ re-init after reset sdhci: Add quirk for controllers that need small delays for PIO sdhci: Add set_clock callback and a quirk for nonstandard clocks sdhci: Add get_{max,timeout}_clock callbacks sdhci: Add support for hosts reporting inverted write-protect state sdhci: Add support for card-detection polling sdhci: Enable only relevant (DMA/PIO) interrupts during transfers sdhci: Split card-detection IRQs management from sdhci_init() sdhci: Add support for bus-specific IO memory accessors mmc_spi: adjust for delayed data token response omap_hsmmc: Wait for SDBP omap_hsmmc: Fix MMC3 dma omap_hsmmc: Disable SDBP at suspend omap_hsmmc: Do not prefix slot name omap_hsmmc: Allow cover switch to cause rescan omap_hsmmc: Add 8-bit bus width mode support ...
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/bus.c8
-rw-r--r--drivers/mmc/core/core.c18
-rw-r--r--drivers/mmc/core/debugfs.c67
-rw-r--r--drivers/mmc/core/sdio_cis.c8
-rw-r--r--drivers/mmc/core/sdio_ops.c8
5 files changed, 109 insertions, 0 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index f210a8ee686..bdb165f9304 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -84,6 +84,14 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
84 } 84 }
85 85
86 retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); 86 retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
87 if (retval)
88 return retval;
89
90 /*
91 * Request the mmc_block device. Note: that this is a direct request
92 * for the module it carries no information as to what is inserted.
93 */
94 retval = add_uevent_var(env, "MODALIAS=mmc:block");
87 95
88 return retval; 96 return retval;
89} 97}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1445ea8f10a..fa073ab3fa3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -298,6 +298,21 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
298 data->timeout_clks = 0; 298 data->timeout_clks = 0;
299 } 299 }
300 } 300 }
301 /*
302 * Some cards need very high timeouts if driven in SPI mode.
303 * The worst observed timeout was 900ms after writing a
304 * continuous stream of data until the internal logic
305 * overflowed.
306 */
307 if (mmc_host_is_spi(card->host)) {
308 if (data->flags & MMC_DATA_WRITE) {
309 if (data->timeout_ns < 1000000000)
310 data->timeout_ns = 1000000000; /* 1s */
311 } else {
312 if (data->timeout_ns < 100000000)
313 data->timeout_ns = 100000000; /* 100ms */
314 }
315 }
301} 316}
302EXPORT_SYMBOL(mmc_set_data_timeout); 317EXPORT_SYMBOL(mmc_set_data_timeout);
303 318
@@ -915,6 +930,7 @@ void mmc_stop_host(struct mmc_host *host)
915 spin_unlock_irqrestore(&host->lock, flags); 930 spin_unlock_irqrestore(&host->lock, flags);
916#endif 931#endif
917 932
933 cancel_delayed_work(&host->detect);
918 mmc_flush_scheduled_work(); 934 mmc_flush_scheduled_work();
919 935
920 mmc_bus_get(host); 936 mmc_bus_get(host);
@@ -942,6 +958,7 @@ void mmc_stop_host(struct mmc_host *host)
942 */ 958 */
943int mmc_suspend_host(struct mmc_host *host, pm_message_t state) 959int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
944{ 960{
961 cancel_delayed_work(&host->detect);
945 mmc_flush_scheduled_work(); 962 mmc_flush_scheduled_work();
946 963
947 mmc_bus_get(host); 964 mmc_bus_get(host);
@@ -975,6 +992,7 @@ int mmc_resume_host(struct mmc_host *host)
975 mmc_bus_get(host); 992 mmc_bus_get(host);
976 if (host->bus_ops && !host->bus_dead) { 993 if (host->bus_ops && !host->bus_dead) {
977 mmc_power_up(host); 994 mmc_power_up(host);
995 mmc_select_voltage(host, host->ocr);
978 BUG_ON(!host->bus_ops->resume); 996 BUG_ON(!host->bus_ops->resume);
979 host->bus_ops->resume(host); 997 host->bus_ops->resume(host);
980 } 998 }
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 1237bb4c722..610dbd1fcc8 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -184,6 +184,68 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
184DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, 184DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
185 NULL, "%08llx\n"); 185 NULL, "%08llx\n");
186 186
187#define EXT_CSD_STR_LEN 1025
188
189static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
190{
191 struct mmc_card *card = inode->i_private;
192 char *buf;
193 ssize_t n = 0;
194 u8 *ext_csd;
195 int err, i;
196
197 buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
198 if (!buf)
199 return -ENOMEM;
200
201 ext_csd = kmalloc(512, GFP_KERNEL);
202 if (!ext_csd) {
203 err = -ENOMEM;
204 goto out_free;
205 }
206
207 mmc_claim_host(card->host);
208 err = mmc_send_ext_csd(card, ext_csd);
209 mmc_release_host(card->host);
210 if (err)
211 goto out_free;
212
213 for (i = 511; i >= 0; i--)
214 n += sprintf(buf + n, "%02x", ext_csd[i]);
215 n += sprintf(buf + n, "\n");
216 BUG_ON(n != EXT_CSD_STR_LEN);
217
218 filp->private_data = buf;
219 kfree(ext_csd);
220 return 0;
221
222out_free:
223 kfree(buf);
224 kfree(ext_csd);
225 return err;
226}
227
228static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
229 size_t cnt, loff_t *ppos)
230{
231 char *buf = filp->private_data;
232
233 return simple_read_from_buffer(ubuf, cnt, ppos,
234 buf, EXT_CSD_STR_LEN);
235}
236
237static int mmc_ext_csd_release(struct inode *inode, struct file *file)
238{
239 kfree(file->private_data);
240 return 0;
241}
242
243static struct file_operations mmc_dbg_ext_csd_fops = {
244 .open = mmc_ext_csd_open,
245 .read = mmc_ext_csd_read,
246 .release = mmc_ext_csd_release,
247};
248
187void mmc_add_card_debugfs(struct mmc_card *card) 249void mmc_add_card_debugfs(struct mmc_card *card)
188{ 250{
189 struct mmc_host *host = card->host; 251 struct mmc_host *host = card->host;
@@ -211,6 +273,11 @@ void mmc_add_card_debugfs(struct mmc_card *card)
211 &mmc_dbg_card_status_fops)) 273 &mmc_dbg_card_status_fops))
212 goto err; 274 goto err;
213 275
276 if (mmc_card_mmc(card))
277 if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
278 &mmc_dbg_ext_csd_fops))
279 goto err;
280
214 return; 281 return;
215 282
216err: 283err:
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 956bd767750..963f2937c5e 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -223,10 +223,18 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
223 if (tpl_code == 0xff) 223 if (tpl_code == 0xff)
224 break; 224 break;
225 225
226 /* null entries have no link field or data */
227 if (tpl_code == 0x00)
228 continue;
229
226 ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link); 230 ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
227 if (ret) 231 if (ret)
228 break; 232 break;
229 233
234 /* a size of 0xff also means we're done */
235 if (tpl_link == 0xff)
236 break;
237
230 this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL); 238 this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
231 if (!this) 239 if (!this)
232 return -ENOMEM; 240 return -ENOMEM;
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index c8fa095a448..4eb7825fd1a 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -76,6 +76,10 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
76 BUG_ON(!card); 76 BUG_ON(!card);
77 BUG_ON(fn > 7); 77 BUG_ON(fn > 7);
78 78
79 /* sanity check */
80 if (addr & ~0x1FFFF)
81 return -EINVAL;
82
79 memset(&cmd, 0, sizeof(struct mmc_command)); 83 memset(&cmd, 0, sizeof(struct mmc_command));
80 84
81 cmd.opcode = SD_IO_RW_DIRECT; 85 cmd.opcode = SD_IO_RW_DIRECT;
@@ -125,6 +129,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
125 WARN_ON(blocks == 0); 129 WARN_ON(blocks == 0);
126 WARN_ON(blksz == 0); 130 WARN_ON(blksz == 0);
127 131
132 /* sanity check */
133 if (addr & ~0x1FFFF)
134 return -EINVAL;
135
128 memset(&mrq, 0, sizeof(struct mmc_request)); 136 memset(&mrq, 0, sizeof(struct mmc_request));
129 memset(&cmd, 0, sizeof(struct mmc_command)); 137 memset(&cmd, 0, sizeof(struct mmc_command));
130 memset(&data, 0, sizeof(struct mmc_data)); 138 memset(&data, 0, sizeof(struct mmc_data));