]> git.sur5r.net Git - u-boot/blobdiff - drivers/mmc/mmc.c
FPGA: fix support for non-Lattice devices
[u-boot] / drivers / mmc / mmc.c
index 95ed21eb0ad2fa8c4c2107f19ab3336abf71fef7..c543d837dc7e286dff1b28546e3ba7af7fd58dd0 100644 (file)
 static struct list_head mmc_devices;
 static int cur_dev_num = -1;
 
+int __board_mmc_getcd(u8 *cd, struct mmc *mmc) {
+       return -1;
+}
+
+int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
+       alias("__board_mmc_getcd")));
+
 int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
        return mmc->send_cmd(mmc, cmd, data);
@@ -85,6 +92,11 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
 
        blklen = mmc->write_bl_len;
 
+       if ((start + blkcnt) > mmc->block_dev.lba) {
+               printf("MMC: block number 0x%lx exceeds max(0x%lx)",
+                       start + blkcnt, mmc->block_dev.lba);
+               return 0;
+       }
        err = mmc_set_blocklen(mmc, mmc->write_bl_len);
 
        if (err) {
@@ -172,7 +184,7 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
        err = mmc_set_blocklen(mmc, mmc->read_bl_len);
 
        if (err)
-               return err;
+               goto free_buffer;
 
        for (i = startblock; i <= endblock; i++) {
                int segment_size;
@@ -212,6 +224,11 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
        if (!mmc)
                return 0;
 
+       if ((start + blkcnt) > mmc->block_dev.lba) {
+               printf("MMC: block number 0x%lx exceeds max(0x%lx)",
+                       start + blkcnt, mmc->block_dev.lba);
+               return 0;
+       }
        /* We always do full block reads from the card */
        err = mmc_set_blocklen(mmc, mmc->read_bl_len);
 
@@ -273,7 +290,15 @@ sd_send_op_cond(struct mmc *mmc)
 
                cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
                cmd.resp_type = MMC_RSP_R3;
-               cmd.cmdarg = mmc->voltages;
+
+               /*
+                * Most cards do not answer if some reserved bits
+                * in the ocr are set. However, Some controller
+                * can set bit 7 (reserved for low voltages), but
+                * how to manage low voltages SD card is not yet
+                * specified.
+                */
+               cmd.cmdarg = mmc->voltages & 0xff8000;
 
                if (mmc->version == SD_VERSION_2)
                        cmd.cmdarg |= OCR_HCS;
@@ -292,7 +317,7 @@ sd_send_op_cond(struct mmc *mmc)
        if (mmc->version != SD_VERSION_2)
                mmc->version = SD_VERSION_1_0;
 
-       mmc->ocr = ((uint *)(cmd.response))[0];
+       mmc->ocr = cmd.response[0];
 
        mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
        mmc->rca = 0;
@@ -327,7 +352,7 @@ int mmc_send_op_cond(struct mmc *mmc)
                return UNUSABLE_ERR;
 
        mmc->version = MMC_VERSION_UNKNOWN;
-       mmc->ocr = ((uint *)(cmd.response))[0];
+       mmc->ocr = cmd.response[0];
 
        mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
        mmc->rca = 0;
@@ -487,8 +512,8 @@ retry_scr:
                return err;
        }
 
-       mmc->scr[0] = scr[0];
-       mmc->scr[1] = scr[1];
+       mmc->scr[0] = __be32_to_cpu(scr[0]);
+       mmc->scr[1] = __be32_to_cpu(scr[1]);
 
        switch ((mmc->scr[0] >> 24) & 0xf) {
                case 0:
@@ -518,7 +543,7 @@ retry_scr:
                        return err;
 
                /* The high-speed function is busy.  Try again */
-               if (!switch_status[7] & SD_HIGHSPEED_BUSY)
+               if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
                        break;
        }
 
@@ -526,7 +551,7 @@ retry_scr:
                mmc->card_caps |= MMC_MODE_4BIT;
 
        /* If high-speed isn't supported, we return */
-       if (!(switch_status[3] & SD_HIGHSPEED_SUPPORTED))
+       if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
                return 0;
 
        err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)&switch_status);
@@ -534,7 +559,7 @@ retry_scr:
        if (err)
                return err;
 
-       if ((switch_status[4] & 0x0f000000) == 0x01000000)
+       if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
                mmc->card_caps |= MMC_MODE_HS;
 
        return 0;
@@ -602,6 +627,7 @@ int mmc_startup(struct mmc *mmc)
        uint mult, freq;
        u64 cmult, csize;
        struct mmc_cmd cmd;
