X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fmmc%2Fmmc.c;h=c543d837dc7e286dff1b28546e3ba7af7fd58dd0;hb=439f6f7ec17e267745d6667f9920514fa8da6b58;hp=7791c3896e98a00461bda3d4f18bb55d599bad82;hpb=f9a109b3adc5e8647535357500e2a38f0558b5c2;p=u-boot diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 7791c3896e..c543d837dc 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -31,10 +31,18 @@ #include #include #include +#include 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); @@ -84,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) { @@ -155,8 +168,8 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size) char *buffer; int i; int blklen = mmc->read_bl_len; - int startblock = src / blklen; - int endblock = (src + size - 1) / blklen; + int startblock = lldiv(src, mmc->read_bl_len); + int endblock = lldiv(src + size - 1, mmc->read_bl_len); int err = 0; /* Make a buffer big enough to hold all the blocks we might read */ @@ -171,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; @@ -211,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); @@ -272,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; @@ -291,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; @@ -326,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; @@ -486,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: @@ -517,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; } @@ -525,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); @@ -533,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; @@ -601,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; @@ -631,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; @@ -644,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: @@ -675,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 @@ -716,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 @@ -789,14 +826,14 @@ int mmc_startup(struct mmc *mmc) mmc->block_dev.lun = 0; mmc->block_dev.type = 0; mmc->block_dev.blksz = mmc->read_bl_len; - mmc->block_dev.lba = 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); + 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); init_part(&mmc->block_dev); return 0; @@ -818,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; @@ -846,7 +883,7 @@ block_dev_desc_t *mmc_get_dev(int dev) { struct mmc *mmc = find_mmc_device(dev); - return &mmc->block_dev; + return mmc ? &mmc->block_dev : NULL; } int mmc_init(struct mmc *mmc) @@ -858,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); @@ -867,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);