]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/mmc/host/sdhci-of.c
Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mv-sheeva.git] / drivers / mmc / host / sdhci-of.c
index 1e8aa590bb39b0a5e650037f61647860fd2b3ec1..01ab916c2802dc90e21bc7aa7513c2d5c0fa2cb6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mmc/host.h>
+#include <asm/machdep.h>
 #include "sdhci.h"
 
 struct sdhci_of_data {
@@ -48,6 +49,8 @@ struct sdhci_of_host {
 #define ESDHC_CLOCK_HCKEN      0x00000002
 #define ESDHC_CLOCK_IPGEN      0x00000001
 
+#define ESDHC_HOST_CONTROL_RES 0x05
+
 static u32 esdhc_readl(struct sdhci_host *host, int reg)
 {
        return in_be32(host->ioaddr + reg);
@@ -109,13 +112,17 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
        int base = reg & ~0x3;
        int shift = (reg & 0x3) * 8;
 
+       /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
+       if (reg == SDHCI_HOST_CONTROL)
+               val &= ~ESDHC_HOST_CONTROL_RES;
+
        clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
 }
 
 static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
 {
-       int div;
        int pre_div = 2;
+       int div = 1;
 
        clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
                  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK);
@@ -123,19 +130,17 @@ static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
        if (clock == 0)
                goto out;
 
-       if (host->max_clk / 16 > clock) {
-               for (; pre_div < 256; pre_div *= 2) {
-                       if (host->max_clk / pre_div < clock * 16)
-                               break;
-               }
-       }
+       while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
+               pre_div *= 2;
 
-       for (div = 1; div <= 16; div++) {
-               if (host->max_clk / (div * pre_div) <= clock)
-                       break;
-       }
+       while (host->max_clk / pre_div / div > clock && div < 16)
+               div++;
+
+       dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+               clock, host->max_clk / pre_div / div);
 
        pre_div >>= 1;
+       div--;
 
        setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
                  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
@@ -165,19 +170,12 @@ static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
        return of_host->clock / 256 / 16;
 }
 
-static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host)
-{
-       struct sdhci_of_host *of_host = sdhci_priv(host);
-
-       return of_host->clock / 1000;
-}
-
 static struct sdhci_of_data sdhci_esdhc = {
        .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
                  SDHCI_QUIRK_BROKEN_CARD_DETECTION |
-                 SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
                  SDHCI_QUIRK_NO_BUSY_IRQ |
                  SDHCI_QUIRK_NONSTANDARD_CLOCK |
+                 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
                  SDHCI_QUIRK_PIO_NEEDS_DELAY |
                  SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET |
                  SDHCI_QUIRK_NO_CARD_NO_RESET,
@@ -192,7 +190,6 @@ static struct sdhci_of_data sdhci_esdhc = {
                .enable_dma = esdhc_enable_dma,
                .get_max_clock = esdhc_get_max_clock,
                .get_min_clock = esdhc_get_min_clock,
-               .get_timeout_clock = esdhc_get_timeout_clock,
        },
 };
 
@@ -219,6 +216,15 @@ static int sdhci_of_resume(struct of_device *ofdev)
 
 #endif
 
+static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
+{
+       if (of_get_property(np, "sdhci,wp-inverted", NULL))
+               return true;
+
+       /* Old device trees don't have the wp-inverted property. */
+       return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
+}
+
 static int __devinit sdhci_of_probe(struct of_device *ofdev,
                                 const struct of_device_id *match)
 {
@@ -261,6 +267,9 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev,
        if (of_get_property(np, "sdhci,1-bit-only", NULL))
                host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
 
+       if (sdhci_of_wp_inverted(np))
+               host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+
        clk = of_get_property(np, "clock-frequency", &size);
        if (clk && size == sizeof(*clk) && *clk)
                of_host->clock = *clk;