int mmc_boot_up(int id, int reset) { int err = MMC_ERR_FAILED; struct mmc_host *host; host = mmc_get_host(id); mmc_init_host(host, id); msdc_emmc_boot_reset(host, reset); err = msdc_emmc_boot_start(host, 25000000, 0, EMMC_BOOT_RST_CMD_MODE, 0); if (err) { printf("[EMMC] Boot Error: %d\n", err); goto done; } err = msdc_emmc_boot_read(host, 128 * 1024, MMC_BUF_ADDR); msdc_emmc_boot_stop(host, EMMC_BOOT_RST_CMD_MODE); done: if (!err) { int i, j; char *buf = MMC_BUF_ADDR; for (i = 0; i < 16; i++) { for (j = 0; j < MMC_BLOCK_SIZE; j++) { if (j % 16 == 0) printf("\n%.8xh: ", i * MMC_BLOCK_SIZE + j); printf("%.2x ", buf[j]); } printf("\n"); buf += MMC_BLOCK_SIZE; } } return err; }
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 mmc_boot_up_test(int id, int reset, u32 freq, int in_idle) { int err = MMC_ERR_FAILED; struct mmc_host *host; struct mmc_card *card; host = mmc_get_host(id); card = mmc_get_card(id); mmc_init_host(host, id); if (in_idle) { printf("[EMMC] Card is in idle mode \n"); /* card in idle mode */ //mmc_go_idle(host); mmc_init_card(host, card); /* note: requires delay before issue boot reset command */ mdelay(5); } else { /* card not in idle mode */ printf("[EMMC] Card is not in idle mode \n"); } msdc_emmc_boot_reset(host, reset); err = msdc_emmc_boot_start(host, freq, 0, EMMC_BOOT_RST_CMD_MODE, 0); if (err) { printf("[EMMC] Boot Error: %d\n", err); goto done; } err = msdc_emmc_boot_read(host, 128 * 1024, MMC_BUF_ADDR); msdc_emmc_boot_stop(host, EMMC_BOOT_RST_CMD_MODE); if (err) { printf("[EMMC] Boot Read Error: %d\n", err); goto done; } done: if (!err) { int i, j; char *buf = (char*)MMC_BUF_ADDR; for (i = 0; i < 16; i++) { for (j = 0; j < MMC_BLOCK_SIZE; j++) { if (j % 16 == 0) printf("\n%xh: ", i * MMC_BLOCK_SIZE + j); printf("%x ", buf[j]); } printf("\n"); buf += MMC_BLOCK_SIZE; } } return err; }
int mmc_boot_enable(int id, int bootpart) { int err = MMC_ERR_FAILED; struct mmc_host *host; struct mmc_card *card; host = mmc_get_host(id); card = mmc_get_card(id); err = mmc_boot_config(card, EXT_CSD_PART_CFG_EN_ACK, bootpart, EXT_CSD_BOOT_BUS_WIDTH_1, EXT_CSD_BOOT_BUS_MODE_DEFT); if (err != 0) goto done; err = mmc_read_ext_csd(host, card); done: return err; }
static int scan(int argc, char *argv[]) { int ret; int i; struct mmc_cid *cid; struct mmc_host *host; if (argc > 1) { usage(); return -EINVAL; } for (i = 0; i < MMC_HOST_NUM; i++) { host = mmc_get_host(i); if(host == NULL && i == 0) { printf("Error: Can't Get MMC Host!\n"); return -ENODEV; } if (host == NULL) { printf("Scan complete\n"); break; } ret = mmc_sd_detect_card(host); if (ret < 0) { printf("Error: No SD Found!\n"); return -ENODEV; } cid = (struct mmc_cid* )(host->card.raw_cid); printf("Manufacturer ID: %x\n" "OEM/Application ID: %x\n" "Product Name: %c%c%c%c%c\n" "Product serial number: %x\n", cid->mid, cid->oid,cid->pnm[4], cid->pnm[3],cid->pnm[2],cid->pnm[1],cid->pnm[0], cid->psn); } return 0; }
int mmc_download_part(int dev_id, char *part_name, int bootarea) { int ret = -1; struct mmc_card *card; struct mmc_host *host; part_t *part = mt6573_part_get_partition(part_name); mmc_download_addr = 0; mmc_download_size = 0; mmc_image_addr = 0; host = mmc_get_host(dev_id); card = mmc_get_card(dev_id); if (part) { printf("[SD%d] Waiting for '%s' image loading from ICE...\n", dev_id, part_name); while (!mmc_download_size); /* Wait for loading image from ICE */ ret = mmc_download(dev_id, mmc_image_addr, mmc_download_size, part->startblk * BLK_SIZE, bootarea); if (ret != 0) goto done; if (bootarea) { /* set reset signal function */ //ret = mmc_set_reset_func(card, 1); //if (ret != 0) // goto done; /* set boot config */ ret = mmc_boot_config(card, EXT_CSD_PART_CFG_EN_ACK, EXT_CSD_PART_CFG_EN_BOOT_PART_1, EXT_CSD_BOOT_BUS_WIDTH_1, EXT_CSD_BOOT_BUS_MODE_DEFT); if (ret != 0) goto done; ret = mmc_read_ext_csd(host, card); } } done: return ret; }
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; }