static int get_first_partition(uint32_t *lba) { struct mbr mbr; if (mmc_block_read((uint32_t *) &mbr, 0, 1)) { /* Unable to read bootsector. */ SERIAL_PUTI(0x00); return -1; } if (mbr.signature != 0xAA55) { /* No MBR detected. */ SERIAL_PUTI(0x01); return -1; } if (mbr.partitions[0].status && mbr.partitions[0].status != 0x80) { /* Unable to detect first physical partition. */ SERIAL_PUTI(0x02); return -1; } *lba = mbr.partitions[0].lba; return 0; }
int mmc_readback_blks(int dev_id, unsigned long addr, int blks, int bootarea) { int i, j, result = 0; u8 val; u8 *ext_csd; unsigned long blknr = addr / MMC_BLOCK_SIZE; unsigned char *buf = (unsigned char*)MMC_BUF_ADDR; struct mmc_card *card; struct mmc_host *host; host = mmc_get_host(dev_id); card = mmc_get_card(dev_id); ext_csd = &card->raw_ext_csd[0]; if (bootarea && !mmc_card_sd(card)) { /* configure to specified partition */ val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_BOOT_PART_1; if (mmc_set_part_config(card, val) != MMC_ERR_NONE) { result = -__LINE__; goto done; } if (mmc_read_ext_csd(host, card) != MMC_ERR_NONE) { result = -__LINE__; goto done; } } printf("[SD%d] Dump %d blks from 0x%x (FLASH)\n", dev_id, blks, blknr * MMC_BLOCK_SIZE); for (i = 0; i < blks; i++) { memset(buf, 0, MMC_BLOCK_SIZE); if (MMC_ERR_NONE != mmc_block_read(dev_id, blknr + i, 1, (unsigned long*)buf)) { printf("\n[SD%d] Read from %dth block error\n", dev_id, blknr + i); break; } for (j = 0; j < MMC_BLOCK_SIZE; j++) { if (j % 16 == 0) printf("\n%xh: ", (blknr + i) * MMC_BLOCK_SIZE + j); printf("%x ", buf[j]); } printf("\n"); buf += MMC_BLOCK_SIZE; } done: if (bootarea && !mmc_card_sd(card)) { /* configure to user partition */ val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_DEFT_PART; if (mmc_set_part_config(card, val) != MMC_ERR_NONE) result = -__LINE__; if (mmc_read_ext_csd(host, card) != MMC_ERR_NONE) { result = -__LINE__; } } return result; }
int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) { int ret = -1; switch (dfu->layout) { case DFU_RAW_ADDR: ret = mmc_block_read(dfu, buf, len); break; case DFU_FS_FAT: ret = mmc_file_read(dfu, buf, len); break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); } return ret; }
int /****************************************************/ mmc_write(uchar *src, ulong dst, int size) /****************************************************/ { ulong end, part_start, part_end, part_len, aligned_start, aligned_end; ulong mmc_block_size, mmc_block_address; if (size == 0) { return 0; } if (!mmc_ready) { printf("Please initial the MMC first\n"); return -1; } mmc_block_size = MMC_BLOCK_SIZE; mmc_block_address = ~(mmc_block_size - 1); dst -= CFG_MMC_BASE; end = dst + size; part_start = ~mmc_block_address & dst; part_end = ~mmc_block_address & end; aligned_start = mmc_block_address & dst; aligned_end = mmc_block_address & end; /* all block aligned accesses */ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if (part_start) { part_len = mmc_block_size - part_start; debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", (ulong)src, dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) { return -1; } memcpy(mmc_buf+part_start, src, part_len); if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0) { return -1; } dst += part_len; src += part_len; } debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) { debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0) { return -1; } } debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if (part_end && dst < end) { debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) { return -1; } memcpy(mmc_buf, src, part_end); if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) { return -1; } } return 0; }
int mmc_test_mem_card(struct mmc_test_config *cfg) { int id, count, forever; int ret, chk_result, tid = 0, result = 0; unsigned int chunks, chunk_blks, left_blks, pass = 0, fail = 0; unsigned int total_blks; unsigned int i, j; unsigned int blksz; unsigned int clkhz; char pattern = 0; char *buf; unsigned long blknr; struct mmc_host *host; struct mmc_card *card; id = cfg->id; count = cfg->count; buf = cfg->buf; blknr = cfg->blknr; blksz = cfg->blksz; chk_result = cfg->chk_result; chunk_blks = cfg->chunk_blks; total_blks = (cfg->total_size + blksz - 1) / blksz; forever = (count == -1) ? 1 : 0; host = mmc_get_host(id); card = mmc_get_card(id); while (forever || count--) { printf("[TST] ==============================================\n"); printf("[TST] BEGIN: %d/%d, No Stop(%d)\n", (cfg->count != -1) ? cfg->count - count : 0, (cfg->count != -1) ? cfg->count : 0, forever); printf("[TST] ----------------------------------------------\n"); printf("[TST] Mode : %d\n", cfg->mode); printf("[TST] Clock : %d kHz\n", cfg->clock / 1000); printf("[TST] BusWidth: %d bits\n", cfg->buswidth); printf("[TST] BurstSz : %d bytes\n", 0x1 << cfg->burstsz); printf("[TST] BlkAddr : %xh\n", blknr); printf("[TST] BlkSize : %dbytes\n", blksz); printf("[TST] TstBlks : %d\n", total_blks); #if defined(BB_MT6575) printf("[TST] AutoCMD : 12(%d), 23(%d)\n", (cfg->autocmd & MSDC_AUTOCMD12) ? 1 : 0, (cfg->autocmd & MSDC_AUTOCMD23) ? 1 : 0); #endif printf("[TST] ----------------------------------------------\n"); if (mmc_init_host(host, id) != 0) { result = -__LINE__; goto failure; } if (mmc_init_card(host, card) != 0) { result = -__LINE__; goto failure; } #if defined(BB_MT6575) msdc_set_dma(host, (u8)cfg->burstsz, (u32)cfg->flags); msdc_set_autocmd(host, cfg->autocmd, 1); #endif /* change uhs-1 mode */ #if 0 if (mmc_card_uhs1(card)) { if (mmc_switch_uhs1(host, card, cfg->uhsmode) != 0) { result = -__LINE__; goto failure; } } #endif /* change clock */ if (cfg->clock) { clkhz = card->maxhz < cfg->clock ? card->maxhz : cfg->clock; mmc_set_clock(host, mmc_card_ddr(card), clkhz); } if (mmc_card_sd(card) && cfg->buswidth == HOST_BUS_WIDTH_8) { printf("[TST] SD card doesn't support 8-bit bus width (SKIP)\n"); result = MMC_ERR_NONE; } if (mmc_set_bus_width(host, card, cfg->buswidth) != 0) { result = -__LINE__; goto failure; } /* cmd16 is illegal while card is in ddr mode */ if (!(mmc_card_mmc(card) && mmc_card_ddr(card))) { if (mmc_set_blk_length(host, blksz) != 0) { result = -__LINE__; goto failure; } } #if defined(BB_MT6575) if (cfg->piobits) { printf("[TST] PIO bits: %d\n", cfg->piobits); msdc_set_pio_bits(host, cfg->piobits); } #endif tid = result = 0; if (mmc_erase_start(card, blknr * blksz) != MMC_ERR_NONE) { result = -__LINE__; goto failure; } if (mmc_erase_end(card, (blknr + total_blks) * blksz) != MMC_ERR_NONE) { result = -__LINE__; goto failure; } if (mmc_erase(card, MMC_ERASE_NORMAL) != MMC_ERR_NONE) { result = -__LINE__; goto failure; } printf("[TST] 0x%x - 0x%x Erased\n", blknr * blksz, (blknr + total_blks) * blksz); mmc_send_status(host, card, &status); if (cfg->tst_single) { /* single block write */ for (i = 0; i < total_blks; i++) { pattern = (i + count) % 256; memset(buf, pattern, blksz); ret = mmc_block_write(id, blknr + i, 1, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { printf("test single block write failed (%d)\n", i); result = -__LINE__; goto failure; } } printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, "test single block write\n"); if (result) break; /* single block read */ for (i = 0; i < total_blks && !result; i++) { pattern = (i + count) % 256; /* populate buffer with different pattern */ memset(buf, pattern + 1, blksz); ret = mmc_block_read(id, blknr + i, 1, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto failure; } if (chk_result) { for (j = 0; j < blksz; j++) { if (buf[j] != pattern) { result = -__LINE__; goto failure; } } } } printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, "test single block read\n"); if (result) { printf("[SD%d]\t\tread back pattern(0x%.2x) failed\n", id, pattern); goto failure; } } mmc_send_status(host, card, &status); if (cfg->tst_multiple) { /* multiple block write */ chunks = total_blks / chunk_blks; left_blks = total_blks % chunk_blks; for (i = 0; i < chunks; i++) { pattern = (i + count) % 256; memset(buf, pattern, blksz * chunk_blks); ret = mmc_block_write(id, blknr + i * chunk_blks, chunk_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto failure; } } if (!result && left_blks) { pattern = (i + count) % 256; memset(buf, pattern, blksz * left_blks); ret = mmc_block_write(id, blknr + chunks * chunk_blks, left_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto failure; } } printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, "test multiple block write\n"); if (result) goto failure; /* multiple block read */ for (i = 0; i < chunks; i++) { pattern = (i + count) % 256; /* populate buffer with different pattern */ memset(buf, pattern + 1, blksz); ret = mmc_block_read(id, blknr + i * chunk_blks, chunk_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { printf("[SD%d]\t\tread %d blks failed(ret = %d blks)\n", host->id, chunk_blks, ret); result = -__LINE__; goto failure; } if (chk_result) { for (j = 0; j < chunk_blks * blksz; j++) { if (buf[j] == pattern) continue; result = -__LINE__; printf("[SD%d]\t\t%xh = %x (!= %x)\n", host->id, blknr + i * chunk_blks + j, buf[j], pattern); goto failure; } } } if (!result && left_blks) { pattern = i % 256; /* populate buffer with different pattern */ memset(buf, pattern + 1, blksz); ret = mmc_block_read(id, blknr + chunks * chunk_blks, left_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { printf("[SD%d]\t\tread %d blks failed(ret = %d blks)\n", host->id, left_blks, ret); result = -__LINE__; goto failure; } if (chk_result) { for (j = 0; j < left_blks * blksz; j++) { if (buf[j] == pattern) continue; printf("[SD%d]\t\t%xh = %x (!= %x)\n", host->id, blknr + chunks * chunk_blks + j, buf[j], pattern); result = -__LINE__; goto failure; } } } printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, "test multiple block read\n"); if (result) goto failure; } mmc_send_status(host, card, &status); if (cfg->tst_interleave) { /* multiple block write */ chunks = total_blks / chunk_blks; left_blks = total_blks % chunk_blks; for (i = 0; i < chunks; i++) { pattern = (i + count) % 256; memset(buf, pattern, blksz * chunk_blks); ret = mmc_block_write(id, blknr + i * chunk_blks, chunk_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto failure; } /* populate buffer with different pattern */ memset(buf, pattern + 1, blksz * chunk_blks); ret = mmc_block_read(id, blknr + i * chunk_blks, chunk_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto failure; } if (chk_result) { for (j = 0; j < chunk_blks * blksz; j++) { if (buf[j] == pattern) continue; result = -__LINE__; goto failure; } } } if (!result && left_blks) { pattern = (i + count) % 256; memset(buf, pattern, blksz * left_blks); ret = mmc_block_write(id, blknr + chunks * chunk_blks, left_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto failure; } /* populate buffer with different pattern */ memset(buf, pattern + 1, blksz * left_blks); ret = mmc_block_read(id, blknr + chunks * chunk_blks, left_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; break; } if (chk_result) { for (j = 0; j < left_blks * blksz; j++) { if (buf[j] == pattern) continue; result = -__LINE__; goto failure; } } } printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, "test multiple block interleave write-read\n"); if (result) goto failure; } if (cfg->desc) { printf("[TST] ----------------------------------------------\n"); printf("[TST] Report - %s \n", cfg->desc); printf("[TST] ----------------------------------------------\n"); } mmc_prof_dump(id); failure: if (result) { printf("[SD%d] mmc test failed (%d)\n", host->id, result); fail++; } else { pass++; } printf("[TST] ----------------------------------------------\n"); printf("[TST] Test Result: TOTAL(%d/%d), PASS(%d), FAIL(%d) \n", cfg->count - count, cfg->count, pass, fail); printf("[TST] ----------------------------------------------\n"); //mdelay(1000); } return result; }
int mmc_download(int dev_id, u32 imgaddr, u32 size, u32 addr, int bootarea) { int ret; int i, j, result = 0; u8 val; u8 *ext_csd; uchar *buf, *chkbuf; u32 chunks, chunk_blks = 128, left_blks, blknr; u32 total_blks; struct mmc_card *card; if (!size) return 0; if (addr % MMC_BLOCK_SIZE) return MMC_ERR_FAILED; card = mmc_get_card(dev_id); ext_csd = &card->raw_ext_csd[0]; if (bootarea && !mmc_card_sd(card) && card->ext_csd.part_en) { /* configure to specified partition */ val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_BOOT_PART_1; if (mmc_set_part_config(card, val) != MMC_ERR_NONE) { result = -__LINE__; goto done; } } blknr = addr / MMC_BLOCK_SIZE; total_blks = (size + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE; /* multiple block write */ chunks = total_blks / chunk_blks; left_blks = total_blks % chunk_blks; buf = (uchar*)imgaddr; chkbuf = (uchar*)MMC_BUF_ADDR; for (i = 0; i < chunks; i++) { ret = mmc_block_write(dev_id, blknr + i * chunk_blks, chunk_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto done; } ret = mmc_block_read(dev_id, blknr + i * chunk_blks, chunk_blks, (unsigned long*)chkbuf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto done; } for (j = 0; j < chunk_blks * MMC_BLOCK_SIZE; j++) { if (buf[j] == chkbuf[j]) continue; result = -__LINE__; goto done; } printf("[SD%d] Write %3d blocks from 0x%.8x(RAM) to 0x%.8x(FLASH).\n", dev_id, chunk_blks, (unsigned int)buf, (blknr + i * chunk_blks) * MMC_BLOCK_SIZE); buf += (chunk_blks * MMC_BLOCK_SIZE); } if (left_blks) { ret = mmc_block_write(dev_id, blknr + chunks * chunk_blks, left_blks, (unsigned long*)buf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto done; } ret = mmc_block_read(dev_id, blknr + chunks * chunk_blks, left_blks, (unsigned long*)chkbuf); if (ret != MMC_ERR_NONE) { result = -__LINE__; goto done; } for (j = 0; j < left_blks * MMC_BLOCK_SIZE; j++) { if (buf[j] == chkbuf[j]) continue; printf("[SD%d] chkbuf[%d] = %xh (!= %xh) \n", dev_id, j, chkbuf[j], buf[j]); result = -__LINE__; goto done; } printf("[SD%d] Write %3d blocks from 0x%.8x(RAM) to 0x%.8x(FLASH).\n", dev_id, left_blks, (unsigned int)buf, (blknr + chunks * chunk_blks) * MMC_BLOCK_SIZE); } done: if (bootarea && !mmc_card_sd(card) && card->ext_csd.part_en) { /* configure to user partition */ val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_DEFT_PART; if (mmc_set_part_config(card, val) != MMC_ERR_NONE) result = -__LINE__; } if (!result) { printf("[SD%d] Download %d blocks (%d bytes) to 0x%.8x successfully\n", dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE); } else { printf("[SD%d] Download %d blocks (%d bytes) to 0x%.8x failed %d\n", dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE, result); } return result; }
int sd_boot(num) { u8 *resp; u32 ret = 0; u32 clk_set = 0, clkrt = 0; DBG("sd_boot\n"); current_boot = SD_BOOT; ctl_num = num; if (ctl_num == 1) REG_CPM_CLKGR &= ~(1 << 11); sd_init(); clk_set = jz_extal / 2; while (200000 < clk_set) { clkrt++; clk_set >>= 1; } if (clkrt > 7) { clkrt = 7; } REG_MSC_CLKRT(ctl_num) = clkrt; REG_MSC_LPM(ctl_num) = 1; /* cmd12 reset when we reading or writing from the card, send this cmd */ resp = mmc_cmd(12, 0, 0x41, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(0, 0, 0x80, MSC_CMDAT_RESPONSE_NONE); resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, 0, 0x1, MSC_CMDAT_RESPONSE_R1); if (resp[0] & 0x20){ if (resp[5] == 0x37){ resp = mmc_cmd(41, 0x40ff8000, 0x3, MSC_CMDAT_RESPONSE_R3); if (resp[5] == 0x3f) ret = sd_found(); else ret = mmc_found(); } else { ret = mmc_found(); } } else { ret = mmc_found(); } if (ret) return error_handler(current_boot); ret = mmc_block_read(SPL_SIZE + redundancy_size, (u32 *)start_addr); //SDRAM ADDR if(!ret) { if (!(REG32(start_addr) == 0x4d53504c)) { if (ctl_num == 0) return sd_boot(1); if (ctl_num == 1) return usb_boot(); } else { return xfer_d2i(start_addr + jump_offset, SPL_SIZE); } } else { return error_handler(current_boot); } }