]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - drivers/mmc/mmc.c
TX6 Release 2013-04-22
[karo-tx-uboot.git] / drivers / mmc / mmc.c
index a60cfe1cb0d181be890bc2a8a2de9d209b3e99b3..d26e89a88c99d4f9958850cd555c94980212fdea 100644 (file)
@@ -47,104 +47,14 @@ int __board_mmc_getcd(struct mmc *mmc) {
 int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
        alias("__board_mmc_getcd")));
 
-#ifdef CONFIG_MMC_BOUNCE_BUFFER
-static int mmc_bounce_need_bounce(struct mmc_data *orig)
-{
-       ulong addr, len;
-
-       if (orig->flags & MMC_DATA_READ)
-               addr = (ulong)orig->dest;
-       else
-               addr = (ulong)orig->src;
-
-       if (addr % ARCH_DMA_MINALIGN) {
-               debug("MMC: Unaligned data destination address %08lx!\n", addr);
-               return 1;
-       }
-
-       len = (ulong)(orig->blocksize * orig->blocks);
-       if (len % ARCH_DMA_MINALIGN) {
-               debug("MMC: Unaligned data destination length %08lx!\n", len);
-               return 1;
-       }
-
-       return 0;
-}
-
-static int mmc_bounce_buffer_start(struct mmc_data *backup,
-                                       struct mmc_data *orig)
-{
-       ulong origlen, len;
-       void *buffer;
-
-       if (!orig)
-               return 0;
-
-       if (!mmc_bounce_need_bounce(orig))
-               return 0;
-
-       memcpy(backup, orig, sizeof(struct mmc_data));
-
-       origlen = orig->blocksize * orig->blocks;
-       len = roundup(origlen, ARCH_DMA_MINALIGN);
-       buffer = memalign(ARCH_DMA_MINALIGN, len);
-       if (!buffer) {
-               puts("MMC: Error allocating MMC bounce buffer!\n");
-               return 1;
-       }
-
-       if (orig->flags & MMC_DATA_READ) {
-               orig->dest = buffer;
-       } else {
-               memcpy(buffer, orig->src, origlen);
-               orig->src = buffer;
-       }
-
-       return 0;
-}
-
-static void mmc_bounce_buffer_stop(struct mmc_data *backup,
-                                       struct mmc_data *orig)
-{
-       ulong len;
-
-       if (!orig)
-               return;
-
-       if (!mmc_bounce_need_bounce(backup))
-               return;
-
-       if (backup->flags & MMC_DATA_READ) {
-               len = backup->blocksize * backup->blocks;
-               memcpy(backup->dest, orig->dest, len);
-               free(orig->dest);
-               orig->dest = backup->dest;
-       } else {
-               free((void *)orig->src);
-               orig->src = backup->src;
-       }
-
-       return;
-
-}
-#else
-static inline int mmc_bounce_buffer_start(struct mmc_data *backup,
-                                       struct mmc_data *orig) { return 0; }
-static inline void mmc_bounce_buffer_stop(struct mmc_data *backup,
-                                       struct mmc_data *orig) { }
-#endif
-
-int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+                       struct mmc_data *data)
 {
        struct mmc_data backup;
        int ret;
 
        memset(&backup, 0, sizeof(backup));
 
-       ret = mmc_bounce_buffer_start(&backup, data);
-       if (ret)
-               return ret;
-
 #ifdef CONFIG_MMC_TRACE
        int i;
        u8 *ptr;
@@ -196,11 +106,10 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 #else
        ret = mmc->send_cmd(mmc, cmd, data);
 #endif
-       mmc_bounce_buffer_stop(&backup, data);
        return ret;
 }
 
-int mmc_send_status(struct mmc *mmc, int timeout)
+static int mmc_send_status(struct mmc *mmc, int timeout)
 {
        struct mmc_cmd cmd;
        int err, retries = 5;
@@ -244,7 +153,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
        return 0;
 }
 
-int mmc_set_blocklen(struct mmc *mmc, int len)
+static int mmc_set_blocklen(struct mmc *mmc, int len)
 {
        struct mmc_cmd cmd;
 
@@ -437,7 +346,8 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
        return blkcnt;
 }
 
-int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
+static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
+                          lbaint_t blkcnt)
 {
        struct mmc_cmd cmd;
        struct mmc_data data;
@@ -507,7 +417,7 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
        return blkcnt;
 }
 
-int mmc_go_idle(struct mmc* mmc)
+static int mmc_go_idle(struct mmc *mmc)
 {
        struct mmc_cmd cmd;
        int err;
@@ -528,8 +438,7 @@ int mmc_go_idle(struct mmc* mmc)
        return 0;
 }
 
-int
-sd_send_op_cond(struct mmc *mmc)
+static int sd_send_op_cond(struct mmc *mmc)
 {
        int timeout = 1000;
        int err;
@@ -594,7 +503,7 @@ sd_send_op_cond(struct mmc *mmc)
        return 0;
 }
 
-int mmc_send_op_cond(struct mmc *mmc)
+static int mmc_send_op_cond(struct mmc *mmc)
 {
        int timeout = 10000;
        struct mmc_cmd cmd;
@@ -634,9 +543,10 @@ int mmc_send_op_cond(struct mmc *mmc)
                udelay(1000);
        } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
 
-       if (timeout <= 0)
+       if (timeout <= 0) {
+debug("%s: timeout\n", __func__);
                return UNUSABLE_ERR;
-
+       }
        if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
                cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
                cmd.resp_type = MMC_RSP_R3;
@@ -658,7 +568,7 @@ int mmc_send_op_cond(struct mmc *mmc)
 }
 
 
