aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c77
1 files changed, 38 insertions, 39 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c279fbc4c2e5..9d4fdfa685e5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -17,6 +17,7 @@
17#include <linux/highmem.h> 17#include <linux/highmem.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/slab.h>
20#include <linux/scatterlist.h> 21#include <linux/scatterlist.h>
21 22
22#include <linux/leds.h> 23#include <linux/leds.h>
@@ -174,20 +175,31 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
174 sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); 175 sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
175} 176}
176 177
177static void sdhci_init(struct sdhci_host *host) 178static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
179
180static void sdhci_init(struct sdhci_host *host, int soft)
178{ 181{
179 sdhci_reset(host, SDHCI_RESET_ALL); 182 if (soft)
183 sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
184 else
185 sdhci_reset(host, SDHCI_RESET_ALL);
180 186
181 sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, 187 sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
182 SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 188 SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
183 SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 189 SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
184 SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 190 SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
185 SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); 191 SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
192
193 if (soft) {
194 /* force clock reconfiguration */
195 host->clock = 0;
196 sdhci_set_ios(host->mmc, &host->mmc->ios);
197 }
186} 198}
187 199
188static void sdhci_reinit(struct sdhci_host *host) 200static void sdhci_reinit(struct sdhci_host *host)
189{ 201{
190 sdhci_init(host); 202 sdhci_init(host, 0);
191 sdhci_enable_card_detection(host); 203 sdhci_enable_card_detection(host);
192} 204}
193 205
@@ -376,6 +388,20 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
376 local_irq_restore(*flags); 388 local_irq_restore(*flags);
377} 389}
378 390
391static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd)
392{
393 __le32 *dataddr = (__le32 __force *)(desc + 4);
394 __le16 *cmdlen = (__le16 __force *)desc;
395
396 /* SDHCI specification says ADMA descriptors should be 4 byte
397 * aligned, so using 16 or 32bit operations should be safe. */
398
399 cmdlen[0] = cpu_to_le16(cmd);
400 cmdlen[1] = cpu_to_le16(len);
401
402 dataddr[0] = cpu_to_le32(addr);
403}
404
379static int sdhci_adma_table_pre(struct sdhci_host *host, 405static int sdhci_adma_table_pre(struct sdhci_host *host,
380 struct mmc_data *data) 406 struct mmc_data *data)
381{ 407{
@@ -443,19 +469,11 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
443 sdhci_kunmap_atomic(buffer, &flags); 469 sdhci_kunmap_atomic(buffer, &flags);
444 } 470 }
445 471
446 desc[7] = (align_addr >> 24) & 0xff; 472 /* tran, valid */
447 desc[6] = (align_addr >> 16) & 0xff; 473 sdhci_set_adma_desc(desc, align_addr, offset, 0x21);
448 desc[5] = (align_addr >> 8) & 0xff;
449 desc[4] = (align_addr >> 0) & 0xff;
450 474
451 BUG_ON(offset > 65536); 475 BUG_ON(offset > 65536);
452 476
453 desc[3] = (offset >> 8) & 0xff;
454 desc[2] = (offset >> 0) & 0xff;
455
456 desc[1] = 0x00;
457 desc[0] = 0x21; /* tran, valid */
458
459 align += 4; 477 align += 4;
460 align_addr += 4; 478 align_addr += 4;
461 479
@@ -465,19 +483,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
465 len -= offset; 483 len -= offset;
466 } 484 }
467 485
468 desc[7] = (addr >> 24) & 0xff;
469 desc[6] = (addr >> 16) & 0xff;
470 desc[5] = (addr >> 8) & 0xff;
471 desc[4] = (addr >> 0) & 0xff;
472
473 BUG_ON(len > 65536); 486 BUG_ON(len > 65536);
474 487
475 desc[3] = (len >> 8) & 0xff; 488 /* tran, valid */
476 desc[2] = (len >> 0) & 0xff; 489 sdhci_set_adma_desc(desc, addr, len, 0x21);
477
478 desc[1] = 0x00;
479 desc[0] = 0x21; /* tran, valid */
480
481 desc += 8; 490 desc += 8;
482 491
483 /* 492 /*
@@ -490,16 +499,9 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
490 /* 499 /*
491 * Add a terminating entry. 500 * Add a terminating entry.
492 */ 501 */
493 desc[7] = 0;
494 desc[6] = 0;
495 desc[5] = 0;
496 desc[4] = 0;
497 502
498 desc[3] = 0; 503 /* nop, end, valid */
499 desc[2] = 0; 504 sdhci_set_adma_desc(desc, 0, 0, 0x3);
500
501 desc[1] = 0x00;
502 desc[0] = 0x03; /* nop, end, valid */
503 505
504 /* 506 /*
505 * Resync align buffer as we might have changed it. 507 * Resync align buffer as we might have changed it.
@@ -1610,16 +1612,13 @@ int sdhci_resume_host(struct sdhci_host *host)
1610 if (ret) 1612 if (ret)
1611 return ret; 1613 return ret;
1612 1614
1613 sdhci_init(host); 1615 sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
1614 mmiowb(); 1616 mmiowb();
1615 1617
1616 ret = mmc_resume_host(host->mmc); 1618 ret = mmc_resume_host(host->mmc);
1617 if (ret)
1618 return ret;
1619
1620 sdhci_enable_card_detection(host); 1619 sdhci_enable_card_detection(host);
1621 1620
1622 return 0; 1621 return ret;
1623} 1622}
1624 1623
1625EXPORT_SYMBOL_GPL(sdhci_resume_host); 1624EXPORT_SYMBOL_GPL(sdhci_resume_host);
@@ -1874,7 +1873,7 @@ int sdhci_add_host(struct sdhci_host *host)
1874 if (ret) 1873 if (ret)
1875 goto untasklet; 1874 goto untasklet;
1876 1875
1877 sdhci_init(host); 1876 sdhci_init(host, 0);
1878 1877
1879#ifdef CONFIG_MMC_DEBUG 1878#ifdef CONFIG_MMC_DEBUG
1880 sdhci_dumpregs(host); 1879 sdhci_dumpregs(host);