Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / mmc / host / sdhci.c
index 401527d..782c0ee 100644 (file)
@@ -47,7 +47,8 @@ static void sdhci_finish_command(struct sdhci_host *);
 
 static void sdhci_dumpregs(struct sdhci_host *host)
 {
-       printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
+       printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
+               mmc_hostname(host->mmc));
 
        printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
                sdhci_readl(host, SDHCI_DMA_ADDRESS),
@@ -1001,13 +1002,28 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        if (clock == 0)
                goto out;
 
-       for (div = 1;div < 256;div *= 2) {
-               if ((host->max_clk / div) <= clock)
-                       break;
+       if (host->version >= SDHCI_SPEC_300) {
+               /* Version 3.00 divisors must be a multiple of 2. */
+               if (host->max_clk <= clock)
+                       div = 1;
+               else {
+                       for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
+                               if ((host->max_clk / div) <= clock)
+                                       break;
+                       }
+               }
+       } else {
+               /* Version 2.00 divisors must be a power of 2. */
+               for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
+                       if ((host->max_clk / div) <= clock)
+                               break;
+               }
        }
        div >>= 1;
 
-       clk = div << SDHCI_DIVIDER_SHIFT;
+       clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+       clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
+               << SDHCI_DIVIDER_HI_SHIFT;
        clk |= SDHCI_CLOCK_INT_EN;
        sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
@@ -1034,11 +1050,9 @@ out:
 
 static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
-       u8 pwr;
+       u8 pwr = 0;
 
-       if (power == (unsigned short)-1)
-               pwr = 0;
-       else {
+       if (power != (unsigned short)-1) {
                switch (1 << power) {
                case MMC_VDD_165_195:
                        pwr = SDHCI_POWER_180;
@@ -1168,6 +1182,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        else
                sdhci_set_power(host, ios->vdd);
 
+       if (host->ops->platform_send_init_74_clocks)
+               host->ops->platform_send_init_74_clocks(host, ios->power_mode);
+
        ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 
        if (ios->bus_width == MMC_BUS_WIDTH_8)
@@ -1180,8 +1197,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        else
                ctrl &= ~SDHCI_CTRL_4BITBUS;
 
-       if (ios->timing == MMC_TIMING_SD_HS &&
-           !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
+       if ((ios->timing == MMC_TIMING_SD_HS ||
+            ios->timing == MMC_TIMING_MMC_HS)
+           && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
                ctrl |= SDHCI_CTRL_HISPD;
        else
                ctrl &= ~SDHCI_CTRL_HISPD;
@@ -1205,22 +1223,25 @@ static int sdhci_get_ro(struct mmc_host *mmc)
 {
        struct sdhci_host *host;
        unsigned long flags;
-       int present;
+       int is_readonly;
 
        host = mmc_priv(mmc);
 
        spin_lock_irqsave(&host->lock, flags);
 
        if (host->flags & SDHCI_DEVICE_DEAD)
-               present = 0;
+               is_readonly = 0;
+       else if (host->ops->get_ro)
+               is_readonly = host->ops->get_ro(host);
        else
-               present = sdhci_readl(host, SDHCI_PRESENT_STATE);
+               is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
+                               & SDHCI_WRITE_PROTECT);
 
        spin_unlock_irqrestore(&host->lock, flags);
 
-       if (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT)
-               return !!(present & SDHCI_WRITE_PROTECT);
-       return !(present & SDHCI_WRITE_PROTECT);
+       /* This quirk needs to be replaced by a callback-function later */
+       return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
+               !is_readonly : is_readonly;
 }
 
 static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1427,7 +1448,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
                sdhci_finish_command(host);
 }
 
-#ifdef DEBUG
+#ifdef CONFIG_MMC_DEBUG
 static void sdhci_show_adma_error(struct sdhci_host *host)
 {
        const char *name = mmc_hostname(host->mmc);
@@ -1708,7 +1729,7 @@ int sdhci_add_host(struct sdhci_host *host)
        host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
        host->version = (host->version & SDHCI_SPEC_VER_MASK)
                                >> SDHCI_SPEC_VER_SHIFT;
-       if (host->version > SDHCI_SPEC_200) {
+       if (host->version > SDHCI_SPEC_300) {
                printk(KERN_ERR "%s: Unknown controller version (%d). "
                        "You may experience problems.\n", mmc_hostname(mmc),
                        host->version);
@@ -1779,8 +1800,13 @@ int sdhci_add_host(struct sdhci_host *host)
                mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
        }
 
-       host->max_clk =
-               (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+       if (host->version >= SDHCI_SPEC_300)
+               host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK)
+                       >> SDHCI_CLOCK_BASE_SHIFT;
+       else
+               host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK)
+                       >> SDHCI_CLOCK_BASE_SHIFT;
+
        host->max_clk *= 1000000;
        if (host->max_clk == 0 || host->quirks &
                        SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
@@ -1815,18 +1841,21 @@ int sdhci_add_host(struct sdhci_host *host)
        mmc->ops = &sdhci_ops;
        if (host->ops->get_min_clock)
                mmc->f_min = host->ops->get_min_clock(host);
+       else if (host->version >= SDHCI_SPEC_300)
+               mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
        else
-               mmc->f_min = host->max_clk / 256;
+               mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
        mmc->f_max = host->max_clk;
        mmc->caps |= MMC_CAP_SDIO_IRQ;
 
        if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
-               mmc->caps |= MMC_CAP_4_BIT_DATA;
+               mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
 
        if (caps & SDHCI_CAN_DO_HISPD)
-               mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+               mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
-       if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
+       if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
+           mmc_card_is_removable(mmc))
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        mmc->ocr_avail = 0;
@@ -1850,12 +1879,11 @@ int sdhci_add_host(struct sdhci_host *host)
         * can do scatter/gather or not.
         */
        if (host->flags & SDHCI_USE_ADMA)
-               mmc->max_hw_segs = 128;
+               mmc->max_segs = 128;
        else if (host->flags & SDHCI_USE_SDMA)
-               mmc->max_hw_segs = 1;
+               mmc->max_segs = 1;
        else /* PIO */
-               mmc->max_hw_segs = 128;
-       mmc->max_phys_segs = 128;
+               mmc->max_segs = 128;
 
        /*
         * Maximum number of sectors in one transfer. Limited by DMA boundary