-int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
+static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
 {
        struct mmc_cmd cmd;
        struct mmc_data data;
@@ -680,7 +590,7 @@ int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
 }
 
 
-int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
+static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 {
        struct mmc_cmd cmd;
        int timeout = 1000;
@@ -702,7 +612,7 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 
 }
 
-int mmc_change_freq(struct mmc *mmc)
+static int mmc_change_freq(struct mmc *mmc)
 {
        ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
        char cardtype;
@@ -772,7 +682,7 @@ int mmc_getcd(struct mmc *mmc)
        return cd;
 }
 
-int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
+static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 {
        struct mmc_cmd cmd;
        struct mmc_data data;
@@ -793,7 +703,7 @@ int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 }
 
 
-int sd_change_freq(struct mmc *mmc)
+static int sd_change_freq(struct mmc *mmc)
 {
        int err;
        struct mmc_cmd cmd;
@@ -932,7 +842,7 @@ static const int multipliers[] = {
        80,
 };
 
-void mmc_set_ios(struct mmc *mmc)
+static void mmc_set_ios(struct mmc *mmc)
 {
        mmc->set_ios(mmc);
 }
@@ -950,16 +860,16 @@ void mmc_set_clock(struct mmc *mmc, uint clock)
        mmc_set_ios(mmc);
 }
 
-void mmc_set_bus_width(struct mmc *mmc, uint width)
+static void mmc_set_bus_width(struct mmc *mmc, uint width)
 {
        mmc->bus_width = width;
 
        mmc_set_ios(mmc);
 }
 
-int mmc_startup(struct mmc *mmc)
+static int mmc_startup(struct mmc *mmc)
 {
-       int err, width;
+       int err;
        uint mult, freq;
        u64 cmult, csize, capacity;
        struct mmc_cmd cmd;
@@ -1105,7 +1015,7 @@ int mmc_startup(struct mmc *mmc)
        if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
                /* check  ext_csd version and capacity */
                err = mmc_send_ext_csd(mmc, ext_csd);
-               if (!err & (ext_csd[EXT_CSD_REV] >= 2)) {
+               if (!err && (ext_csd[EXT_CSD_REV] >= 2)) {
                        /*
                         * According to the JEDEC Standard, the value of
                         * ext_csd's capacity is valid if the value is more
@@ -1178,21 +1088,44 @@ int mmc_startup(struct mmc *mmc)
                else
                        mmc->tran_speed = 25000000;
        } else {
-               width = ((mmc->host_caps & MMC_MODE_MASK_WIDTH_BITS) >>
-                        MMC_MODE_WIDTH_BITS_SHIFT);
-               for (; width >= 0; width--) {
-                       /* Set the card to use 4 bit*/
+               int idx;
+
+               /* An array of possible bus widths in order of preference */
+               static unsigned ext_csd_bits[] = {
+                       EXT_CSD_BUS_WIDTH_8,
+                       EXT_CSD_BUS_WIDTH_4,
+                       EXT_CSD_BUS_WIDTH_1,
+               };
+
+               /* An array to map CSD bus widths to host cap bits */
+               static unsigned ext_to_hostcaps[] = {
+                       [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
+                       [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
+               };
+
+               /* An array to map chosen bus width to an integer */
+               static unsigned widths[] = {
+                       8, 4, 1,
+               };
+
+               for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
+                       unsigned int extw = ext_csd_bits[idx];
+
+                       /*
+                        * Check to make sure the controller supports
+                        * this bus width, if it's more than 1
+                        */
+                       if (extw != EXT_CSD_BUS_WIDTH_1 &&
+                                       !(mmc->host_caps & ext_to_hostcaps[extw]))
+                               continue;
+
                        err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
-                                       EXT_CSD_BUS_WIDTH, width);
+                                       EXT_CSD_BUS_WIDTH, extw);
 
                        if (err)
                                continue;
 
-                       if (!width) {
-                               mmc_set_bus_width(mmc, 1);
-                               break;
-                       } else
-                               mmc_set_bus_width(mmc, 4 * width);
+                       mmc_set_bus_width(mmc, widths[idx]);
 
                        err = mmc_send_ext_csd(mmc, test_csd);
                        if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
@@ -1206,7 +1139,7 @@ int mmc_startup(struct mmc *mmc)
                                 && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
                                        &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
 
-                               mmc->card_caps |= width;
+                               mmc->card_caps |= ext_to_hostcaps[extw];
                                break;
                        }
                }
@@ -1226,13 +1159,15 @@ int mmc_startup(struct mmc *mmc)
        mmc->block_dev.type = 0;
        mmc->block_dev.blksz = mmc->read_bl_len;
        mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
-       sprintf(mmc->block_dev.vendor, "Man %06x Snr %08x", mmc->cid[0] >> 8,
-                       (mmc->cid[2] << 8) | (mmc->cid[3] >> 24));
-       sprintf(mmc->block_dev.product, "%c%c%c%c%c", mmc->cid[0] & 0xff,
-                       (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
-                       (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
-       sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28,
-                       (mmc->cid[2] >> 24) & 0xf);
+       sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
+               mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
+               (mmc->cid[3] >> 16) & 0xffff);
+       sprintf(mmc->block_dev.product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
+               (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
+               (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
+               (mmc->cid[2] >> 24) & 0xff);
+       sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
+               (mmc->cid[2] >> 16) & 0xf);
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
        init_part(&mmc->block_dev);
 #endif
@@ -1240,7 +1175,7 @@ int mmc_startup(struct mmc *mmc)
        return 0;
 }
 
-int mmc_send_if_cond(struct mmc *mmc)
+static int mmc_send_if_cond(struct mmc *mmc)
 {
        struct mmc_cmd cmd;
        int err;