+       char ext_csd[512];
 
        /* Put the Card in Identify Mode */
        cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
@@ -632,7 +658,7 @@ int mmc_startup(struct mmc *mmc)
                return err;
 
        if (IS_SD(mmc))
-               mmc->rca = (((uint *)(cmd.response))[0] >> 16) & 0xffff;
+               mmc->rca = (cmd.response[0] >> 16) & 0xffff;
 
        /* Get the Card-Specific Data */
        cmd.cmdidx = MMC_CMD_SEND_CSD;
@@ -645,13 +671,13 @@ int mmc_startup(struct mmc *mmc)
        if (err)
                return err;
 
-       mmc->csd[0] = ((uint *)(cmd.response))[0];
-       mmc->csd[1] = ((uint *)(cmd.response))[1];
-       mmc->csd[2] = ((uint *)(cmd.response))[2];
-       mmc->csd[3] = ((uint *)(cmd.response))[3];
+       mmc->csd[0] = cmd.response[0];
+       mmc->csd[1] = cmd.response[1];
+       mmc->csd[2] = cmd.response[2];
+       mmc->csd[3] = cmd.response[3];
 
        if (mmc->version == MMC_VERSION_UNKNOWN) {
-               int version = (cmd.response[0] >> 2) & 0xf;
+               int version = (cmd.response[0] >> 26) & 0xf;
 
                switch (version) {
                        case 0:
@@ -676,17 +702,17 @@ int mmc_startup(struct mmc *mmc)
        }
 
        /* divide frequency by 10, since the mults are 10x bigger */
-       freq = fbase[(cmd.response[3] & 0x7)];
-       mult = multipliers[((cmd.response[3] >> 3) & 0xf)];
+       freq = fbase[(cmd.response[0] & 0x7)];
+       mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
 
        mmc->tran_speed = freq * mult;
 
-       mmc->read_bl_len = 1 << ((((uint *)(cmd.response))[1] >> 16) & 0xf);
+       mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
 
        if (IS_SD(mmc))
                mmc->write_bl_len = mmc->read_bl_len;
        else
-               mmc->write_bl_len = 1 << ((((uint *)(cmd.response))[3] >> 22) & 0xf);
+               mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
 
        if (mmc->high_capacity) {
                csize = (mmc->csd[1] & 0x3f) << 16
@@ -717,6 +743,16 @@ int mmc_startup(struct mmc *mmc)
        if (err)
                return err;
 
+       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[192] >= 2)) {
+                       mmc->capacity = ext_csd[212] << 0 | ext_csd[213] << 8 |
+                                       ext_csd[214] << 16 | ext_csd[215] << 24;
+                       mmc->capacity *= 512;
+               }
+       }
+
        if (IS_SD(mmc))
                err = sd_change_freq(mmc);
        else
@@ -791,13 +827,13 @@ 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 %02x%02x%02x Snr %02x%02x%02x%02x",
-                       mmc->cid[0], mmc->cid[1], mmc->cid[2],
-                       mmc->cid[9], mmc->cid[10], mmc->cid[11], mmc->cid[12]);
-       sprintf(mmc->block_dev.product,"%c%c%c%c%c", mmc->cid[3],
-                       mmc->cid[4], mmc->cid[5], mmc->cid[6], mmc->cid[7]);
-       sprintf(mmc->block_dev.revision,"%d.%d", mmc->cid[8] >> 4,
-                       mmc->cid[8] & 0xf);
+       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);
        init_part(&mmc->block_dev);
 
        return 0;
@@ -819,7 +855,7 @@ int mmc_send_if_cond(struct mmc *mmc)
        if (err)
                return err;
 
-       if ((((uint *)(cmd.response))[0] & 0xff) != 0xaa)
+       if ((cmd.response[0] & 0xff) != 0xaa)
                return UNUSABLE_ERR;
        else
                mmc->version = SD_VERSION_2;
@@ -859,6 +895,9 @@ int mmc_init(struct mmc *mmc)
        if (err)
                return err;
 
+       mmc_set_bus_width(mmc, 1);
+       mmc_set_clock(mmc, 1);
+
        /* Reset the Card */
        err = mmc_go_idle(mmc);
 
@@ -868,10 +907,6 @@ int mmc_init(struct mmc *mmc)
        /* Test for SD version 2 */
        err = mmc_send_if_cond(mmc);
 
-       /* If we got an error other than timeout, we bail */
-       if (err && err != TIMEOUT)
-               return err;
-
        /* Now try to get the SD card's operating condition */
        err = sd_send_op_cond(mmc);