aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-08-07 04:55:03 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-08-07 04:55:03 -0400
commit4fb8af10d0fd09372d52966b76922b9e82bbc950 (patch)
treed240e4d40357583e3f3eb228dccf20122a5b31ed /drivers/mmc
parentf44f82e8a20b98558486eb14497b2f71c78fa325 (diff)
parent64a99d2a8c3ed5c4e39f3ae1cc682aa8fd3977fc (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/block.c17
-rw-r--r--drivers/mmc/card/mmc_test.c85
-rw-r--r--drivers/mmc/core/core.c5
-rw-r--r--drivers/mmc/host/au1xmmc.c8
-rw-r--r--drivers/mmc/host/sdhci-pci.c3
-rw-r--r--drivers/mmc/host/sdhci.c15
-rw-r--r--drivers/mmc/host/sdhci.h2
7 files changed, 40 insertions, 95 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 66e5a5487c20..86dbb366415a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -213,7 +213,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
213 struct mmc_blk_data *md = mq->data; 213 struct mmc_blk_data *md = mq->data;
214 struct mmc_card *card = md->queue.card; 214 struct mmc_card *card = md->queue.card;
215 struct mmc_blk_request brq; 215 struct mmc_blk_request brq;
216 int ret = 1, sg_pos, data_size; 216 int ret = 1, data_size, i;
217 struct scatterlist *sg;
217 218
218 mmc_claim_host(card->host); 219 mmc_claim_host(card->host);
219 220
@@ -267,18 +268,22 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
267 268
268 mmc_queue_bounce_pre(mq); 269 mmc_queue_bounce_pre(mq);
269 270
271 /*
272 * Adjust the sg list so it is the same size as the
273 * request.
274 */
270 if (brq.data.blocks != 275 if (brq.data.blocks !=
271 (req->nr_sectors >> (md->block_bits - 9))) { 276 (req->nr_sectors >> (md->block_bits - 9))) {
272 data_size = brq.data.blocks * brq.data.blksz; 277 data_size = brq.data.blocks * brq.data.blksz;
273 for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) { 278 for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
274 data_size -= mq->sg[sg_pos].length; 279 data_size -= sg->length;
275 if (data_size <= 0) { 280 if (data_size <= 0) {
276 mq->sg[sg_pos].length += data_size; 281 sg->length += data_size;
277 sg_pos++; 282 i++;
278 break; 283 break;
279 } 284 }
280 } 285 }
281 brq.data.sg_len = sg_pos; 286 brq.data.sg_len = i;
282 } 287 }
283 288
284 mmc_wait_for_req(card->host, &brq.mrq); 289 mmc_wait_for_req(card->host, &brq.mrq);
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index a067fe436301..f26b01d811ae 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -388,16 +388,14 @@ static int mmc_test_transfer(struct mmc_test_card *test,
388 int ret, i; 388 int ret, i;
389 unsigned long flags; 389 unsigned long flags;
390 390
391 BUG_ON(blocks * blksz > BUFFER_SIZE);
392
393 if (write) { 391 if (write) {
394 for (i = 0;i < blocks * blksz;i++) 392 for (i = 0;i < blocks * blksz;i++)
395 test->scratch[i] = i; 393 test->scratch[i] = i;
396 } else { 394 } else {
397 memset(test->scratch, 0, blocks * blksz); 395 memset(test->scratch, 0, BUFFER_SIZE);
398 } 396 }
399 local_irq_save(flags); 397 local_irq_save(flags);
400 sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz); 398 sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
401 local_irq_restore(flags); 399 local_irq_restore(flags);
402 400
403 ret = mmc_test_set_blksize(test, blksz); 401 ret = mmc_test_set_blksize(test, blksz);
@@ -444,7 +442,7 @@ static int mmc_test_transfer(struct mmc_test_card *test,
444 } 442 }
445 } else { 443 } else {
446 local_irq_save(flags); 444 local_irq_save(flags);
447 sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz); 445 sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
448 local_irq_restore(flags); 446 local_irq_restore(flags);
449 for (i = 0;i < blocks * blksz;i++) { 447 for (i = 0;i < blocks * blksz;i++) {
450 if (test->scratch[i] != (u8)i) 448 if (test->scratch[i] != (u8)i)
@@ -805,69 +803,6 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
805 return 0; 803 return 0;
806} 804}
807 805
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 806#ifdef CONFIG_HIGHMEM
872 807
873static int mmc_test_write_high(struct mmc_test_card *test) 808static int mmc_test_write_high(struct mmc_test_card *test)
@@ -1071,20 +1006,6 @@ static const struct mmc_test_case mmc_test_cases[] = {
1071 .run = mmc_test_multi_xfersize_read, 1006 .run = mmc_test_multi_xfersize_read,
1072 }, 1007 },
1073 1008
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 1009#ifdef CONFIG_HIGHMEM
1089 1010
1090 { 1011 {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 3ee5b8c3b5ce..044d84eeed7c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -121,6 +121,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
121{ 121{
122#ifdef CONFIG_MMC_DEBUG 122#ifdef CONFIG_MMC_DEBUG
123 unsigned int i, sz; 123 unsigned int i, sz;
124 struct scatterlist *sg;
124#endif 125#endif
125 126
126 pr_debug("%s: starting CMD%u arg %08x flags %08x\n", 127 pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
@@ -156,8 +157,8 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
156 157
157#ifdef CONFIG_MMC_DEBUG 158#ifdef CONFIG_MMC_DEBUG
158 sz = 0; 159 sz = 0;
159 for (i = 0;i < mrq->data->sg_len;i++) 160 for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
160 sz += mrq->data->sg[i].length; 161 sz += sg->length;
161 BUG_ON(sz != mrq->data->blocks * mrq->data->blksz); 162 BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
162#endif 163#endif
163 164
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 99b20917cc0f..d3f55615c099 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -61,7 +61,13 @@
61 61
62/* Hardware definitions */ 62/* Hardware definitions */
63#define AU1XMMC_DESCRIPTOR_COUNT 1 63#define AU1XMMC_DESCRIPTOR_COUNT 1
64#define AU1XMMC_DESCRIPTOR_SIZE 2048 64
65/* max DMA seg size: 64KB on Au1100, 4MB on Au1200 */
66#ifdef CONFIG_SOC_AU1100
67#define AU1XMMC_DESCRIPTOR_SIZE 0x0000ffff
68#else /* Au1200 */
69#define AU1XMMC_DESCRIPTOR_SIZE 0x003fffff
70#endif
65 71
66#define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \ 72#define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \
67 MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \ 73 MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index deb607c52c0d..fcb14c2346cc 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -143,7 +143,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
143 chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR | 143 chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR |
144 SDHCI_QUIRK_32BIT_DMA_SIZE | 144 SDHCI_QUIRK_32BIT_DMA_SIZE |
145 SDHCI_QUIRK_32BIT_ADMA_SIZE | 145 SDHCI_QUIRK_32BIT_ADMA_SIZE |
146 SDHCI_QUIRK_RESET_AFTER_REQUEST; 146 SDHCI_QUIRK_RESET_AFTER_REQUEST |
147 SDHCI_QUIRK_BROKEN_SMALL_PIO;
147 } 148 }
148 149
149 /* 150 /*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5f95e10229b5..e3a8133560a2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -278,6 +278,15 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
278 else 278 else
279 mask = SDHCI_SPACE_AVAILABLE; 279 mask = SDHCI_SPACE_AVAILABLE;
280 280
281 /*
282 * Some controllers (JMicron JMB38x) mess up the buffer bits
283 * for transfers < 4 bytes. As long as it is just one block,
284 * we can ignore the bits.
285 */
286 if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) &&
287 (host->data->blocks == 1))
288 mask = ~0;
289
281 while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { 290 while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
282 if (host->data->flags & MMC_DATA_READ) 291 if (host->data->flags & MMC_DATA_READ)
283 sdhci_read_block_pio(host); 292 sdhci_read_block_pio(host);
@@ -439,7 +448,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
439 448
440 host->adma_addr = dma_map_single(mmc_dev(host->mmc), 449 host->adma_addr = dma_map_single(mmc_dev(host->mmc),
441 host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); 450 host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
442 if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) 451 if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
443 goto unmap_entries; 452 goto unmap_entries;
444 BUG_ON(host->adma_addr & 0x3); 453 BUG_ON(host->adma_addr & 0x3);
445 454
@@ -645,7 +654,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
645 * us an invalid request. 654 * us an invalid request.
646 */ 655 */
647 WARN_ON(1); 656 WARN_ON(1);
648 host->flags &= ~SDHCI_USE_DMA; 657 host->flags &= ~SDHCI_REQ_USE_DMA;
649 } else { 658 } else {
650 writel(host->adma_addr, 659 writel(host->adma_addr,
651 host->ioaddr + SDHCI_ADMA_ADDRESS); 660 host->ioaddr + SDHCI_ADMA_ADDRESS);
@@ -664,7 +673,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
664 * us an invalid request. 673 * us an invalid request.
665 */ 674 */
666 WARN_ON(1); 675 WARN_ON(1);
667 host->flags &= ~SDHCI_USE_DMA; 676 host->flags &= ~SDHCI_REQ_USE_DMA;
668 } else { 677 } else {
669 WARN_ON(sg_cnt != 1); 678 WARN_ON(sg_cnt != 1);
670 writel(sg_dma_address(data->sg), 679 writel(sg_dma_address(data->sg),
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index e354faee5df0..197d4a05f4ae 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -206,6 +206,8 @@ struct sdhci_host {
206#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) 206#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11)
207/* Controller provides an incorrect timeout value for transfers */ 207/* Controller provides an incorrect timeout value for transfers */
208#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) 208#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
209/* Controller has an issue with buffer bits for small transfers */
210#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
209 211
210 int irq; /* Device IRQ */ 212 int irq; /* Device IRQ */
211 void __iomem * ioaddr; /* Mapped address */ 213 void __iomem * ioaddr; /* Mapped address */