]> git.sur5r.net Git - u-boot/commitdiff
mmc: atmel_mci: using IP version for different setting
authorBo Shen <voice.shen@atmel.com>
Fri, 26 Apr 2013 00:27:06 +0000 (00:27 +0000)
committerAndreas Bießmann <andreas.devel@googlemail.com>
Sun, 12 May 2013 14:47:05 +0000 (16:47 +0200)
Using IP version for different setting
  - Higher version supports 8bit mode
  - Higher version bus width setting is different

Signed-off-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
drivers/mmc/gen_atmel_mci.c
include/atmel_mci.h

index 70a9f91c8d97408ed5e38347487094e2ff742bf4..fc0a1812318bb6af90a233c70c5dac74a1b259ae 100644 (file)
 
 static int initialized = 0;
 
+/* Read Atmel MCI IP version */
+static unsigned int atmel_mci_get_version(struct atmel_mci *mci)
+{
+       return readl(&mci->version) & 0x00000fff;
+}
+
 /*
  * Print command and status:
  *
@@ -297,7 +303,9 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 static void mci_set_ios(struct mmc *mmc)
 {
        atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
-       int busw = (mmc->bus_width == 4) ? 1 : 0;
+       int bus_width = mmc->bus_width;
+       unsigned int version = atmel_mci_get_version(mci);
+       int busw;
 
        /* Set the clock speed */
        mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
@@ -305,9 +313,26 @@ static void mci_set_ios(struct mmc *mmc)
        /*
         * set the bus width and select slot for this interface
         * there is no capability for multiple slots on the same interface yet
-        * Bitfield SCDBUS needs to be expanded to 2 bits for 8-bit buses
         */
-       writel(MMCI_BF(SCDBUS, busw) | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+       if ((version & 0xf00) >= 0x300) {
+               switch (bus_width) {
+               case 8:
+                       busw = 3;
+                       break;
+               case 4:
+                       busw = 2;
+                       break;
+               default:
+                       busw = 0;
+                       break;
+               }
+
+               writel(busw << 6 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+       } else {
+               busw = (bus_width == 4) ? 1 : 0;
+
+               writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+       }
 }
 
 /* Entered into mmc structure during driver init */
@@ -340,9 +365,12 @@ static int mci_init(struct mmc *mmc)
 int atmel_mci_init(void *regs)
 {
        struct mmc *mmc = malloc(sizeof(struct mmc));
+       struct atmel_mci *mci;
+       unsigned int version;
 
        if (!mmc)
                return -1;
+
        strcpy(mmc->name, "mci");
        mmc->priv = regs;
        mmc->send_cmd = mci_send_cmd;
@@ -353,7 +381,13 @@ int atmel_mci_init(void *regs)
 
        /* need to be able to pass these in on a board by board basis */
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->host_caps = MMC_MODE_4BIT;
+       mci = (struct atmel_mci *)mmc->priv;
+       version = atmel_mci_get_version(mci);
+       if ((version & 0xf00) >= 0x300)
+               mmc->host_caps = MMC_MODE_8BIT;
+
+       mmc->host_caps |= MMC_MODE_4BIT;
+
        /*
         * min and max frequencies determined by
         * max and min of clock divider
index c711881276bdd8dc4366095364c3d43aae2df771..31c4569c8fbf9eea2ff0731bf090358657a16f0c 100644 (file)
@@ -52,6 +52,8 @@ typedef struct atmel_mci {
        u32     ier;    /* 0x44 */
        u32     idr;    /* 0x48 */
        u32     imr;    /* 0x4c */
+       u32     reserved[43];
+       u32     version;
 } atmel_mci_t;
 
 #endif /* __ASSEMBLY__ */