aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-07-27 07:54:08 -0400
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-07-27 07:54:08 -0400
commiteda3d8f5604860aae1bb9996bb5efc4213778369 (patch)
tree9d3887d2665bcc5f5abf200758794545c7b2c69b /drivers/mmc
parent87a9f704658a40940e740b1d73d861667e9164d3 (diff)
parent8be1a6d6c77ab4532e4476fdb8177030ef48b52c (diff)
Merge commit 'upstream/master'
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/mmc_test.c225
-rw-r--r--drivers/mmc/card/queue.c97
-rw-r--r--drivers/mmc/core/Makefile1
-rw-r--r--drivers/mmc/core/bus.c8
-rw-r--r--drivers/mmc/core/core.h7
-rw-r--r--drivers/mmc/core/debugfs.c225
-rw-r--r--drivers/mmc/core/host.c8
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h2
-rw-r--r--drivers/mmc/host/atmel-mci.c189
-rw-r--r--drivers/mmc/host/au1xmmc.c54
-rw-r--r--drivers/mmc/host/imxmmc.c50
-rw-r--r--drivers/mmc/host/mmc_spi.c3
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c50
-rw-r--r--drivers/mmc/host/sdhci.c171
-rw-r--r--drivers/mmc/host/sdhci.h9
16 files changed, 865 insertions, 236 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index d6b9b486417c..a067fe436301 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -21,13 +21,17 @@
21#define RESULT_UNSUP_HOST 2 21#define RESULT_UNSUP_HOST 2
22#define RESULT_UNSUP_CARD 3 22#define RESULT_UNSUP_CARD 3
23 23
24#define BUFFER_SIZE (PAGE_SIZE * 4) 24#define BUFFER_ORDER 2
25#define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER)
25 26
26struct mmc_test_card { 27struct mmc_test_card {
27 struct mmc_card *card; 28 struct mmc_card *card;
28 29
29 u8 scratch[BUFFER_SIZE]; 30 u8 scratch[BUFFER_SIZE];
30 u8 *buffer; 31 u8 *buffer;
32#ifdef CONFIG_HIGHMEM
33 struct page *highmem;
34#endif
31}; 35};
32 36
33/*******************************************************************/ 37/*******************************************************************/
@@ -384,14 +388,16 @@ static int mmc_test_transfer(struct mmc_test_card *test,
384 int ret, i; 388 int ret, i;
385 unsigned long flags; 389 unsigned long flags;
386 390
391 BUG_ON(blocks * blksz > BUFFER_SIZE);
392
387 if (write) { 393 if (write) {
388 for (i = 0;i < blocks * blksz;i++) 394 for (i = 0;i < blocks * blksz;i++)
389 test->scratch[i] = i; 395 test->scratch[i] = i;
390 } else { 396 } else {
391 memset(test->scratch, 0, BUFFER_SIZE); 397 memset(test->scratch, 0, blocks * blksz);
392 } 398 }
393 local_irq_save(flags); 399 local_irq_save(flags);
394 sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); 400 sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz);
395 local_irq_restore(flags); 401 local_irq_restore(flags);
396 402
397 ret = mmc_test_set_blksize(test, blksz); 403 ret = mmc_test_set_blksize(test, blksz);
@@ -438,7 +444,7 @@ static int mmc_test_transfer(struct mmc_test_card *test,
438 } 444 }
439 } else { 445 } else {
440 local_irq_save(flags); 446 local_irq_save(flags);
441 sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); 447 sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz);
442 local_irq_restore(flags); 448 local_irq_restore(flags);
443 for (i = 0;i < blocks * blksz;i++) { 449 for (i = 0;i < blocks * blksz;i++) {
444 if (test->scratch[i] != (u8)i) 450 if (test->scratch[i] != (u8)i)
@@ -799,6 +805,157 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
799 return 0; 805 return 0;
800} 806}
801 807
808static int mmc_test_bigsg_write(struct mmc_test_card *test)
809{
810 int ret;
811 unsigned int size;
812 struct scatterlist sg;
813
814 if (test->card->host->max_blk_count == 1)
815 return RESULT_UNSUP_HOST;
816
817 size = PAGE_SIZE * 2;
818 size = min(size, test->card->host->max_req_size);
819 size = min(size, test->card->host->max_seg_size);
820 size = min(size, test->card->host->max_blk_count * 512);
821
822 memset(test->buffer, 0, BUFFER_SIZE);
823
824 if (size < 1024)
825 return RESULT_UNSUP_HOST;
826
827 sg_init_table(&sg, 1);
828 sg_init_one(&sg, test->buffer, BUFFER_SIZE);
829
830 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
831 if (ret)
832 return ret;
833
834 return 0;
835}
836
837static int mmc_test_bigsg_read(struct mmc_test_card *test)
838{
839 int ret, i;
840 unsigned int size;
841 struct scatterlist sg;
842
843 if (test->card->host->max_blk_count == 1)
844 return RESULT_UNSUP_HOST;
845
846 size = PAGE_SIZE * 2;
847 size = min(size, test->card->host->max_req_size);
848 size = min(size, test->card->host->max_seg_size);
849 size = min(size, test->card->host->max_blk_count * 512);
850
851 if (size < 1024)
852 return RESULT_UNSUP_HOST;
853
854 memset(test->buffer, 0xCD, BUFFER_SIZE);
855
856 sg_init_table(&sg, 1);
857 sg_init_one(&sg, test->buffer, BUFFER_SIZE);
858 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
859 if (ret)
860 return ret;
861
862 /* mmc_test_transfer() doesn't check for read overflows */
863 for (i = size;i < BUFFER_SIZE;i++) {
864 if (test->buffer[i] != 0xCD)
865 return RESULT_FAIL;
866 }
867
868 return 0;
869}
870
871#ifdef CONFIG_HIGHMEM
872
873static int mmc_test_write_high(struct mmc_test_card *test)
874{
875 int ret;
876 struct scatterlist sg;
877
878 sg_init_table(&sg, 1);
879 sg_set_page(&sg, test->highmem, 512, 0);
880
881 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
882 if (ret)
883 return ret;
884
885 return 0;
886}
887
888static int mmc_test_read_high(struct mmc_test_card *test)
889{
890 int ret;
891 struct scatterlist sg;
892
893 sg_init_table(&sg, 1);
894 sg_set_page(&sg, test->highmem, 512, 0);
895
896 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
897 if (ret)
898 return ret;
899
900 return 0;
901}
902
903static int mmc_test_multi_write_high(struct mmc_test_card *test)
904{
905 int ret;
906 unsigned int size;
907 struct scatterlist sg;
908
909 if (test->card->host->max_blk_count == 1)
910 return RESULT_UNSUP_HOST;
911
912 size = PAGE_SIZE * 2;
913 size = min(size, test->card->host->max_req_size);
914 size = min(size, test->card->host->max_seg_size);
915 size = min(size, test->card->host->max_blk_count * 512);
916
917 if (size < 1024)
918 return RESULT_UNSUP_HOST;
919
920 sg_init_table(&sg, 1);
921 sg_set_page(&sg, test->highmem, size, 0);
922
923 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
924 if (ret)
925 return ret;
926
927 return 0;
928}
929
930static int mmc_test_multi_read_high(struct mmc_test_card *test)
931{
932 int ret;
933 unsigned int size;
934 struct scatterlist sg;
935
936 if (test->card->host->max_blk_count == 1)
937 return RESULT_UNSUP_HOST;
938
939 size = PAGE_SIZE * 2;
940 size = min(size, test->card->host->max_req_size);
941 size = min(size, test->card->host->max_seg_size);
942 size = min(size, test->card->host->max_blk_count * 512);
943
944 if (size < 1024)
945 return RESULT_UNSUP_HOST;
946
947 sg_init_table(&sg, 1);
948 sg_set_page(&sg, test->highmem, size, 0);
949
950 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
951 if (ret)
952 return ret;
953
954 return 0;
955}
956
957#endif /* CONFIG_HIGHMEM */
958
802static const struct mmc_test_case mmc_test_cases[] = { 959static const struct mmc_test_case mmc_test_cases[] = {
803 { 960 {
804 .name = "Basic write (no data verification)", 961 .name = "Basic write (no data verification)",
@@ -913,6 +1070,53 @@ static const struct mmc_test_case mmc_test_cases[] = {
913 .name = "Correct xfer_size at read (midway failure)", 1070 .name = "Correct xfer_size at read (midway failure)",
914 .run = mmc_test_multi_xfersize_read, 1071 .run = mmc_test_multi_xfersize_read,
915 }, 1072 },
1073
1074 {
1075 .name = "Over-sized SG list write",
1076 .prepare = mmc_test_prepare_write,
1077 .run = mmc_test_bigsg_write,
1078 .cleanup = mmc_test_cleanup,
1079 },
1080
1081 {
1082 .name = "Over-sized SG list read",
1083 .prepare = mmc_test_prepare_read,
1084 .run = mmc_test_bigsg_read,
1085 .cleanup = mmc_test_cleanup,
1086 },
1087
1088#ifdef CONFIG_HIGHMEM
1089
1090 {
1091 .name = "Highmem write",
1092 .prepare = mmc_test_prepare_write,
1093 .run = mmc_test_write_high,
1094 .cleanup = mmc_test_cleanup,
1095 },
1096
1097 {
1098 .name = "Highmem read",
1099 .prepare = mmc_test_prepare_read,
1100 .run = mmc_test_read_high,
1101 .cleanup = mmc_test_cleanup,
1102 },
1103
1104 {
1105 .name = "Multi-block highmem write",
1106 .prepare = mmc_test_prepare_write,
1107 .run = mmc_test_multi_write_high,
1108 .cleanup = mmc_test_cleanup,
1109 },
1110
1111 {
1112 .name = "Multi-block highmem read",
1113 .prepare = mmc_test_prepare_read,
1114 .run = mmc_test_multi_read_high,
1115 .cleanup = mmc_test_cleanup,
1116 },
1117
1118#endif /* CONFIG_HIGHMEM */
1119
916}; 1120};
917 1121
918static struct mutex mmc_test_lock; 1122static struct mutex mmc_test_lock;
@@ -1014,12 +1218,23 @@ static ssize_t mmc_test_store(struct device *dev,
1014 test->card = card; 1218 test->card = card;
1015 1219
1016 test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); 1220 test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
1221#ifdef CONFIG_HIGHMEM
1222 test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
1223#endif
1224
1225#ifdef CONFIG_HIGHMEM
1226 if (test->buffer && test->highmem) {
1227#else
1017 if (test->buffer) { 1228 if (test->buffer) {
1229#endif
1018 mutex_lock(&mmc_test_lock); 1230 mutex_lock(&mmc_test_lock);
1019 mmc_test_run(test, testcase); 1231 mmc_test_run(test, testcase);
1020 mutex_unlock(&mmc_test_lock); 1232 mutex_unlock(&mmc_test_lock);
1021 } 1233 }
1022 1234
1235#ifdef CONFIG_HIGHMEM
1236 __free_pages(test->highmem, BUFFER_ORDER);
1237#endif
1023 kfree(test->buffer); 1238 kfree(test->buffer);
1024 kfree(test); 1239 kfree(test);
1025 1240
@@ -1041,6 +1256,8 @@ static int mmc_test_probe(struct mmc_card *card)
1041 if (ret) 1256 if (ret)
1042 return ret; 1257 return ret;
1043 1258
1259 dev_info(&card->dev, "Card claimed for testing.\n");
1260
1044 return 0; 1261 return 0;
1045} 1262}
1046 1263
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 7731ddefdc1b..3dee97e7d165 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -148,7 +148,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
148 printk(KERN_WARNING "%s: unable to allocate " 148 printk(KERN_WARNING "%s: unable to allocate "
149 "bounce buffer\n", mmc_card_name(card)); 149 "bounce buffer\n", mmc_card_name(card));
150 } else { 150 } else {
151 blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH); 151 blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
152 blk_queue_max_sectors(mq->queue, bouncesz / 512); 152 blk_queue_max_sectors(mq->queue, bouncesz / 512);
153 blk_queue_max_phys_segments(mq->queue, bouncesz / 512); 153 blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
154 blk_queue_max_hw_segments(mq->queue, bouncesz / 512); 154 blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
@@ -290,55 +290,15 @@ void mmc_queue_resume(struct mmc_queue *mq)
290 } 290 }
291} 291}
292 292
293static void copy_sg(struct scatterlist *dst, unsigned int dst_len, 293/*
294 struct scatterlist *src, unsigned int src_len) 294 * Prepare the sg list(s) to be handed of to the host driver
295{ 295 */
296 unsigned int chunk;
297 char *dst_buf, *src_buf;
298 unsigned int dst_size, src_size;
299
300 dst_buf = NULL;
301 src_buf = NULL;
302 dst_size = 0;
303 src_size = 0;
304
305 while (src_len) {
306 BUG_ON(dst_len == 0);
307
308 if (dst_size == 0) {
309 dst_buf = sg_virt(dst);
310 dst_size = dst->length;
311 }
312
313 if (src_size == 0) {
314 src_buf = sg_virt(src);
315 src_size = src->length;
316 }
317
318 chunk = min(dst_size, src_size);
319
320 memcpy(dst_buf, src_buf, chunk);
321
322 dst_buf += chunk;
323 src_buf += chunk;
324 dst_size -= chunk;
325 src_size -= chunk;
326
327 if (dst_size == 0) {
328 dst++;
329 dst_len--;
330 }
331
332 if (src_size == 0) {
333 src++;
334 src_len--;
335 }
336 }
337}
338
339unsigned int mmc_queue_map_sg(struct mmc_queue *mq) 296unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
340{ 297{
341 unsigned int sg_len; 298 unsigned int sg_len;
299 size_t buflen;
300 struct scatterlist *sg;
301 int i;
342 302
343 if (!mq->bounce_buf) 303 if (!mq->bounce_buf)
344 return blk_rq_map_sg(mq->queue, mq->req, mq->sg); 304 return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
@@ -349,47 +309,52 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
349 309
350 mq->bounce_sg_len = sg_len; 310 mq->bounce_sg_len = sg_len;
351 311
352 /* 312 buflen = 0;
353 * Shortcut in the event we only get a single entry. 313 for_each_sg(mq->bounce_sg, sg, sg_len, i)
354 */ 314 buflen += sg->length;
355 if (sg_len == 1) {
356 memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
357 return 1;
358 }
359 315
360 sg_init_one(mq->sg, mq->bounce_buf, 0); 316 sg_init_one(mq->sg, mq->bounce_buf, buflen);
361
362 while (sg_len) {
363 mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
364 sg_len--;
365 }
366 317
367 return 1; 318 return 1;
368} 319}
369 320
321/*
322 * If writing, bounce the data to the buffer before the request
323 * is sent to the host driver
324 */
370void mmc_queue_bounce_pre(struct mmc_queue *mq) 325void mmc_queue_bounce_pre(struct mmc_queue *mq)
371{ 326{
327 unsigned long flags;
328
372 if (!mq->bounce_buf) 329 if (!mq->bounce_buf)
373 return; 330 return;
374 331
375 if (mq->bounce_sg_len == 1)
376 return;
377 if (rq_data_dir(mq->req) != WRITE) 332 if (rq_data_dir(mq->req) != WRITE)
378 return; 333 return;
379 334
380 copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len); 335 local_irq_save(flags);
336 sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
337 mq->bounce_buf, mq->sg[0].length);
338 local_irq_restore(flags);
381} 339}
382 340
341/*
342 * If reading, bounce the data from the buffer after the request
343 * has been handled by the host driver
344 */
383void mmc_queue_bounce_post(struct mmc_queue *mq) 345void mmc_queue_bounce_post(struct mmc_queue *mq)
384{ 346{
347 unsigned long flags;
348
385 if (!mq->bounce_buf) 349 if (!mq->bounce_buf)
386 return; 350 return;
387 351
388 if (mq->bounce_sg_len == 1)
389 return;
390 if (rq_data_dir(mq->req) != READ) 352 if (rq_data_dir(mq->req) != READ)
391 return; 353 return;
392 354
393 copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1); 355 local_irq_save(flags);
356 sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
357 mq->bounce_buf, mq->sg[0].length);
358 local_irq_restore(flags);
394} 359}
395 360
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 19a1a254a0c5..889e5f898f6f 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -12,3 +12,4 @@ mmc_core-y := core.o bus.o host.o \
12 sdio.o sdio_ops.o sdio_bus.o \ 12 sdio.o sdio_ops.o sdio_bus.o \
13 sdio_cis.o sdio_io.o sdio_irq.o 13 sdio_cis.o sdio_io.o sdio_irq.o
14 14
15mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index fd95b18e988b..0d9b2d6f9ebf 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -252,6 +252,10 @@ int mmc_add_card(struct mmc_card *card)
252 if (ret) 252 if (ret)
253 return ret; 253 return ret;
254 254
255#ifdef CONFIG_DEBUG_FS
256 mmc_add_card_debugfs(card);
257#endif
258
255 mmc_card_set_present(card); 259 mmc_card_set_present(card);
256 260
257 return 0; 261 return 0;
@@ -263,6 +267,10 @@ int mmc_add_card(struct mmc_card *card)
263 */ 267 */
264void mmc_remove_card(struct mmc_card *card) 268void mmc_remove_card(struct mmc_card *card)
265{ 269{
270#ifdef CONFIG_DEBUG_FS
271 mmc_remove_card_debugfs(card);
272#endif
273
266 if (mmc_card_present(card)) { 274 if (mmc_card_present(card)) {
267 if (mmc_host_is_spi(card->host)) { 275 if (mmc_host_is_spi(card->host)) {
268 printk(KERN_INFO "%s: SPI card removed\n", 276 printk(KERN_INFO "%s: SPI card removed\n",
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index cdb332b7dedc..c819effa1032 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -52,5 +52,12 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
52 52
53extern int use_spi_crc; 53extern int use_spi_crc;
54 54
55/* Debugfs information for hosts and cards */
56void mmc_add_host_debugfs(struct mmc_host *host);
57void mmc_remove_host_debugfs(struct mmc_host *host);
58
59void mmc_add_card_debugfs(struct mmc_card *card);
60void mmc_remove_card_debugfs(struct mmc_card *card);
61
55#endif 62#endif
56 63
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
new file mode 100644
index 000000000000..1237bb4c722b
--- /dev/null
+++ b/drivers/mmc/core/debugfs.c
@@ -0,0 +1,225 @@
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. */
22static 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
124static int mmc_ios_open(struct inode *inode, struct file *file)
125{
126 return single_open(file, mmc_ios_show, inode->i_private);
127}
128
129static 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
136void 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
156err_ios:
157 debugfs_remove_recursive(root);
158 host->debugfs_root = NULL;
159err_root:
160 dev_err(&host->class_dev, "failed to initialize debugfs\n");
161}
162
163void mmc_remove_host_debugfs(struct mmc_host *host)
164{
165 debugfs_remove_recursive(host->debugfs_root);
166}
167
168static 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}
184DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
185 NULL, "%08llx\n");
186
187void 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
216err:
217 debugfs_remove_recursive(root);
218 card->debugfs_root = NULL;
219 dev_err(&card->dev, "failed to initialize debugfs\n");
220}
221
222void mmc_remove_card_debugfs(struct mmc_card *card)
223{
224 debugfs_remove_recursive(card->debugfs_root);
225}
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 1d795c5379b5..6da80fd4d974 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -127,6 +127,10 @@ int mmc_add_host(struct mmc_host *host)
127 if (err) 127 if (err)
128 return err; 128 return err;
129 129
130#ifdef CONFIG_DEBUG_FS
131 mmc_add_host_debugfs(host);
132#endif
133
130 mmc_start_host(host); 134 mmc_start_host(host);
131 135
132 return 0; 136 return 0;
@@ -146,6 +150,10 @@ void mmc_remove_host(struct mmc_host *host)
146{ 150{
147 mmc_stop_host(host); 151 mmc_stop_host(host);
148 152
153#ifdef CONFIG_DEBUG_FS
154 mmc_remove_host_debugfs(host);
155#endif
156
149 device_del(&host->class_dev); 157 device_del(&host->class_dev);
150 158
151 led_trigger_unregister_simple(host->led); 159 led_trigger_unregister_simple(host->led);
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
index a9a5657706c6..26bd80e65031 100644
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -82,6 +82,8 @@
82# define MCI_OVRE ( 1 << 30) /* RX Overrun Error */ 82# define MCI_OVRE ( 1 << 30) /* RX Overrun Error */
83# define MCI_UNRE ( 1 << 31) /* TX Underrun Error */ 83# define MCI_UNRE ( 1 << 31) /* TX Underrun Error */
84 84
85#define MCI_REGS_SIZE 0x100
86
85/* Register access macros */ 87/* Register access macros */
86#define mci_readl(port,reg) \ 88#define mci_readl(port,reg) \
87 __raw_readl((port)->regs + MCI_##reg) 89 __raw_readl((port)->regs + MCI_##reg)
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index c2f8aa840e82..82bbbe998169 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -9,6 +9,7 @@
9 */ 9 */
10#include <linux/blkdev.h> 10#include <linux/blkdev.h>
11#include <linux/clk.h> 11#include <linux/clk.h>
12#include <linux/debugfs.h>
12#include <linux/device.h> 13#include <linux/device.h>
13#include <linux/err.h> 14#include <linux/err.h>
14#include <linux/init.h> 15#include <linux/init.h>
@@ -17,6 +18,8 @@
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/platform_device.h> 19#include <linux/platform_device.h>
19#include <linux/scatterlist.h> 20#include <linux/scatterlist.h>
21#include <linux/seq_file.h>
22#include <linux/stat.h>
20 23
21#include <linux/mmc/host.h> 24#include <linux/mmc/host.h>
22 25
@@ -89,6 +92,188 @@ struct atmel_mci {
89#define atmci_clear_pending(host, event) \ 92#define atmci_clear_pending(host, event) \
90 clear_bit(event, &host->pending_events) 93 clear_bit(event, &host->pending_events)
91 94
95/*
96 * The debugfs stuff below is mostly optimized away when
97 * CONFIG_DEBUG_FS is not set.
98 */
99static int atmci_req_show(struct seq_file *s, void *v)
100{
101 struct atmel_mci *host = s->private;
102 struct mmc_request *mrq = host->mrq;
103 struct mmc_command *cmd;
104 struct mmc_command *stop;
105 struct mmc_data *data;
106
107 /* Make sure we get a consistent snapshot */
108 spin_lock_irq(&host->mmc->lock);
109
110 if (mrq) {
111 cmd = mrq->cmd;
112 data = mrq->data;
113 stop = mrq->stop;
114
115 if (cmd)
116 seq_printf(s,
117 "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
118 cmd->opcode, cmd->arg, cmd->flags,
119 cmd->resp[0], cmd->resp[1], cmd->resp[2],
120 cmd->resp[2], cmd->error);
121 if (data)
122 seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
123 data->bytes_xfered, data->blocks,
124 data->blksz, data->flags, data->error);
125 if (stop)
126 seq_printf(s,
127 "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
128 stop->opcode, stop->arg, stop->flags,
129 stop->resp[0], stop->resp[1], stop->resp[2],
130 stop->resp[2], stop->error);
131 }
132
133 spin_unlock_irq(&host->mmc->lock);
134
135 return 0;
136}
137
138static int atmci_req_open(struct inode *inode, struct file *file)
139{
140 return single_open(file, atmci_req_show, inode->i_private);
141}
142
143static const struct file_operations atmci_req_fops = {
144 .owner = THIS_MODULE,
145 .open = atmci_req_open,
146 .read = seq_read,
147 .llseek = seq_lseek,
148 .release = single_release,
149};
150
151static void atmci_show_status_reg(struct seq_file *s,
152 const char *regname, u32 value)
153{
154 static const char *sr_bit[] = {
155 [0] = "CMDRDY",
156 [1] = "RXRDY",
157 [2] = "TXRDY",
158 [3] = "BLKE",
159 [4] = "DTIP",
160 [5] = "NOTBUSY",
161 [8] = "SDIOIRQA",
162 [9] = "SDIOIRQB",
163 [16] = "RINDE",
164 [17] = "RDIRE",
165 [18] = "RCRCE",
166 [19] = "RENDE",
167 [20] = "RTOE",
168 [21] = "DCRCE",
169 [22] = "DTOE",
170 [30] = "OVRE",
171 [31] = "UNRE",
172 };
173 unsigned int i;
174
175 seq_printf(s, "%s:\t0x%08x", regname, value);
176 for (i = 0; i < ARRAY_SIZE(sr_bit); i++) {
177 if (value & (1 << i)) {
178 if (sr_bit[i])
179 seq_printf(s, " %s", sr_bit[i]);
180 else
181 seq_puts(s, " UNKNOWN");
182 }
183 }
184 seq_putc(s, '\n');
185}
186
187static int atmci_regs_show(struct seq_file *s, void *v)
188{
189 struct atmel_mci *host = s->private;
190 u32 *buf;
191
192 buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL);
193 if (!buf)
194 return -ENOMEM;
195
196 /* Grab a more or less consistent snapshot */
197 spin_lock_irq(&host->mmc->lock);
198 memcpy_fromio(buf, host->regs, MCI_REGS_SIZE);
199 spin_unlock_irq(&host->mmc->lock);
200
201 seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
202 buf[MCI_MR / 4],
203 buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "",
204 buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "",
205 buf[MCI_MR / 4] & 0xff);
206 seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]);
207 seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]);
208 seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]);
209 seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n",
210 buf[MCI_BLKR / 4],
211 buf[MCI_BLKR / 4] & 0xffff,
212 (buf[MCI_BLKR / 4] >> 16) & 0xffff);
213
214 /* Don't read RSPR and RDR; it will consume the data there */
215
216 atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]);
217 atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]);
218
219 return 0;
220}
221
222static int atmci_regs_open(struct inode *inode, struct file *file)
223{
224 return single_open(file, atmci_regs_show, inode->i_private);
225}
226
227static const struct file_operations atmci_regs_fops = {
228 .owner = THIS_MODULE,
229 .open = atmci_regs_open,
230 .read = seq_read,
231 .llseek = seq_lseek,
232 .release = single_release,
233};
234
235static void atmci_init_debugfs(struct atmel_mci *host)
236{
237 struct mmc_host *mmc;
238 struct dentry *root;
239 struct dentry *node;
240 struct resource *res;
241
242 mmc = host->mmc;
243 root = mmc->debugfs_root;
244 if (!root)
245 return;
246
247 node = debugfs_create_file("regs", S_IRUSR, root, host,
248 &atmci_regs_fops);
249 if (IS_ERR(node))
250 return;
251 if (!node)
252 goto err;
253
254 res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
255 node->d_inode->i_size = res->end - res->start + 1;
256
257 node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops);
258 if (!node)
259 goto err;
260
261 node = debugfs_create_x32("pending_events", S_IRUSR, root,
262 (u32 *)&host->pending_events);
263 if (!node)
264 goto err;
265
266 node = debugfs_create_x32("completed_events", S_IRUSR, root,
267 (u32 *)&host->completed_events);
268 if (!node)
269 goto err;
270
271 return;
272
273err:
274 dev_err(&host->pdev->dev,
275 "failed to initialize debugfs for controller\n");
276}
92 277
93static void atmci_enable(struct atmel_mci *host) 278static void atmci_enable(struct atmel_mci *host)
94{ 279{
@@ -906,6 +1091,8 @@ static int __init atmci_probe(struct platform_device *pdev)
906 "Atmel MCI controller at 0x%08lx irq %d\n", 1091 "Atmel MCI controller at 0x%08lx irq %d\n",
907 host->mapbase, irq); 1092 host->mapbase, irq);
908 1093
1094 atmci_init_debugfs(host);
1095
909 return 0; 1096 return 0;
910 1097
911err_request_irq: 1098err_request_irq:
@@ -924,6 +1111,8 @@ static int __exit atmci_remove(struct platform_device *pdev)
924 platform_set_drvdata(pdev, NULL); 1111 platform_set_drvdata(pdev, NULL);
925 1112
926 if (host) { 1113 if (host) {
1114 /* Debugfs stuff is cleaned up by mmc core */
1115
927 if (host->detect_pin >= 0) { 1116 if (host->detect_pin >= 0) {
928 int pin = host->detect_pin; 1117 int pin = host->detect_pin;
929 1118
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 3f15eb204895..99b20917cc0f 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1043,7 +1043,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
1043 goto out6; 1043 goto out6;
1044 } 1044 }
1045 1045
1046 platform_set_drvdata(pdev, mmc); 1046 platform_set_drvdata(pdev, host);
1047 1047
1048 printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X" 1048 printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
1049 " (mode=%s)\n", pdev->id, host->iobase, 1049 " (mode=%s)\n", pdev->id, host->iobase,
@@ -1087,13 +1087,10 @@ out0:
1087 1087
1088static int __devexit au1xmmc_remove(struct platform_device *pdev) 1088static int __devexit au1xmmc_remove(struct platform_device *pdev)
1089{ 1089{
1090 struct mmc_host *mmc = platform_get_drvdata(pdev); 1090 struct au1xmmc_host *host = platform_get_drvdata(pdev);
1091 struct au1xmmc_host *host;
1092
1093 if (mmc) {
1094 host = mmc_priv(mmc);
1095 1091
1096 mmc_remove_host(mmc); 1092 if (host) {
1093 mmc_remove_host(host->mmc);
1097 1094
1098#ifdef CONFIG_LEDS_CLASS 1095#ifdef CONFIG_LEDS_CLASS
1099 if (host->platdata && host->platdata->led) 1096 if (host->platdata && host->platdata->led)
@@ -1101,8 +1098,8 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
1101#endif 1098#endif
1102 1099
1103 if (host->platdata && host->platdata->cd_setup && 1100 if (host->platdata && host->platdata->cd_setup &&
1104 !(mmc->caps & MMC_CAP_NEEDS_POLL)) 1101 !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
1105 host->platdata->cd_setup(mmc, 0); 1102 host->platdata->cd_setup(host->mmc, 0);
1106 1103
1107 au_writel(0, HOST_ENABLE(host)); 1104 au_writel(0, HOST_ENABLE(host));
1108 au_writel(0, HOST_CONFIG(host)); 1105 au_writel(0, HOST_CONFIG(host));
@@ -1122,16 +1119,49 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
1122 release_resource(host->ioarea); 1119 release_resource(host->ioarea);
1123 kfree(host->ioarea); 1120 kfree(host->ioarea);
1124 1121
1125 mmc_free_host(mmc); 1122 mmc_free_host(host->mmc);
1123 platform_set_drvdata(pdev, NULL);
1126 } 1124 }
1127 return 0; 1125 return 0;
1128} 1126}
1129 1127
1128#ifdef CONFIG_PM
1129static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
1130{
1131 struct au1xmmc_host *host = platform_get_drvdata(pdev);
1132 int ret;
1133
1134 ret = mmc_suspend_host(host->mmc, state);
1135 if (ret)
1136 return ret;
1137
1138 au_writel(0, HOST_CONFIG2(host));
1139 au_writel(0, HOST_CONFIG(host));
1140 au_writel(0xffffffff, HOST_STATUS(host));
1141 au_writel(0, HOST_ENABLE(host));
1142 au_sync();
1143
1144 return 0;
1145}
1146
1147static int au1xmmc_resume(struct platform_device *pdev)
1148{
1149 struct au1xmmc_host *host = platform_get_drvdata(pdev);
1150
1151 au1xmmc_reset_controller(host);
1152
1153 return mmc_resume_host(host->mmc);
1154}
1155#else
1156#define au1xmmc_suspend NULL
1157#define au1xmmc_resume NULL
1158#endif
1159
1130static struct platform_driver au1xmmc_driver = { 1160static struct platform_driver au1xmmc_driver = {
1131 .probe = au1xmmc_probe, 1161 .probe = au1xmmc_probe,
1132 .remove = au1xmmc_remove, 1162 .remove = au1xmmc_remove,
1133 .suspend = NULL, 1163 .suspend = au1xmmc_suspend,
1134 .resume = NULL, 1164 .resume = au1xmmc_resume,
1135 .driver = { 1165 .driver = {
1136 .name = DRIVER_NAME, 1166 .name = DRIVER_NAME,
1137 .owner = THIS_MODULE, 1167 .owner = THIS_MODULE,
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
index 5e880c0f1349..f61406da65d2 100644
--- a/drivers/mmc/host/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -26,12 +26,6 @@
26 * 26 *
27 */ 27 */
28 28
29#ifdef CONFIG_MMC_DEBUG
30#define DEBUG
31#else
32#undef DEBUG
33#endif
34
35#include <linux/module.h> 29#include <linux/module.h>
36#include <linux/init.h> 30#include <linux/init.h>
37#include <linux/ioport.h> 31#include <linux/ioport.h>
@@ -907,31 +901,12 @@ static const struct mmc_host_ops imxmci_ops = {
907 .get_ro = imxmci_get_ro, 901 .get_ro = imxmci_get_ro,
908}; 902};
909 903
910static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
911{
912 int i;
913
914 for (i = 0; i < dev->num_resources; i++)
915 if (dev->resource[i].flags == mask && nr-- == 0)
916 return &dev->resource[i];
917 return NULL;
918}
919
920static int platform_device_irq(struct platform_device *dev, int nr)
921{
922 int i;
923
924 for (i = 0; i < dev->num_resources; i++)
925 if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
926 return dev->resource[i].start;
927 return NO_IRQ;
928}
929
930static void imxmci_check_status(unsigned long data) 904static void imxmci_check_status(unsigned long data)
931{ 905{
932 struct imxmci_host *host = (struct imxmci_host *)data; 906 struct imxmci_host *host = (struct imxmci_host *)data;
933 907
934 if( host->pdata->card_present(mmc_dev(host->mmc)) != host->present ) { 908 if (host->pdata && host->pdata->card_present &&
909 host->pdata->card_present(mmc_dev(host->mmc)) != host->present) {
935 host->present ^= 1; 910 host->present ^= 1;
936 dev_info(mmc_dev(host->mmc), "card %s\n", 911 dev_info(mmc_dev(host->mmc), "card %s\n",
937 host->present ? "inserted" : "removed"); 912 host->present ? "inserted" : "removed");
@@ -962,13 +937,12 @@ static int imxmci_probe(struct platform_device *pdev)
962 937
963 printk(KERN_INFO "i.MX mmc driver\n"); 938 printk(KERN_INFO "i.MX mmc driver\n");
964 939
965 r = platform_device_resource(pdev, IORESOURCE_MEM, 0); 940 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
966 irq = platform_device_irq(pdev, 0); 941 irq = platform_get_irq(pdev, 0);
967 if (!r || irq == NO_IRQ) 942 if (!r || irq < 0)
968 return -ENXIO; 943 return -ENXIO;
969 944
970 r = request_mem_region(r->start, 0x100, "IMXMCI"); 945 if (!request_mem_region(r->start, 0x100, pdev->name))
971 if (!r)
972 return -EBUSY; 946 return -EBUSY;
973 947
974 mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev); 948 mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
@@ -995,6 +969,8 @@ static int imxmci_probe(struct platform_device *pdev)
995 host->mmc = mmc; 969 host->mmc = mmc;
996 host->dma_allocated = 0; 970 host->dma_allocated = 0;
997 host->pdata = pdev->dev.platform_data; 971 host->pdata = pdev->dev.platform_data;
972 if (!host->pdata)
973 dev_warn(&pdev->dev, "No platform data provided!\n");
998 974
999 spin_lock_init(&host->lock); 975 spin_lock_init(&host->lock);
1000 host->res = r; 976 host->res = r;
@@ -1047,7 +1023,11 @@ static int imxmci_probe(struct platform_device *pdev)
1047 if (ret) 1023 if (ret)
1048 goto out; 1024 goto out;
1049 1025
1050 host->present = host->pdata->card_present(mmc_dev(mmc)); 1026 if (host->pdata && host->pdata->card_present)
1027 host->present = host->pdata->card_present(mmc_dev(mmc));
1028 else /* if there is no way to detect assume that card is present */
1029 host->present = 1;
1030
1051 init_timer(&host->timer); 1031 init_timer(&host->timer);
1052 host->timer.data = (unsigned long)host; 1032 host->timer.data = (unsigned long)host;
1053 host->timer.function = imxmci_check_status; 1033 host->timer.function = imxmci_check_status;
@@ -1073,7 +1053,7 @@ out:
1073 } 1053 }
1074 if (mmc) 1054 if (mmc)
1075 mmc_free_host(mmc); 1055 mmc_free_host(mmc);
1076 release_resource(r); 1056 release_mem_region(r->start, 0x100);
1077 return ret; 1057 return ret;
1078} 1058}
1079 1059
@@ -1102,7 +1082,7 @@ static int imxmci_remove(struct platform_device *pdev)
1102 clk_disable(host->clk); 1082 clk_disable(host->clk);
1103 clk_put(host->clk); 1083 clk_put(host->clk);
1104 1084
1105 release_resource(host->res); 1085 release_mem_region(host->res->start, 0x100);
1106 1086
1107 mmc_free_host(mmc); 1087 mmc_free_host(mmc);
1108 } 1088 }
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 41cc63360e43..7503b81374e0 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1076,6 +1076,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1076 */ 1076 */
1077 if (canpower && ios->power_mode == MMC_POWER_OFF) { 1077 if (canpower && ios->power_mode == MMC_POWER_OFF) {
1078 int mres; 1078 int mres;
1079 u8 nullbyte = 0;
1079 1080
1080 host->spi->mode &= ~(SPI_CPOL|SPI_CPHA); 1081 host->spi->mode &= ~(SPI_CPOL|SPI_CPHA);
1081 mres = spi_setup(host->spi); 1082 mres = spi_setup(host->spi);
@@ -1083,7 +1084,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1083 dev_dbg(&host->spi->dev, 1084 dev_dbg(&host->spi->dev,
1084 "switch to SPI mode 0 failed\n"); 1085 "switch to SPI mode 0 failed\n");
1085 1086
1086 if (spi_w8r8(host->spi, 0x00) < 0) 1087 if (spi_write(host->spi, &nullbyte, 1) < 0)
1087 dev_dbg(&host->spi->dev, 1088 dev_dbg(&host->spi->dev,
1088 "put spi signals to low failed\n"); 1089 "put spi signals to low failed\n");
1089 1090
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index d39f59738866..a8e18fe53077 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -177,7 +177,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
177 if (dalgn) 177 if (dalgn)
178 DALGN |= (1 << host->dma); 178 DALGN |= (1 << host->dma);
179 else 179 else
180 DALGN &= (1 << host->dma); 180 DALGN &= ~(1 << host->dma);
181 DDADR(host->dma) = host->sg_dma; 181 DDADR(host->dma) = host->sg_dma;
182 DCSR(host->dma) = DCSR_RUN; 182 DCSR(host->dma) = DCSR_RUN;
183} 183}
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 6a1e4994b724..be550c26da68 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1331,21 +1331,30 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
1331 return ret; 1331 return ret;
1332} 1332}
1333 1333
1334static void s3cmci_shutdown(struct platform_device *pdev)
1335{
1336 struct mmc_host *mmc = platform_get_drvdata(pdev);
1337 struct s3cmci_host *host = mmc_priv(mmc);
1338
1339 if (host->irq_cd >= 0)
1340 free_irq(host->irq_cd, host);
1341
1342 mmc_remove_host(mmc);
1343 clk_disable(host->clk);
1344}
1345
1334static int __devexit s3cmci_remove(struct platform_device *pdev) 1346static int __devexit s3cmci_remove(struct platform_device *pdev)
1335{ 1347{
1336 struct mmc_host *mmc = platform_get_drvdata(pdev); 1348 struct mmc_host *mmc = platform_get_drvdata(pdev);
1337 struct s3cmci_host *host = mmc_priv(mmc); 1349 struct s3cmci_host *host = mmc_priv(mmc);
1338 1350
1339 mmc_remove_host(mmc); 1351 s3cmci_shutdown(pdev);
1340 1352
1341 clk_disable(host->clk);
1342 clk_put(host->clk); 1353 clk_put(host->clk);
1343 1354
1344 tasklet_disable(&host->pio_tasklet); 1355 tasklet_disable(&host->pio_tasklet);
1345 s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client); 1356 s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
1346 1357
1347 if (host->irq_cd >= 0)
1348 free_irq(host->irq_cd, host);
1349 free_irq(host->irq, host); 1358 free_irq(host->irq, host);
1350 1359
1351 iounmap(host->base); 1360 iounmap(host->base);
@@ -1355,17 +1364,17 @@ static int __devexit s3cmci_remove(struct platform_device *pdev)
1355 return 0; 1364 return 0;
1356} 1365}
1357 1366
1358static int __devinit s3cmci_probe_2410(struct platform_device *dev) 1367static int __devinit s3cmci_2410_probe(struct platform_device *dev)
1359{ 1368{
1360 return s3cmci_probe(dev, 0); 1369 return s3cmci_probe(dev, 0);
1361} 1370}
1362 1371
1363static int __devinit s3cmci_probe_2412(struct platform_device *dev) 1372static int __devinit s3cmci_2412_probe(struct platform_device *dev)
1364{ 1373{
1365 return s3cmci_probe(dev, 1); 1374 return s3cmci_probe(dev, 1);
1366} 1375}
1367 1376
1368static int __devinit s3cmci_probe_2440(struct platform_device *dev) 1377static int __devinit s3cmci_2440_probe(struct platform_device *dev)
1369{ 1378{
1370 return s3cmci_probe(dev, 1); 1379 return s3cmci_probe(dev, 1);
1371} 1380}
@@ -1392,29 +1401,32 @@ static int s3cmci_resume(struct platform_device *dev)
1392#endif /* CONFIG_PM */ 1401#endif /* CONFIG_PM */
1393 1402
1394 1403
1395static struct platform_driver s3cmci_driver_2410 = { 1404static struct platform_driver s3cmci_2410_driver = {
1396 .driver.name = "s3c2410-sdi", 1405 .driver.name = "s3c2410-sdi",
1397 .driver.owner = THIS_MODULE, 1406 .driver.owner = THIS_MODULE,
1398 .probe = s3cmci_probe_2410, 1407 .probe = s3cmci_2410_probe,
1399 .remove = __devexit_p(s3cmci_remove), 1408 .remove = __devexit_p(s3cmci_remove),
1409 .shutdown = s3cmci_shutdown,
1400 .suspend = s3cmci_suspend, 1410 .suspend = s3cmci_suspend,
1401 .resume = s3cmci_resume, 1411 .resume = s3cmci_resume,
1402}; 1412};
1403 1413
1404static struct platform_driver s3cmci_driver_2412 = { 1414static struct platform_driver s3cmci_2412_driver = {
1405 .driver.name = "s3c2412-sdi", 1415 .driver.name = "s3c2412-sdi",
1406 .driver.owner = THIS_MODULE, 1416 .driver.owner = THIS_MODULE,
1407 .probe = s3cmci_probe_2412, 1417 .probe = s3cmci_2412_probe,
1408 .remove = __devexit_p(s3cmci_remove), 1418 .remove = __devexit_p(s3cmci_remove),
1419 .shutdown = s3cmci_shutdown,
1409 .suspend = s3cmci_suspend, 1420 .suspend = s3cmci_suspend,
1410 .resume = s3cmci_resume, 1421 .resume = s3cmci_resume,
1411}; 1422};
1412 1423
1413static struct platform_driver s3cmci_driver_2440 = { 1424static struct platform_driver s3cmci_2440_driver = {
1414 .driver.name = "s3c2440-sdi", 1425 .driver.name = "s3c2440-sdi",
1415 .driver.owner = THIS_MODULE, 1426 .driver.owner = THIS_MODULE,
1416 .probe = s3cmci_probe_2440, 1427 .probe = s3cmci_2440_probe,
1417 .remove = __devexit_p(s3cmci_remove), 1428 .remove = __devexit_p(s3cmci_remove),
1429 .shutdown = s3cmci_shutdown,
1418 .suspend = s3cmci_suspend, 1430 .suspend = s3cmci_suspend,
1419 .resume = s3cmci_resume, 1431 .resume = s3cmci_resume,
1420}; 1432};
@@ -1422,17 +1434,17 @@ static struct platform_driver s3cmci_driver_2440 = {
1422 1434
1423static int __init s3cmci_init(void) 1435static int __init s3cmci_init(void)
1424{ 1436{
1425 platform_driver_register(&s3cmci_driver_2410); 1437 platform_driver_register(&s3cmci_2410_driver);
1426 platform_driver_register(&s3cmci_driver_2412); 1438 platform_driver_register(&s3cmci_2412_driver);
1427 platform_driver_register(&s3cmci_driver_2440); 1439 platform_driver_register(&s3cmci_2440_driver);
1428 return 0; 1440 return 0;
1429} 1441}
1430 1442
1431static void __exit s3cmci_exit(void) 1443static void __exit s3cmci_exit(void)
1432{ 1444{
1433 platform_driver_unregister(&s3cmci_driver_2410); 1445 platform_driver_unregister(&s3cmci_2410_driver);
1434 platform_driver_unregister(&s3cmci_driver_2412); 1446 platform_driver_unregister(&s3cmci_2412_driver);
1435 platform_driver_unregister(&s3cmci_driver_2440); 1447 platform_driver_unregister(&s3cmci_2440_driver);
1436} 1448}
1437 1449
1438module_init(s3cmci_init); 1450module_init(s3cmci_init);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 17701c3da733..5f95e10229b5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -173,119 +173,95 @@ static void sdhci_led_control(struct led_classdev *led,
173 * * 173 * *
174\*****************************************************************************/ 174\*****************************************************************************/
175 175
176static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
177{
178 return sg_virt(host->cur_sg);
179}
180
181static inline int sdhci_next_sg(struct sdhci_host* host)
182{
183 /*
184 * Skip to next SG entry.
185 */
186 host->cur_sg++;
187 host->num_sg--;
188
189 /*
190 * Any entries left?
191 */
192 if (host->num_sg > 0) {
193 host->offset = 0;
194 host->remain = host->cur_sg->length;
195 }
196
197 return host->num_sg;
198}
199
200static void sdhci_read_block_pio(struct sdhci_host *host) 176static void sdhci_read_block_pio(struct sdhci_host *host)
201{ 177{
202 int blksize, chunk_remain; 178 unsigned long flags;
203 u32 data; 179 size_t blksize, len, chunk;
204 char *buffer; 180 u32 scratch;
205 int size; 181 u8 *buf;
206 182
207 DBG("PIO reading\n"); 183 DBG("PIO reading\n");
208 184
209 blksize = host->data->blksz; 185 blksize = host->data->blksz;
210 chunk_remain = 0; 186 chunk = 0;
211 data = 0;
212 187
213 buffer = sdhci_sg_to_buffer(host) + host->offset; 188 local_irq_save(flags);
214 189
215 while (blksize) { 190 while (blksize) {
216 if (chunk_remain == 0) { 191 if (!sg_miter_next(&host->sg_miter))
217 data = readl(host->ioaddr + SDHCI_BUFFER); 192 BUG();
218 chunk_remain = min(blksize, 4);
219 }
220 193
221 size = min(host->remain, chunk_remain); 194 len = min(host->sg_miter.length, blksize);
222 195
223 chunk_remain -= size; 196 blksize -= len;
224 blksize -= size; 197 host->sg_miter.consumed = len;
225 host->offset += size;
226 host->remain -= size;
227 198
228 while (size) { 199 buf = host->sg_miter.addr;
229 *buffer = data & 0xFF;
230 buffer++;
231 data >>= 8;
232 size--;
233 }
234 200
235 if (host->remain == 0) { 201 while (len) {
236 if (sdhci_next_sg(host) == 0) { 202 if (chunk == 0) {
237 BUG_ON(blksize != 0); 203 scratch = readl(host->ioaddr + SDHCI_BUFFER);
238 return; 204 chunk = 4;
239 } 205 }
240 buffer = sdhci_sg_to_buffer(host); 206
207 *buf = scratch & 0xFF;
208
209 buf++;
210 scratch >>= 8;
211 chunk--;
212 len--;
241 } 213 }
242 } 214 }
215
216 sg_miter_stop(&host->sg_miter);
217
218 local_irq_restore(flags);
243} 219}
244 220
245static void sdhci_write_block_pio(struct sdhci_host *host) 221static void sdhci_write_block_pio(struct sdhci_host *host)
246{ 222{
247 int blksize, chunk_remain; 223 unsigned long flags;
248 u32 data; 224 size_t blksize, len, chunk;
249 char *buffer; 225 u32 scratch;
250 int bytes, size; 226 u8 *buf;
251 227
252 DBG("PIO writing\n"); 228 DBG("PIO writing\n");
253 229
254 blksize = host->data->blksz; 230 blksize = host->data->blksz;
255 chunk_remain = 4; 231 chunk = 0;
256 data = 0; 232 scratch = 0;
257 233
258 bytes = 0; 234 local_irq_save(flags);
259 buffer = sdhci_sg_to_buffer(host) + host->offset;
260 235
261 while (blksize) { 236 while (blksize) {
262 size = min(host->remain, chunk_remain); 237 if (!sg_miter_next(&host->sg_miter))
263 238 BUG();
264 chunk_remain -= size;
265 blksize -= size;
266 host->offset += size;
267 host->remain -= size;
268
269 while (size) {
270 data >>= 8;
271 data |= (u32)*buffer << 24;
272 buffer++;
273 size--;
274 }
275 239
276 if (chunk_remain == 0) { 240 len = min(host->sg_miter.length, blksize);
277 writel(data, host->ioaddr + SDHCI_BUFFER); 241
278 chunk_remain = min(blksize, 4); 242 blksize -= len;
279 } 243 host->sg_miter.consumed = len;
244
245 buf = host->sg_miter.addr;
280 246
281 if (host->remain == 0) { 247 while (len) {
282 if (sdhci_next_sg(host) == 0) { 248 scratch |= (u32)*buf << (chunk * 8);
283 BUG_ON(blksize != 0); 249
284 return; 250 buf++;
251 chunk++;
252 len--;
253
254 if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
255 writel(scratch, host->ioaddr + SDHCI_BUFFER);
256 chunk = 0;
257 scratch = 0;
285 } 258 }
286 buffer = sdhci_sg_to_buffer(host);
287 } 259 }
288 } 260 }
261
262 sg_miter_stop(&host->sg_miter);
263
264 local_irq_restore(flags);
289} 265}
290 266
291static void sdhci_transfer_pio(struct sdhci_host *host) 267static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -294,7 +270,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
294 270
295 BUG_ON(!host->data); 271 BUG_ON(!host->data);
296 272
297 if (host->num_sg == 0) 273 if (host->blocks == 0)
298 return; 274 return;
299 275
300 if (host->data->flags & MMC_DATA_READ) 276 if (host->data->flags & MMC_DATA_READ)
@@ -308,7 +284,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
308 else 284 else
309 sdhci_write_block_pio(host); 285 sdhci_write_block_pio(host);
310 286
311 if (host->num_sg == 0) 287 host->blocks--;
288 if (host->blocks == 0)
312 break; 289 break;
313 } 290 }
314 291
@@ -360,7 +337,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
360 337
361 host->align_addr = dma_map_single(mmc_dev(host->mmc), 338 host->align_addr = dma_map_single(mmc_dev(host->mmc),
362 host->align_buffer, 128 * 4, direction); 339 host->align_buffer, 128 * 4, direction);
363 if (dma_mapping_error(host->align_addr)) 340 if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
364 goto fail; 341 goto fail;
365 BUG_ON(host->align_addr & 0x3); 342 BUG_ON(host->align_addr & 0x3);
366 343
@@ -389,6 +366,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
389 if (offset) { 366 if (offset) {
390 if (data->flags & MMC_DATA_WRITE) { 367 if (data->flags & MMC_DATA_WRITE) {
391 buffer = sdhci_kmap_atomic(sg, &flags); 368 buffer = sdhci_kmap_atomic(sg, &flags);
369 WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
392 memcpy(align, buffer, offset); 370 memcpy(align, buffer, offset);
393 sdhci_kunmap_atomic(buffer, &flags); 371 sdhci_kunmap_atomic(buffer, &flags);
394 } 372 }
@@ -461,7 +439,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
461 439
462 host->adma_addr = dma_map_single(mmc_dev(host->mmc), 440 host->adma_addr = dma_map_single(mmc_dev(host->mmc),
463 host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 441 host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
464 if (dma_mapping_error(host->align_addr)) 442 if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
465 goto unmap_entries; 443 goto unmap_entries;
466 BUG_ON(host->adma_addr & 0x3); 444 BUG_ON(host->adma_addr & 0x3);
467 445
@@ -510,6 +488,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
510 size = 4 - (sg_dma_address(sg) & 0x3); 488 size = 4 - (sg_dma_address(sg) & 0x3);
511 489
512 buffer = sdhci_kmap_atomic(sg, &flags); 490 buffer = sdhci_kmap_atomic(sg, &flags);
491 WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
513 memcpy(buffer, align, size); 492 memcpy(buffer, align, size);
514 sdhci_kunmap_atomic(buffer, &flags); 493 sdhci_kunmap_atomic(buffer, &flags);
515 494
@@ -687,7 +666,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
687 WARN_ON(1); 666 WARN_ON(1);
688 host->flags &= ~SDHCI_USE_DMA; 667 host->flags &= ~SDHCI_USE_DMA;
689 } else { 668 } else {
690 WARN_ON(count != 1); 669 WARN_ON(sg_cnt != 1);
691 writel(sg_dma_address(data->sg), 670 writel(sg_dma_address(data->sg),
692 host->ioaddr + SDHCI_DMA_ADDRESS); 671 host->ioaddr + SDHCI_DMA_ADDRESS);
693 } 672 }
@@ -711,11 +690,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
711 } 690 }
712 691
713 if (!(host->flags & SDHCI_REQ_USE_DMA)) { 692 if (!(host->flags & SDHCI_REQ_USE_DMA)) {
714 host->cur_sg = data->sg; 693 sg_miter_start(&host->sg_miter,
715 host->num_sg = data->sg_len; 694 data->sg, data->sg_len, SG_MITER_ATOMIC);
716 695 host->blocks = data->blocks;
717 host->offset = 0;
718 host->remain = host->cur_sg->length;
719 } 696 }
720 697
721 /* We do not handle DMA boundaries, so set it to max (512 KiB) */ 698 /* We do not handle DMA boundaries, so set it to max (512 KiB) */
@@ -1581,9 +1558,15 @@ int sdhci_add_host(struct sdhci_host *host)
1581 } 1558 }
1582 } 1559 }
1583 1560
1584 /* XXX: Hack to get MMC layer to avoid highmem */ 1561 /*
1585 if (!(host->flags & SDHCI_USE_DMA)) 1562 * If we use DMA, then it's up to the caller to set the DMA
1586 mmc_dev(host->mmc)->dma_mask = NULL; 1563 * mask, but PIO does not need the hw shim so we set a new
1564 * mask here in that case.
1565 */
1566 if (!(host->flags & SDHCI_USE_DMA)) {
1567 host->dma_mask = DMA_BIT_MASK(64);
1568 mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
1569 }
1587 1570
1588 host->max_clk = 1571 host->max_clk =
1589 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 1572 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 5bb355281765..e354faee5df0 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -9,6 +9,8 @@
9 * your option) any later version. 9 * your option) any later version.
10 */ 10 */
11 11
12#include <linux/scatterlist.h>
13
12/* 14/*
13 * Controller registers 15 * Controller registers
14 */ 16 */
@@ -212,6 +214,7 @@ struct sdhci_host {
212 214
213 /* Internal data */ 215 /* Internal data */
214 struct mmc_host *mmc; /* MMC structure */ 216 struct mmc_host *mmc; /* MMC structure */
217 u64 dma_mask; /* custom DMA mask */
215 218
216#ifdef CONFIG_LEDS_CLASS 219#ifdef CONFIG_LEDS_CLASS
217 struct led_classdev led; /* LED control */ 220 struct led_classdev led; /* LED control */
@@ -238,10 +241,8 @@ struct sdhci_host {
238 struct mmc_data *data; /* Current data request */ 241 struct mmc_data *data; /* Current data request */
239 unsigned int data_early:1; /* Data finished before cmd */ 242 unsigned int data_early:1; /* Data finished before cmd */
240 243
241 struct scatterlist *cur_sg; /* We're working on this */ 244 struct sg_mapping_iter sg_miter; /* SG state for PIO */
242 int num_sg; /* Entries left */ 245 unsigned int blocks; /* remaining PIO blocks */
243 int offset; /* Offset into current sg */
244 int remain; /* Bytes left in current */
245 246
246 int sg_count; /* Mapped sg entries */ 247 int sg_count; /* Mapped sg entries */
247 248